@lblod/ember-rdfa-editor-lblod-plugins 3.0.0 → 4.0.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.0.2] - 2023-04-04
11
+
12
+ ### Fixed
13
+ - Prevent decision nodes regenerating when (de)serializing
14
+ - Ensure editor is focused after inserting a citation
15
+ - fix(citation): make plugin trigger correctly when `doc` is passed as an allowed nodeType
16
+
17
+ ### Added
18
+ - docs: add examples on how to enable the citation plugin for the entire document
19
+
20
+ ## [4.0.1] - 2023-03-27
21
+
22
+ ### Dependencies
23
+ - bump `ember-rdfa-editor` to v3.4.1
24
+
25
+ ## [4.0.0] - 2023-03-27
26
+
27
+ ### Fixed
28
+ - Ensure citation suggestions are only updated when search-text or document-legislation-type updates.
29
+
30
+ ### Changed
31
+ - Feature: make citation use the new link node
32
+ - BREAKING: citation mark has been removed
33
+ - Table of contents now is able to be inserted in the corresponding place instead of always being inserted at position 0
34
+ - Change paragraph symbol to §
35
+ - Update schema on dummy page to make articles insertable in empty document
36
+ - Add padding to structure card
37
+ - Placeholder text when inserting date
38
+
39
+ ### Removed:
40
+ - Removal of prosemirror-plugin dependency of `CitationPlugin::CitationInsert` component.
41
+
42
+ ### Dependencies
43
+ - bump `ember-rdfa-editor` to v3.4.0
44
+
45
+ ## [3.1.0] - 2023-03-02
46
+
47
+ ### Fixed
48
+ - Article paragraph numbering is no longer continuous
49
+ - Fixed white-space issue in variables
50
+ ### Changed
51
+ - Use `AuModalContainer` component instead of #ember-appuniversum-wormhole element in dummy app
52
+ - Improved documentation of the plugins
53
+
54
+ ### Dependencies
55
+ - bump `ember-rdfa-editor` to v3.3.0
56
+
10
57
  ## [3.0.0] - 2023-02-27
11
58
 
12
59
  ### Changed
@@ -344,7 +391,11 @@ add onclick handler to pencil icon in variable plugin
344
391
 
345
392
  # Changelog
346
393
 
