@lblod/ember-rdfa-editor-lblod-plugins 22.3.0 → 22.4.0-dev.488ef3259e12430c4bb92a2ce203e9d15a5c84d2
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/.changeset/mean-deers-call.md +5 -0
- package/CHANGELOG.md +10 -0
- package/addon/components/decision-plugin/insert-article.gts +57 -7
- package/addon/components/variable-plugin/autofilled/insert.hbs +32 -0
- package/addon/components/variable-plugin/autofilled/insert.ts +105 -0
- package/addon/components/variable-plugin/autofilled/nodeview.hbs +25 -0
- package/addon/components/variable-plugin/autofilled/nodeview.ts +49 -0
- package/addon/plugins/location-plugin/utils/geo-helpers.ts +5 -5
- package/addon/plugins/variable-plugin/plugins/autofiller.ts +88 -0
- package/addon/plugins/variable-plugin/utils/address-helpers.ts +4 -4
- package/addon/plugins/variable-plugin/variables/autofilled.ts +162 -0
- package/addon/plugins/variable-plugin/variables/index.ts +1 -0
- package/app/components/variable-plugin/autofilled/insert.js +1 -0
- package/app/components/variable-plugin/autofilled/nodeview.js +1 -0
- package/declarations/addon/components/decision-plugin/insert-article.d.ts +12 -2
- package/declarations/addon/components/variable-plugin/autofilled/insert.d.ts +20 -0
- package/declarations/addon/components/variable-plugin/autofilled/nodeview.d.ts +11 -0
- package/declarations/addon/plugins/variable-plugin/plugins/autofiller.d.ts +8 -0
- package/declarations/addon/plugins/variable-plugin/variables/autofilled.d.ts +2 -0
- package/declarations/addon/plugins/variable-plugin/variables/index.d.ts +1 -0
- package/package.json +1 -1
- package/translations/en-US.yaml +4 -0
- package/translations/nl-BE.yaml +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @lblod/ember-rdfa-editor-lblod-plugins
|
|
2
2
|
|
|
3
|
+
## 22.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#471](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/471) [`8132a55`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/8132a550124cf90b47c3d1c759ce43bd9f72cfab) Thanks [@elpoelma](https://github.com/elpoelma)! - Introduce opt-in option to `insert-article` component to allow for inserting decision articles everywhere in a document (not just to the article-container of a decision). Useful when e.g. creating snippets.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#470](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/470) [`fdfd8b8`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/fdfd8b80c58adc07e968d131dce7618b57b27e49) Thanks [@piemonkey](https://github.com/piemonkey)! - Correct CRS URI used in location plugin to correctly use http: instead of https:
|
|
12
|
+
|
|
3
13
|
## 22.3.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
|
@@ -3,36 +3,69 @@ import { on } from '@ember/modifier';
|
|
|
3
3
|
import { action } from '@ember/object';
|
|
4
4
|
import Component from '@glimmer/component';
|
|
5
5
|
import { AddIcon } from '@appuniversum/ember-appuniversum/components/icons/add';
|
|
6
|
-
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
6
|
+
import { PNode, SayController } from '@lblod/ember-rdfa-editor';
|
|
7
7
|
import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
|
|
8
8
|
import insertArticle from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/decision-plugin/commands/insert-article-command';
|
|
9
9
|
import { buildArticleStructure } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/decision-plugin/utils/build-article-structure';
|
|
10
|
-
import t from 'ember-intl/helpers/t';
|
|
11
10
|
import { not } from 'ember-truth-helpers';
|
|
11
|
+
import { service } from '@ember/service';
|
|
12
|
+
import IntlService from 'ember-intl/services/intl';
|
|
13
|
+
import { recalculateNumbers } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/structure-plugin/recalculate-structure-numbers';
|
|
14
|
+
import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
|
|
12
15
|
|
|
13
16
|
export interface InsertArticleOptions {
|
|
14
17
|
uriGenerator?: () => string;
|
|
18
|
+
insertFreely?: boolean;
|
|
15
19
|
}
|
|
16
20
|
interface Sig {
|
|
17
|
-
Args: {
|
|
21
|
+
Args: {
|
|
22
|
+
controller: SayController;
|
|
23
|
+
label: string;
|
|
24
|
+
options?: InsertArticleOptions;
|
|
25
|
+
};
|
|
18
26
|
}
|
|
19
27
|
export default class InsertArticleComponent extends Component<Sig> {
|
|
28
|
+
@service declare intl: IntlService;
|
|
29
|
+
|
|
20
30
|
get controller() {
|
|
21
31
|
return this.args.controller;
|
|
22
32
|
}
|
|
23
33
|
|
|
34
|
+
get options() {
|
|
35
|
+
return this.args.options;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get label() {
|
|
39
|
+
return this.args.label ?? this.intl.t('besluit-plugin.insert.article');
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
get schema() {
|
|
25
43
|
return this.controller.schema;
|
|
26
44
|
}
|
|
45
|
+
|
|
27
46
|
get decisionRange() {
|
|
28
47
|
return getCurrentBesluitRange(this.controller);
|
|
29
48
|
}
|
|
49
|
+
|
|
30
50
|
get decisionLocation() {
|
|
31
51
|
return this.decisionRange
|
|
32
52
|
? { pos: this.decisionRange.from, node: this.decisionRange.node }
|
|
33
53
|
: null;
|
|
34
54
|
}
|
|
55
|
+
|
|
35
56
|
get canInsert() {
|
|
57
|
+
if (this.options?.insertFreely) {
|
|
58
|
+
return this.canInsertFreely;
|
|
59
|
+
} else {
|
|
60
|
+
return this.canInsertInDecision;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get canInsertFreely() {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get canInsertInDecision() {
|
|
36
69
|
if (!this.decisionLocation) {
|
|
37
70
|
return false;
|
|
38
71
|
}
|
|
@@ -51,15 +84,32 @@ export default class InsertArticleComponent extends Component<Sig> {
|
|
|
51
84
|
this.schema,
|
|
52
85
|
this.args.options?.uriGenerator,
|
|
53
86
|
);
|
|
54
|
-
if (
|
|
55
|
-
|
|
87
|
+
if (this.args.options?.insertFreely) {
|
|
88
|
+
this.insertFreely(structureNode);
|
|
89
|
+
} else {
|
|
90
|
+
this.insertInDecision(structureNode);
|
|
56
91
|
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@action
|
|
95
|
+
insertFreely(node: PNode) {
|
|
96
|
+
this.controller.withTransaction((tr) => {
|
|
97
|
+
return transactionCombinator(
|
|
98
|
+
this.controller.activeEditorState,
|
|
99
|
+
tr.replaceSelectionWith(node),
|
|
100
|
+
)([recalculateNumbers]).transaction;
|
|
101
|
+
});
|
|
102
|
+
this.controller.focus();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@action
|
|
106
|
+
insertInDecision(node: PNode) {
|
|
57
107
|
if (!this.decisionLocation) {
|
|
58
108
|
return;
|
|
59
109
|
}
|
|
60
110
|
this.controller.doCommand(
|
|
61
111
|
insertArticle({
|
|
62
|
-
node
|
|
112
|
+
node,
|
|
63
113
|
decisionLocation: this.decisionLocation,
|
|
64
114
|
}),
|
|
65
115
|
);
|
|
@@ -75,7 +125,7 @@ export default class InsertArticleComponent extends Component<Sig> {
|
|
|
75
125
|
@disabled={{not this.canInsert}}
|
|
76
126
|
{{on 'click' this.doInsert}}
|
|
77
127
|
>
|
|
78
|
-
{{
|
|
128
|
+
{{this.label}}
|
|
79
129
|
</AuButton>
|
|
80
130
|
</li>
|
|
81
131
|
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{{! @glint-nocheck: not typesafe yet }}
|
|
2
|
+
<AuFormRow>
|
|
3
|
+
<VariablePlugin::Utils::LabelInput
|
|
4
|
+
@label={{this.label}}
|
|
5
|
+
@updateLabel={{this.updateLabel}}
|
|
6
|
+
/>
|
|
7
|
+
</AuFormRow>
|
|
8
|
+
<AuFormRow>
|
|
9
|
+
<AuLabel for='autofill_key'>
|
|
10
|
+
{{t 'variable-plugin.autofill.autofillKey'}}
|
|
11
|
+
</AuLabel>
|
|
12
|
+
<AuNativeInput
|
|
13
|
+
id='autofill_key'
|
|
14
|
+
placeholder={{t 'variable-plugin.autofill.autofillKeyPlaceholder'}}
|
|
15
|
+
@type='text'
|
|
16
|
+
@width='block'
|
|
17
|
+
value={{this.autofillKey}}
|
|
18
|
+
{{on 'input' this.updateAutofillKey}}
|
|
19
|
+
/>
|
|
20
|
+
</AuFormRow>
|
|
21
|
+
<AuFormRow>
|
|
22
|
+
<AuCheckbox
|
|
23
|
+
id='convert_to_string'
|
|
24
|
+
@checked={{this.convertToString}}
|
|
25
|
+
@onChange={{this.updateConvertToString}}
|
|
26
|
+
>
|
|
27
|
+
{{t 'variable-plugin.autofill.convertToString'}}
|
|
28
|
+
</AuCheckbox>
|
|
29
|
+
</AuFormRow>
|
|
30
|
+
<AuButton {{on 'click' this.insert}}>
|
|
31
|
+
{{t 'variable-plugin.button'}}
|
|
32
|
+
</AuButton>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { service } from '@ember/service';
|
|
5
|
+
import { type SayController } from '@lblod/ember-rdfa-editor';
|
|
6
|
+
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
|
|
7
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
8
|
+
import IntlService from 'ember-intl/services/intl';
|
|
9
|
+
import {
|
|
10
|
+
DCT,
|
|
11
|
+
EXT,
|
|
12
|
+
RDF,
|
|
13
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
14
|
+
import { replaceSelectionWithAndSelectNode } from '@lblod/ember-rdfa-editor-lblod-plugins/commands';
|
|
15
|
+
|
|
16
|
+
type Args = {
|
|
17
|
+
controller: SayController;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default class AutoFilledVariableInsertComponent extends Component<Args> {
|
|
21
|
+
@service declare intl: IntlService;
|
|
22
|
+
@tracked label?: string;
|
|
23
|
+
@tracked autofillKey?: string;
|
|
24
|
+
@tracked convertToString?: boolean;
|
|
25
|
+
|
|
26
|
+
get controller() {
|
|
27
|
+
return this.args.controller;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get schema() {
|
|
31
|
+
return this.args.controller.schema;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get documentLanguage() {
|
|
35
|
+
return this.controller.documentLanguage;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@action
|
|
39
|
+
updateLabel(event: InputEvent) {
|
|
40
|
+
this.label = (event.target as HTMLInputElement).value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@action
|
|
44
|
+
updateAutofillKey(event: InputEvent) {
|
|
45
|
+
this.autofillKey = (event.target as HTMLInputElement).value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@action
|
|
49
|
+
updateConvertToString(value: boolean) {
|
|
50
|
+
this.convertToString = value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@action
|
|
54
|
+
insert() {
|
|
55
|
+
const mappingSubject = `http://data.lblod.info/mappings/${uuidv4()}`;
|
|
56
|
+
const variableInstance = `http://data.lblod.info/variables/${uuidv4()}`;
|
|
57
|
+
const variableId = uuidv4();
|
|
58
|
+
|
|
59
|
+
const placeholder = this.intl.t('variable.autofilled.label', {
|
|
60
|
+
locale: this.documentLanguage,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const label = this.label ?? placeholder;
|
|
64
|
+
const node = this.schema.nodes.autofilled_variable.create(
|
|
65
|
+
{
|
|
66
|
+
subject: mappingSubject,
|
|
67
|
+
rdfaNodeType: 'resource',
|
|
68
|
+
__rdfaId: variableId,
|
|
69
|
+
properties: [
|
|
70
|
+
{
|
|
71
|
+
predicate: RDF('type').full,
|
|
72
|
+
object: sayDataFactory.namedNode(EXT('Mapping').full),
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
predicate: EXT('instance').full,
|
|
76
|
+
object: sayDataFactory.namedNode(variableInstance),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
predicate: EXT('label').full,
|
|
80
|
+
object: sayDataFactory.literal(label),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
predicate: DCT('type').full,
|
|
84
|
+
object: sayDataFactory.literal('autofilled'),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
predicate: EXT('content').full,
|
|
88
|
+
object: sayDataFactory.contentLiteral(),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
autofillKey: this.autofillKey,
|
|
92
|
+
convertToString: this.convertToString,
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
this.schema.node('placeholder', {
|
|
96
|
+
placeholderText: `Autofill ${this.autofillKey}`,
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
this.label = undefined;
|
|
100
|
+
|
|
101
|
+
this.controller.doCommand(replaceSelectionWithAndSelectNode(node), {
|
|
102
|
+
view: this.controller.mainEditorView,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{{! @glint-nocheck: not typesafe yet }}
|
|
2
|
+
<AuPill
|
|
3
|
+
@icon={{this.PencilIcon}}
|
|
4
|
+
@iconAlignment='right'
|
|
5
|
+
class='variable'
|
|
6
|
+
{{on 'click' this.onClick}}
|
|
7
|
+
>
|
|
8
|
+
<EmberNode::EmbeddedEditor
|
|
9
|
+
@controller={{@controller}}
|
|
10
|
+
@view={{@view}}
|
|
11
|
+
@getPos={{@getPos}}
|
|
12
|
+
@node={{@node}}
|
|
13
|
+
@selected={{@selected}}
|
|
14
|
+
@initEditor={{this.initEditor}}
|
|
15
|
+
@nodeViews={{@nodeViews}}
|
|
16
|
+
@plugins={{this.plugins}}
|
|
17
|
+
@decorations={{@decorations}}
|
|
18
|
+
@contentDecorations={{@contentDecorations}}
|
|
19
|
+
/>
|
|
20
|
+
{{#if this.label}}
|
|
21
|
+
<span class='label'>
|
|
22
|
+
({{this.label}})
|
|
23
|
+
</span>
|
|
24
|
+
{{/if}}
|
|
25
|
+
</AuPill>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { NodeSelection, ProsePlugin, SayView } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import { editableNodePlugin } from '@lblod/ember-rdfa-editor/plugins/editable-node';
|
|
4
|
+
import { tracked } from '@glimmer/tracking';
|
|
5
|
+
import { action } from '@ember/object';
|
|
6
|
+
import { PencilIcon } from '@appuniversum/ember-appuniversum/components/icons/pencil';
|
|
7
|
+
|
|
8
|
+
import { EmberNodeArgs } from '@lblod/ember-rdfa-editor/utils/ember-node';
|
|
9
|
+
import { getOutgoingTriple } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
|
|
10
|
+
import { EXT } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
11
|
+
|
|
12
|
+
export default class AutoFilledVariableNodeViewComponent extends Component<EmberNodeArgs> {
|
|
13
|
+
PencilIcon = PencilIcon;
|
|
14
|
+
|
|
15
|
+
@tracked innerView?: SayView;
|
|
16
|
+
|
|
17
|
+
get plugins(): ProsePlugin[] {
|
|
18
|
+
return [editableNodePlugin(this.args.getPos)];
|
|
19
|
+
}
|
|
20
|
+
@action
|
|
21
|
+
onClick() {
|
|
22
|
+
if (this.innerView) {
|
|
23
|
+
if (this.innerView.state.doc.firstChild?.type.name === 'placeholder') {
|
|
24
|
+
this.innerView.focus();
|
|
25
|
+
// Use request animation frame to only change the selection when the focus has been established
|
|
26
|
+
window.requestAnimationFrame(() => {
|
|
27
|
+
if (this.innerView) {
|
|
28
|
+
const tr = this.innerView.state.tr;
|
|
29
|
+
tr.setSelection(NodeSelection.create(this.innerView?.state.doc, 0));
|
|
30
|
+
this.innerView?.dispatch(tr);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
this.innerView.focus();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
@action
|
|
39
|
+
initEditor(view: SayView) {
|
|
40
|
+
this.innerView = view;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get label() {
|
|
44
|
+
if (this.innerView?.state.doc.firstChild?.type.name !== 'placeholder') {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
return getOutgoingTriple(this.args.node.attrs, EXT('label'))?.object.value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -110,7 +110,7 @@ export type GeoPos = {
|
|
|
110
110
|
};
|
|
111
111
|
|
|
112
112
|
export function constructLambert72GMLString({ x, y }: Lambert72Coordinates) {
|
|
113
|
-
return `<gml:Point srsName="
|
|
113
|
+
return `<gml:Point srsName="http://www.opengis.net/def/crs/EPSG/0/31370" xmlns:gml="http://www.opengis.net/gml/3.2"><gml:pos>${x} ${y}</gml:pos></gml:Point>`;
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
116
|
* Use a regex to parse a simple point as a GML string and return the coordinates.
|
|
@@ -122,7 +122,7 @@ export function parseLambert72GMLString(gml: string): GeoPos {
|
|
|
122
122
|
// which can be represented. Since we handle only simple points, it's much less complex to just
|
|
123
123
|
// use a simple regex.
|
|
124
124
|
const [_, crs, x, y] =
|
|
125
|
-
/<gml.Point .*srsName="https
|
|
125
|
+
/<gml.Point .*srsName="https?:\/\/www.opengis.net\/def\/crs\/([^"]+)".+<gml.pos>(\S+) ([^<]+)<\/gml:pos>/.exec(
|
|
126
126
|
gml,
|
|
127
127
|
) || [];
|
|
128
128
|
if (!crs || crs !== 'EPSG/0/31370') {
|
|
@@ -144,11 +144,11 @@ export function constructLambert72WKTString(
|
|
|
144
144
|
) {
|
|
145
145
|
if (!Array.isArray(coords)) {
|
|
146
146
|
const { x, y } = coords;
|
|
147
|
-
return `<
|
|
147
|
+
return `<http://www.opengis.net/def/crs/EPSG/0/31370> POINT(${x} ${y})`;
|
|
148
148
|
} else {
|
|
149
149
|
const points = coords.map(({ x, y }) => `${x} ${y}`).join(', ');
|
|
150
150
|
// Double brackets are not a mistake...
|
|
151
|
-
return `<
|
|
151
|
+
return `<http://www.opengis.net/def/crs/EPSG/0/31370> POLYGON((${points}))`;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -171,7 +171,7 @@ export function parseLambert72WKTString(gml: string): GeoPos | GeoPos[] {
|
|
|
171
171
|
// cases, it's much less complex to just use a simple regex.
|
|
172
172
|
|
|
173
173
|
const [_, crs, shape, dimensions] =
|
|
174
|
-
/<https
|
|
174
|
+
/<https?:\/\/www.opengis.net\/def\/crs\/([^"]+)> (POLYGON|POINT)\(\(?([\d,. ]+)\)\)?/.exec(
|
|
175
175
|
gml,
|
|
176
176
|
) || [];
|
|
177
177
|
if (crs && crs === 'EPSG/0/31370') {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EditorState,
|
|
3
|
+
PNode,
|
|
4
|
+
ProsePlugin,
|
|
5
|
+
Schema,
|
|
6
|
+
Transaction,
|
|
7
|
+
} from '@lblod/ember-rdfa-editor';
|
|
8
|
+
import { changedDescendants } from '@lblod/ember-rdfa-editor/utils/_private/changed-descendants';
|
|
9
|
+
import { undoDepth } from '@lblod/ember-rdfa-editor/plugins/history';
|
|
10
|
+
|
|
11
|
+
type AutofilledArgs = {
|
|
12
|
+
autofilledValues: {
|
|
13
|
+
[Key: string]: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function variableAutofillerPlugin(config: AutofilledArgs): ProsePlugin {
|
|
18
|
+
return new ProsePlugin({
|
|
19
|
+
appendTransaction(
|
|
20
|
+
transactions: readonly Transaction[],
|
|
21
|
+
oldState: EditorState,
|
|
22
|
+
newState: EditorState,
|
|
23
|
+
) {
|
|
24
|
+
const autofilledVariables: { node: PNode; pos: number }[] = [];
|
|
25
|
+
if (undoDepth(oldState)) {
|
|
26
|
+
changedDescendants(
|
|
27
|
+
oldState.doc,
|
|
28
|
+
newState.doc,
|
|
29
|
+
0,
|
|
30
|
+
(node: PNode, pos: number) => {
|
|
31
|
+
if (node.type.name === 'autofilled_variable') {
|
|
32
|
+
autofilledVariables.push({ node, pos });
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
} else {
|
|
39
|
+
newState.doc.descendants((node: PNode, pos: number) => {
|
|
40
|
+
if (node.type.name === 'autofilled_variable') {
|
|
41
|
+
autofilledVariables.push({ node, pos });
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (autofilledVariables.length) {
|
|
48
|
+
const tr = newState.tr;
|
|
49
|
+
autofilledVariables.reverse();
|
|
50
|
+
for (const { node, pos } of autofilledVariables) {
|
|
51
|
+
autofillVariable(
|
|
52
|
+
node,
|
|
53
|
+
pos,
|
|
54
|
+
config.autofilledValues,
|
|
55
|
+
tr,
|
|
56
|
+
newState.schema,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return tr;
|
|
60
|
+
}
|
|
61
|
+
return newState.tr;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function autofillVariable(
|
|
67
|
+
node: PNode,
|
|
68
|
+
pos: number,
|
|
69
|
+
values: { [Key: string]: string },
|
|
70
|
+
tr: Transaction,
|
|
71
|
+
schema: Schema,
|
|
72
|
+
) {
|
|
73
|
+
const autofillKey = node.attrs.autofillKey as string;
|
|
74
|
+
const value = values[autofillKey];
|
|
75
|
+
if (value) {
|
|
76
|
+
const nodeSize = node.nodeSize;
|
|
77
|
+
const valueNode = schema.text(value);
|
|
78
|
+
if (
|
|
79
|
+
node.attrs.convertToString === true ||
|
|
80
|
+
node.attrs.convertToString === 'true'
|
|
81
|
+
) {
|
|
82
|
+
tr.replaceRangeWith(pos, pos + nodeSize, valueNode);
|
|
83
|
+
return;
|
|
84
|
+
} else {
|
|
85
|
+
tr.replaceRangeWith(pos + 1, pos + nodeSize - 1, valueNode);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -342,7 +342,7 @@ export type Lambert72Coordinates = {
|
|
|
342
342
|
};
|
|
343
343
|
|
|
344
344
|
export function constructLambert72GMLString({ x, y }: Lambert72Coordinates) {
|
|
345
|
-
return `<gml:Point srsName="
|
|
345
|
+
return `<gml:Point srsName="http://www.opengis.net/def/crs/EPSG/0/31370" xmlns:gml="http://www.opengis.net/gml/3.2"><gml:pos>${x} ${y}</gml:pos></gml:Point>`;
|
|
346
346
|
}
|
|
347
347
|
/**
|
|
348
348
|
* Use a regex to parse a simple point as a GML string and return the coordinates.
|
|
@@ -354,7 +354,7 @@ export function parseLambert72GMLString(gml: string): Lambert72Coordinates {
|
|
|
354
354
|
// which can be represented. Since we handle only simple points, it's much less complex to just
|
|
355
355
|
// use a simple regex.
|
|
356
356
|
const [_, crs, x, y] =
|
|
357
|
-
/<gml.Point .*srsName="https
|
|
357
|
+
/<gml.Point .*srsName="https?:\/\/www.opengis.net\/def\/crs\/([^"]+)".+<gml.pos>(\S+) ([^<]+)<\/gml:pos>/.exec(
|
|
358
358
|
gml,
|
|
359
359
|
) || [];
|
|
360
360
|
if (!crs || crs !== 'EPSG/0/31370') {
|
|
@@ -370,7 +370,7 @@ export function parseLambert72GMLString(gml: string): Lambert72Coordinates {
|
|
|
370
370
|
* [the GeoSPARQL spec]{@link https://docs.ogc.org/is/22-047r1/22-047r1.html#10-8-1-%C2%A0-well-known-text}
|
|
371
371
|
*/
|
|
372
372
|
export function constructLambert72WKTString({ x, y }: Lambert72Coordinates) {
|
|
373
|
-
return `<
|
|
373
|
+
return `<http://www.opengis.net/def/crs/EPSG/0/31370> POINT(${x} ${y})`;
|
|
374
374
|
}
|
|
375
375
|
/**
|
|
376
376
|
* Use a regex to parse a simple point as a WKT string and return the coordinates.
|
|
@@ -382,7 +382,7 @@ export function parseLambert72WKTString(gml: string): Lambert72Coordinates {
|
|
|
382
382
|
// which can be represented or within untyped libraries (e.g. wicket). Since we handle only simple
|
|
383
383
|
// points, it's much less complex to just use a simple regex.
|
|
384
384
|
const [_, crs, x, y] =
|
|
385
|
-
/<https
|
|
385
|
+
/<https?:\/\/www.opengis.net\/def\/crs\/([^"]+)> POINT\((\S+) ([^)]+)\)/.exec(
|
|
386
386
|
gml,
|
|
387
387
|
) || [];
|
|
388
388
|
if (!crs || crs !== 'EPSG/0/31370') {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DCT,
|
|
3
|
+
EXT,
|
|
4
|
+
RDF,
|
|
5
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
|
|
6
|
+
import {
|
|
7
|
+
createEmberNodeSpec,
|
|
8
|
+
createEmberNodeView,
|
|
9
|
+
EmberNodeConfig,
|
|
10
|
+
} from '@lblod/ember-rdfa-editor/utils/ember-node';
|
|
11
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
12
|
+
import {
|
|
13
|
+
DOMOutputSpec,
|
|
14
|
+
getRdfaAttrs,
|
|
15
|
+
PNode,
|
|
16
|
+
rdfaAttrSpec,
|
|
17
|
+
} from '@lblod/ember-rdfa-editor';
|
|
18
|
+
import {
|
|
19
|
+
hasRdfaVariableType,
|
|
20
|
+
isVariable,
|
|
21
|
+
parseLabel,
|
|
22
|
+
parseVariableInstance,
|
|
23
|
+
parseVariableType,
|
|
24
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/variable-attribute-parsers';
|
|
25
|
+
import AutofilledNodeViewComponent from '@lblod/ember-rdfa-editor-lblod-plugins/components/variable-plugin/autofilled/nodeview';
|
|
26
|
+
import type { ComponentLike } from '@glint/template';
|
|
27
|
+
import { hasOutgoingNamedNodeTriple } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
|
|
28
|
+
import { renderRdfaAware } from '@lblod/ember-rdfa-editor/core/schema';
|
|
29
|
+
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
|
|
30
|
+
|
|
31
|
+
const CONTENT_SELECTOR = `span[property~='${EXT('content').prefixed}'],
|
|
32
|
+
span[property~='${EXT('content').full}']`;
|
|
33
|
+
const rdfaAware = true;
|
|
34
|
+
const parseDOM = [
|
|
35
|
+
{
|
|
36
|
+
tag: 'span',
|
|
37
|
+
getAttrs: (node: HTMLElement) => {
|
|
38
|
+
const attrs = getRdfaAttrs(node, { rdfaAware });
|
|
39
|
+
if (!attrs) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (
|
|
43
|
+
hasOutgoingNamedNodeTriple(attrs, RDF('type'), EXT('Mapping')) &&
|
|
44
|
+
node.querySelector('[data-content-container="true"]') &&
|
|
45
|
+
hasRdfaVariableType(attrs, 'autofilled')
|
|
46
|
+
) {
|
|
47
|
+
if (attrs.rdfaNodeType !== 'resource') {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const autofillKey = node.dataset.autofillKey;
|
|
51
|
+
const convertToString = node.dataset.convertToString;
|
|
52
|
+
return {
|
|
53
|
+
...attrs,
|
|
54
|
+
autofillKey,
|
|
55
|
+
convertToString,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return false;
|
|
60
|
+
},
|
|
61
|
+
contentElement: '[data-content-container="true"]',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
tag: 'span',
|
|
65
|
+
getAttrs: (node: HTMLElement) => {
|
|
66
|
+
if (
|
|
67
|
+
isVariable(node) &&
|
|
68
|
+
node.querySelector(CONTENT_SELECTOR) &&
|
|
69
|
+
parseVariableType(node) === 'autofilled'
|
|
70
|
+
) {
|
|
71
|
+
const mappingSubject =
|
|
72
|
+
node.getAttribute('subject') ||
|
|
73
|
+
node.getAttribute('resource') ||
|
|
74
|
+
node.getAttribute('about');
|
|
75
|
+
if (!mappingSubject) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const variableInstance = parseVariableInstance(node);
|
|
79
|
+
const label = parseLabel(node);
|
|
80
|
+
const autofillKey = node.dataset.autofillKey;
|
|
81
|
+
const convertToString = node.dataset.convertToString;
|
|
82
|
+
return {
|
|
83
|
+
__rdfaId: uuidv4(),
|
|
84
|
+
subject: mappingSubject,
|
|
85
|
+
rdfaNodeType: 'resource',
|
|
86
|
+
properties: [
|
|
87
|
+
{
|
|
88
|
+
predicate: RDF('type').full,
|
|
89
|
+
object: sayDataFactory.namedNode(EXT('Mapping').full),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
predicate: EXT('instance').full,
|
|
93
|
+
object: sayDataFactory.namedNode(
|
|
94
|
+
variableInstance ??
|
|
95
|
+
`http://data.lblod.info/variables/${uuidv4()}`,
|
|
96
|
+
),
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
predicate: EXT('label').full,
|
|
100
|
+
object: sayDataFactory.literal(label || ''),
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
predicate: DCT('type').full,
|
|
104
|
+
object: sayDataFactory.literal('autofilled'),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
predicate: EXT('content').full,
|
|
108
|
+
object: sayDataFactory.contentLiteral(),
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
autofillKey,
|
|
112
|
+
convertToString,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return false;
|
|
117
|
+
},
|
|
118
|
+
contentElement: CONTENT_SELECTOR,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const toDOM = (node: PNode): DOMOutputSpec => {
|
|
123
|
+
return renderRdfaAware({
|
|
124
|
+
renderable: node,
|
|
125
|
+
tag: 'span',
|
|
126
|
+
attrs: {
|
|
127
|
+
...node.attrs,
|
|
128
|
+
'data-autofill-key': node.attrs.autofillKey,
|
|
129
|
+
'data-convert-to-string': node.attrs.convertToString,
|
|
130
|
+
},
|
|
131
|
+
content: 0,
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const emberNodeConfig: EmberNodeConfig = {
|
|
136
|
+
name: 'autofilled-variable',
|
|
137
|
+
component: AutofilledNodeViewComponent as unknown as ComponentLike,
|
|
138
|
+
inline: true,
|
|
139
|
+
group: 'inline variable',
|
|
140
|
+
content: 'inline*',
|
|
141
|
+
atom: true,
|
|
142
|
+
recreateUri: true,
|
|
143
|
+
uriAttributes: ['variableInstance'],
|
|
144
|
+
draggable: false,
|
|
145
|
+
needsFFKludge: true,
|
|
146
|
+
editable: true,
|
|
147
|
+
selectable: true,
|
|
148
|
+
attrs: {
|
|
149
|
+
...rdfaAttrSpec({ rdfaAware }),
|
|
150
|
+
autofillKey: {
|
|
151
|
+
default: '',
|
|
152
|
+
},
|
|
153
|
+
convertToString: {
|
|
154
|
+
default: false,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
toDOM,
|
|
158
|
+
parseDOM,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const autofilled_variable = createEmberNodeSpec(emberNodeConfig);
|
|
162
|
+
export const autofilledVariableView = createEmberNodeView(emberNodeConfig);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/variable-plugin/autofilled/insert';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/variable-plugin/autofilled/nodeview';
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
-
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
2
|
+
import { PNode, SayController } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import IntlService from 'ember-intl/services/intl';
|
|
3
4
|
export interface InsertArticleOptions {
|
|
4
5
|
uriGenerator?: () => string;
|
|
6
|
+
insertFreely?: boolean;
|
|
5
7
|
}
|
|
6
8
|
interface Sig {
|
|
7
9
|
Args: {
|
|
8
10
|
controller: SayController;
|
|
11
|
+
label: string;
|
|
9
12
|
options?: InsertArticleOptions;
|
|
10
13
|
};
|
|
11
14
|
}
|
|
12
15
|
export default class InsertArticleComponent extends Component<Sig> {
|
|
16
|
+
intl: IntlService;
|
|
13
17
|
get controller(): SayController;
|
|
18
|
+
get options(): InsertArticleOptions | undefined;
|
|
19
|
+
get label(): string;
|
|
14
20
|
get schema(): import("prosemirror-model").Schema<any, any>;
|
|
15
21
|
get decisionRange(): import("@lblod/ember-rdfa-editor/plugins/datastore").ElementPNode | undefined;
|
|
16
22
|
get decisionLocation(): {
|
|
17
23
|
pos: number;
|
|
18
|
-
node:
|
|
24
|
+
node: PNode;
|
|
19
25
|
} | null;
|
|
20
26
|
get canInsert(): boolean;
|
|
27
|
+
get canInsertFreely(): boolean;
|
|
28
|
+
get canInsertInDecision(): boolean;
|
|
21
29
|
doInsert(): void;
|
|
30
|
+
insertFreely(node: PNode): void;
|
|
31
|
+
insertInDecision(node: PNode): void;
|
|
22
32
|
}
|
|
23
33
|
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { type SayController } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import IntlService from 'ember-intl/services/intl';
|
|
4
|
+
type Args = {
|
|
5
|
+
controller: SayController;
|
|
6
|
+
};
|
|
7
|
+
export default class AutoFilledVariableInsertComponent extends Component<Args> {
|
|
8
|
+
intl: IntlService;
|
|
9
|
+
label?: string;
|
|
10
|
+
autofillKey?: string;
|
|
11
|
+
convertToString?: boolean;
|
|
12
|
+
get controller(): SayController;
|
|
13
|
+
get schema(): import("prosemirror-model").Schema<any, any>;
|
|
14
|
+
get documentLanguage(): string;
|
|
15
|
+
updateLabel(event: InputEvent): void;
|
|
16
|
+
updateAutofillKey(event: InputEvent): void;
|
|
17
|
+
updateConvertToString(value: boolean): void;
|
|
18
|
+
insert(): void;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { ProsePlugin, SayView } from '@lblod/ember-rdfa-editor';
|
|
3
|
+
import { EmberNodeArgs } from '@lblod/ember-rdfa-editor/utils/ember-node';
|
|
4
|
+
export default class AutoFilledVariableNodeViewComponent extends Component<EmberNodeArgs> {
|
|
5
|
+
PencilIcon: TOC<import("@appuniversum/ember-appuniversum/components/icons/pencil").PencilIconSignature>;
|
|
6
|
+
innerView?: SayView;
|
|
7
|
+
get plugins(): ProsePlugin[];
|
|
8
|
+
onClick(): void;
|
|
9
|
+
initEditor(view: SayView): void;
|
|
10
|
+
get label(): string | undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const autofilled_variable: import("@lblod/ember-rdfa-editor/core/say-node-spec").default;
|
|
2
|
+
export declare const autofilledVariableView: (controller: import("@lblod/ember-rdfa-editor").SayController) => import("@lblod/ember-rdfa-editor/utils/ember-node").SayNodeViewConstructor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lblod/ember-rdfa-editor-lblod-plugins",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.4.0-dev.488ef3259e12430c4bb92a2ce203e9d15a5c84d2",
|
|
4
4
|
"description": "Ember addon providing lblod specific plugins for the ember-rdfa-editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon",
|
package/translations/en-US.yaml
CHANGED
|
@@ -269,6 +269,10 @@ variable-plugin:
|
|
|
269
269
|
person:
|
|
270
270
|
card-title: Insert person
|
|
271
271
|
nodeview-placeholder: Insert person
|
|
272
|
+
autofill:
|
|
273
|
+
autofillKey: Autofill Key
|
|
274
|
+
convertToString: Automatically convert to text
|
|
275
|
+
autofillKeyPlaceholder: Autofill Key
|
|
272
276
|
|
|
273
277
|
table-of-contents-plugin:
|
|
274
278
|
title: Table of Contents
|
package/translations/nl-BE.yaml
CHANGED
|
@@ -273,6 +273,10 @@ variable-plugin:
|
|
|
273
273
|
person:
|
|
274
274
|
card-title: Persoon invoegen
|
|
275
275
|
nodeview-placeholder: Voeg persoon in
|
|
276
|
+
autofill:
|
|
277
|
+
autofillKey: Autovultoets
|
|
278
|
+
convertToString: Automatisch converteren naar tekst
|
|
279
|
+
autofillKeyPlaceholder: Autovultoets
|
|
276
280
|
dummy:
|
|
277
281
|
validation-card:
|
|
278
282
|
title: Documentvalidatie
|