@lblod/ember-rdfa-editor-lblod-plugins 1.0.0-beta.1 → 1.0.0-beta.2

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/addon/components/article-structure-plugin/article-structure-card.hbs +3 -1
  3. package/addon/components/au-dropdown-pill.hbs +32 -0
  4. package/addon/components/au-dropdown-pill.ts +65 -0
  5. package/addon/components/besluit-type-plugin/toolbar-dropdown.ts +19 -12
  6. package/addon/components/citation-plugin/citation-card.ts +1 -1
  7. package/addon/components/citation-plugin/citation-insert.ts +1 -1
  8. package/addon/components/import-snippet-plugin/card.ts +8 -12
  9. package/addon/components/rdfa-date-plugin/card.hbs +28 -0
  10. package/addon/components/rdfa-date-plugin/card.ts +72 -38
  11. package/addon/components/rdfa-date-plugin/date-time-picker.ts +1 -0
  12. package/addon/components/rdfa-date-plugin/insert.hbs +2 -2
  13. package/addon/components/rdfa-date-plugin/insert.ts +14 -23
  14. package/addon/components/roadsign-regulation-plugin/roadsign-regulation-card.ts +24 -25
  15. package/addon/components/roadsign-regulation-plugin/roadsigns-modal.ts +36 -17
  16. package/addon/components/standard-template-plugin/template-provider.ts +54 -11
  17. package/addon/components/{insert-variable-plugin → variable-plugin}/insert-variable-card.hbs +4 -4
  18. package/addon/components/{insert-variable-plugin → variable-plugin}/insert-variable-card.ts +26 -35
  19. package/addon/components/{template-variable-plugin → variable-plugin}/template-variable-card.hbs +6 -6
  20. package/addon/components/variable-plugin/template-variable-card.ts +174 -0
  21. package/addon/components/variable-plugin/variable.hbs +4 -0
  22. package/addon/components/variable-plugin/variable.ts +250 -0
  23. package/addon/plugins/article-structure-plugin/commands/insert-structure.ts +4 -2
  24. package/addon/plugins/article-structure-plugin/index.ts +1 -1
  25. package/addon/plugins/article-structure-plugin/structures/article-paragraph.ts +6 -2
  26. package/addon/plugins/article-structure-plugin/structures/article.ts +1 -1
  27. package/addon/plugins/article-structure-plugin/structures/chapter.ts +1 -2
  28. package/addon/plugins/article-structure-plugin/structures/section.ts +1 -1
  29. package/addon/plugins/article-structure-plugin/structures/subsection.ts +1 -1
  30. package/addon/plugins/article-structure-plugin/structures/title.ts +1 -2
  31. package/addon/plugins/citation-plugin/index.ts +184 -113
  32. package/addon/plugins/rdfa-date-plugin/index.ts +42 -3
  33. package/addon/plugins/rdfa-date-plugin/nodes/date.ts +127 -0
  34. package/addon/plugins/rdfa-date-plugin/nodes/index.ts +1 -0
  35. package/addon/plugins/rdfa-date-plugin/utils.ts +10 -0
  36. package/addon/plugins/roadsign-regulation-plugin/nodes.ts +107 -0
  37. package/addon/plugins/standard-template-plugin/index.ts +26 -0
  38. package/addon/plugins/standard-template-plugin/utils/nodes.ts +366 -0
  39. package/addon/plugins/{insert-variable-plugin → variable-plugin}/index.ts +6 -1
  40. package/addon/plugins/variable-plugin/nodes.ts +137 -0
  41. package/addon/plugins/variable-plugin/utils/constants.ts +107 -0
  42. package/addon/plugins/{template-variable-plugin → variable-plugin}/utils/fetch-data.ts +41 -0
  43. package/addon/services/standard-template-plugin.ts +16 -12
  44. package/addon/utils/changed-descendants.ts +29 -0
  45. package/addon/utils/constants.ts +11 -0
  46. package/addon/utils/namespace.ts +42 -7
  47. package/app/components/au-dropdown-pill.js +1 -0
  48. package/app/components/{insert-variable-plugin → variable-plugin}/insert-variable-card.js +1 -1
  49. package/app/components/{template-variable-plugin → variable-plugin}/template-variable-card.js +1 -1
  50. package/app/components/variable-plugin/variable-edit-modal.js +1 -0
  51. package/app/components/variable-plugin/variable.js +1 -0
  52. package/app/styles/date-plugin.scss +17 -0
  53. package/app/styles/variable-plugin.scss +65 -0
  54. package/components/au-dropdown-pill.d.ts +19 -0
  55. package/components/au-native-input.d.ts +1 -1
  56. package/components/citation-plugin/citation-card.d.ts +1 -1
  57. package/components/rdfa-date-plugin/card.d.ts +14 -5
  58. package/components/rdfa-date-plugin/insert.d.ts +1 -2
  59. package/components/roadsign-regulation-plugin/roadsign-regulation-card.d.ts +1 -0
  60. package/components/roadsign-regulation-plugin/roadsigns-modal.d.ts +3 -0
  61. package/components/standard-template-plugin/template-provider.d.ts +6 -1
  62. package/components/{insert-variable-plugin → variable-plugin}/insert-variable-card.d.ts +3 -4
  63. package/components/{template-variable-plugin → variable-plugin}/template-variable-card.d.ts +8 -5
  64. package/components/variable-plugin/variable.d.ts +42 -0
  65. package/package.json +4 -4
  66. package/plugins/article-structure-plugin/commands/insert-structure.d.ts +2 -2
  67. package/plugins/article-structure-plugin/index.d.ts +1 -1
  68. package/plugins/citation-plugin/index.d.ts +11 -4
  69. package/plugins/rdfa-date-plugin/index.d.ts +13 -1
  70. package/plugins/rdfa-date-plugin/nodes/date.d.ts +9 -0
  71. package/plugins/rdfa-date-plugin/nodes/index.d.ts +1 -0
  72. package/plugins/rdfa-date-plugin/utils.d.ts +1 -0
  73. package/plugins/roadsign-regulation-plugin/nodes.d.ts +2 -0
  74. package/plugins/standard-template-plugin/index.d.ts +12 -0
  75. package/plugins/standard-template-plugin/utils/nodes.d.ts +12 -0
  76. package/plugins/{insert-variable-plugin → variable-plugin}/index.d.ts +1 -0
  77. package/plugins/variable-plugin/nodes.d.ts +2 -0
  78. package/plugins/variable-plugin/utils/constants.d.ts +9 -0
  79. package/plugins/{template-variable-plugin → variable-plugin}/utils/fetch-data.d.ts +5 -0
  80. package/services/standard-template-plugin.d.ts +9 -10
  81. package/translations/en-US.yaml +4 -3
  82. package/translations/nl-BE.yaml +5 -4
  83. package/utils/changed-descendants.d.ts +2 -0
  84. package/utils/constants.d.ts +5 -0
  85. package/utils/namespace.d.ts +8 -3
  86. package/addon/components/template-variable-plugin/template-variable-card.ts +0 -227
  87. package/addon/plugins/insert-variable-plugin/utils/constants.ts +0 -67
  88. package/addon/plugins/insert-variable-plugin/utils/fetch-data.ts +0 -41
  89. package/addon/plugins/rdfa-date-plugin/commands/index.ts +0 -1
  90. package/addon/plugins/rdfa-date-plugin/commands/modify-date.ts +0 -48
  91. package/addon/plugins/template-variable-plugin/index.ts +0 -6
  92. package/addon/plugins/template-variable-plugin/utils/constants.ts +0 -2
  93. package/plugins/insert-variable-plugin/utils/constants.d.ts +0 -7
  94. package/plugins/insert-variable-plugin/utils/fetch-data.d.ts +0 -5
  95. package/plugins/rdfa-date-plugin/commands/index.d.ts +0 -1
  96. package/plugins/rdfa-date-plugin/commands/modify-date.d.ts +0 -2
  97. package/plugins/template-variable-plugin/index.d.ts +0 -2
  98. package/plugins/template-variable-plugin/utils/constants.d.ts +0 -1