347
- [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v3.0.0...HEAD
394
+ [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v4.0.2...HEAD
395
+ [4.0.2]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v4.0.1...v4.0.2
396
+ [4.0.1]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v4.0.0...v4.0.1
397
+ [4.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v3.1.0...v4.0.0
398
+ [3.1.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v3.0.0...v3.1.0
348
399
  [3.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.2...v3.0.0
349
400
  [2.1.2]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.1...v2.1.2
350
401
  [2.1.1]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.0...v2.1.1
package/README.md CHANGED
@@ -26,7 +26,6 @@ ember install ember-rdfa-editor-lblod-plugins
26
26
  This addon contains the following editor plugins:
27
27
  * besluit-type-plugin
28
28
  * citaten-plugin
29
- * generate-template-plugin
30
29
  * import-snippet-plugin
31
30
  * insert-variable-plugin
32
31
  * rdfa-date-plugin
@@ -35,40 +34,100 @@ This addon contains the following editor plugins:
35
34
  * table-of-contents-plugin
36
35
  * template-variable-plugin
37
36
 
38
- An array of plugin configurations can be passed to an instance of the ember-rdfa-editor in order to enable them.
39
- This is typically done in the following manner:
37
+ You can configure your editor like this:
40
38
  ```hbs
41
- <Rdfa::RdfaEditor
42
- class="au-c-rdfa-editor"
43
- @profile={{@profile}}
44
- @rdfaEditorInit={{this.rdfaEditorInit}}
45
- @editorOptions={{this.editorOptions}}
46
- @toolbarOptions={{this.toolbarOptions}}
39
+ <EditorContainer
40
+ @editorOptions={{hash
41
+ showRdfa='true'
42
+ showRdfaHighlight='true'
43
+ showRdfaHover='true'
44
+ showPaper='true'
45
+ showToolbarBottom=null
46
+ }}
47
+ @showRdfaBlocks={{this.controller.showRdfaBlocks}}
48
+ >
49
+ <:top>
50
+ {...}
51
+ </:top>
52
+ <:default>
53
+ <Editor
47
54
  @plugins={{this.plugins}}
48
- />
55
+ @schema={{this.schema}}
56
+ @nodeViews={{this.nodeViews}}
57
+ @rdfaEditorInit={{this.rdfaEditorInit}}/>
58
+ </:default>
59
+ <:aside>
60
+ {...}
61
+ </:aside>
62
+ </EditorContainer>
49
63
  ```
50
- Where `this.plugins` is an array of plugin configurations found in the backing class of the template shown above.
64
+ You will have 2 anchor points where to put your plugins: `top` for a toolbar, and `aside` for plugin cards.
65
+
51
66
 
52
67
  ## besluit-type-plugin
53
68
 
54
69
  Plugin which allows a user to change the type of a [besluit](https://data.vlaanderen.be/ns/besluit#Besluit).
55
70
 
56
- This plugin can be configured in the following manner:
57
-
58
- ```js
59
- this.plugins = ["besluit"];
71
+ This plugin needs to be added to the toolbar as a dropdown with the following syntax:
72
+ ```hbs
73
+ <BesluitTypePlugin::ToolbarDropdown @controller={{this.controller}}/>
60
74
  ```
75
+
61
76
  ## citaten-plugin
62
77
  Plugin which allows a user to insert references to a legal resource or legal expression into the document.
63
78
 
64
- This plugin can be configured in the following manner:
65
-
79
+ This plugin provides a card that needs to be added to the sidebar of the editor like
80
+ ```hbs
81
+ <CitationPlugin::CitationCard
82
+ @controller={{this.controller}}
83
+ @plugin={{this.citationPlugin}}
84
+ />
85
+ ```
86
+ Being this.citationPlugin a tracked reference to the plugin created with the function exported from the package and the wished configuration
66
87
  ```js
67
- this.plugins = ["citaten"];
88
+ import { citationPlugin } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
89
+
90
+ @tracked citationPlugin = citationPlugin({
91
+ type: 'nodes',
92
+ activeInNodeTypes(schema) {
93
+ return new Set([schema.nodes.motivering]);
94
+ },
95
+ });
68
96
  ```
69
97
 
98
+ Configuration:
99
+ - type: it can be 'nodes' or 'ranges' if nodes is selected you are expected to pass the `activeInNodeTypes` function, otherwise you should pass the `activeInRanges` function
100
+ - activeInNodeTypes: it's a function that gets the prosemirror schema and the state of the actual instance of the editor and returns a `Set` of nodetypes where the plugin should be active
101
+ - activeInRanges: it's a function that gets the state of the actual instance of the editor and returns an array of ranges for the plugin to be active in, for example `[[0,50], [70,100]]`
102
+ - regex: you can provide your custom regex to detect citations, if not the default one will be used
103
+
104
+
105
+ A common usecase is to have the plugin active in the entire document. Here's how to do that using each configuration type:
106
+
107
+ ```js
108
+ import { citationPlugin } from "@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin";
109
+
110
+ const configA = {
111
+ type: "nodes",
112
+ activeInNodeTypes(schema) {
113
+ // the root node of the document should always have the doc type
114
+ return new Set([schema.nodes.doc]);
115
+ }
116
+ };
117
+
118
+ const configB = {
119
+ type: "ranges",
120
+ activeInRanges(state) {
121
+ // a node's nodeSize follows the Prosemirror definition
122
+ // a non-leaf node's size is the sum of its children's sizes + 2
123
+ // so to get the last valid position "inside" a node, you need to subtract two from its nodeSize
124
+ // ref: https://prosemirror.net/docs/ref/#model.Node.nodeSize
125
+ return [[0, state.doc.nodeSize - 2]];
126
+ }
127
+ };
128
+ ```
70
129
  ### Using the plugin
71
- This plugin can be triggered by typing one of the following in the correct RDFa context (the [besluit:motivering](http://data.vlaanderen.be/ns/besluit#motivering) of a [besluit:Besluit](https://data.vlaanderen.be/ns/besluit#Besluit)).
130
+ If used with the example configuration provided this plugin can be triggered by typing one of the following in the correct RDFa context (the [besluit:motivering](http://data.vlaanderen.be/ns/besluit#motivering) of a [besluit:Besluit](https://data.vlaanderen.be/ns/besluit#Besluit)).
72
131
 
73
132
  * [specification]**decreet** [words to search for] *(e.g. "gemeentedecreet wijziging")*
74
133
  * **omzendbrief** [words to search for]
@@ -86,30 +145,12 @@ This plugin can be triggered by typing one of the following in the correct RDFa
86
145
 
87
146
  You should be able to add a reference manually by clicking on the `Insert` > `Insert reference` item in the Insert menu located on the top right of the editor. This will open the advanced search window. **Note** that this will only be avaliable in the proper context (see above in this section).
88
147
 
89
- ## generate-template-plugin
90
- Plugin which provides an editor command which replaces resource URIs in a document by a generic template URI containing `${generateUuid()}`. This allows for the generation of template documents. Template documents can be used by other applications, these other applications can create an instance of a template by replacing the `${generateUuid()}` keywords by real URIs.
91
-
92
- This plugin can be configured in the following manner:
93
-
94
- ```js
95
- this.plugins = ["generate-template"];
96
- ```
97
-
98
- The command can be used by executing:
99
-
100
- ```js
101
- controller.executeCommand('generateTemplate', controller);
102
- ```
103
-
104
- Where `controller` is an editor-controller.
105
-
106
148
  ## import-snippet-plugin
107
149
  Plugin allowing importing of external RDFA snippets and inserting it in the document.
108
150
 
109
- This plugin can be configured in the following manner:
110
-
111
- ```js
112
- this.plugins = ["import-snippet"];
151
+ The plugin has a card that needs to be added to the sidebar:
152
+ ```hbs
153
+ <ImportSnippetPlugin::Card @controller={{this.controller}}/>
113
154
  ```
114
155
 
115
156
  ### Using the plugin
@@ -134,68 +175,90 @@ When opening a new document, users will get the option to either include the sni
134
175
  ## insert-variable-plugin
135
176
  Plugin which allows users to insert variable placeholders into a document.
136
177
 
178
+ The plugin provides a card that needs to be attached to the editor sidebar like
179
+ ```hbs
180
+ <VariablePlugin::InsertVariableCard
181
+ @controller={{this.controller}}
182
+ @options={{this.config.variable}}
183
+ />
184
+ ```
185
+
137
186
  ### Configuring the plugin
138
187
 
139
- The plugin can be configured through the following optional attributes:
188
+ The plugin can be configured through the following optional attributes that can be added as a json to the options attribute of the card:
140
189
  - `publisher`: the URI of a specific codelist publisher which you can use if you want to filter the codelists by its publisher.
141
190
  - `defaultEndpoint`: The default endpoint where the codelists are fetched, this is also the variable that gets passed to the fetchSubtypes and template function
142
191
  - `variableTypes`: a custom list of variable types you want the plugin to use. This list can contain the following default variable types: `text`, `number`,`date`,`location` and `codelist`. Additionally this list can also contain custom variable types, configured by the following three sub-attributes:
143
192
  * `label`: the label of the custom variable type
144
193
  * `fetchSubTypes` (optional): a function which returns a list of possible variable values. The function takes two optional arguments: an `endpoint` and a `publisher`.
145
- * `template`: function which returns an html template which should be resolved and inserted when inserting a variable of the custom variable type. The function takes two arguments: an `endpoint` and a `selectedVariableValue`.
194
+ * `constructor`: function which returns a prosemirror node to be inserted, the function takes three arguments, the prosemirror `schema`, the `endpoint` and the `selectedSubtype` if you are using subtypes.
146
195
 
147
196
  #### Example
148
197
 
149
198
  ```js
150
199
  {
151
- name:'insert-variable',
152
- options: {
153
- publisher: 'http://data.lblod.info/id/bestuurseenheden/141d9d6b-54af-4d17-b313-8d1c30bc3f5b',
154
- defaultEndpoint: 'https://dev.roadsigns.lblod.info/sparql',
155
- variableTypes: [
156
- 'text',
157
- 'number',
158
- 'date',
159
- 'location',
160
- 'codelist',
200
+ publisher: 'http://data.lblod.info/id/bestuurseenheden/141d9d6b-54af-4d17-b313-8d1c30bc3f5b',
201
+ defaultEndpoint: 'https://dev.roadsigns.lblod.info/sparql',
202
+ variableTypes: [
203
+ 'text',
204
+ 'number',
205
+ 'date',
206
+ 'location',
207
+ 'codelist',
208
+ {
209
+ label: 'Simple Variable',
210
+ constructor: (schema) => {
211
+ const mappingURI = `http://data.lblod.info/mappings/${uuidv4()}`;
212
+ const variableInstance = `http://data.lblod.info/variables/${uuidv4()}`;
213
+ return schema.node(
214
+ 'variable',
161
215
  {
162
- label: 'Simple Variable',
163
- template: `
164
- <span property="ext:content" datatype="ext:myNewType">
165
- <span class="mark-highlight-manual">\${Simple variable}</span>
166
- </span>
167
- `,
216
+ mappingResource: mappingURI,
217
+ variableInstance,
218
+ type: 'Simple Variable',
168
219
  },
220
+ schema.node('placeholder', { placeholderText: 'text' })
221
+ );
222
+ },
223
+ },
224
+ {
225
+ label: 'Complex Variable',
226
+ fetchSubtypes: async (endpoint, publisher) => {
227
+ const subtypes = [
169
228
  {
170
- label: 'Complex Variable',
171
- fetchSubtypes: async (endpoint, publisher) => {
172
- const codelists = [
173
- {
174
- uri: '1',
175
- label: '1',
176
- },
177
- {
178
- uri: '2',
179
- label: '2',
180
- },
181
- {
182
- uri: '3',
183
- label: '3',
184
- },
185
- ];
186
- return codelists;
187
- },
188
- template: (endpoint, selectedCodelist) => `
189
- <span property="ext:codelist" resource="${selectedCodelist.uri}"></span>
190
- <span property="dct:type" content="location"></span>
191
- <span property="dct:source" resource="${endpoint}"></span>
192
- <span property="ext:content" datatype="xsd:date">
193
- <span class="mark-highlight-manual">\${${selectedCodelist.label}}</span>
194
- </span>
195
- `,
229
+ uri: '1',
230
+ label: '1',
196
231
  },
197
- ],
198
- }
232
+ {
233
+ uri: '2',
234
+ label: '2',
235
+ },
236
+ {
237
+ uri: '3',
238
+ label: '3',
239
+ },
240
+ ];
241
+ return subtypes;
242
+ },
243
+ constructor: (schema, endpoint, selectedSubtype) => {
244
+ const mappingURI = `http://data.lblod.info/mappings/${uuidv4()}`;
245
+ const variableInstance = `http://data.lblod.info/variables/${uuidv4()}`;
246
+ return schema.node(
247
+ 'variable',
248
+ {
249
+ type: 'Complex Variable',
250
+ mappingResource: mappingURI,
251
+ subTypeResource: selectedSubtype?.uri,
252
+ variableInstance,
253
+ source: endpoint,
254
+ },
255
+ schema.node('placeholder', {
256
+ placeholderText: selectedSubtype?.label ?? '',
257
+ })
258
+ );
259
+ }
260
+ },
261
+ ],
199
262
  }
