aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/FormattedTextBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx48
1 files changed, 32 insertions, 16 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c12c4acf0..ab2d84893 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -63,6 +63,7 @@ import React = require("react");
import { SidebarAnnos } from '../../SidebarAnnos';
import { Colors } from '../../global/globalEnums';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { LinkManager } from '../../../util/LinkManager';
const translateGoogleApi = require("translate-google-api");
export interface FormattedTextBoxProps {
@@ -346,7 +347,23 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
+ autoLink = () => {
+ if (this._editorView) {
+ const newAutoLinks = new Set<Doc>();
+ const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship = "automatic");
+ const f = this._editorView.state.selection.from;
+ const t = this._editorView.state.selection.to;
+ var tr = this._editorView.state.tr as any;
+ tr = tr.removeMark(0, tr.doc.content.size, this._editorView!.state.schema.marks.autoLinkAnchor);
+ DocListCast(Doc.UserDoc().myPublishedDocs).forEach(term => tr = this.hyperlinkTerm(tr, term, newAutoLinks));
+ tr = tr.setSelection(new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t)));
+ this._editorView?.dispatch(tr);
+ oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink)).forEach(LinkManager.Instance.deleteLink);
+ }
+ }
+
updateTitle = () => {
+ const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship = "automatic");
if (!this.props.dontRegisterView && // (this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
StrCast(this.dataDoc.title).startsWith("-") && this._editorView && !this.dataDoc["title-custom"] &&
(Doc.LayoutFieldKey(this.rootDoc) === this.fieldKey || this.fieldKey === "text")) {
@@ -357,26 +374,24 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
- // needs a better API for taking in a set of words with target documents instead of just one target
- hyperlinkTerms = (terms: string[], target: Doc) => {
- if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) {
- const res1 = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term));
- let tr = this._editorView.state.tr;
- const flattened1: TextSelection[] = [];
- res1.map(r => r.map(h => flattened1.push(h)));
+ // creates links between terms in a document and documents which have a matching Id
+ hyperlinkTerm = (tr: any, target: Doc, newAutoLinks: Set<Doc>) => {
+ if (this._editorView && (this._editorView as any).docView) {
+ const flattened1 = this.findInNode(this._editorView, this._editorView.state.doc, StrCast(target.title).replace(/^@/, ""));
+ var alink: Doc | undefined;
flattened1.forEach((flat, i) => {
- const flattened: TextSelection[] = [];
- const res = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term));
- res.map(r => r.map(h => flattened.push(h)));
+ const flattened = this.findInNode(this._editorView!, this._editorView!.state.doc, StrCast(target.title).replace(/^@/, ""));
this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
- const anchor = Docs.Create.TextanchorDocument();
- const alink = DocUtils.MakeLink({ doc: anchor }, { doc: target }, "automatic")!;
- const allAnchors = [{ href: Doc.localServerPath(anchor), title: "a link", anchorId: anchor[Id] }];
- const link = this._editorView!.state.schema.marks.linkAnchor.create({ allAnchors, title: "auto link", location });
+ alink = alink ?? (DocListCast(this.Document.links).find(link =>
+ Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) &&
+ Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) || DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, "automatic")!);
+ newAutoLinks.add(alink);
+ const allAnchors = [{ href: Doc.localServerPath(this.props.Document), title: "a link", anchorId: this.props.Document[Id] }];
+ const link = this._editorView!.state.schema.marks.autoLinkAnchor.create({ allAnchors, linkDoc: alink[Id], title: "auto link", location });
tr = tr.addMark(flattened[i].from, flattened[i].to, link);
});
- this._editorView.dispatch(tr);
}
+ return tr;
}
highlightSearchTerms = (terms: string[], backward: boolean) => {
if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) {
@@ -1256,7 +1271,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
let target = (e.target as any).parentElement; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
while (target && !target.dataset?.targethrefs) target = target.parentElement;
- FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs);
+ FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc);
}
(e.nativeEvent as any).formattedHandled = true;
@@ -1399,6 +1414,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@action
onBlur = (e: any) => {
+ this.autoLink();
FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) {
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined);