@lblod/ember-rdfa-editor-lblod-plugins 8.2.2 → 8.4.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/.woodpecker/.test.yml +5 -0
- package/CHANGELOG.md +31 -1
- package/addon/components/citation-plugin/citations/search-modal.hbs +18 -41
- package/addon/components/citation-plugin/citations/search-modal.ts +0 -17
- package/addon/components/document-title-plugin/insert-title-card.hbs +5 -0
- package/addon/components/document-title-plugin/insert-title-card.ts +41 -0
- package/addon/components/pagination/pagination-view.hbs +39 -0
- package/addon/components/snippet-plugin/helpers/alert-load-error.hbs +22 -0
- package/addon/components/snippet-plugin/helpers/alert-no-items.hbs +8 -0
- package/addon/components/snippet-plugin/search-modal.hbs +83 -0
- package/addon/components/snippet-plugin/search-modal.ts +97 -0
- package/addon/components/snippet-plugin/snippet-insert.hbs +17 -0
- package/addon/components/snippet-plugin/snippet-insert.ts +50 -0
- package/addon/components/snippet-plugin/snippets/snippet-list.hbs +12 -0
- package/addon/components/snippet-plugin/snippets/snippet-preview.hbs +27 -0
- package/addon/components/snippet-plugin/snippets/snippet-preview.ts +28 -0
- package/addon/helpers/pagination.ts +40 -0
- package/addon/plugins/article-structure-plugin/commands/insert-structure.ts +2 -79
- package/addon/plugins/citation-plugin/utils/vlaamse-codex.ts +4 -34
- package/addon/plugins/document-title-plugin/commands/insert-document-title.ts +45 -0
- package/addon/plugins/document-title-plugin/nodes/document-title.ts +36 -0
- package/addon/plugins/document-title-plugin/nodes/index.ts +1 -0
- package/addon/plugins/snippet-plugin/index.ts +27 -0
- package/addon/plugins/snippet-plugin/utils/fetch-data.ts +96 -0
- package/addon/plugins/variable-plugin/nodes.ts +15 -11
- package/addon/plugins/variable-plugin/utils/fetch-data.ts +6 -6
- package/addon/utils/_private/find-insertion-range.ts +77 -0
- package/addon/utils/sparql-helpers.ts +28 -6
- package/addon/utils/strings.ts +34 -0
- package/addon/utils/types.ts +3 -0
- package/app/components/document-title-plugin/insert-title-card.js +1 -0
- package/app/components/pagination/pagination-view.js +1 -0
- package/app/components/snippet-plugin/helpers/alert-load-error.js +1 -0
- package/app/components/snippet-plugin/helpers/alert-no-items.js +1 -0
- package/app/components/snippet-plugin/search-modal.js +1 -0
- package/app/components/snippet-plugin/snippet-insert.js +1 -0
- package/app/components/snippet-plugin/snippets/snippet-list.js +1 -0
- package/app/components/snippet-plugin/snippets/snippet-preview.js +1 -0
- package/app/helpers/pagination.js +4 -0
- package/app/styles/document-title-plugin.scss +9 -0
- package/app/styles/snippet-plugin.scss +66 -0
- package/components/besluit-type-plugin/toolbar-dropdown.d.ts +1 -1
- package/components/citation-plugin/citations/search-modal.d.ts +0 -4
- package/components/document-title-plugin/insert-title-card.d.ts +12 -0
- package/components/snippet-plugin/search-modal.d.ts +22 -0
- package/components/snippet-plugin/snippet-insert.d.ts +16 -0
- package/components/snippet-plugin/snippets/snippet-preview.d.ts +14 -0
- package/helpers/pagination.d.ts +25 -0
- package/package.json +5 -5
- package/plugins/document-title-plugin/commands/insert-document-title.d.ts +6 -0
- package/plugins/document-title-plugin/nodes/document-title.d.ts +2 -0
- package/plugins/document-title-plugin/nodes/index.d.ts +1 -0
- package/plugins/snippet-plugin/index.d.ts +16 -0
- package/plugins/snippet-plugin/utils/fetch-data.d.ts +18 -0
- package/plugins/table-of-contents-plugin/nodes/table-of-contents.d.ts +1 -1
- package/plugins/variable-plugin/nodes.d.ts +3 -3
- package/translations/en-US.yaml +28 -0
- package/translations/nl-BE.yaml +28 -1
- package/tsconfig.json +5 -13
- package/utils/_private/find-insertion-range.d.ts +11 -0
- package/utils/sparql-helpers.d.ts +11 -4
- package/utils/strings.d.ts +2 -0
- package/utils/types.d.ts +2 -0
|
@@ -2,19 +2,13 @@ import {
|
|
|
2
2
|
Command,
|
|
3
3
|
Fragment,
|
|
4
4
|
NodeSelection,
|
|
5
|
-
NodeType,
|
|
6
|
-
PNode,
|
|
7
|
-
Schema,
|
|
8
|
-
Selection,
|
|
9
5
|
TextSelection,
|
|
10
6
|
} from '@lblod/ember-rdfa-editor';
|
|
11
7
|
import recalculateStructureNumbers from './recalculate-structure-numbers';
|
|
12
8
|
import { StructureSpec } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/article-structure-plugin';
|
|
13
9
|
import wrapStructureContent from './wrap-structure-content';
|
|
14
10
|
import IntlService from 'ember-intl/services/intl';
|
|
15
|
-
import {
|
|
16
|
-
import { containsOnlyPlaceholder } from '../utils/structure';
|
|
17
|
-
import { findParentNodeOfType } from '@curvenote/prosemirror-utils';
|
|
11
|
+
import { findInsertionRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/_private/find-insertion-range';
|
|
18
12
|
|
|
19
13
|
const insertStructure = (
|
|
20
14
|
structureSpec: StructureSpec,
|
|
@@ -28,7 +22,7 @@ const insertStructure = (
|
|
|
28
22
|
}
|
|
29
23
|
const insertionRange = findInsertionRange({
|
|
30
24
|
doc,
|
|
31
|
-
selection,
|
|
25
|
+
$from: selection.$from,
|
|
32
26
|
nodeType: schema.nodes[structureSpec.name],
|
|
33
27
|
schema,
|
|
34
28
|
limitTo: structureSpec.limitTo,
|
|
@@ -65,75 +59,4 @@ const insertStructure = (
|
|
|
65
59
|
};
|
|
66
60
|
};
|
|
67
61
|
|
|
68
|
-
function findInsertionRange(args: {
|
|
69
|
-
doc: PNode;
|
|
70
|
-
selection: Selection;
|
|
71
|
-
nodeType: NodeType;
|
|
72
|
-
schema: Schema;
|
|
73
|
-
limitTo?: string;
|
|
74
|
-
}) {
|
|
75
|
-
const { doc, selection, nodeType, schema, limitTo } = args;
|
|
76
|
-
const { $from } = selection;
|
|
77
|
-
for (let currentDepth = $from.depth; currentDepth >= 0; currentDepth--) {
|
|
78
|
-
const currentAncestor = $from.node(currentDepth);
|
|
79
|
-
const index = $from.index(currentDepth);
|
|
80
|
-
if (currentAncestor.canReplaceWith(index, index, nodeType)) {
|
|
81
|
-
if (containsOnlyPlaceholder(schema, currentAncestor)) {
|
|
82
|
-
return { from: $from.start(currentDepth), to: $from.end(currentDepth) };
|
|
83
|
-
} else {
|
|
84
|
-
const insertPos = $from.after(currentDepth + 1);
|
|
85
|
-
return { from: insertPos, to: insertPos };
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const limitContainer = limitTo
|
|
90
|
-
? findParentNodeOfType(schema.nodes[limitTo])(selection)
|
|
91
|
-
: null;
|
|
92
|
-
|
|
93
|
-
const limitContainerRange = limitContainer
|
|
94
|
-
? {
|
|
95
|
-
from: limitContainer.pos,
|
|
96
|
-
to: limitContainer.pos + limitContainer.node.nodeSize,
|
|
97
|
-
}
|
|
98
|
-
: { from: 0, to: doc.nodeSize };
|
|
99
|
-
const filterFunction = ({ from, to }: { from: number; to: number }) => {
|
|
100
|
-
if (from >= limitContainerRange.from && to <= limitContainerRange.to) {
|
|
101
|
-
const node = doc.nodeAt(from);
|
|
102
|
-
if (node) {
|
|
103
|
-
if (node.canReplaceWith(node.childCount, node.childCount, nodeType)) {
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return false;
|
|
109
|
-
};
|
|
110
|
-
const nextContainerRange =
|
|
111
|
-
findNodes({
|
|
112
|
-
doc,
|
|
113
|
-
start: selection.from,
|
|
114
|
-
visitParentUpwards: true,
|
|
115
|
-
reverse: false,
|
|
116
|
-
filter: filterFunction,
|
|
117
|
-
}).next().value ??
|
|
118
|
-
findNodes({
|
|
119
|
-
doc,
|
|
120
|
-
start: selection.from,
|
|
121
|
-
visitParentUpwards: true,
|
|
122
|
-
reverse: true,
|
|
123
|
-
filter: filterFunction,
|
|
124
|
-
}).next().value;
|
|
125
|
-
if (nextContainerRange) {
|
|
126
|
-
const { from, to } = nextContainerRange;
|
|
127
|
-
const containerNode = doc.nodeAt(from);
|
|
128
|
-
if (containerNode) {
|
|
129
|
-
if (containsOnlyPlaceholder(schema, containerNode)) {
|
|
130
|
-
return { from: from + 1, to: to - 1 };
|
|
131
|
-
} else {
|
|
132
|
-
return { from: to - 1, to: to - 1 };
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
62
|
export default insertStructure;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { LEGISLATION_TYPE_CONCEPTS } from './legislation-types';
|
|
2
|
-
import { warn } from '@ember/debug';
|
|
3
2
|
import {
|
|
4
3
|
Option,
|
|
5
4
|
optionMapOr,
|
|
6
5
|
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
|
|
6
|
+
import {
|
|
7
|
+
dateValue,
|
|
8
|
+
escapeValue,
|
|
9
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
|
|
7
10
|
|
|
8
11
|
interface DecisionArgs {
|
|
9
12
|
uri: string;
|
|
@@ -470,39 +473,6 @@ function cleanCaches() {
|
|
|
470
473
|
fetchArticlesMemory.clear();
|
|
471
474
|
}
|
|
472
475
|
|
|
473
|
-
function escapeValue(value?: string) {
|
|
474
|
-
if (value) {
|
|
475
|
-
const shadowDomElement = document.createElement('textarea');
|
|
476
|
-
shadowDomElement.innerHTML = value;
|
|
477
|
-
return shadowDomElement.textContent;
|
|
478
|
-
} else {
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
function dateValue(value?: string): string | null {
|
|
484
|
-
if (value) {
|
|
485
|
-
try {
|
|
486
|
-
return new Intl.DateTimeFormat('nl-BE').format(
|
|
487
|
-
new Date(Date.parse(value))
|
|
488
|
-
);
|
|
489
|
-
} catch (e) {
|
|
490
|
-
let message: string;
|
|
491
|
-
if (e instanceof Error) {
|
|
492
|
-
message = e.message;
|
|
493
|
-
} else {
|
|
494
|
-
message = e as string;
|
|
495
|
-
}
|
|
496
|
-
warn(`Error parsing date ${value}: ${message}`, {
|
|
497
|
-
id: 'date-parsing-error',
|
|
498
|
-
});
|
|
499
|
-
return null;
|
|
500
|
-
}
|
|
501
|
-
} else {
|
|
502
|
-
return null;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
476
|
async function executeCountQuery({
|
|
507
477
|
query,
|
|
508
478
|
config,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Command } from '@lblod/ember-rdfa-editor';
|
|
2
|
+
import { findInsertionRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/_private/find-insertion-range';
|
|
3
|
+
import { v4 as uuid } from 'uuid';
|
|
4
|
+
|
|
5
|
+
interface InsertDocumentTitleArgs {
|
|
6
|
+
placeholder: string;
|
|
7
|
+
}
|
|
8
|
+
export default function insertDocumentTitle({
|
|
9
|
+
placeholder,
|
|
10
|
+
}: InsertDocumentTitleArgs): Command {
|
|
11
|
+
return function (state, dispatch) {
|
|
12
|
+
const { schema } = state;
|
|
13
|
+
const insertionRange = findInsertionRange({
|
|
14
|
+
doc: state.doc,
|
|
15
|
+
$from: state.doc.resolve(0),
|
|
16
|
+
nodeType: schema.nodes.document_title,
|
|
17
|
+
schema,
|
|
18
|
+
});
|
|
19
|
+
if (!insertionRange) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (dispatch) {
|
|
24
|
+
const tr = state.tr;
|
|
25
|
+
tr.replaceWith(
|
|
26
|
+
insertionRange.from,
|
|
27
|
+
insertionRange.to,
|
|
28
|
+
schema.node(
|
|
29
|
+
'document_title',
|
|
30
|
+
{ __rdfaId: uuid() },
|
|
31
|
+
schema.node(
|
|
32
|
+
'paragraph',
|
|
33
|
+
null,
|
|
34
|
+
schema.node('placeholder', {
|
|
35
|
+
placeholderText: placeholder,
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
dispatch(tr);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NodeSpec, getRdfaAttrs, rdfaAttrs } from '@lblod/ember-rdfa-editor';
|
|
2
|
+
|
|
3
|
+
import { ELI } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
4
|
+
|
|
5
|
+
import { hasRDFaAttribute } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
|
|
6
|
+
|
|
7
|
+
export const document_title: NodeSpec = {
|
|
8
|
+
content: 'paragraph{1}',
|
|
9
|
+
inline: false,
|
|
10
|
+
defining: true,
|
|
11
|
+
canSplit: false,
|
|
12
|
+
group: '',
|
|
13
|
+
attrs: {
|
|
14
|
+
...rdfaAttrs,
|
|
15
|
+
property: {
|
|
16
|
+
default: 'eli:title',
|
|
17
|
+
},
|
|
18
|
+
datatype: {
|
|
19
|
+
default: 'xsd:string',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
toDOM(node) {
|
|
23
|
+
return ['h4', node.attrs, 0];
|
|
24
|
+
},
|
|
25
|
+
parseDOM: [
|
|
26
|
+
{
|
|
27
|
+
tag: 'h1,h2,h3,h4,h5',
|
|
28
|
+
getAttrs(element: HTMLElement) {
|
|
29
|
+
if (hasRDFaAttribute(element, 'property', ELI('title'))) {
|
|
30
|
+
return getRdfaAttrs(element);
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { document_title } from './document-title';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { htmlSafe } from '@ember/template';
|
|
2
|
+
|
|
3
|
+
import { optionMapOr } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
|
|
4
|
+
import { dateValue } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
|
|
5
|
+
import { SafeString } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/types';
|
|
6
|
+
|
|
7
|
+
export type SnippetPluginConfig = {
|
|
8
|
+
endpoint: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
interface SnippetArgs {
|
|
12
|
+
title: string | null;
|
|
13
|
+
createdOn: string | null;
|
|
14
|
+
content: string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Snippet {
|
|
18
|
+
content: SafeString | null;
|
|
19
|
+
createdOn: string | null;
|
|
20
|
+
title: string | null;
|
|
21
|
+
|
|
22
|
+
constructor({ title, createdOn, content }: SnippetArgs) {
|
|
23
|
+
this.content = optionMapOr(null, htmlSafe, content);
|
|
24
|
+
this.createdOn = dateValue(createdOn ?? undefined);
|
|
25
|
+
this.title = title;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
executeCountQuery,
|
|
3
|
+
executeQuery,
|
|
4
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/sparql-helpers';
|
|
5
|
+
import { Snippet } from '../index';
|
|
6
|
+
|
|
7
|
+
type Filter = { name?: string };
|
|
8
|
+
type Pagination = { pageNumber: number; pageSize: number };
|
|
9
|
+
|
|
10
|
+
const buildCountQuery = ({ name }: Filter) => {
|
|
11
|
+
return `
|
|
12
|
+
PREFIX dct: <http://purl.org/dc/terms/>
|
|
13
|
+
PREFIX pav: <http://purl.org/pav/>
|
|
14
|
+
PREFIX ext: <http://mu.semte.ch/vocabularies/ext/>
|
|
15
|
+
|
|
16
|
+
SELECT (COUNT(?snippetDocument) AS ?count)
|
|
17
|
+
WHERE {
|
|
18
|
+
?snippetList a ext:SnippetList ;
|
|
19
|
+
ext:hasSnippet/pav:hasCurrentVersion ?snippetDocument .
|
|
20
|
+
?snippetDocument dct:title ?title ;
|
|
21
|
+
ext:editorDocumentContent ?content ;
|
|
22
|
+
pav:createdOn ?createdOn .
|
|
23
|
+
${name ? `FILTER (CONTAINS(LCASE(?title), "${name}"))` : ''}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const buildFetchQuery = ({
|
|
29
|
+
filter: { name },
|
|
30
|
+
pagination: { pageSize, pageNumber },
|
|
31
|
+
}: {
|
|
32
|
+
filter: Filter;
|
|
33
|
+
pagination: Pagination;
|
|
34
|
+
}) => {
|
|
35
|
+
return `
|
|
36
|
+
PREFIX dct: <http://purl.org/dc/terms/>
|
|
37
|
+
PREFIX pav: <http://purl.org/pav/>
|
|
38
|
+
PREFIX ext: <http://mu.semte.ch/vocabularies/ext/>
|
|
39
|
+
|
|
40
|
+
SELECT DISTINCT ?title ?content ?createdOn
|
|
41
|
+
WHERE {
|
|
42
|
+
?snippetList a ext:SnippetList ;
|
|
43
|
+
ext:hasSnippet/pav:hasCurrentVersion ?snippetDocument .
|
|
44
|
+
?snippetDocument dct:title ?title ;
|
|
45
|
+
ext:editorDocumentContent ?content ;
|
|
46
|
+
pav:createdOn ?createdOn .
|
|
47
|
+
${name ? `FILTER (CONTAINS(LCASE(?title), "${name}"))` : ''}
|
|
48
|
+
}
|
|
49
|
+
ORDER BY DESC(?createdOn) LIMIT ${pageSize} OFFSET ${
|
|
50
|
+
pageNumber * pageSize
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const fetchSnippets = async ({
|
|
56
|
+
endpoint,
|
|
57
|
+
abortSignal,
|
|
58
|
+
filter,
|
|
59
|
+
pagination,
|
|
60
|
+
}: {
|
|
61
|
+
endpoint: string;
|
|
62
|
+
abortSignal: AbortSignal;
|
|
63
|
+
filter: Filter;
|
|
64
|
+
pagination: Pagination;
|
|
65
|
+
}) => {
|
|
66
|
+
const totalCount = await executeCountQuery({
|
|
67
|
+
endpoint,
|
|
68
|
+
query: buildCountQuery(filter),
|
|
69
|
+
abortSignal,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (totalCount === 0) {
|
|
73
|
+
return { totalCount, results: [] };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const queryResult = await executeQuery<{
|
|
77
|
+
title: { value: string };
|
|
78
|
+
createdOn: { value: string };
|
|
79
|
+
content: { value: string };
|
|
80
|
+
}>({
|
|
81
|
+
endpoint,
|
|
82
|
+
query: buildFetchQuery({ filter, pagination }),
|
|
83
|
+
abortSignal,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const results = queryResult.results.bindings.map(
|
|
87
|
+
(binding) =>
|
|
88
|
+
new Snippet({
|
|
89
|
+
title: binding.title?.value,
|
|
90
|
+
createdOn: binding.createdOn?.value,
|
|
91
|
+
content: binding.content?.value,
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return { totalCount, results };
|
|
96
|
+
};
|
|
@@ -73,20 +73,19 @@ export const contentToDom = ({
|
|
|
73
73
|
type,
|
|
74
74
|
node,
|
|
75
75
|
}: {
|
|
76
|
-
content: string;
|
|
76
|
+
content: string | null;
|
|
77
77
|
type: string;
|
|
78
78
|
node: PNode;
|
|
79
79
|
}) => {
|
|
80
80
|
if (type === 'number') {
|
|
81
|
-
if (
|
|
82
|
-
node.attrs[WRITTEN_NUMBER_PNODE_KEY]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return n2words(Number(content), { lang: 'nl' });
|
|
81
|
+
if (!Number.isNaN(Number(content)) && content !== null && content !== '') {
|
|
82
|
+
if (node.attrs[WRITTEN_NUMBER_PNODE_KEY]) {
|
|
83
|
+
return n2words(Number(content), { lang: 'nl' });
|
|
84
|
+
} else {
|
|
85
|
+
return content;
|
|
86
|
+
}
|
|
88
87
|
} else {
|
|
89
|
-
return
|
|
88
|
+
return 'Voeg getal in';
|
|
90
89
|
}
|
|
91
90
|
} else {
|
|
92
91
|
return content;
|
|
@@ -137,7 +136,10 @@ export const parseAttributes = (node: HTMLElement): false | Attrs => {
|
|
|
137
136
|
return false;
|
|
138
137
|
};
|
|
139
138
|
|
|
140
|
-
export const attributesToDOM = (
|
|
139
|
+
export const attributesToDOM = (
|
|
140
|
+
node: PNode,
|
|
141
|
+
content?: string | null
|
|
142
|
+
): DOMOutputSpec => {
|
|
141
143
|
const {
|
|
142
144
|
mappingResource,
|
|
143
145
|
codelistResource,
|
|
@@ -192,7 +194,9 @@ export const attributesToDOM = (node: PNode, content = null): DOMOutputSpec => {
|
|
|
192
194
|
content: content ? content : '',
|
|
193
195
|
...(!!datatype && { datatype: datatype as string }),
|
|
194
196
|
},
|
|
195
|
-
content
|
|
197
|
+
content !== undefined
|
|
198
|
+
? contentToDom({ content, type: type as string, node })
|
|
199
|
+
: 0,
|
|
196
200
|
],
|
|
197
201
|
];
|
|
198
202
|
};
|
|
@@ -43,10 +43,10 @@ export async function fetchCodeListOptions(
|
|
|
43
43
|
endpoint: string,
|
|
44
44
|
codelistUri: string
|
|
45
45
|
): Promise<CodeListOptions> {
|
|
46
|
-
const codelistsOptionsQueryResult = await executeQuery(
|
|
46
|
+
const codelistsOptionsQueryResult = await executeQuery({
|
|
47
47
|
endpoint,
|
|
48
|
-
generateCodeListOptionsQuery(codelistUri)
|
|
49
|
-
);
|
|
48
|
+
query: generateCodeListOptionsQuery(codelistUri),
|
|
49
|
+
});
|
|
50
50
|
const options = parseCodelistOptions(codelistsOptionsQueryResult);
|
|
51
51
|
return {
|
|
52
52
|
type:
|
|
@@ -95,10 +95,10 @@ export async function fetchCodeListsByPublisher(
|
|
|
95
95
|
endpoint: string,
|
|
96
96
|
publisher: string
|
|
97
97
|
): Promise<CodeList[]> {
|
|
98
|
-
const codelistsOptionsQueryResult = await executeQuery(
|
|
98
|
+
const codelistsOptionsQueryResult = await executeQuery({
|
|
99
99
|
endpoint,
|
|
100
|
-
generateCodeListsByPublisherQuery(publisher)
|
|
101
|
-
);
|
|
100
|
+
query: generateCodeListsByPublisherQuery(publisher),
|
|
101
|
+
});
|
|
102
102
|
const bindings = codelistsOptionsQueryResult.results.bindings;
|
|
103
103
|
return bindings.map((binding) => ({
|
|
104
104
|
uri: binding['uri']?.value,
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { findParentNodeClosestToPos } from '@curvenote/prosemirror-utils';
|
|
2
|
+
import { NodeType, PNode, ResolvedPos, Schema } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import { containsOnlyPlaceholder } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/article-structure-plugin/utils/structure';
|
|
4
|
+
import { findNodes } from '@lblod/ember-rdfa-editor/utils/position-utils';
|
|
5
|
+
|
|
6
|
+
export function findInsertionRange(args: {
|
|
7
|
+
doc: PNode;
|
|
8
|
+
$from: ResolvedPos;
|
|
9
|
+
nodeType: NodeType;
|
|
10
|
+
schema: Schema;
|
|
11
|
+
limitTo?: string;
|
|
12
|
+
}) {
|
|
13
|
+
const { doc, $from, nodeType, schema, limitTo } = args;
|
|
14
|
+
for (let currentDepth = $from.depth; currentDepth >= 0; currentDepth--) {
|
|
15
|
+
const currentAncestor = $from.node(currentDepth);
|
|
16
|
+
const index = $from.index(currentDepth);
|
|
17
|
+
if (currentAncestor.canReplaceWith(index, index, nodeType)) {
|
|
18
|
+
if (containsOnlyPlaceholder(schema, currentAncestor)) {
|
|
19
|
+
return { from: $from.start(currentDepth), to: $from.end(currentDepth) };
|
|
20
|
+
} else {
|
|
21
|
+
const insertPos = $from.after(currentDepth + 1);
|
|
22
|
+
return { from: insertPos, to: insertPos };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const limitContainer = limitTo
|
|
27
|
+
? findParentNodeClosestToPos(
|
|
28
|
+
$from,
|
|
29
|
+
(node) => node.type === schema.nodes[limitTo]
|
|
30
|
+
)
|
|
31
|
+
: null;
|
|
32
|
+
|
|
33
|
+
const limitContainerRange = limitContainer
|
|
34
|
+
? {
|
|
35
|
+
from: limitContainer.pos,
|
|
36
|
+
to: limitContainer.pos + limitContainer.node.nodeSize,
|
|
37
|
+
}
|
|
38
|
+
: { from: 0, to: doc.nodeSize };
|
|
39
|
+
const filterFunction = ({ from, to }: { from: number; to: number }) => {
|
|
40
|
+
if (from >= limitContainerRange.from && to <= limitContainerRange.to) {
|
|
41
|
+
const node = doc.nodeAt(from);
|
|
42
|
+
if (node) {
|
|
43
|
+
if (node.canReplaceWith(node.childCount, node.childCount, nodeType)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
const nextContainerRange =
|
|
51
|
+
findNodes({
|
|
52
|
+
doc,
|
|
53
|
+
start: $from.pos,
|
|
54
|
+
visitParentUpwards: true,
|
|
55
|
+
reverse: false,
|
|
56
|
+
filter: filterFunction,
|
|
57
|
+
}).next().value ??
|
|
58
|
+
findNodes({
|
|
59
|
+
doc,
|
|
60
|
+
start: $from.pos,
|
|
61
|
+
visitParentUpwards: true,
|
|
62
|
+
reverse: true,
|
|
63
|
+
filter: filterFunction,
|
|
64
|
+
}).next().value;
|
|
65
|
+
if (nextContainerRange) {
|
|
66
|
+
const { from, to } = nextContainerRange;
|
|
67
|
+
const containerNode = doc.nodeAt(from);
|
|
68
|
+
if (containerNode) {
|
|
69
|
+
if (containsOnlyPlaceholder(schema, containerNode)) {
|
|
70
|
+
return { from: from + 1, to: to - 1 };
|
|
71
|
+
} else {
|
|
72
|
+
return { from: to - 1, to: to - 1 };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import * as RDF from '@rdfjs/types';
|
|
2
|
+
import { optionMapOr } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
+
export interface QueryResult<Binding = Record<string, RDF.Term>> {
|
|
4
5
|
results: {
|
|
5
|
-
bindings:
|
|
6
|
+
bindings: Binding[];
|
|
6
7
|
};
|
|
7
|
-
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface QueryConfig {
|
|
11
|
+
query: string;
|
|
12
|
+
endpoint: string;
|
|
13
|
+
abortSignal?: AbortSignal;
|
|
14
|
+
}
|
|
8
15
|
|
|
9
|
-
export async function executeQuery
|
|
16
|
+
export async function executeQuery<Binding = Record<string, RDF.Term>>({
|
|
17
|
+
query,
|
|
18
|
+
endpoint,
|
|
19
|
+
abortSignal,
|
|
20
|
+
}: QueryConfig) {
|
|
10
21
|
const encodedQuery = encodeURIComponent(query.trim());
|
|
22
|
+
|
|
11
23
|
const response = await fetch(endpoint, {
|
|
12
24
|
method: 'POST',
|
|
13
25
|
mode: 'cors',
|
|
@@ -16,12 +28,22 @@ export async function executeQuery(endpoint: string, query: string) {
|
|
|
16
28
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
17
29
|
},
|
|
18
30
|
body: `query=${encodedQuery}`,
|
|
31
|
+
signal: abortSignal,
|
|
19
32
|
});
|
|
33
|
+
|
|
20
34
|
if (response.ok) {
|
|
21
|
-
return response.json() as
|
|
35
|
+
return response.json() as Promise<QueryResult<Binding>>;
|
|
22
36
|
} else {
|
|
23
37
|
throw new Error(
|
|
24
|
-
`Request to
|
|
38
|
+
`Request to ${endpoint} was unsuccessful: [${response.status}] ${response.statusText}`
|
|
25
39
|
);
|
|
26
40
|
}
|
|
27
41
|
}
|
|
42
|
+
|
|
43
|
+
export async function executeCountQuery(queryConfig: QueryConfig) {
|
|
44
|
+
const response = await executeQuery<{ count: { value: string } }>(
|
|
45
|
+
queryConfig
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return optionMapOr(0, parseInt, response.results.bindings[0]?.count.value);
|
|
49
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { warn } from '@ember/debug';
|
|
2
|
+
|
|
3
|
+
export function escapeValue(value?: string) {
|
|
4
|
+
if (value) {
|
|
5
|
+
const shadowDomElement = document.createElement('textarea');
|
|
6
|
+
shadowDomElement.innerHTML = value;
|
|
7
|
+
return shadowDomElement.textContent;
|
|
8
|
+
} else {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function dateValue(value?: string): string | null {
|
|
14
|
+
if (value) {
|
|
15
|
+
try {
|
|
16
|
+
return new Intl.DateTimeFormat('nl-BE').format(
|
|
17
|
+
new Date(Date.parse(value))
|
|
18
|
+
);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
let message: string;
|
|
21
|
+
if (e instanceof Error) {
|
|
22
|
+
message = e.message;
|
|
23
|
+
} else {
|
|
24
|
+
message = e as string;
|
|
25
|
+
}
|
|
26
|
+
warn(`Error parsing date ${value}: ${message}`, {
|
|
27
|
+
id: 'date-parsing-error',
|
|
28
|
+
});
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/document-title-plugin/insert-title-card';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/pagination/pagination-view';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/helpers/alert-load-error';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/helpers/alert-no-items';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/search-modal';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/snippet-insert';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/snippets/snippet-list';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/snippet-plugin/snippets/snippet-preview';
|