200
263
  ```
201
264
  ### Using the plugin
@@ -206,21 +269,39 @@ When the insert-variable-plugin is enabled, users will have the option to insert
206
269
  ## rdfa-date-plugin
207
270
  Plugin to insert and modify semantic dates and timestamps in an editor document.
208
271
 
209
- This plugin can be configured in the following manner:
272
+ This plugin provides a card to modify dates that needs to be added to the editor sidebar like
210
273
 
211
- ```js
212
- this.plugins = ["rdfa-date"];
274
+ ```hbs
275
+ <RdfaDatePlugin::Card
276
+ @controller={{this.controller}}
277
+ @options={{this.config.date}}/>
213
278
  ```
214
279
 
280
+ And a insert button to insert new dates that needs to be added to the insert part of the sidebar:
281
+ ```hbs
282
+ <RdfaDatePlugin::Insert
283
+ @controller={{this.controller}}
284
+ @options={{this.config.date}}
285
+ />
286
+ ```
215
287
 
288
+ You will also need to add the date node with the following configuration (being the insertDate and insertDateTime the placeholder strings):
289
+ ```js
290
+ date: date({
291
+ placeholder: {
292
+ insertDate: this.intl.t('date-plugin.insert.date'),
293
+ insertDateTime: this.intl.t('date-plugin.insert.datetime'),
294
+ },
295
+ }),
296
+ ```
216
297
 
