@lblod/ember-rdfa-editor 13.2.1 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/declarations/components/ember-node/embedded-editor.d.ts +14 -34
- package/declarations/components/ember-node/inline-rdfa.d.ts +2 -2
- package/declarations/components/ember-node/link.d.ts +18 -12
- package/declarations/components/pill.d.ts +15 -7
- package/declarations/components/plugins/link/_private/link-editor.d.ts +37 -0
- package/declarations/components/plugins/link/link-editor.d.ts +6 -20
- package/declarations/components/plugins/link/link-menu.d.ts +3 -0
- package/declarations/components/plugins/link/link-sidebar-widget.d.ts +16 -0
- package/declarations/plugins/link/input-rule.d.ts +19 -0
- package/declarations/plugins/link/nodes/link.d.ts +2 -0
- package/declarations/plugins/link/parser.d.ts +17 -0
- package/dist/_app_/components/plugins/link/_private/link-editor.js +1 -0
- package/dist/_app_/components/plugins/link/link-sidebar-widget.js +1 -0
- package/dist/components/ember-node/embedded-editor.js +13 -29
- package/dist/components/ember-node/embedded-editor.js.map +1 -1
- package/dist/components/ember-node/inline-rdfa.js +12 -4
- package/dist/components/ember-node/inline-rdfa.js.map +1 -1
- package/dist/components/ember-node/link.js +86 -49
- package/dist/components/ember-node/link.js.map +1 -1
- package/dist/components/ember-node/slot.js +10 -4
- package/dist/components/ember-node/slot.js.map +1 -1
- package/dist/components/pill.js +12 -3
- package/dist/components/pill.js.map +1 -1
- package/dist/components/plugins/link/_private/link-editor.js +128 -0
- package/dist/components/plugins/link/_private/link-editor.js.map +1 -0
- package/dist/components/plugins/link/link-editor.js +5 -78
- package/dist/components/plugins/link/link-editor.js.map +1 -1
- package/dist/components/plugins/link/link-menu.js +25 -8
- package/dist/components/plugins/link/link-menu.js.map +1 -1
- package/dist/components/plugins/link/link-sidebar-widget.js +40 -0
- package/dist/components/plugins/link/link-sidebar-widget.js.map +1 -0
- package/dist/nodes/inline-rdfa.js.map +1 -1
- package/dist/plugins/link/input-rule.js +82 -0
- package/dist/plugins/link/input-rule.js.map +1 -0
- package/dist/plugins/link/nodes/link.js +11 -1
- package/dist/plugins/link/nodes/link.js.map +1 -1
- package/dist/plugins/link/parser.js +58 -0
- package/dist/plugins/link/parser.js.map +1 -0
- package/package.json +4 -1
- package/scss/_c-formatting-marks.scss +0 -1
- package/scss/_c-link.scss +27 -27
- package/scss/_c-table.scss +4 -0
- package/vendor/ember-rdfa-editor.css +26 -25
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { action } from '@ember/object';
|
|
2
2
|
import Component from '@glimmer/component';
|
|
3
3
|
import { wrapSelection } from '../../../commands/wrap-selection.js';
|
|
4
|
-
import { linkToHref } from '../../../utils/_private/string-utils.js';
|
|
5
4
|
import { LinkIcon } from '@appuniversum/ember-appuniversum/components/icons/link';
|
|
5
|
+
import ToolbarButton from '../../toolbar/button.js';
|
|
6
|
+
import t from 'ember-intl/helpers/t';
|
|
7
|
+
import { on } from '@ember/modifier';
|
|
8
|
+
import { not } from 'ember-truth-helpers';
|
|
9
|
+
import { defaultLinkParser } from '../../../plugins/link/parser.js';
|
|
6
10
|
import { precompileTemplate } from '@ember/template-compilation';
|
|
7
|
-
import { n } from 'decorator-transforms/runtime';
|
|
8
11
|
import { setComponentTemplate } from '@ember/component';
|
|
9
|
-
|
|
10
|
-
var TEMPLATE = precompileTemplate("{{! @glint-nocheck: not typesafe yet }}\n{{#if @controller}}\n <Toolbar::Button\n @title={{t \"ember-rdfa-editor.link.insert\"}}\n @icon={{this.LinkIcon}}\n {{on \"click\" this.insert}}\n @disabled={{not this.canInsert}}\n />\n{{/if}}");
|
|
12
|
+
import { n } from 'decorator-transforms/runtime';
|
|
11
13
|
|
|
12
14
|
class LinkMenu extends Component {
|
|
13
15
|
LinkIcon = LinkIcon;
|
|
14
16
|
get controller() {
|
|
15
17
|
return this.args.controller;
|
|
16
18
|
}
|
|
19
|
+
parseLink = input => {
|
|
20
|
+
return this.args.linkParser ? this.args.linkParser(input) : defaultLinkParser()(input);
|
|
21
|
+
};
|
|
17
22
|
get schema() {
|
|
18
23
|
return this.controller.schema;
|
|
19
24
|
}
|
|
@@ -25,12 +30,14 @@ class LinkMenu extends Component {
|
|
|
25
30
|
this.controller.doCommand(wrapSelection(this.schema.nodes['link'], nodeRange => {
|
|
26
31
|
if (nodeRange) {
|
|
27
32
|
const text = nodeRange.$from.doc.textBetween(nodeRange.$from.pos, nodeRange.$to.pos);
|
|
28
|
-
const
|
|
33
|
+
const linkParserResult = this.parseLink(text);
|
|
29
34
|
return {
|
|
30
|
-
href
|
|
35
|
+
href: linkParserResult.value ?? text
|
|
31
36
|
};
|
|
32
37
|
} else {
|
|
33
|
-
return
|
|
38
|
+
return {
|
|
39
|
+
isNew: true
|
|
40
|
+
};
|
|
34
41
|
}
|
|
35
42
|
}));
|
|
36
43
|
this.controller.focus();
|
|
@@ -40,8 +47,18 @@ class LinkMenu extends Component {
|
|
|
40
47
|
static {
|
|
41
48
|
n(this.prototype, "insert", [action]);
|
|
42
49
|
}
|
|
50
|
+
static {
|
|
51
|
+
setComponentTemplate(precompileTemplate("\n {{#if @controller}}\n <ToolbarButton @title={{t \"ember-rdfa-editor.link.insert\"}} @icon={{this.LinkIcon}} {{on \"click\" this.insert}} @disabled={{not this.canInsert}} />\n {{/if}}\n ", {
|
|
52
|
+
strictMode: true,
|
|
53
|
+
scope: () => ({
|
|
54
|
+
ToolbarButton,
|
|
55
|
+
t,
|
|
56
|
+
not,
|
|
57
|
+
on
|
|
58
|
+
})
|
|
59
|
+
}), this);
|
|
60
|
+
}
|
|
43
61
|
}
|
|
44
|
-
setComponentTemplate(TEMPLATE, LinkMenu);
|
|
45
62
|
|
|
46
63
|
export { LinkMenu as default };
|
|
47
64
|
//# sourceMappingURL=link-menu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-menu.js","sources":["../../../../src/components/plugins/link/link-menu.
|
|
1
|
+
{"version":3,"file":"link-menu.js","sources":["../../../../src/components/plugins/link/link-menu.gts"],"sourcesContent":["import { action } from '@ember/object';\nimport Component from '@glimmer/component';\nimport { wrapSelection } from '#root/commands/wrap-selection.ts';\nimport { LinkIcon } from '@appuniversum/ember-appuniversum/components/icons/link';\nimport type SayController from '#root/core/say-controller.ts';\nimport ToolbarButton from '#root/components/toolbar/button.gts';\nimport t from 'ember-intl/helpers/t';\nimport { on } from '@ember/modifier';\nimport { not } from 'ember-truth-helpers';\nimport {\n defaultLinkParser,\n type LinkParser,\n} from '#root/plugins/link/parser.ts';\n\ntype Args = {\n controller: SayController;\n onActivate?: () => void;\n linkParser?: LinkParser;\n};\nexport default class LinkMenu extends Component<Args> {\n LinkIcon = LinkIcon;\n\n get controller() {\n return this.args.controller;\n }\n\n parseLink: LinkParser = (input?: string) => {\n return this.args.linkParser\n ? this.args.linkParser(input)\n : defaultLinkParser()(input);\n };\n\n get schema() {\n return this.controller.schema;\n }\n\n get canInsert() {\n return (\n !this.controller.inEmbeddedView &&\n this.controller.checkCommand(wrapSelection(this.schema.nodes['link']))\n );\n }\n\n @action\n insert() {\n if (!this.controller.inEmbeddedView) {\n this.controller.doCommand(\n wrapSelection(this.schema.nodes['link'], (nodeRange) => {\n if (nodeRange) {\n const text = nodeRange.$from.doc.textBetween(\n nodeRange.$from.pos,\n nodeRange.$to.pos,\n );\n const linkParserResult = this.parseLink(text);\n return { href: linkParserResult.value ?? text };\n } else {\n return { isNew: true };\n }\n }),\n );\n this.controller.focus();\n this.args.onActivate?.();\n }\n }\n\n <template>\n {{#if @controller}}\n <ToolbarButton\n @title={{t \"ember-rdfa-editor.link.insert\"}}\n @icon={{this.LinkIcon}}\n {{on \"click\" this.insert}}\n @disabled={{not this.canInsert}}\n />\n {{/if}}\n </template>\n}\n"],"names":["LinkMenu","Component","LinkIcon","controller","args","parseLink","input","linkParser","defaultLinkParser","schema","canInsert","inEmbeddedView","checkCommand","wrapSelection","nodes","insert","doCommand","nodeRange","text","$from","doc","textBetween","pos","$to","linkParserResult","href","value","isNew","focus","onActivate","n","prototype","action","setComponentTemplate","precompileTemplate","strictMode","scope","ToolbarButton","t","not","on"],"mappings":";;;;;;;;;;;;;AAmBe,MAAMA,iBAAiBC,SAAA,CAAU;AAC9CC,EAAAA,QAAA,GAAWA,QAAA;EAEX,IAAIC,UAAAA,GAAa;AACf,IAAA,OAAO,IAAI,CAACC,IAAI,CAACD,UAAU;AAC7B,EAAA;EAEAE,SAAA,GAAyBC,KAAc,IAAA;IACrC,OAAO,IAAI,CAACF,IAAI,CAACG,UAAU,GACvB,IAAI,CAACH,IAAI,CAACG,UAAU,CAACD,SACrBE,iBAAA,EAAA,CAAoBF,KAAA,CAAA;EAC1B,CAAA;EAEA,IAAIG,MAAAA,GAAS;AACX,IAAA,OAAO,IAAI,CAACN,UAAU,CAACM,MAAM;AAC/B,EAAA;EAEA,IAAIC,SAAAA,GAAY;IACd,OACE,CAAC,IAAI,CAACP,UAAU,CAACQ,cAAc,IAC/B,IAAI,CAACR,UAAU,CAACS,YAAY,CAACC,cAAc,IAAI,CAACJ,MAAM,CAACK,KAAK,CAAC,MAAA,CAAO,CAAA,CACtE;AACF,EAAA;AAGAC,EAAAA,MAAAA,GAAS;AACP,IAAA,IAAI,CAAC,IAAI,CAACZ,UAAU,CAACQ,cAAc,EAAE;AACnC,MAAA,IAAI,CAACR,UAAU,CAACa,SAAS,CACvBH,aAAA,CAAc,IAAI,CAACJ,MAAM,CAACK,KAAK,CAAC,MAAA,CAAO,EAAGG,SAAA,IAAA;AACxC,QAAA,IAAIA,SAAA,EAAW;UACb,MAAMC,OAAOD,SAAA,CAAUE,KAAK,CAACC,GAAG,CAACC,WAAW,CAC1CJ,SAAA,CAAUE,KAAK,CAACG,GAAG,EACnBL,SAAA,CAAUM,GAAG,CAACD,GAAG,CAAA;AAEnB,UAAA,MAAME,gBAAA,GAAmB,IAAI,CAACnB,SAAS,CAACa,IAAA,CAAA;UACxC,OAAO;AAAEO,YAAAA,IAAA,EAAMD,gBAAA,CAAiBE,KAAK,IAAIR;WAAK;AAChD,QAAA,CAAA,MAAO;UACL,OAAO;AAAES,YAAAA,KAAA,EAAO;WAAK;AACvB,QAAA;AACF,MAAA,CAAA,CAAA,CAAA;AAEF,MAAA,IAAI,CAACxB,UAAU,CAACyB,KAAK,EAAA;AACrB,MAAA,IAAI,CAACxB,IAAI,CAACyB,UAAU,IAAA;AACtB,IAAA;AACF,EAAA;AAAA,EAAA;IAAAC,CAAA,CAAA,IAAA,CAAAC,SAAA,EAAA,QAAA,EAAA,CApBCC,MAAA,CAAA,CAAA;AAAA;AAsBD,EAAA;IAAAC,oBAAA,CAAAC,kBAAA,CAAA,0MAAA,EASA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;QAAAC,aAAA;QAAAC,CAAA;QAAAC,GAAA;AAAAC,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
3
|
+
import { defaultLinkParser } from '../../../plugins/link/parser.js';
|
|
4
|
+
import LinkEditor from './_private/link-editor.js';
|
|
5
|
+
import { precompileTemplate } from '@ember/template-compilation';
|
|
6
|
+
import { setComponentTemplate } from '@ember/component';
|
|
7
|
+
|
|
8
|
+
class LinkSidebarWidget extends Component {
|
|
9
|
+
get linkParser() {
|
|
10
|
+
return this.args.linkParser ?? defaultLinkParser();
|
|
11
|
+
}
|
|
12
|
+
get controller() {
|
|
13
|
+
return this.args.controller;
|
|
14
|
+
}
|
|
15
|
+
get link() {
|
|
16
|
+
if (this.controller) {
|
|
17
|
+
const {
|
|
18
|
+
selection
|
|
19
|
+
} = this.controller.mainEditorState;
|
|
20
|
+
if (selection instanceof NodeSelection && selection.node.type === this.controller.schema.nodes['link']) {
|
|
21
|
+
return {
|
|
22
|
+
pos: selection.from,
|
|
23
|
+
node: selection.node
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
static {
|
|
30
|
+
setComponentTemplate(precompileTemplate("\n {{#if this.controller}}\n {{#if this.link}}\n <LinkEditor @link={{this.link}} @linkParser={{this.linkParser}} @controller={{this.controller}} @showTitle={{true}} />\n {{/if}}\n {{/if}}\n ", {
|
|
31
|
+
strictMode: true,
|
|
32
|
+
scope: () => ({
|
|
33
|
+
LinkEditor
|
|
34
|
+
})
|
|
35
|
+
}), this);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { LinkSidebarWidget as default };
|
|
40
|
+
//# sourceMappingURL=link-sidebar-widget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-sidebar-widget.js","sources":["../../../../src/components/plugins/link/link-sidebar-widget.gts"],"sourcesContent":["import Component from '@glimmer/component';\nimport { NodeSelection } from 'prosemirror-state';\nimport type SayController from '#root/core/say-controller.ts';\nimport type { LinkParser } from '#root/plugins/link/parser.js';\nimport { defaultLinkParser } from '#root/plugins/link/parser.ts';\nimport LinkEditor from './_private/link-editor.gts';\n\ntype Args = {\n controller?: SayController;\n linkParser?: LinkParser;\n};\n\nexport default class LinkSidebarWidget extends Component<Args> {\n get linkParser() {\n return this.args.linkParser ?? defaultLinkParser();\n }\n\n get controller() {\n return this.args.controller;\n }\n\n get link() {\n if (this.controller) {\n const { selection } = this.controller.mainEditorState;\n if (\n selection instanceof NodeSelection &&\n selection.node.type === this.controller.schema.nodes['link']\n ) {\n return { pos: selection.from, node: selection.node };\n }\n }\n return;\n }\n\n <template>\n {{#if this.controller}}\n {{#if this.link}}\n <LinkEditor\n @link={{this.link}}\n @linkParser={{this.linkParser}}\n @controller={{this.controller}}\n @showTitle={{true}}\n />\n {{/if}}\n {{/if}}\n </template>\n}\n"],"names":["LinkSidebarWidget","Component","linkParser","args","defaultLinkParser","controller","link","selection","mainEditorState","NodeSelection","node","type","schema","nodes","pos","from","setComponentTemplate","precompileTemplate","strictMode","scope","LinkEditor"],"mappings":";;;;;;;AAYe,MAAMA,0BAA0BC,SAAA,CAAU;EACvD,IAAIC,UAAAA,GAAa;IACf,OAAO,IAAI,CAACC,IAAI,CAACD,UAAU,IAAIE,iBAAA,EAAA;AACjC,EAAA;EAEA,IAAIC,UAAAA,GAAa;AACf,IAAA,OAAO,IAAI,CAACF,IAAI,CAACE,UAAU;AAC7B,EAAA;EAEA,IAAIC,IAAAA,GAAO;IACT,IAAI,IAAI,CAACD,UAAU,EAAE;MACnB,MAAM;AAAEE,QAAAA;AAAS,OAAE,GAAG,IAAI,CAACF,UAAU,CAACG,eAAe;MACrD,IACED,qBAAqBE,aAAA,IACrBF,SAAA,CAAUG,IAAI,CAACC,IAAI,KAAK,IAAI,CAACN,UAAU,CAACO,MAAM,CAACC,KAAK,CAAC,OAAO,EAC5D;QACA,OAAO;UAAEC,GAAA,EAAKP,UAAUQ,IAAI;UAAEL,IAAA,EAAMH,UAAUG;SAAK;AACrD,MAAA;AACF,IAAA;AACA,IAAA;AACF,EAAA;AAEA,EAAA;IAAAM,oBAAA,CAAAC,kBAAA,CAAA,wNAAA,EAWA;MAAAC,UAAA,EAAA,IAAA;AAAAC,MAAAA,KAAA,EAAAA,OAAA;AAAAC,QAAAA;AAAA,OAAA;KAAU,CAAA,EAAV,IAAW,CAAA;AAAD;AACZ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-rdfa.js","sources":["../../src/nodes/inline-rdfa.ts"],"sourcesContent":["import { Node as PNode } from 'prosemirror-model';\nimport {\n getRdfaAttrs,\n getRdfaContentElement,\n rdfaAttrSpec,\n renderRdfaAware,\n} from '../core/schema.ts';\nimport {\n type EmberNodeConfig,\n createEmberNodeSpec,\n createEmberNodeView,\n} from '../utils/ember-node.ts';\nimport InlineRdfaComponent from '../components/ember-node/inline-rdfa.
|
|
1
|
+
{"version":3,"file":"inline-rdfa.js","sources":["../../src/nodes/inline-rdfa.ts"],"sourcesContent":["import { Node as PNode } from 'prosemirror-model';\nimport {\n getRdfaAttrs,\n getRdfaContentElement,\n rdfaAttrSpec,\n renderRdfaAware,\n} from '../core/schema.ts';\nimport {\n type EmberNodeConfig,\n createEmberNodeSpec,\n createEmberNodeView,\n} from '../utils/ember-node.ts';\nimport InlineRdfaComponent from '../components/ember-node/inline-rdfa.gts';\nimport type { ComponentLike } from '@glint/template';\nimport getClassnamesFromNode from '../utils/get-classnames-from-node.ts';\nimport type {\n ModelMigrationGenerator,\n RdfaAttrs,\n} from '#root/core/rdfa-types.ts';\n\ntype Options = {\n rdfaAware?: boolean;\n /**\n * Migrations to apply to nodes parsed as inline-rdfa, to modify the data model.\n * @returns false to use the default parsing or an object to define overrides\n **/\n modelMigrations?: ModelMigrationGenerator[];\n};\n\nconst emberNodeConfig: (options?: Options) => EmberNodeConfig = ({\n rdfaAware = false,\n modelMigrations = [],\n} = {}) => {\n return {\n name: 'inline-rdfa',\n inline: true,\n component: InlineRdfaComponent as unknown as ComponentLike,\n group: 'inline',\n content: 'inline*',\n atom: true,\n draggable: false,\n selectable: true,\n editable: rdfaAware,\n isolating: rdfaAware,\n classNames: ['say-inline-rdfa'],\n toDOM(node: PNode) {\n if (rdfaAware) {\n return renderRdfaAware({\n renderable: node,\n tag: 'span',\n attrs: { class: getClassnamesFromNode(node) },\n content: 0,\n });\n } else {\n return [\n 'span',\n { ...node.attrs, class: getClassnamesFromNode(node) },\n 0,\n ];\n }\n },\n parseDOM: [\n {\n tag: 'span',\n // default prio is 50, highest prio comes first, and this parserule should at least come after all other nodes\n priority: 10,\n getAttrs(element: string | HTMLElement) {\n if (typeof element === 'string') {\n return false;\n }\n const attrs = getRdfaAttrs(element, { rdfaAware });\n if (attrs) {\n const migration = modelMigrations.find((migration) =>\n migration(attrs as unknown as RdfaAttrs),\n )?.(attrs as unknown as RdfaAttrs);\n if (migration && migration.getAttrs) {\n return migration.getAttrs(element);\n }\n return attrs;\n }\n return false;\n },\n contentElement: (element) => {\n if (rdfaAware && modelMigrations.length > 0) {\n const attrs = getRdfaAttrs(element, { rdfaAware });\n if (attrs) {\n const migration = modelMigrations.find((migration) =>\n migration(attrs as unknown as RdfaAttrs),\n )?.(attrs as unknown as RdfaAttrs);\n if (migration && migration.contentElement) {\n return migration.contentElement(element);\n }\n }\n }\n return getRdfaContentElement(element);\n },\n },\n ],\n attrs: rdfaAttrSpec({ rdfaAware }),\n };\n};\n\nexport const inlineRdfaWithConfig = (options?: Options) =>\n createEmberNodeSpec(emberNodeConfig(options));\n\nexport const inlineRdfaWithConfigView = (options?: Options) =>\n createEmberNodeView(emberNodeConfig(options));\n"],"names":["emberNodeConfig","rdfaAware","modelMigrations","name","inline","component","InlineRdfaComponent","group","content","atom","draggable","selectable","editable","isolating","classNames","toDOM","node","renderRdfaAware","renderable","tag","attrs","class","getClassnamesFromNode","parseDOM","priority","getAttrs","element","getRdfaAttrs","migration","find","contentElement","length","getRdfaContentElement","rdfaAttrSpec","inlineRdfaWithConfig","options","createEmberNodeSpec","inlineRdfaWithConfigView","createEmberNodeView"],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { InputRule } from 'prosemirror-inputrules';
|
|
2
|
+
import { defaultLinkParser } from './parser.js';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_REGEX = new RegExp(String.raw`
|
|
5
|
+
(^|\s)
|
|
6
|
+
(
|
|
7
|
+
(?: ${/* parse email */''}
|
|
8
|
+
(?:mailto:)? ${/* optional mailto: protocol */''}
|
|
9
|
+
[A-Za-z0-9._%+-]+ ${/* local-part */''}
|
|
10
|
+
@
|
|
11
|
+
[A-Za-z0-9.-]+ ${/* domain */''}
|
|
12
|
+
\.
|
|
13
|
+
[A-Za-z]{2,} ${/* extension */''}
|
|
14
|
+
)
|
|
15
|
+
|
|
|
16
|
+
(?: ${/* parse weblinks */''}
|
|
17
|
+
(?:https?:\/\/)? ${/* optional http(s): protocol */''}
|
|
18
|
+
(?:www\.)? ${/* optional www */''}
|
|
19
|
+
[A-Za-z0-9.-]+ ${/* domain */''}
|
|
20
|
+
\.
|
|
21
|
+
[A-Za-z]{2,} ${/* extension */''}
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
(\s)$ ${/* single space after url/email */''}
|
|
25
|
+
`.replace(/^\s+|\s+$/gm, '') // remove white space before and at the end of lines (trimming)
|
|
26
|
+
.replace(/\n/g, '')) // remove newlines
|
|
27
|
+
;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Input rule which is able to detect plain text links and convert them to a link object.
|
|
31
|
+
* It may be configured with a `nodeType`, a custom `regex` and a custom `linkParser`.
|
|
32
|
+
*
|
|
33
|
+
* If using a custom `regex`, it should meet the following conditions:
|
|
34
|
+
* - The first group should capture the text typed before the (possible) link
|
|
35
|
+
* - The second group should capture the text representing the (possible) link
|
|
36
|
+
* - The third group should capture the text typed after the (possible) link
|
|
37
|
+
*/
|
|
38
|
+
const link_input_rule = ({
|
|
39
|
+
nodeType,
|
|
40
|
+
regex = DEFAULT_REGEX,
|
|
41
|
+
linkParser = defaultLinkParser()
|
|
42
|
+
}) => {
|
|
43
|
+
return new InputRule(regex, (state, match, start, end) => {
|
|
44
|
+
// Ensure both the start and end of the input-rule match are within the same parent node
|
|
45
|
+
if (state.doc.resolve(start).parent !== state.doc.resolve(end).parent) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (!rangeContainsOnlyText(state.doc, start, end)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const textBeforeLink = match[1];
|
|
52
|
+
const link = match[2];
|
|
53
|
+
const textAfterLink = match[3];
|
|
54
|
+
const linkStart = start + textBeforeLink.length;
|
|
55
|
+
const linkParserResult = linkParser(link);
|
|
56
|
+
if (!linkParserResult.isSuccessful) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const node = nodeType.create({
|
|
60
|
+
href: linkParserResult.value
|
|
61
|
+
}, state.schema.text(link));
|
|
62
|
+
const tr = state.tr;
|
|
63
|
+
|
|
64
|
+
// replace only the email text
|
|
65
|
+
tr.replaceWith(linkStart, end, node);
|
|
66
|
+
tr.insertText(textAfterLink, linkStart + node.nodeSize);
|
|
67
|
+
return tr;
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const rangeContainsOnlyText = (doc, from, to) => {
|
|
71
|
+
let onlyText = true;
|
|
72
|
+
doc.nodesBetween(from, to, node => {
|
|
73
|
+
if (node.isInline && !node.isText) {
|
|
74
|
+
onlyText = false;
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return onlyText;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { link_input_rule };
|
|
82
|
+
//# sourceMappingURL=input-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-rule.js","sources":["../../../src/plugins/link/input-rule.ts"],"sourcesContent":["import { InputRule } from 'prosemirror-inputrules';\nimport { defaultLinkParser, type LinkParser } from './parser.ts';\nimport type { NodeType } from 'prosemirror-model';\nimport type { PNode } from '#root/prosemirror-aliases.ts';\n\ntype LinkInputRuleOptions = {\n nodeType: NodeType;\n regex?: RegExp;\n linkParser?: LinkParser;\n};\n\nconst DEFAULT_REGEX = new RegExp(\n String.raw`\n (^|\\s)\n (\n (?: ${/* parse email */ ''}\n (?:mailto:)? ${/* optional mailto: protocol */ ''}\n [A-Za-z0-9._%+-]+ ${/* local-part */ ''}\n @\n [A-Za-z0-9.-]+ ${/* domain */ ''}\n \\.\n [A-Za-z]{2,} ${/* extension */ ''}\n )\n |\n (?: ${/* parse weblinks */ ''}\n (?:https?:\\/\\/)? ${/* optional http(s): protocol */ ''}\n (?:www\\.)? ${/* optional www */ ''}\n [A-Za-z0-9.-]+ ${/* domain */ ''}\n \\.\n [A-Za-z]{2,} ${/* extension */ ''}\n )\n )\n (\\s)$ ${/* single space after url/email */ ''}\n `\n .replace(/^\\s+|\\s+$/gm, '') // remove white space before and at the end of lines (trimming)\n .replace(/\\n/g, ''), // remove newlines\n);\n\n/**\n * Input rule which is able to detect plain text links and convert them to a link object.\n * It may be configured with a `nodeType`, a custom `regex` and a custom `linkParser`.\n *\n * If using a custom `regex`, it should meet the following conditions:\n * - The first group should capture the text typed before the (possible) link\n * - The second group should capture the text representing the (possible) link\n * - The third group should capture the text typed after the (possible) link\n */\nexport const link_input_rule = ({\n nodeType,\n regex = DEFAULT_REGEX,\n linkParser = defaultLinkParser(),\n}: LinkInputRuleOptions) => {\n return new InputRule(regex, (state, match, start, end) => {\n // Ensure both the start and end of the input-rule match are within the same parent node\n if (state.doc.resolve(start).parent !== state.doc.resolve(end).parent) {\n return null;\n }\n\n if (!rangeContainsOnlyText(state.doc, start, end)) {\n return null;\n }\n\n const textBeforeLink = match[1];\n const link = match[2];\n const textAfterLink = match[3];\n const linkStart = start + textBeforeLink.length;\n\n const linkParserResult = linkParser(link);\n if (!linkParserResult.isSuccessful) {\n return null;\n }\n const node = nodeType.create(\n {\n href: linkParserResult.value,\n },\n state.schema.text(link),\n );\n const tr = state.tr;\n\n // replace only the email text\n tr.replaceWith(linkStart, end, node);\n\n tr.insertText(textAfterLink, linkStart + node.nodeSize);\n\n return tr;\n });\n};\n\nconst rangeContainsOnlyText = (doc: PNode, from: number, to: number) => {\n let onlyText = true;\n doc.nodesBetween(from, to, (node) => {\n if (node.isInline && !node.isText) {\n onlyText = false;\n return false;\n }\n });\n return onlyText;\n};\n"],"names":["DEFAULT_REGEX","RegExp","String","raw","replace","link_input_rule","nodeType","regex","linkParser","defaultLinkParser","InputRule","state","match","start","end","doc","resolve","parent","rangeContainsOnlyText","textBeforeLink","link","textAfterLink","linkStart","length","linkParserResult","isSuccessful","node","create","href","value","schema","text","tr","replaceWith","insertText","nodeSize","from","to","onlyText","nodesBetween","isInline","isText"],"mappings":"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"}
|
|
@@ -2,13 +2,15 @@ import getClassnamesFromNode from '../../../utils/get-classnames-from-node.js';
|
|
|
2
2
|
import { renderRdfaAware, getRdfaContentElement, getRdfaAttrs, rdfaAttrSpec } from '../../../core/schema.js';
|
|
3
3
|
import { createEmberNodeSpec, createEmberNodeView } from '../../../utils/_private/ember-node.js';
|
|
4
4
|
import Link from '../../../components/ember-node/link.js';
|
|
5
|
+
import { defaultLinkParser } from '../parser.js';
|
|
5
6
|
|
|
6
7
|
// TODO this spec doesn't play well with RDFa editing tools. It has been modified so that any
|
|
7
8
|
// additional RDFa annotations are not striped. This is for example, used by the citation plugin in
|
|
8
9
|
// lblod-plugins
|
|
9
10
|
const emberNodeConfig = ({
|
|
10
11
|
interactive = false,
|
|
11
|
-
rdfaAware = false
|
|
12
|
+
rdfaAware = false,
|
|
13
|
+
linkParser = defaultLinkParser()
|
|
12
14
|
} = {}) => {
|
|
13
15
|
return {
|
|
14
16
|
name: 'link',
|
|
@@ -27,6 +29,12 @@ const emberNodeConfig = ({
|
|
|
27
29
|
},
|
|
28
30
|
interactive: {
|
|
29
31
|
default: interactive
|
|
32
|
+
},
|
|
33
|
+
linkParser: {
|
|
34
|
+
default: linkParser
|
|
35
|
+
},
|
|
36
|
+
isNew: {
|
|
37
|
+
default: false
|
|
30
38
|
}
|
|
31
39
|
};
|
|
32
40
|
return {
|
|
@@ -62,6 +70,8 @@ const emberNodeConfig = ({
|
|
|
62
70
|
} = node.attrs;
|
|
63
71
|
delete attrs['interactive'];
|
|
64
72
|
delete attrs['placeholder'];
|
|
73
|
+
delete attrs['linkParser'];
|
|
74
|
+
delete attrs['isNew'];
|
|
65
75
|
if (rdfaAware) {
|
|
66
76
|
return renderRdfaAware({
|
|
67
77
|
renderable: node,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sources":["../../../../src/plugins/link/nodes/link.ts"],"sourcesContent":["import getClassnamesFromNode from '#root/utils/get-classnames-from-node.ts';\nimport {\n getRdfaAttrs,\n getRdfaContentElement,\n rdfaAttrSpec,\n renderRdfaAware,\n} from '../../../core/schema.ts';\nimport {\n createEmberNodeSpec,\n createEmberNodeView,\n type EmberNodeConfig,\n} from '../../../utils/ember-node.ts';\nimport type { ComponentLike } from '@glint/template';\nimport Link from '#root/components/ember-node/link.ts';\n\ntype LinkOptions = {\n interactive?: boolean;\n rdfaAware?: boolean;\n};\n\n// TODO this spec doesn't play well with RDFa editing tools. It has been modified so that any\n// additional RDFa annotations are not striped. This is for example, used by the citation plugin in\n// lblod-plugins\nconst emberNodeConfig: (options?: LinkOptions) => EmberNodeConfig = ({\n interactive = false,\n rdfaAware = false,\n} = {}) => {\n return {\n name: 'link',\n component: Link as unknown as ComponentLike,\n inline: true,\n group: 'inline',\n content: 'text*',\n atom: true,\n defining: true,\n draggable: false,\n classNames: ['say-pill', 'say-link'],\n get attrs() {\n const baseAttrs = {\n href: {\n default: null,\n },\n interactive: {\n default: interactive,\n },\n };\n return {\n ...rdfaAttrSpec({ rdfaAware }),\n ...baseAttrs,\n };\n },\n needsFFKludge: true,\n needsChromeCursorFix: true,\n get parseDOM() {\n return [\n {\n tag: 'a',\n getAttrs(dom: string | HTMLElement) {\n if (typeof dom === 'string') {\n return false;\n }\n const href = dom.getAttribute('href');\n return {\n ...getRdfaAttrs(dom, { rdfaAware }),\n href,\n };\n },\n contentElement: getRdfaContentElement,\n },\n ];\n },\n toDOM(node) {\n const { ...attrs }: Record<string, unknown> = node.attrs;\n delete attrs['interactive'];\n delete attrs['placeholder'];\n if (rdfaAware) {\n return renderRdfaAware({\n renderable: node,\n tag: 'a',\n attrs: { ...attrs, class: getClassnamesFromNode(node) },\n content: 0,\n });\n } else {\n return ['a', { ...attrs, class: getClassnamesFromNode(node) }, 0];\n }\n },\n };\n};\n\nexport const link = (options?: LinkOptions) =>\n createEmberNodeSpec(emberNodeConfig(options));\n\nexport const linkView = (options?: LinkOptions) =>\n createEmberNodeView(emberNodeConfig(options));\n"],"names":["emberNodeConfig","interactive","rdfaAware","name","component","Link","inline","group","content","atom","defining","draggable","classNames","attrs","baseAttrs","href","default","rdfaAttrSpec","needsFFKludge","needsChromeCursorFix","parseDOM","tag","getAttrs","dom","getAttribute","getRdfaAttrs","contentElement","getRdfaContentElement","toDOM","node","renderRdfaAware","renderable","class","getClassnamesFromNode","link","options","createEmberNodeSpec","linkView","createEmberNodeView"],"mappings":"
|
|
1
|
+
{"version":3,"file":"link.js","sources":["../../../../src/plugins/link/nodes/link.ts"],"sourcesContent":["import getClassnamesFromNode from '#root/utils/get-classnames-from-node.ts';\nimport {\n getRdfaAttrs,\n getRdfaContentElement,\n rdfaAttrSpec,\n renderRdfaAware,\n} from '../../../core/schema.ts';\nimport {\n createEmberNodeSpec,\n createEmberNodeView,\n type EmberNodeConfig,\n} from '../../../utils/ember-node.ts';\nimport type { ComponentLike } from '@glint/template';\nimport Link from '#root/components/ember-node/link.gts';\nimport { defaultLinkParser, type LinkParser } from '../parser.ts';\n\ntype LinkOptions = {\n interactive?: boolean;\n rdfaAware?: boolean;\n linkParser?: LinkParser;\n};\n\n// TODO this spec doesn't play well with RDFa editing tools. It has been modified so that any\n// additional RDFa annotations are not striped. This is for example, used by the citation plugin in\n// lblod-plugins\nconst emberNodeConfig: (options?: LinkOptions) => EmberNodeConfig = ({\n interactive = false,\n rdfaAware = false,\n linkParser = defaultLinkParser(),\n} = {}) => {\n return {\n name: 'link',\n component: Link as unknown as ComponentLike,\n inline: true,\n group: 'inline',\n content: 'text*',\n atom: true,\n defining: true,\n draggable: false,\n classNames: ['say-pill', 'say-link'],\n get attrs() {\n const baseAttrs = {\n href: {\n default: null,\n },\n interactive: {\n default: interactive,\n },\n linkParser: {\n default: linkParser,\n },\n isNew: {\n default: false,\n },\n };\n return {\n ...rdfaAttrSpec({ rdfaAware }),\n ...baseAttrs,\n };\n },\n needsFFKludge: true,\n needsChromeCursorFix: true,\n get parseDOM() {\n return [\n {\n tag: 'a',\n getAttrs(dom: string | HTMLElement) {\n if (typeof dom === 'string') {\n return false;\n }\n const href = dom.getAttribute('href');\n return {\n ...getRdfaAttrs(dom, { rdfaAware }),\n href,\n };\n },\n contentElement: getRdfaContentElement,\n },\n ];\n },\n toDOM(node) {\n const { ...attrs }: Record<string, unknown> = node.attrs;\n delete attrs['interactive'];\n delete attrs['placeholder'];\n delete attrs['linkParser'];\n delete attrs['isNew'];\n if (rdfaAware) {\n return renderRdfaAware({\n renderable: node,\n tag: 'a',\n attrs: { ...attrs, class: getClassnamesFromNode(node) },\n content: 0,\n });\n } else {\n return ['a', { ...attrs, class: getClassnamesFromNode(node) }, 0];\n }\n },\n };\n};\n\nexport const link = (options?: LinkOptions) =>\n createEmberNodeSpec(emberNodeConfig(options));\n\nexport const linkView = (options?: LinkOptions) =>\n createEmberNodeView(emberNodeConfig(options));\n"],"names":["emberNodeConfig","interactive","rdfaAware","linkParser","defaultLinkParser","name","component","Link","inline","group","content","atom","defining","draggable","classNames","attrs","baseAttrs","href","default","isNew","rdfaAttrSpec","needsFFKludge","needsChromeCursorFix","parseDOM","tag","getAttrs","dom","getAttribute","getRdfaAttrs","contentElement","getRdfaContentElement","toDOM","node","renderRdfaAware","renderable","class","getClassnamesFromNode","link","options","createEmberNodeSpec","linkView","createEmberNodeView"],"mappings":";;;;;;AAsBA;AACA;AACA;AACA,MAAMA,eAA2D,GAAGA,CAAC;AACnEC,EAAAA,WAAW,GAAG,KAAK;AACnBC,EAAAA,SAAS,GAAG,KAAK;EACjBC,UAAU,GAAGC,iBAAiB;AAChC,CAAC,GAAG,EAAE,KAAK;EACT,OAAO;AACLC,IAAAA,IAAI,EAAE,MAAM;AACZC,IAAAA,SAAS,EAAEC,IAAgC;AAC3CC,IAAAA,MAAM,EAAE,IAAI;AACZC,IAAAA,KAAK,EAAE,QAAQ;AACfC,IAAAA,OAAO,EAAE,OAAO;AAChBC,IAAAA,IAAI,EAAE,IAAI;AACVC,IAAAA,QAAQ,EAAE,IAAI;AACdC,IAAAA,SAAS,EAAE,KAAK;AAChBC,IAAAA,UAAU,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;IACpC,IAAIC,KAAKA,GAAG;AACV,MAAA,MAAMC,SAAS,GAAG;AAChBC,QAAAA,IAAI,EAAE;AACJC,UAAAA,OAAO,EAAE;SACV;AACDjB,QAAAA,WAAW,EAAE;AACXiB,UAAAA,OAAO,EAAEjB;SACV;AACDE,QAAAA,UAAU,EAAE;AACVe,UAAAA,OAAO,EAAEf;SACV;AACDgB,QAAAA,KAAK,EAAE;AACLD,UAAAA,OAAO,EAAE;AACX;OACD;MACD,OAAO;AACL,QAAA,GAAGE,YAAY,CAAC;AAAElB,UAAAA;AAAU,SAAC,CAAC;QAC9B,GAAGc;OACJ;IACH,CAAC;AACDK,IAAAA,aAAa,EAAE,IAAI;AACnBC,IAAAA,oBAAoB,EAAE,IAAI;IAC1B,IAAIC,QAAQA,GAAG;AACb,MAAA,OAAO,CACL;AACEC,QAAAA,GAAG,EAAE,GAAG;QACRC,QAAQA,CAACC,GAAyB,EAAE;AAClC,UAAA,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE;AAC3B,YAAA,OAAO,KAAK;AACd,UAAA;AACA,UAAA,MAAMT,IAAI,GAAGS,GAAG,CAACC,YAAY,CAAC,MAAM,CAAC;UACrC,OAAO;YACL,GAAGC,YAAY,CAACF,GAAG,EAAE;AAAExB,cAAAA;AAAU,aAAC,CAAC;AACnCe,YAAAA;WACD;QACH,CAAC;AACDY,QAAAA,cAAc,EAAEC;AAClB,OAAC,CACF;IACH,CAAC;IACDC,KAAKA,CAACC,IAAI,EAAE;MACV,MAAM;QAAE,GAAGjB;OAAgC,GAAGiB,IAAI,CAACjB,KAAK;MACxD,OAAOA,KAAK,CAAC,aAAa,CAAC;MAC3B,OAAOA,KAAK,CAAC,aAAa,CAAC;MAC3B,OAAOA,KAAK,CAAC,YAAY,CAAC;MAC1B,OAAOA,KAAK,CAAC,OAAO,CAAC;AACrB,MAAA,IAAIb,SAAS,EAAE;AACb,QAAA,OAAO+B,eAAe,CAAC;AACrBC,UAAAA,UAAU,EAAEF,IAAI;AAChBR,UAAAA,GAAG,EAAE,GAAG;AACRT,UAAAA,KAAK,EAAE;AAAE,YAAA,GAAGA,KAAK;YAAEoB,KAAK,EAAEC,qBAAqB,CAACJ,IAAI;WAAG;AACvDtB,UAAAA,OAAO,EAAE;AACX,SAAC,CAAC;AACJ,MAAA,CAAC,MAAM;QACL,OAAO,CAAC,GAAG,EAAE;AAAE,UAAA,GAAGK,KAAK;UAAEoB,KAAK,EAAEC,qBAAqB,CAACJ,IAAI;SAAG,EAAE,CAAC,CAAC;AACnE,MAAA;AACF,IAAA;GACD;AACH,CAAC;AAEM,MAAMK,IAAI,GAAIC,OAAqB,IACxCC,mBAAmB,CAACvC,eAAe,CAACsC,OAAO,CAAC;AAEvC,MAAME,QAAQ,GAAIF,OAAqB,IAC5CG,mBAAmB,CAACzC,eAAe,CAACsC,OAAO,CAAC;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { test, find } from 'linkifyjs';
|
|
2
|
+
import parsePhoneNumber from 'libphonenumber-js';
|
|
3
|
+
|
|
4
|
+
const defaultLinkParser = ({
|
|
5
|
+
defaultCountryCode = 'BE',
|
|
6
|
+
supportedProtocols = ['http:', 'https:', 'mailto:', 'tel:', 'sms:']
|
|
7
|
+
} = {}) => {
|
|
8
|
+
return input => {
|
|
9
|
+
const link = input?.trim();
|
|
10
|
+
if (!link) {
|
|
11
|
+
return {
|
|
12
|
+
isSuccessful: false,
|
|
13
|
+
errors: ['URL mag niet leeg zijn']
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
let href;
|
|
17
|
+
if (test(link)) {
|
|
18
|
+
href = find(link)[0].href;
|
|
19
|
+
}
|
|
20
|
+
if (!href) {
|
|
21
|
+
const phoneNumber = parsePhoneNumber(link, defaultCountryCode);
|
|
22
|
+
if (phoneNumber) {
|
|
23
|
+
const phoneNumberUri = phoneNumber.getURI();
|
|
24
|
+
const value = link.startsWith('sms:') ?
|
|
25
|
+
// libphonenumber-js transforms sms: automatically to tel:, so revert this transform if necessary
|
|
26
|
+
phoneNumberUri.replace('tel:', 'sms:') : phoneNumberUri;
|
|
27
|
+
href = value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!href) {
|
|
31
|
+
return {
|
|
32
|
+
isSuccessful: false,
|
|
33
|
+
errors: ['De ingegeven URL/link is niet geldig']
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (!hasSupportedProtocol(href, supportedProtocols)) {
|
|
37
|
+
return {
|
|
38
|
+
isSuccessful: false,
|
|
39
|
+
errors: ['de ingegeven URL/link is niet toegestaan']
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
isSuccessful: true,
|
|
44
|
+
value: href
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const hasSupportedProtocol = (href, supportedProtocols) => {
|
|
49
|
+
try {
|
|
50
|
+
const protocol = new URL(href).protocol;
|
|
51
|
+
return supportedProtocols.includes(protocol);
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export { defaultLinkParser };
|
|
58
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sources":["../../../src/plugins/link/parser.ts"],"sourcesContent":["import { find as linkifyFind, test as linkifyTest } from 'linkifyjs';\nimport parsePhoneNumber, { type CountryCode } from 'libphonenumber-js';\n\nexport type LinkParserResult =\n | {\n isSuccessful: true;\n value: string;\n errors?: never;\n }\n | {\n isSuccessful: false;\n value?: never;\n errors: [string, ...string[]];\n };\nexport type LinkParser = (input?: string) => LinkParserResult;\n\ntype DefaultLinkParserOptions = {\n defaultCountryCode?: CountryCode;\n supportedProtocols?: string[];\n};\n\nexport const defaultLinkParser = ({\n defaultCountryCode = 'BE',\n supportedProtocols = ['http:', 'https:', 'mailto:', 'tel:', 'sms:'],\n}: DefaultLinkParserOptions = {}): LinkParser => {\n return (input?: string) => {\n const link = input?.trim();\n if (!link) {\n return { isSuccessful: false, errors: ['URL mag niet leeg zijn'] };\n }\n\n let href: string | undefined;\n\n if (linkifyTest(link)) {\n href = linkifyFind(link)[0].href;\n }\n\n if (!href) {\n const phoneNumber = parsePhoneNumber(link, defaultCountryCode);\n if (phoneNumber) {\n const phoneNumberUri = phoneNumber.getURI();\n const value = link.startsWith('sms:')\n ? // libphonenumber-js transforms sms: automatically to tel:, so revert this transform if necessary\n phoneNumberUri.replace('tel:', 'sms:')\n : phoneNumberUri;\n href = value;\n }\n }\n if (!href) {\n return {\n isSuccessful: false,\n errors: ['De ingegeven URL/link is niet geldig'],\n };\n }\n\n if (!hasSupportedProtocol(href, supportedProtocols)) {\n return {\n isSuccessful: false,\n errors: ['de ingegeven URL/link is niet toegestaan'],\n };\n }\n\n return {\n isSuccessful: true,\n value: href,\n };\n };\n};\n\nconst hasSupportedProtocol = (href: string, supportedProtocols: string[]) => {\n try {\n const protocol = new URL(href).protocol;\n return supportedProtocols.includes(protocol);\n } catch {\n return false;\n }\n};\n"],"names":["defaultLinkParser","defaultCountryCode","supportedProtocols","input","link","trim","isSuccessful","errors","href","linkifyTest","linkifyFind","phoneNumber","parsePhoneNumber","phoneNumberUri","getURI","value","startsWith","replace","hasSupportedProtocol","protocol","URL","includes"],"mappings":";;;AAqBO,MAAMA,iBAAiB,GAAGA,CAAC;AAChCC,EAAAA,kBAAkB,GAAG,IAAI;EACzBC,kBAAkB,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM;AAC1C,CAAC,GAAG,EAAE,KAAiB;AAC/C,EAAA,OAAQC,KAAc,IAAK;AACzB,IAAA,MAAMC,IAAI,GAAGD,KAAK,EAAEE,IAAI,EAAE;IAC1B,IAAI,CAACD,IAAI,EAAE;MACT,OAAO;AAAEE,QAAAA,YAAY,EAAE,KAAK;QAAEC,MAAM,EAAE,CAAC,wBAAwB;OAAG;AACpE,IAAA;AAEA,IAAA,IAAIC,IAAwB;AAE5B,IAAA,IAAIC,IAAW,CAACL,IAAI,CAAC,EAAE;MACrBI,IAAI,GAAGE,IAAW,CAACN,IAAI,CAAC,CAAC,CAAC,CAAC,CAACI,IAAI;AAClC,IAAA;IAEA,IAAI,CAACA,IAAI,EAAE;AACT,MAAA,MAAMG,WAAW,GAAGC,gBAAgB,CAACR,IAAI,EAAEH,kBAAkB,CAAC;AAC9D,MAAA,IAAIU,WAAW,EAAE;AACf,QAAA,MAAME,cAAc,GAAGF,WAAW,CAACG,MAAM,EAAE;AAC3C,QAAA,MAAMC,KAAK,GAAGX,IAAI,CAACY,UAAU,CAAC,MAAM,CAAC;AACjC;QACAH,cAAc,CAACI,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,GACtCJ,cAAc;AAClBL,QAAAA,IAAI,GAAGO,KAAK;AACd,MAAA;AACF,IAAA;IACA,IAAI,CAACP,IAAI,EAAE;MACT,OAAO;AACLF,QAAAA,YAAY,EAAE,KAAK;QACnBC,MAAM,EAAE,CAAC,sCAAsC;OAChD;AACH,IAAA;AAEA,IAAA,IAAI,CAACW,oBAAoB,CAACV,IAAI,EAAEN,kBAAkB,CAAC,EAAE;MACnD,OAAO;AACLI,QAAAA,YAAY,EAAE,KAAK;QACnBC,MAAM,EAAE,CAAC,0CAA0C;OACpD;AACH,IAAA;IAEA,OAAO;AACLD,MAAAA,YAAY,EAAE,IAAI;AAClBS,MAAAA,KAAK,EAAEP;KACR;EACH,CAAC;AACH;AAEA,MAAMU,oBAAoB,GAAGA,CAACV,IAAY,EAAEN,kBAA4B,KAAK;EAC3E,IAAI;IACF,MAAMiB,QAAQ,GAAG,IAAIC,GAAG,CAACZ,IAAI,CAAC,CAACW,QAAQ;AACvC,IAAA,OAAOjB,kBAAkB,CAACmB,QAAQ,CAACF,QAAQ,CAAC;AAC9C,EAAA,CAAC,CAAC,MAAM;AACN,IAAA,OAAO,KAAK;AACd,EAAA;AACF,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lblod/ember-rdfa-editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.3.0",
|
|
4
4
|
"description": "Ember addon wrapping an RDFa editor with a public API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -239,6 +239,7 @@
|
|
|
239
239
|
"ember-velcro": "^2.2.0",
|
|
240
240
|
"iter-tools": "^7.5.4",
|
|
241
241
|
"js-beautify": "^1.15.4",
|
|
242
|
+
"libphonenumber-js": "^1.12.38",
|
|
242
243
|
"linkifyjs": "^4.3.2",
|
|
243
244
|
"mdn-polyfills": "^5.20.0",
|
|
244
245
|
"mongoose": "^8.21.0",
|
|
@@ -397,8 +398,10 @@
|
|
|
397
398
|
"./components/plugins/image/insert-menu.js": "./dist/_app_/components/plugins/image/insert-menu.js",
|
|
398
399
|
"./components/plugins/image/node.js": "./dist/_app_/components/plugins/image/node.js",
|
|
399
400
|
"./components/plugins/indentation/indentation-menu.js": "./dist/_app_/components/plugins/indentation/indentation-menu.js",
|
|
401
|
+
"./components/plugins/link/_private/link-editor.js": "./dist/_app_/components/plugins/link/_private/link-editor.js",
|
|
400
402
|
"./components/plugins/link/link-editor.js": "./dist/_app_/components/plugins/link/link-editor.js",
|
|
401
403
|
"./components/plugins/link/link-menu.js": "./dist/_app_/components/plugins/link/link-menu.js",
|
|
404
|
+
"./components/plugins/link/link-sidebar-widget.js": "./dist/_app_/components/plugins/link/link-sidebar-widget.js",
|
|
402
405
|
"./components/plugins/list/indentation-controls.js": "./dist/_app_/components/plugins/list/indentation-controls.js",
|
|
403
406
|
"./components/plugins/list/ordered.js": "./dist/_app_/components/plugins/list/ordered.js",
|
|
404
407
|
"./components/plugins/list/unordered.js": "./dist/_app_/components/plugins/list/unordered.js",
|
package/scss/_c-link.scss
CHANGED
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
@use "@appuniversum/ember-appuniversum/styles/settings/s-root";
|
|
2
|
+
@use "@appuniversum/ember-appuniversum/styles/a-settings" as au-settings;
|
|
2
3
|
|
|
3
|
-
.say-link-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
width: 28rem;
|
|
10
|
-
|
|
11
|
-
a,
|
|
12
|
-
button {
|
|
13
|
-
padding: 0;
|
|
14
|
-
flex: 1;
|
|
15
|
-
border: 0;
|
|
16
|
-
justify-content: center;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.au-c-input {
|
|
20
|
-
border-width: 0 0.1rem;
|
|
21
|
-
border-radius: 0%;
|
|
22
|
-
padding: 0 0.3rem;
|
|
23
|
-
flex: 7;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.au-c-input:focus {
|
|
27
|
-
border-width: 0 0 !important;
|
|
28
|
-
}
|
|
4
|
+
.say-link-editor {
|
|
5
|
+
height: auto;
|
|
6
|
+
z-index: 1;
|
|
7
|
+
background: var(--au-gray-100);
|
|
8
|
+
border: 0.1rem solid var(--au-gray-300);
|
|
9
|
+
border-radius: 0.5rem;
|
|
29
10
|
}
|
|
30
11
|
|
|
31
12
|
.say-pill {
|
|
32
|
-
gap: 0;
|
|
33
13
|
vertical-align: bottom;
|
|
34
14
|
min-height: 2.55rem;
|
|
35
15
|
margin-bottom: -0.1rem;
|
|
@@ -47,6 +27,17 @@
|
|
|
47
27
|
cursor: text;
|
|
48
28
|
color: var(--au-blue-700);
|
|
49
29
|
}
|
|
30
|
+
|
|
31
|
+
&--error {
|
|
32
|
+
color: var(--au-red-700);
|
|
33
|
+
background-color: var(--au-red-200);
|
|
34
|
+
border-color: var(--au-red-300);
|
|
35
|
+
text-decoration-color: var(--au-red-300);
|
|
36
|
+
|
|
37
|
+
[contenteditable] {
|
|
38
|
+
color: var(--au-red-700);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
50
41
|
}
|
|
51
42
|
|
|
52
43
|
.ember-node.ProseMirror-selectednode {
|
|
@@ -58,5 +49,14 @@
|
|
|
58
49
|
::selection {
|
|
59
50
|
background-color: var(--au-blue-300);
|
|
60
51
|
}
|
|
52
|
+
|
|
53
|
+
&--error {
|
|
54
|
+
background-color: var(--au-red-200);
|
|
55
|
+
outline: 2px solid var(--au-red-500);
|
|
56
|
+
|
|
57
|
+
::selection {
|
|
58
|
+
background-color: var(--au-red-300);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
61
|
}
|
|
62
62
|
}
|
package/scss/_c-table.scss
CHANGED
|
@@ -94,6 +94,10 @@ table.ProseMirror-selectednode,
|
|
|
94
94
|
.say-table-tooltip {
|
|
95
95
|
display: flex;
|
|
96
96
|
flex-direction: column;
|
|
97
|
+
box-shadow:
|
|
98
|
+
0 1px 3px rgba(au-settings.$au-gray-900, 0.1),
|
|
99
|
+
0 4px 20px rgba(au-settings.$au-gray-900, 0.035),
|
|
100
|
+
0 1px 1px rgba(au-settings.$au-gray-900, 0.025);
|
|
97
101
|
|
|
98
102
|
.color-selector__grid {
|
|
99
103
|
padding: 0 12px;
|
|
@@ -1159,33 +1159,15 @@
|
|
|
1159
1159
|
--au-z-index-gamma: 3;
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
|
-
.say-link-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
width: 28rem;
|
|
1169
|
-
}
|
|
1170
|
-
.say-link-tooltip a,
|
|
1171
|
-
.say-link-tooltip button {
|
|
1172
|
-
padding: 0;
|
|
1173
|
-
flex: 1;
|
|
1174
|
-
border: 0;
|
|
1175
|
-
justify-content: center;
|
|
1176
|
-
}
|
|
1177
|
-
.say-link-tooltip .au-c-input {
|
|
1178
|
-
border-width: 0 0.1rem;
|
|
1179
|
-
border-radius: 0%;
|
|
1180
|
-
padding: 0 0.3rem;
|
|
1181
|
-
flex: 7;
|
|
1182
|
-
}
|
|
1183
|
-
.say-link-tooltip .au-c-input:focus {
|
|
1184
|
-
border-width: 0 0 !important;
|
|
1162
|
+
.say-link-editor {
|
|
1163
|
+
height: auto;
|
|
1164
|
+
z-index: 1;
|
|
1165
|
+
background: var(--au-gray-100);
|
|
1166
|
+
border: 0.1rem solid var(--au-gray-300);
|
|
1167
|
+
border-radius: 0.5rem;
|
|
1185
1168
|
}
|
|
1186
1169
|
|
|
1187
1170
|
.say-pill {
|
|
1188
|
-
gap: 0;
|
|
1189
1171
|
vertical-align: bottom;
|
|
1190
1172
|
min-height: 2.55rem;
|
|
1191
1173
|
margin-bottom: -0.1rem;
|
|
@@ -1204,6 +1186,15 @@
|
|
|
1204
1186
|
cursor: text;
|
|
1205
1187
|
color: var(--au-blue-700);
|
|
1206
1188
|
}
|
|
1189
|
+
.say-pill--error {
|
|
1190
|
+
color: var(--au-red-700);
|
|
1191
|
+
background-color: var(--au-red-200);
|
|
1192
|
+
border-color: var(--au-red-300);
|
|
1193
|
+
text-decoration-color: var(--au-red-300);
|
|
1194
|
+
}
|
|
1195
|
+
.say-pill--error [contenteditable] {
|
|
1196
|
+
color: var(--au-red-700);
|
|
1197
|
+
}
|
|
1207
1198
|
|
|
1208
1199
|
.ember-node.ProseMirror-selectednode .say-pill {
|
|
1209
1200
|
background-color: var(--au-blue-200);
|
|
@@ -1216,6 +1207,16 @@
|
|
|
1216
1207
|
.ember-node.ProseMirror-selectednode .say-pill ::selection {
|
|
1217
1208
|
background-color: var(--au-blue-300);
|
|
1218
1209
|
}
|
|
1210
|
+
.ember-node.ProseMirror-selectednode .say-pill--error {
|
|
1211
|
+
background-color: var(--au-red-200);
|
|
1212
|
+
outline: 2px solid var(--au-red-500);
|
|
1213
|
+
}
|
|
1214
|
+
.ember-node.ProseMirror-selectednode .say-pill--error ::-moz-selection {
|
|
1215
|
+
background-color: var(--au-red-300);
|
|
1216
|
+
}
|
|
1217
|
+
.ember-node.ProseMirror-selectednode .say-pill--error ::selection {
|
|
1218
|
+
background-color: var(--au-red-300);
|
|
1219
|
+
}
|
|
1219
1220
|
|
|
1220
1221
|
.say-placeholder {
|
|
1221
1222
|
font-style: italic;
|
|
@@ -1376,6 +1377,7 @@ table.ProseMirror-selectednode,
|
|
|
1376
1377
|
.say-table-tooltip {
|
|
1377
1378
|
display: flex;
|
|
1378
1379
|
flex-direction: column;
|
|
1380
|
+
box-shadow: 0 1px 3px rgba(33, 35, 38, 0.1), 0 4px 20px rgba(33, 35, 38, 0.035), 0 1px 1px rgba(33, 35, 38, 0.025);
|
|
1379
1381
|
}
|
|
1380
1382
|
.say-table-tooltip .color-selector__grid {
|
|
1381
1383
|
padding: 0 12px;
|
|
@@ -1591,7 +1593,6 @@ span.ember-node {
|
|
|
1591
1593
|
width: 0;
|
|
1592
1594
|
top: 0;
|
|
1593
1595
|
left: 0;
|
|
1594
|
-
z-index: 1;
|
|
1595
1596
|
}
|
|
1596
1597
|
.say-editor .invisible.invisible--space::before {
|
|
1597
1598
|
content: "·";
|