@@ -6,7 +6,7 @@ import {
6
6
  EditorState,
7
7
  } from '@lblod/ember-rdfa-editor';
8
8
  import IntlService from 'ember-intl/services/intl';
9
- import { Transaction } from 'prosemirror-state';
9
+ import { Transaction } from '@lblod/ember-rdfa-editor';
10
10
  import { STRUCTURE_SPECS } from './structures';
11
11
 
12
12
  export type SpecName = string;
@@ -117,8 +117,12 @@ export const article_paragraph: NodeSpec = {
117
117
  return false;
118
118
  },
119
119
  getContent: (node, schema) => {
120
- const content = node.lastChild?.textContent ?? '';
121
- return Fragment.from(schema.text(content));
120
+ const content = node.lastChild?.textContent;
121
+ if (content) {
122
+ return Fragment.from(schema.text(content));
123
+ } else {
124
+ return Fragment.empty;
125
+ }
122
126
  },
123
127
  },
124
128
  ],
@@ -134,5 +134,5 @@ export const article_header: NodeSpec = {
134
134
  };
135
135
 
136
136
  export const article_body = constructStructureBodyNodeSpec({
137
- content: '(paragraph|article_paragraph)+',
137
+ content: '(block|article_paragraph)+',
138
138
  });
@@ -74,9 +74,8 @@ export const chapterSpec: StructureSpec = {
74
74
  export const chapter = constructStructureNodeSpec({
75
75
  type: SAY('Chapter'),
76
76
  content: 'structure_header chapter_body',
77
- group: 'block',
78
77
  });
79
78
 
80
79
  export const chapter_body = constructStructureBodyNodeSpec({
81
- content: '(section|paragraph)+|(article|paragraph)+',
80
+ content: '(section|block)+|(article|block)+',
82
81
  });
@@ -77,5 +77,5 @@ export const section = constructStructureNodeSpec({
77
77
  });
78
78
 
79
79
  export const section_body = constructStructureBodyNodeSpec({
80
- content: '(subsection|paragraph)+|(article|paragraph)+',
80
+ content: '(subsection|block)+|(article|block)+',
81
81
  });
@@ -78,5 +78,5 @@ export const subsection = constructStructureNodeSpec({
78
78
  });
79
79
 
80
80
  export const subsection_body = constructStructureBodyNodeSpec({
81
- content: '(article|paragraph)+',
81
+ content: '(article|block)+',
82
82
  });
@@ -74,9 +74,8 @@ export const titleSpec: StructureSpec = {
74
74
  export const title = constructStructureNodeSpec({
75
75
  type: SAY('Title'),
76
76
  content: 'structure_header title_body',
77
- group: 'block',
78
77
  });
79
78
 
80
79
  export const title_body = constructStructureBodyNodeSpec({
81
- content: '(chapter|paragraph)+|(article|paragraph)+',
80
+ content: '(chapter|block)+|(article|block)+',
82
81
  });
@@ -5,20 +5,17 @@ import {
5
5
  EditorStateConfig,
6
6
  InlineDecorationSpec,
7
7
  MarkSpec,
8
+ NodeType,
8
9
  PNode,
9
10
  ProsePlugin,
10
11
  Schema,
11
12
  WidgetSpec,
12
13
  } from '@lblod/ember-rdfa-editor';
13
- import {
14
- datastoreKey,
15
- ProseStore,
16
- } from '@lblod/ember-rdfa-editor/plugins/datastore';
17
14
  import processMatch, {
18
15
  RegexpMatchArrayWithIndices,
19
16
  } from './utils/process-match';
20
- import { expect } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
21
17
  import { citation } from './marks/citation';
18
+ import { changedDescendants } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/changed-descendants';
22
19
 
23
20
  const BASIC_MULTIPLANE_CHARACTER = '\u0021-\uFFFF'; // most of the characters used around the world
24
21
 
@@ -60,54 +57,6 @@ export interface CitationDecoration extends Decoration {
60
57
  spec: CitationDecorationSpec;
61
58
  }
62
59
 
63
- function calculateDecorations(
64
- schema: CitationSchema,
65
- doc: PNode,
66
- activeRanges: [number, number][]
67
- ) {
68
- const decorations: Decoration[] = [];
69
-
70
- for (const [start, end] of activeRanges) {
71
- doc.nodesBetween(start, end, (node: PNode, pos: number): boolean => {
72
- if (
73
- node.isText &&
74
- node.text &&
75
- !schema.marks.citation.isInSet(node.marks)
76
- ) {
77
- for (const match of node.text.matchAll(CITATION_REGEX)) {
78
- const processedMatch = processMatch(
79
- match as RegexpMatchArrayWithIndices
80
- );
81
-
82
- if (processedMatch) {
83
- const { text, legislationTypeUri, searchTextMatch } =
84
- processedMatch;
85
- const { start: matchStart, end: matchEnd } = searchTextMatch;
86
- const decorationStart = pos + matchStart;
87
- const decorationEnd = pos + matchEnd;
88
- decorations.push(
89
- Decoration.inline(
90
- decorationStart,
91
- decorationEnd,
92
-
93
- {
94
- 'data-editor-highlight': 'true',
95
- },
96
- {
97
- searchText: text,
98
- legislationTypeUri,
99
- }
100
- )
101
- );
102
- }
103
- }
104
- }
105
- return true;
106
- });
107
- }
108
- return DecorationSet.create(doc, decorations);
109
- }
110
-
111
60
  interface CitationPluginState {
112
61
  highlights: DecorationSet;
113
62
  activeRanges: [number, number][];
@@ -115,63 +64,6 @@ interface CitationPluginState {
115
64
 
116
65
  export type CitationPlugin = ProsePlugin<CitationPluginState>;
117
66
 
118
- function citationPlugin({
119
- activeIn = defaultActiveIn,
120
- }: CitationPluginConfig): CitationPlugin {
121
- const citation: CitationPlugin = new ProsePlugin({
122
- state: {
123
- init(stateConfig: EditorStateConfig, state: EditorState) {
124
- const { doc, schema } = state;
125
- const activeRanges = activeIn(
126
- state,
127
- expect(
128
- 'the datastore plugin is required for this plugin',
129
- datastoreKey.getState(state)
130
- )()
131
- );
132
- return {
133
- highlights: calculateDecorations(schema, doc, activeRanges),
134
- activeRanges,
135
- };
136
- },
137
- apply(tr, set, oldState, newState) {
138
- const { doc, schema } = newState;
139
- const activeRanges = activeIn(
140
- newState,
141
- expect(
142
- 'the datastore plugin is required for this plugin',
143
- datastoreKey.getState(newState)
144
- )()
145
- );
146
- return {
147
- highlights: calculateDecorations(schema, doc, activeRanges),
148
- activeRanges,
149
- };
150
- },
151
- },
152
- props: {
153
- decorations(state): DecorationSet | undefined {
154
- return citation.getState(state)?.highlights;
155
- },
156
- },
157
- });
158
- return citation;
159
- }
160
-
161
- function defaultActiveIn(
162
- state: EditorState,
163
- datastore: ProseStore
164
- ): [number, number][] {
165
- const result: [number, number][] = [];
166
- for (const { from, to } of datastore
167
- .match(null, 'besluit:motivering')
168
- .asPredicateNodeMapping()
169
- .nodes()) {
170
- result.push([from, to]);
171
- }
172
- return result;
173
- }
174
-
175
67
  export interface CitationPluginBundle {
176
68
  plugin: ProsePlugin<CitationPluginState>;
177
69
  widgets: {
@@ -183,12 +75,31 @@ export interface CitationPluginBundle {
183
75
  };
184
76
  }
185
77
 
186
- export interface CitationPluginConfig {
187
- activeIn?(state: EditorState, datastore: ProseStore): [number, number][];
78
+ export interface CitationPluginNodeConfig {
79
+ type: 'nodes';
80
+ regex?: RegExp;
81
+
82
+ activeInNodeTypes(schema: Schema, state: EditorState): Set<NodeType>;
83
+ }
84
+
85
+ export interface CitationPluginRangeConfig {
86
+ type: 'ranges';
87
+ regex?: RegExp;
88
+
89
+ activeInRanges(state: EditorState): [number, number][];
188
90
  }
189
91
 
92
+ export type CitationPluginConfig =
93
+ | CitationPluginNodeConfig
94
+ | CitationPluginRangeConfig;
95
+
190
96
  export function setupCitationPlugin(
191
- config: CitationPluginConfig = {}
97
+ config: CitationPluginConfig = {
98
+ type: 'nodes',
99
+ activeInNodeTypes(schema): Set<NodeType> {
100
+ return new Set([schema.nodes.doc]);
101
+ },
102
+ }
192
103
  ): CitationPluginBundle {
193
104
  const plugin = citationPlugin(config);
194
105
  return {
@@ -214,3 +125,163 @@ export function setupCitationPlugin(
214
125
  },
215
126
  };
216
127
  }
128
+
129
+ function citationPlugin(config: CitationPluginConfig): CitationPlugin {
130
+ const citation: CitationPlugin = new ProsePlugin({
131
+ state: {
132
+ init(stateConfig: EditorStateConfig, state: EditorState) {
133
+ return calculateCitationPluginState(state, config);
134
+ },
135
+ apply(tr, set, oldState, newState) {
136
+ return calculateCitationPluginState(newState, config, oldState);
137
+ },
138
+ },
139
+ props: {
140
+ decorations(state): DecorationSet | undefined {
141
+ return citation.getState(state)?.highlights;
142
+ },
143
+ },
144
+ });
145
+ return citation;
146
+ }
147
+
148
+ function calculateCitationPluginState(
149
+ state: EditorState,
150
+ config: CitationPluginConfig,
151
+ oldState?: EditorState
152
+ ) {
153
+ const { doc, schema } = state;
154
+ let activeRanges;
155
+ let highlights;
156
+ if (config.type === 'ranges') {
157
+ activeRanges = config.activeInRanges(state);
158
+ const calculatedDecs = calculateDecorationsInRanges(
159
+ config,
160
+ schema,
161
+ doc,
162
+ activeRanges
163
+ );
164
+ highlights = calculatedDecs.decorations;
165
+ } else {
166
+ const nodes = config.activeInNodeTypes(schema, state);
167
+ const calculatedDecs = calculateDecorationsInNodes(
168
+ config,
169
+ schema,
170
+ nodes,
171
+ doc,
172
+ oldState?.doc
173
+ );
174
+ activeRanges = calculatedDecs.activeRanges;
175
+ highlights = calculatedDecs.decorations;
176
+ }
177
+ return {
178
+ highlights,
179
+ activeRanges,
180
+ };
181
+ }
182
+
183
+ function calculateDecorationsInNodes(
184
+ config: CitationPluginConfig,
185
+ schema: CitationSchema,
186
+ nodes: Set<NodeType>,
187
+ newDoc: PNode,
188
+ oldDoc?: PNode
189
+ ): { decorations: DecorationSet; activeRanges: [number, number][] } {
190
+ const activeRanges: [number, number][] = [];
191
+ const decorations: Decoration[] = [];
192
+ const collector = collectDecorations(decorations, schema, config.regex);
193
+ if (nodes.has(newDoc.type)) {
194
+ oldDoc
195
+ ? changedDescendants(oldDoc, newDoc, 0, collector)
196
+ : newDoc.descendants(collector);
197
+ activeRanges.push([0, newDoc.nodeSize]);
198
+ } else {
199
+ oldDoc
200
+ ? changedDescendants(
201
+ oldDoc,
202
+ newDoc,
203
+ 0,
204
+
205
+ (node, pos) => {
206
+ if (nodes.has(node.type)) {
207
+ node.nodesBetween(0, node.nodeSize - 2, collector, pos + 1);
208
+ activeRanges.push([pos, pos + node.nodeSize]);
209
+ return false;
210
+ }
211
+ return true;
212
+ }
213
+ )
214
+ : newDoc.descendants((node, pos) => {
215
+ if (nodes.has(node.type)) {
216
+ node.nodesBetween(0, node.nodeSize - 2, collector, pos + 1);
217
+ activeRanges.push([pos, pos + node.nodeSize]);
218
+ return false;
219
+ }
220
+ return true;
221
+ });
222
+ }
223
+ return {
224
+ decorations: DecorationSet.create(newDoc, decorations),
225
+ activeRanges,
226
+ };
227
+ }
228
+
229
+ function calculateDecorationsInRanges(
230
+ config: CitationPluginConfig,
231
+ schema: CitationSchema,
232
+ doc: PNode,
233
+ activeRanges: [number, number][]
234
+ ): { decorations: DecorationSet; activeRanges: [number, number][] } {
235
+ const decorations: Decoration[] = [];
236
+ const collector = collectDecorations(decorations, schema, config.regex);
237
+
238
+ for (const [start, end] of activeRanges) {
239
+ doc.nodesBetween(start, end, collector);
240
+ }
241
+ return {
242
+ decorations: DecorationSet.create(doc, decorations),
243
+ activeRanges: activeRanges,
244
+ };
245
+ }
246
+
247
+ function collectDecorations(
248
+ decorations: Decoration[],
249
+ schema: CitationSchema,
250
+ regex: RegExp = CITATION_REGEX
251
+ ) {
252
+ return function (node: PNode, pos: number): boolean {
253
+ if (
254
+ node.isText &&
255
+ node.text &&
256
+ !schema.marks.citation.isInSet(node.marks)
257
+ ) {
258
+ for (const match of node.text.matchAll(regex)) {
259
+ const processedMatch = processMatch(
260
+ match as RegexpMatchArrayWithIndices
261
+ );
262
+
263
+ if (processedMatch) {
264
+ const { text, legislationTypeUri, searchTextMatch } = processedMatch;
265
+ const { start: matchStart, end: matchEnd } = searchTextMatch;
266
+ const decorationStart = pos + matchStart;
267
+ const decorationEnd = pos + matchEnd;
268
+ decorations.push(
269
+ Decoration.inline(
270
+ decorationStart,
271
+ decorationEnd,
272
+
273
+ {
274
+ 'data-editor-highlight': 'true',
275
+ },
276
+ {
277
+ searchText: text,
278
+ legislationTypeUri,
279
+ }
280
+ )
281
+ );
282
+ }
283
+ }
284
+ }
285
+ return true;
286
+ };
287
+ }
@@ -1,11 +1,50 @@
1
1
  import { WidgetSpec } from '@lblod/ember-rdfa-editor';
2
2
 
3
- export const rdfaDateCardWidget: WidgetSpec = {
4
- componentName: 'rdfa-date-plugin/card',
5
- desiredLocation: 'sidebar',
3
+ export const defaultDateFormats: DateFormat[] = [
4
+ {
5
+ label: 'Short small Date',
6
+ key: 'short',
7
+ dateFormat: 'dd/MM/yy',
8
+ dateTimeFormat: 'dd/MM/yy HH:mm',
9
+ },
10
+ {
11
+ label: 'Long Date',
12
+ key: 'long',
13
+ dateFormat: 'EEEE dd MMMM yyyy',
14
+ dateTimeFormat: 'EEEE dd MMMM yyyy at HH:mm',
15
+ },
16
+ ];
17
+
18
+ const defaultOptions = {
19
+ formats: defaultDateFormats,
20
+ allowCustomFormat: true,
21
+ };
22
+
23
+ export const rdfaDateCardWidget: (options?: DatePluginOptions) => WidgetSpec = (
24
+ options
25
+ ) => {
26
+ return {
27
+ componentName: 'rdfa-date-plugin/card',
28
+ desiredLocation: 'sidebar',
29
+ widgetArgs: {
30
+ options: options ? options : defaultOptions,
31
+ },
32
+ };
6
33
  };
7
34
 
8
35
  export const rdfaDateInsertWidget: WidgetSpec = {
9
36
  componentName: 'rdfa-date-plugin/insert',
10
37
  desiredLocation: 'insertSidebar',
11
38
  };
39
+
40
+ export type DateFormat = {
41
+ label: string;
42
+ key: string;
43
+ dateFormat: string;
44
+ dateTimeFormat: string;
45
+ };
46
+
47
+ type DatePluginOptions = {
48
+ formats: DateFormat[];
49
+ allowCustomFormat: boolean;
50
+ };
@@ -0,0 +1,127 @@
1
+ import { NodeSpec } from '@lblod/ember-rdfa-editor';
2
+ import {
3
+ DCT,
4
+ EXT,
5
+ XSD,
6
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
7
+ import { hasRDFaAttribute } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
8
+ import { formatDate } from '../utils';
9
+
10
+ export type DateOptions = {
11
+ placeholder: {
12
+ insertDate: string;
13
+ insertDateTime: string;
14
+ };
15
+ };
16
+ const date: (options: DateOptions) => NodeSpec = (options) => {
17
+ return {
18
+ group: 'inline',
19
+ inline: true,
20
+ attrs: {
21
+ mappingResource: {
22
+ default: null,
23
+ },
24
+ value: {
25
+ default: null,
26
+ },
27
+ format: {
28
+ default: 'dd/mm/yyyy',
29
+ },
30
+ onlyDate: {
31
+ default: true,
32
+ },
33
+ },
34
+ selectable: true,
35
+ leafText: (node) => {
36
+ const { value, onlyDate, format } = node.attrs;
37
+ const humanReadableDate = value
38
+ ? formatDate(new Date(value), format)
39
+ : onlyDate
40
+ ? options.placeholder.insertDate
41
+ : options.placeholder.insertDateTime;
42
+ return humanReadableDate;
43
+ },
44
+ toDOM: (node) => {
45
+ const { value, onlyDate, format, mappingResource } = node.attrs;
46
+ const datatype = onlyDate ? XSD('date') : XSD('dateTime');
47
+ const humanReadableDate = value
48
+ ? formatDate(new Date(value), format)
49
+ : onlyDate
50
+ ? options.placeholder.insertDate
51
+ : options.placeholder.insertDateTime;
52
+ const dateAttrs = {
53
+ datatype: datatype.prefixed,
54
+ property: EXT('content').prefixed,
55
+ 'data-format': format as string,
56
+ ...(!!value && { content: value as string }),
57
+ };
58
+ if (mappingResource) {
59
+ return [
60
+ 'span',
61
+ {
62
+ resource: mappingResource as string,
63
+ typeof: EXT('Mapping').prefixed,
64
+ class: 'date',
65
+ },
66
+ ['span', { property: DCT('type').prefixed, content: 'date' }],
67
+ ['span', dateAttrs, humanReadableDate],
68
+ ];
69
+ } else {
70
+ return ['span', { class: 'date', ...dateAttrs }, humanReadableDate];
71
+ }
72
+ },
73
+ parseDOM: [
74
+ {
75
+ tag: 'span',
76
+ getAttrs: (node: HTMLElement) => {
77
+ if (
78
+ hasRDFaAttribute(node, 'datatype', XSD('date')) ||
79
+ hasRDFaAttribute(node, 'datatype', XSD('dateTime'))
80
+ ) {
81
+ const onlyDate = hasRDFaAttribute(node, 'datatype', XSD('date'));
82
+ return {
83
+ value: node.getAttribute('content'),
84
+ onlyDate,
85
+ format: node.dataset.format,
86
+ };
87
+ }
88
+ return false;
89
+ },
90
+ },
91
+ {
92
+ tag: 'span',
93
+ getAttrs: (node: HTMLElement) => {
94
+ if (hasRDFaAttribute(node, 'typeof', EXT('Mapping'))) {
95
+ const mappingResource = node.getAttribute('resource');
96
+ if (!mappingResource) {
97
+ return false;
98
+ }
99
+ const variableType = [...node.children]
100
+ .find((el) => hasRDFaAttribute(el, 'property', DCT('type')))
101
+ ?.getAttribute('content');
102
+ const datatype = [...node.children]
103
+ .find((el) => hasRDFaAttribute(el, 'property', EXT('content')))
104
+ ?.getAttribute('datatype');
105
+ if (variableType === 'date' && datatype) {
106
+ const onlyDate = !![...node.children].find((el) =>
107
+ hasRDFaAttribute(el, 'datatype', XSD('date'))
108
+ );
109
+ const dateNode = [...node.children].find((el) =>
110
+ hasRDFaAttribute(el, 'property', EXT('content'))
111
+ );
112
+ return {
113
+ mappingResource,
114
+ onlyDate,
115
+ value: dateNode?.getAttribute('content'),
116
+ format: dateNode?.getAttribute('data-format'),
117
+ };
118
+ }
119
+ }
120
+ return false;
121
+ },
122
+ },
123
+ ],
124
+ };
125
+ };
126
+
127
+ export default date;
@@ -0,0 +1 @@
1
+ export { default as date, DateOptions } from './date';
@@ -0,0 +1,10 @@
1
+ import { formatWithOptions } from 'date-fns/fp';
2
+ import { nlBE } from 'date-fns/locale';
3
+
4
+ export function formatDate(date: Date, format: string) {
5
+ try {
6
+ return formatWithOptions({ locale: nlBE }, format)(date);
7
+ } catch (e) {
8
+ return '';
9
+ }
10
+ }