217
298
  ## roadsign-regulation-plugin
218
299
  A plugin that fetches data from the mow regulation and roadsign registry and allows users to insert roadsign regulations inside an editor document.
219
300
 
220
- This plugin can be configured in the following manner:
301
+ This plugin provides a card that needs to be added to the editor sidebar like:
221
302
 
222
- ```js
223
- this.plugins = ["roadsign-regulation"];
303
+ ```hbs
304
+ <RoadsignRegulationPlugin::RoadsignRegulationCard @controller={{this.controller}}/>
224
305
  ```
225
306
 
226
307
  The default endpoint the plugin will query is https://roadsigns.lblod.info/sparql . This can be overwritten by setting `roadsignRegulationPlugin.endpoint` in your `config/environment.js`.
@@ -228,10 +309,9 @@ The default endpoint the plugin will query is https://roadsigns.lblod.info/sparq
228
309
  ## standard-template-plugin
229
310
  Plugin which allows users to insert standard templates in the editor. Depending on the position of the cursor or selected text, a dropdown will appear in the toolbar of the editor that lets you insert a template for the proper context at the location of the cursor.
230
311
 
231
- This plugin can be configured in the following manner:
232
-
233
- ```js
234
- this.plugins = ["standard-template"];
312
+ In order to use this plugin you will need to add its card:
313
+ ```hbs
314
+ <StandardTemplatePlugin::Card @controller={{this.controller}}/>
235
315
  ```
236
316
 
237
317
  ### Template resource used by the plugin
@@ -246,72 +326,59 @@ When creating a template in your database, the following properties are used by
246
326
 
247
327
  ### Using the plugin
248
328
 
249
-
250
329
  The plugin will search for RDFa contexts in the content of the editor and the editor itself. Based on the contexts, the plugin will show possible templates to be added at the location of the cursor. E.g. if an element in the editor has the `typeof="besluit:BehandelingVanAgendapunt"` attribute, the plugin will show the templates related to [`besluit:BehandelingVanAgendapunt`](http://data.vlaanderen.be/ns/besluit#BehandelingVanAgendapunt) in the dropdown menu. This attribute can be set on an element in the content of the editor or predefined in the editor itself.
251
330
 
252
331
  ## table-of-contents-plugin
253
332
 
254
333
  Plugin implementing an auto-refreshing table of contents using an ember-rdfa-editor inline component.
255
334
 
256
- In order to enable the plugin you need to add `table-of-contents` to the list of plugins passed to the rdfa-editor. You can configure the plugin with a custom table of contents configuration.
257
- ### Configuring the plugin with a custom config
335
+ In order to enable the plugin you need to add the table of contents button to the toolbar and the table of contents node view to the list of editor node views.
336
+ ```hbs
337
+ <TableOfContentsPlugin::ToolbarButton @controller={{this.editor}}/>
338
+ ```
258
339
 
259
- ```js
260
- this.plugins = [
261
- { name: 'table-of-contents',
262
- options: {
263
- config: {
264
- sectionPredicate: 'https://say.data.gift/ns/hasPart',
265
- value: {
266
- predicate: 'https://say.data.gift/ns/heading',
267
- },
268
- },
269
- {
270
- sectionPredicate: 'https://say.data.gift/ns/hasParagraph',
271
- value: '§',
272
- },
273
- }
274
- },
275
- ]
340
+ ```
341
+ tableOfContentsView(this.config.tableOfContents)(controller),
276
342
  ```
277
343
 
278
- You can insert an instance of a table of contents using the `insert-component` command:
344
+
345
+ ### Configuring the plugin with a custom config
346
+
347
+ You can configure the nodeview with the hiearchy of the nodes
279
348
 
280
349
  ```js
281
- controller.executeCommand(
282
- 'insert-component',
283
- 'table-of-contents-plugin/inline-components/table-of-contents',
284
- {
285
- config: [
286
- {
287
- sectionPredicate: 'https://say.data.gift/ns/hasPart',
288
- value: {
289
- predicate: 'https://say.data.gift/ns/heading',
290
- },
291
- },
292
- {
293
- sectionPredicate: 'https://say.data.gift/ns/hasParagraph',
294
- value: '§',
295
- },
296
- ],
297
- },
298
- {},
299
- false
300
- );
350
+ {
351
+ nodeHierarchy: [
352
+ 'title|chapter|section|subsection|article',
353
+ 'structure_header|article_header',
354
+ ],
355
+ },
301
356
  ```
357
+
358
+
302
359
  ## template-variable-plugin
303
360
 
304
361
  Editor plugin which allows you to interact with placeholders created by the insert-variable-plugin.
305
362
 
306
- ### Configuring the plugin
363
+ For enabling it, you need to add the card provided by the plugin to the editor sidebar
364
+ ```hbs
365
+ <VariablePlugin::TemplateVariableCard @controller={{this.controller}}/>
366
+ ```
307
367
 
308
- You can enable the plugin by adding it to the list of plugins:
368
+ You will also need to add the variable node to the list of nodes of your prosemirror schema and the variable view to the list of nodeviews like `variable: variableView(controller)` imported from:
309
369
 
310
370
  ```js
311
- this.plugins = ['template-variable'];
371
+ import {
372
+ variable,
373
+ variableView,
374
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/nodes';
375
+
312
376
  ```
313
377
 
314
- Additionally, you can configure the plugin in your `environment.js` file:
378
+ ### Configuring the plugin
379
+
380
+
381
+ You can configure the plugin in your `environment.js` file:
315
382
 
316
383
  ```js
317
384
  templateVariablePlugin: {
@@ -27,10 +27,13 @@
27
27
  </Item>
28
28
  <Item>
29
29
  {{#unless this.currentStructureType.noUnwrap}}
30
- <AuToggleSwitch
31
- @label={{t "article-structure-plugin.remove.content"}}
32
- @checked={{this.removeStructureContent}}
33
- @onChange={{this.setRemoveStructureContent}}/>
30
+ <div class="au-u-padding-tiny">
31
+ <AuToggleSwitch
32
+ @label={{t "article-structure-plugin.remove.content"}}
33
+ @checked={{this.removeStructureContent}}
34
+ @onChange={{this.setRemoveStructureContent}}
35
+ />
36
+ </div>
34
37
  {{/unless}}
35
38
  <AuButton
36
39
  @icon="bin"
@@ -11,6 +11,10 @@
11
11
  this.documentText
12
12
  this.documentLegislationType
13
13
  }}
14
+ {{did-update
15
+ this.update
16
+ this.activeDecoration
17
+ }}
14
18
  as |c|
15
19
  >
16
20
  <c.header>
@@ -42,6 +42,21 @@ export default class CitationCardComponent extends Component<Args> {
42
42
  @tracked decision: Decision | null = null;
43
43
  @tracked cardText: string | null = null;
44
44
  @tracked cardLegislationType: string | null = null;
45
+ @tracked documentLegislationType: Option<string>;
46
+ @tracked documentText: Option<string>;
47
+
48
+ @action
49
+ update() {
50
+ if (this.activeDecoration) {
51
+ const { legislationTypeUri, searchText } = this.activeDecoration?.spec;
52
+ if (legislationTypeUri !== this.documentLegislationType) {
53
+ this.documentLegislationType = legislationTypeUri;
54
+ }
55
+ if (searchText !== this.documentText) {
56
+ this.documentText = searchText;
57
+ }
58
+ }
59
+ }
45
60
 
46
61
  get controller(): SayController {
47
62
  return this.args.controller;
@@ -64,14 +79,6 @@ export default class CitationCardComponent extends Component<Args> {
64
79
  return this.decorations?.find(from, to)[0];
65
80
  }
66
81
 
67
- get documentLegislationType(): Option<string> {
68
- return this.activeDecoration?.spec.legislationTypeUri;
69
- }
70
-
71
- get documentText(): Option<string> {
72
- return this.activeDecoration?.spec.searchText;
73
- }
74
-
75
82
  get searchText(): string {
76
83
  return (this.cardText ?? this.documentText) || '';
77
84
  }
@@ -195,6 +202,7 @@ export default class CitationCardComponent extends Component<Args> {
195
202
  .scrollIntoView(),
196
203
  { view: this.controller.mainEditorView }
197
204
  );
205
+ this.controller.focus();
198
206
  }
199
207
 
200
208
  @action
@@ -12,10 +12,7 @@ import {
12
12
  Decision,
13
13
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/vlaamse-codex';
14
14
  import { citedText } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/cited-text';
15
- import {
16
- CitationPlugin,
17
- CitationPluginConfig,
18
- } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
15
+ import { CitationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
19
16
  import {
20
17
  LEGISLATION_TYPE_CONCEPTS,
21
18
  LEGISLATION_TYPES,
@@ -25,7 +22,6 @@ import { findParentNodeOfType } from '@curvenote/prosemirror-utils';
25
22
 
26
23
  interface Args {
27
24
  controller: SayController;
28
- plugin: CitationPlugin;
29
25
  config: CitationPluginConfig;
30
26
  }
31
27
 
@@ -80,18 +76,16 @@ export default class EditorPluginsCitationInsertComponent extends Component<Args
80
76
  this.controller.schema,
81
77
  this.controller.mainEditorState
82
78
  );
79
+ // if the doc node is included, the button should always be active
80
+ // the findParentNodeOfType util we import does NOT consider the doc node
81
+ // in its search.
82
+ if (nodeTypes.has(this.controller.schema.nodes.doc)) {
83
+ return false;
84
+ }
83
85
  return !findParentNodeOfType([...nodeTypes])(selection);
84
86
  }
85
87
  }
86
88
 
87
- get plugin() {
88
- return this.args.plugin;
89
- }
90
-
91
- get activeRanges() {
92
- return this.plugin.getState(this.controller.mainEditorState)?.activeRanges;
93
- }
94
-
95
89
  get controller() {
96
90
  return this.args.controller;
97
91
  }
@@ -157,8 +157,8 @@ export default class RdfaDatePluginCardComponent extends Component<Args> {
157
157
  return null;
158
158
  }
159
159
 
160
- get pickerDate(): Date {
161
- return this.documentDate ?? new Date();
160
+ get pickerDate(): Option<Date> {
161
+ return this.documentDate;
162
162
  }
163
163
 
164
164
  @action
@@ -38,12 +38,43 @@ export default class TableOfContentsCardComponent extends Component<Args> {
38
38
  );
39
39
  } else {
40
40
  const { schema } = this.controller;
41
- this.controller.withTransaction(
42
- (tr) => {
43
- return tr.replaceRangeWith(0, 0, schema.node('table_of_contents'));
44
- },
45
- { view: this.controller.mainEditorView }
46
- );
41
+ const state = this.controller.activeEditorState;
42
+ let replacePosition: number | undefined = undefined;
43
+ state.doc.descendants((node, pos, parent, index) => {
44
+ if (
45
+ replacePosition === undefined &&
46
+ state.doc.canReplaceWith(
47
+ index,
48
+ index,
49
+ schema.nodes['table_of_contents']
50
+ )
51
+ ) {
52
+ replacePosition = pos;
53
+ } else if (
54
+ index === state.doc.childCount - 1 &&
55
+ replacePosition === undefined &&
56
+ state.doc.canReplaceWith(
57
+ index + 1,
58
+ index + 1,
59
+ schema.nodes['table_of_contents']
60
+ )
61
+ ) {
62
+ replacePosition = pos + node.nodeSize;
63
+ }
64
+ return false;
65
+ });
66
+ if (replacePosition !== undefined) {
67
+ this.controller.withTransaction(
68
+ (transaction) => {
69
+ return transaction.replaceWith(
70
+ replacePosition as number,
71
+ replacePosition as number,
72
+ schema.node('table_of_contents')
73
+ );
74
+ },
75
+ { view: this.controller.mainEditorView }
76
+ );
77
+ }
47
78
  }
48
79
  }
49
80
  }
@@ -1,8 +1,16 @@
1
1
  {{#if this.showCard}}
2
- <AuCard @flex={{true}} @divided={{true}} @isOpenInitially={{true}} @expandable={{true}} @shadow={{true}} @size="small" as |c|>
2
+ <AuCard
3
+ @flex={{true}}
4
+ @divided={{true}}
5
+ @isOpenInitially={{true}}
6
+ @expandable={{true}}
7
+ @shadow={{true}}
8
+ @size='small'
9
+ as |c|
10
+ >
3
11
  <c.header>
4
- <AuHeading @level="3" @skin="6">
5
- {{t "variable-plugin.insert-variable"}}
12
+ <AuHeading @level='3' @skin='6'>
13
+ {{t 'variable-plugin.insert-variable'}}
6
14
  </AuHeading>
7
15
  </c.header>
8
16
  <c.content>
@@ -11,7 +19,8 @@
11
19
  @searchEnabled={{false}}
12
20
  @options={{this.variablesArray}}
13
21
  @selected={{this.selectedVariable}}
14
- @onChange={{this.updateSelectedVariable}} as |variable|
22
+ @onChange={{this.updateSelectedVariable}}
23
+ as |variable|
15
24
  >
16
25
  {{variable.label}}
17
26
  </PowerSelect>
@@ -21,14 +30,19 @@
21
30
  @searchEnabled={{false}}
22
31
  @options={{this.subtypes}}
23
32
  @selected={{this.selectedSubtype}}
24
- @onChange={{this.updateSubtype}} as |subtype|
33
+ @onChange={{this.updateSubtype}}
34
+ as |subtype|
25
35
  >
26
36
  {{subtype.label}}
27
37
  </PowerSelect>
28
38
  {{/if}}
29
- <AuButton {{on 'click' this.insert}} @disabled={{or (not this.selectedVariable)
30
- (and this.hasSubtype (not this.selectedSubtype))}}>{{t
31
- "variable-plugin.button"}}</AuButton>
39
+ <AuButton
40
+ {{on 'click' this.insert}}
41
+ @disabled={{or
42
+ (not this.selectedVariable)
43
+ (and this.hasSubtype (not this.selectedSubtype))
44
+ }}
45
+ >{{t 'variable-plugin.button'}}</AuButton>
32
46
  </c.content>
33
47
  </AuCard>
34
- {{/if}}
48
+ {{/if}}
@@ -22,7 +22,7 @@ export const articleParagraphSpec: StructureSpec = {
22
22
  },
23
23
  remove: 'article-structure-plugin.remove.paragraph',
24
24
  },
25
- continuous: true,
25
+ continuous: false,
26
26
  noUnwrap: true,
27
27
  constructor: ({ schema, number, intl }) => {
28
28
  const numberConverted = number?.toString() ?? '1';
@@ -76,7 +76,7 @@ export const article_paragraph: NodeSpec = {
76
76
  typeof: node.attrs.typeof as string,
77
77
  resource: node.attrs.resource as string,
78
78
  },
79
- ['span', { contenteditable: false }, '$'],
79
+ ['span', { contenteditable: false }, '§'],
80
80
  [
81
81
  'span',
82
82
  {
@@ -7,12 +7,14 @@ import {
7
7
  NodeType,
8
8
  PNode,
9
9
  ProsePlugin,
10
+ ResolvedPos,
10
11
  Schema,
11
12
  } from '@lblod/ember-rdfa-editor';
12
13
  import processMatch, {
13
14
  RegexpMatchArrayWithIndices,
14
15
  } from './utils/process-match';
15
16
  import { changedDescendants } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/changed-descendants';
17
+ import { findParentNodeOfTypeClosestToPos } from '@curvenote/prosemirror-utils';
16
18
 
17
19
  const BASIC_MULTIPLANE_CHARACTER = '\u0021-\uFFFF'; // most of the characters used around the world
18
20
 
@@ -206,6 +208,7 @@ function calculateDecorationsInNodes(
206
208
  decsToAdd,
207
209
  schema,
208
210
  config.regex,
211
+ newDoc,
209
212
  decsToRemove,
210
213
  oldDecorations
211
214
  );
@@ -254,7 +257,12 @@ function calculateDecorationsInRanges(
254
257
  activeRanges: [number, number][]
255
258
  ): { decorations: DecorationSet; activeRanges: [number, number][] } {
256
259
  const decorationsToAdd: Decoration[] = [];
257
- const collector = collectDecorations(decorationsToAdd, schema, config.regex);
260
+ const collector = collectDecorations(
261
+ decorationsToAdd,
262
+ schema,
263
+ config.regex,
264
+ doc
265
+ );
258
266
 
259
267
  for (const [start, end] of activeRanges) {
260
268
  doc.nodesBetween(start, end, collector);
@@ -269,15 +277,17 @@ function collectDecorations(
269
277
  decsToAdd: Decoration[],
270
278
  schema: CitationSchema,
271
279
  regex: RegExp = CITATION_REGEX,
280
+ doc: PNode,
272
281
  decsToRemove?: Decoration[],
273
282
  oldDecs?: DecorationSet
274
283
  ) {
275
284
  return function (node: PNode, pos: number): boolean {
276
- if (
277
- node.isText &&
278
- node.text &&
279
- !schema.marks.citation.isInSet(node.marks)
280
- ) {
285
+ const resolvedPos: ResolvedPos = doc.resolve(pos);
286
+ const link = findParentNodeOfTypeClosestToPos(
287
+ resolvedPos,
288
+ schema.nodes.link
289
+ );
290
+ if (node.isText && node.text && !link) {
281
291
  if (decsToRemove && oldDecs) {
282
292
  decsToRemove.push(
283
293
  ...oldDecs.find(
@@ -8,12 +8,13 @@ export function citedText(
8
8
  title: string,
9
9
  uri: string
10
10
  ): PNode {
11
- return schema.text(title, [
12
- unwrap(schema.marks.citation).create({
11
+ return unwrap(schema.nodes.link).create(
12
+ {
13
13
  href: uri,
14
14
  property: 'eli:cites',
15
15
  typeof: 'eli:LegalExpression',
16
16
  __rdfaId: uuid(),
17
- }),
18
- ]);
17
+ },
18
+ [schema.text(title)]
19
+ );
19
20
  }
@@ -127,14 +127,12 @@ export const article_container: NodeSpec = {
127
127
  {
128
128
  tag: 'div',
129
129
  getAttrs(element: HTMLElement) {
130
- if (
131
- hasRDFaAttribute(element, 'property', PROV('value')) &&
132
- hasRDFaAttribute(element, 'typeof', BESLUIT('Besluit'))
133
- ) {
130
+ if (hasRDFaAttribute(element, 'property', PROV('value'))) {
134
131
  return getRdfaAttrs(element);
135
132
  }
136
133
  return false;
137
134
  },
135
+ context: 'besluit/',
138
136
  },
139
137
  ],
140
138
  };
@@ -279,6 +277,7 @@ export const besluit_article_header: NodeSpec = {
279
277
  };
280
278
 
281
279
  export const besluit_article_content: NodeSpec = {
280
+ group: 'block',
282
281
  content: 'block+',
283
282
  inline: false,
284
283
  attrs: {
@@ -302,6 +301,7 @@ export const besluit_article_content: NodeSpec = {
302
301
  }
303
302
  return false;
304
303
  },
304
+ context: 'besluit_article//',
305
305
  },
306
306
  ],
307
307
  };
@@ -57,6 +57,7 @@ export const DEFAULT_VARIABLE_TYPES: Record<string, VariableType> = {
57
57
  return unwrap(
58
58
  schema.nodes.date.createAndFill({
59
59
  mappingResource: `http://data.lblod.info/mappings/${uuidv4()}`,
60
+ value: null,
60
61
  })
61
62
  );
62
63
  },
@@ -46,7 +46,7 @@
46
46
  .ember-node {
47
47
  .variable {
48
48
  [contenteditable] {
49
- white-space: pre-wrap;
49
+ white-space: break-spaces;
50
50
  word-break: break-all;
51
51
  word-wrap: break-word;
52
52
  outline: 0px;
@@ -18,13 +18,14 @@ export default class CitationCardComponent extends Component<Args> {
18
18
  decision: Decision | null;
19
19
  cardText: string | null;
20
20
  cardLegislationType: string | null;
21
+ documentLegislationType: Option<string>;
22
+ documentText: Option<string>;
23
+ update(): void;
21
24
  get controller(): SayController;
22
25
  get showCard(): false | Option<CitationDecoration>;
23
26
  get plugin(): CitationPlugin;
24
27
  get decorations(): import("prosemirror-view").DecorationSet | undefined;
25
28
  get activeDecoration(): Option<CitationDecoration>;
26
- get documentLegislationType(): Option<string>;
27
- get documentText(): Option<string>;
28
29
  get searchText(): string;
29
30
  get legislationTypes(): string[];
30
31
  get selectedLegislationType(): {
@@ -1,10 +1,9 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { SayController } from '@lblod/ember-rdfa-editor';
3
3
  import { Article, Decision } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/vlaamse-codex';
4
- import { CitationPlugin, CitationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
4
+ import { CitationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
5
5
  interface Args {
6
6
  controller: SayController;
7
- plugin: CitationPlugin;
8
7
  config: CitationPluginConfig;
9
8
  }
10
9
  export default class EditorPluginsCitationInsertComponent extends Component<Args> {
@@ -20,8 +19,6 @@ export default class EditorPluginsCitationInsertComponent extends Component<Args
20
19
  };
21
20
  selectLegislationType(type: string): void;
22
21
  get disableInsert(): boolean;
23
- get plugin(): CitationPlugin;
24
- get activeRanges(): [number, number][] | undefined;
25
22
  get controller(): SayController;
26
23
  openModal(): void;
27
24
  closeModal(): void;
@@ -28,7 +28,7 @@ export default class RdfaDatePluginCardComponent extends Component<Args> {
28
28
  get dateFormatType(): string;
29
29
  get customDateFormatError(): ValidationError | null;
30
30
  get humanError(): string | null;
31
- get pickerDate(): Date;
31
+ get pickerDate(): Option<Date>;
32
32
  showTooltip(): void;
33
33
  hideTooltip(): void;
34
34
  changeDate(date: Date): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lblod/ember-rdfa-editor-lblod-plugins",
3
- "version": "3.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "Ember addon providing lblod specific plugins for the ember-rdfa-editor",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -63,7 +63,7 @@
63
63
  "@embroider/test-setup": "^1.8.3",
64
64
  "@glimmer/component": "^1.1.2",
65
65
  "@glimmer/tracking": "^1.1.2",
66
- "@lblod/ember-rdfa-editor": "^3.2.0",
66
+ "@lblod/ember-rdfa-editor": "^3.4.1",
67
67
  "@rdfjs/types": "^1.1.0",
68
68
  "@release-it/keep-a-changelog": "^3.1.0",
69
69
  "@tsconfig/ember": "^1.0.1",
@@ -143,7 +143,7 @@
143
143
  },
144
144
  "peerDependencies": {
145
145
  "@appuniversum/ember-appuniversum": "^2.4.2",
146
- "@lblod/ember-rdfa-editor": "^3.2.0",
146
+ "@lblod/ember-rdfa-editor": "^3.4.1",
147
147
  "ember-concurrency": "^2.3.7"
148
148
  },
149
149
  "engines": {
@@ -1,27 +0,0 @@
1
- import { getRdfaAttrs, MarkSpec, rdfaAttrs } from '@lblod/ember-rdfa-editor';
2
-
3
- export const citation: MarkSpec = {
4
- attrs: { test: { default: 'yeet' }, ...rdfaAttrs },
5
- inclusive: false,
6
- group: 'linkmarks',
7
- excludes: 'linkmarks',
8
- parseDOM: [
9
- {
10
- tag: 'a[href]',
11
- getAttrs(dom) {
12
- if (typeof dom === 'string') {
13
- return false;
14
- }
15
- const type = dom.attributes.getNamedItem('typeof')?.value;
16
- const property = dom.attributes.getNamedItem('property')?.value;
17
- if (type === 'eli:LegalExpression' && property === 'eli:cites') {
18
- return getRdfaAttrs(dom);
19
- }
20
- return false;
21
- },
22
- },
23
- ],
24
- toDOM(node) {
25
- return ['a', { ...node.attrs, class: 'annotation' }, 0];
26
- },
27
- };
@@ -1,2 +0,0 @@
1
- import { MarkSpec } from '@lblod/ember-rdfa-editor';
2
- export declare const citation: MarkSpec;