@lblod/ember-rdfa-editor-lblod-plugins 32.3.0 → 32.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/addon/components/document-validation-plugin/card.gts +137 -0
  3. package/addon/components/location-plugin/insert-location-placeholder.gts +76 -0
  4. package/addon/components/location-plugin/insert.gts +2 -1
  5. package/addon/components/location-plugin/nodeview.gts +1 -1
  6. package/addon/components/roadsign-regulation-plugin/expanded-measure.gts +5 -1
  7. package/addon/components/roadsign-regulation-plugin/roadsigns-modal.gts +1 -1
  8. package/addon/plugins/document-validation-plugin/index.ts +196 -0
  9. package/addon/plugins/location-plugin/_private/node-contents/address.ts +252 -0
  10. package/addon/plugins/location-plugin/_private/node-contents/area.ts +64 -0
  11. package/addon/plugins/location-plugin/_private/node-contents/index.ts +46 -0
  12. package/addon/plugins/location-plugin/_private/node-contents/place.ts +64 -0
  13. package/addon/plugins/location-plugin/_private/node-contents/point.ts +89 -0
  14. package/addon/plugins/location-plugin/_private/utils/address-helpers.ts +407 -0
  15. package/addon/plugins/location-plugin/_private/utils/geo-helpers.ts +210 -0
  16. package/addon/plugins/location-plugin/_private/utils/node-utils.ts +82 -0
  17. package/addon/plugins/location-plugin/node-contents/address.ts +2 -252
  18. package/addon/plugins/location-plugin/node-contents/area.ts +2 -64
  19. package/addon/plugins/location-plugin/node-contents/index.ts +2 -46
  20. package/addon/plugins/location-plugin/node-contents/place.ts +2 -64
  21. package/addon/plugins/location-plugin/node-contents/point.ts +2 -89
  22. package/addon/plugins/location-plugin/node.ts +48 -16
  23. package/addon/plugins/location-plugin/utils/address-helpers.ts +2 -407
  24. package/addon/plugins/location-plugin/utils/geo-helpers.ts +2 -210
  25. package/addon/plugins/location-plugin/utils/node-utils.ts +10 -61
  26. package/addon/plugins/roadsign-regulation-plugin/queries/mobility-measure-concept.ts +3 -1
  27. package/addon/utils/remove-quotes.ts +7 -0
  28. package/app/components/document-validation-plugin/card.js +1 -0
  29. package/app/components/location-plugin/insert-location-placeholder.js +1 -0
  30. package/app/styles/document-validation.scss +26 -0
  31. package/declarations/addon/components/document-validation-plugin/card.d.ts +22 -0
  32. package/declarations/addon/components/location-plugin/insert-location-placeholder.d.ts +20 -0
  33. package/declarations/addon/plugins/document-validation-plugin/index.d.ts +28 -0
  34. package/declarations/addon/plugins/location-plugin/_private/node-contents/address.d.ts +11 -0
  35. package/declarations/addon/plugins/location-plugin/_private/node-contents/area.d.ts +9 -0
  36. package/declarations/addon/plugins/location-plugin/_private/node-contents/index.d.ts +32 -0
  37. package/declarations/addon/plugins/location-plugin/_private/node-contents/place.d.ts +9 -0
  38. package/declarations/addon/plugins/location-plugin/_private/node-contents/point.d.ts +6 -0
  39. package/declarations/addon/plugins/location-plugin/_private/utils/address-helpers.d.ts +62 -0
  40. package/declarations/addon/plugins/location-plugin/_private/utils/geo-helpers.d.ts +82 -0
  41. package/declarations/addon/plugins/location-plugin/_private/utils/node-utils.d.ts +17 -0
  42. package/declarations/addon/plugins/location-plugin/node-contents/address.d.ts +2 -11
  43. package/declarations/addon/plugins/location-plugin/node-contents/area.d.ts +2 -9
  44. package/declarations/addon/plugins/location-plugin/node-contents/index.d.ts +2 -32
  45. package/declarations/addon/plugins/location-plugin/node-contents/place.d.ts +2 -9
  46. package/declarations/addon/plugins/location-plugin/node-contents/point.d.ts +2 -6
  47. package/declarations/addon/plugins/location-plugin/utils/address-helpers.d.ts +2 -62
  48. package/declarations/addon/plugins/location-plugin/utils/geo-helpers.d.ts +2 -82
  49. package/declarations/addon/plugins/location-plugin/utils/node-utils.d.ts +1 -0
  50. package/declarations/addon/utils/remove-quotes.d.ts +1 -0
  51. package/package.json +7 -3
  52. package/pnpm-lock.yaml +1527 -1163
  53. package/translations/en-US.yaml +9 -0
  54. package/translations/nl-BE.yaml +9 -0
  55. package/types/global.d.ts +4 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @lblod/ember-rdfa-editor-lblod-plugins
2
2
 
3
+ ## 32.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#582](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/582) [`96baaf4`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/96baaf43e1a976b167eea65f4d0255b6e74cd85f) Thanks [@lagartoverde](https://github.com/lagartoverde)! - Add new plugin for document validation with SHACL
8
+
9
+ - [#584](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/584) [`b8f445a`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/b8f445ae720134f2dd579cb7c831812210c7c8f7) Thanks [@elpoelma](https://github.com/elpoelma)! - Add simple placeholder-mode to location variable
10
+ To correctly identify location placeholder nodes, the `data-say-variable` and `data-say-variable-type: oslo_location` attributes have been added to the serialization of oslo location nodes. This is similar to the approach used by other variable nodes.
11
+
12
+ ### Patch Changes
13
+
14
+ - [#586](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/586) [`810f867`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/810f86766ac5fbc11e20a68545ab950ec07f61a7) Thanks [@lagartoverde](https://github.com/lagartoverde)! - Fix bug in roadsign regulation plugin where you couldn't search a sign if you had selected a category
15
+
16
+ - [#587](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/587) [`d5914c0`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/d5914c0ce63dba5aca15fbb00d634e811ece41b9) Thanks [@elpoelma](https://github.com/elpoelma)! - roadsign-regulation plugin: fix issue where measure could not be inserted as being variable/dynamic
17
+
18
+ - [#582](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/582) [`b21bd08`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/b21bd08744fd58b7e7e7286d9f31da7de692defe) Thanks [@lagartoverde](https://github.com/lagartoverde)! - Fix missing translations in citation-plugin
19
+
3
20
  ## 32.3.0
4
21
 
5
22
  ### Minor Changes
@@ -0,0 +1,137 @@
1
+ import Component from '@glimmer/component';
2
+ import { SayController } from '@lblod/ember-rdfa-editor';
3
+ import AuCard from '@appuniversum/ember-appuniversum/components/au-card';
4
+ import { documentValidationPluginKey } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/document-validation-plugin';
5
+ import AuIcon from '@appuniversum/ember-appuniversum/components/au-icon';
6
+ import { CloseFilledIcon } from '@appuniversum/ember-appuniversum/components/icons/close-filled';
7
+ import { CheckFilledIcon } from '@appuniversum/ember-appuniversum/components/icons/check-filled';
8
+ import { selectNodeBySubject } from '@lblod/ember-rdfa-editor/commands/_private/rdfa-commands/select-node-by-subject';
9
+ import { on } from '@ember/modifier';
10
+ import { fn } from '@ember/helper';
11
+ import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
12
+ import { ExternalLinkIcon } from '@appuniversum/ember-appuniversum/components/icons/external-link';
13
+ import t from 'ember-intl/helpers/t';
14
+ import { eq } from 'ember-truth-helpers';
15
+
16
+ interface Sig {
17
+ Args: {
18
+ controller: SayController;
19
+ };
20
+ }
21
+
22
+ export default class DocumentValidationPluginCard extends Component<Sig> {
23
+ get controller() {
24
+ return this.args.controller;
25
+ }
26
+ get validationState() {
27
+ const state = documentValidationPluginKey.getState(
28
+ this.controller.mainEditorState,
29
+ );
30
+ if (!state) {
31
+ console.warn(
32
+ 'DocumentValidationPluginCard needs the documentValidation plugin to function. Is it configured?',
33
+ );
34
+ return undefined;
35
+ }
36
+ return state;
37
+ }
38
+ get documentValidationErrors() {
39
+ if (!this.validationState) return [];
40
+ const { propertiesWithErrors } = this.validationState;
41
+ if (!propertiesWithErrors) return undefined;
42
+
43
+ return propertiesWithErrors;
44
+ }
45
+ get propertiesWithoutErrors() {
46
+ if (!this.validationState) return [];
47
+ const { propertiesWithoutErrors } = this.validationState;
48
+ return propertiesWithoutErrors;
49
+ }
50
+ goToSubject = (subject: string) => {
51
+ this.controller.doCommand(selectNodeBySubject({ subject }), {
52
+ view: this.controller.mainEditorView,
53
+ });
54
+ this.controller.focus();
55
+ };
56
+ get status() {
57
+ if (!this.validationState?.report) return 'not-run';
58
+ if (this.documentValidationErrors?.length === 0) {
59
+ if (this.propertiesWithoutErrors?.length === 0) return 'no-matches';
60
+ return 'valid';
61
+ }
62
+ return 'invalid';
63
+ }
64
+ get isSuccesslike() {
65
+ return ['valid', 'no-matches'].includes(this.status);
66
+ }
67
+
68
+ <template>
69
+ <AuCard
70
+ @flex={{true}}
71
+ @divided={{true}}
72
+ @isOpenInitially={{true}}
73
+ @expandable={{true}}
74
+ @shadow={{true}}
75
+ @size='small'
76
+ class={{if
77
+ this.isSuccesslike
78
+ 'say-document-validation__card-valid'
79
+ 'say-document-validation__card-invalid'
80
+ }}
81
+ as |c|
82
+ >
83
+ <c.header>
84
+ <p class='au-u-medium au-u-h6'>
85
+ {{#if (eq this.status 'valid')}}
86
+ {{t 'document-validation-plugin.valid-document-title'}}
87
+ {{else if (eq this.status 'invalid')}}
88
+ {{t 'document-validation-plugin.invalid-document-title'}}
89
+ {{else if (eq this.status 'not-run')}}
90
+ {{t 'document-validation-plugin.document-not-validated-title'}}
91
+ {{else if (eq this.status 'no-matches')}}
92
+ {{t 'document-validation-plugin.no-matching-rules'}}
93
+ {{/if}}
94
+ </p>
95
+ </c.header>
96
+ <c.content>
97
+ <p class='au-u-medium au-u-para-small'>{{t
98
+ 'document-validation-plugin.description'
99
+ }}</p>
100
+ {{#each this.documentValidationErrors as |error|}}
101
+ <div class='say-document-validation__error-container'>
102
+ <AuIcon
103
+ @icon={{CloseFilledIcon}}
104
+ @size='large'
105
+ @ariaHidden={{true}}
106
+ class='say-document-validation__icon-error au-u-margin-right-small'
107
+ />
108
+ <div>
109
+ {{error.message}}
110
+ <AuButton
111
+ class='au-u-padding-left-none au-u-padding-right-none'
112
+ @icon={{ExternalLinkIcon}}
113
+ @skin='link'
114
+ title={{error.subject}}
115
+ {{on 'click' (fn this.goToSubject error.subject)}}
116
+ >{{t 'document-validation-plugin.see-related-node'}}</AuButton>
117
+ </div>
118
+ </div>
119
+ {{/each}}
120
+ {{#each this.propertiesWithoutErrors as |property|}}
121
+ <div class='say-document-validation__error-container'>
122
+ <div class='au-u-margin-right-small'>
123
+ <AuIcon
124
+ @icon={{CheckFilledIcon}}
125
+ @size='large'
126
+ @ariaHidden={{true}}
127
+ class='say-document-validation__icon-success'
128
+ />
129
+ </div>
130
+ {{property.message}}
131
+ </div>
132
+ {{/each}}
133
+ </c.content>
134
+
135
+ </AuCard>
136
+ </template>
137
+ }
@@ -0,0 +1,76 @@
1
+ import Component from '@glimmer/component';
2
+ import { service } from '@ember/service';
3
+ import { on } from '@ember/modifier';
4
+ import not from 'ember-truth-helpers/helpers/not';
5
+ import IntlService from 'ember-intl/services/intl';
6
+ import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
7
+ import { AddIcon } from '@appuniversum/ember-appuniversum/components/icons/add';
8
+ import { NodeSelection, SayController } from '@lblod/ember-rdfa-editor';
9
+ import { type LocationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/node';
10
+ import { action } from '@ember/object';
11
+ import t from 'ember-intl/helpers/t';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import { replaceSelectionWithLocation } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/_private/utils/node-utils';
14
+
15
+ interface Signature {
16
+ Args: {
17
+ controller: SayController;
18
+ config: LocationPluginConfig;
19
+ templateMode?: boolean;
20
+ };
21
+ Element: HTMLLIElement;
22
+ }
23
+
24
+ export default class LocationPluginInsertComponent extends Component<Signature> {
25
+ @service declare intl: IntlService;
26
+
27
+ get selectedLocationNode() {
28
+ const { selection, schema } = this.controller.activeEditorState;
29
+ if (
30
+ selection instanceof NodeSelection &&
31
+ selection.node.type === schema.nodes.oslo_location
32
+ ) {
33
+ return selection.node;
34
+ } else {
35
+ return;
36
+ }
37
+ }
38
+
39
+ get controller() {
40
+ return this.args.controller;
41
+ }
42
+
43
+ get canInsert() {
44
+ return (
45
+ !!this.controller.activeEditorView.props.nodeViews?.oslo_location &&
46
+ !this.selectedLocationNode
47
+ );
48
+ }
49
+
50
+ @action
51
+ insertLocationPlaceholder() {
52
+ const uri = `http://data.lblod.info/variables/${
53
+ this.args.templateMode ? '--ref-uuid4-' : ''
54
+ }${uuidv4()}`;
55
+ replaceSelectionWithLocation(
56
+ this.controller,
57
+ uri,
58
+ undefined,
59
+ this.args.config.subjectTypesToLinkTo,
60
+ );
61
+ }
62
+
63
+ <template>
64
+ <li class='au-c-list__item' ...attributes>
65
+ <AuButton
66
+ @icon={{AddIcon}}
67
+ @iconAlignment='left'
68
+ @skin='link'
69
+ {{on 'click' this.insertLocationPlaceholder}}
70
+ @disabled={{not this.canInsert}}
71
+ >
72
+ {{t 'location-plugin.insert-placeholder'}}
73
+ </AuButton>
74
+ </li>
75
+ </template>
76
+ }
@@ -24,7 +24,6 @@ import {
24
24
  Point,
25
25
  Polygon,
26
26
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/geo-helpers';
27
- import { replaceSelectionWithLocation } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/node-utils';
28
27
  import { type LocationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/node';
29
28
  import { NodeContentsUtils } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/node-contents';
30
29
  import Edit from './edit';
@@ -34,6 +33,7 @@ import LocationMap, {
34
33
  } from './map';
35
34
  import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
36
35
  import { updateSubject } from '@lblod/ember-rdfa-editor/plugins/rdfa-info/utils';
36
+ import { replaceSelectionWithLocation } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/_private/utils/node-utils';
37
37
 
38
38
  export type CurrentLocation = Address | GlobalCoordinates | undefined;
39
39
 
@@ -293,6 +293,7 @@ export default class LocationPluginInsertComponent extends Component<Signature>
293
293
  // Insert
294
294
  replaceSelectionWithLocation(
295
295
  this.controller,
296
+ toInsert.uri,
296
297
  toInsert,
297
298
  this.args.config.subjectTypesToLinkTo,
298
299
  );
@@ -42,7 +42,7 @@ export default class AddressNodeviewComponent extends Component<Signature> {
42
42
  if (this.filled) {
43
43
  return this.address?.formatted;
44
44
  } else {
45
- return this.label;
45
+ return this.label ?? this.intl.t('location-plugin.nodeview.placeholder');
46
46
  }
47
47
  }
48
48
  get class() {
@@ -12,6 +12,7 @@ import { action } from '@ember/object';
12
12
  import { on } from '@ember/modifier';
13
13
  import { ZONALITY_OPTIONS } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
14
14
  import { Task } from 'ember-concurrency';
15
+ import { isSome } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
15
16
 
16
17
  export type InsertMobilityMeasureTask = Task<
17
18
  void,
@@ -41,7 +42,10 @@ export default class ExpandedMeasure extends Component<Signature> {
41
42
  }
42
43
 
43
44
  get insertButtonDisabled() {
44
- return this.isPotentiallyZonal && !this.zonalityValue;
45
+ return (
46
+ (this.isPotentiallyZonal && !this.zonalityValue) ||
47
+ (this.args.concept.variableSignage && !isSome(this.temporalValue))
48
+ );
45
49
  }
46
50
 
47
51
  @action
@@ -151,7 +151,7 @@ export default class RoadsignsModal extends Component<Signature> {
151
151
  }
152
152
 
153
153
  searchCodes = restartableTask(async (term: string) => {
154
- const category = this.selectedCategory?.label;
154
+ const category = this.selectedCategory?.uri;
155
155
  const type = this.selectedType?.label;
156
156
  const types = type ? [type] : undefined;
157
157
  await timeout(DEBOUNCE_MS);
@@ -0,0 +1,196 @@
1
+ import factory from '@rdfjs/dataset';
2
+ import SHACLValidator from 'rdf-validate-shacl';
3
+ import { Parser as ParserN3 } from 'n3';
4
+ import { RdfaParser } from 'rdfa-streaming-parser';
5
+ import { ProsePlugin, PluginKey, EditorView } from '@lblod/ember-rdfa-editor';
6
+ import removeQuotes from '@lblod/ember-rdfa-editor-lblod-plugins/utils/remove-quotes';
7
+ import {
8
+ BlankNode,
9
+ DataFactory,
10
+ DatasetCore,
11
+ DatasetCoreFactory,
12
+ NamedNode,
13
+ Quad,
14
+ } from '@rdfjs/types';
15
+ import ValidationReport from 'rdf-validate-shacl/src/validation-report';
16
+ import { SayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
17
+
18
+ export const documentValidationPluginKey =
19
+ new PluginKey<DocumentValidationPluginState>('DOCUMENT_VALIDATION');
20
+
21
+ interface DocumentValidationPluginArgs {
22
+ documentShape: string;
23
+ }
24
+
25
+ export type ShaclValidationReport = ValidationReport.ValidationReport<
26
+ DataFactory<Quad, Quad> &
27
+ DatasetCoreFactory<Quad, Quad, DatasetCore<Quad, Quad>>
28
+ >;
29
+
30
+ interface DocumentValidationResult {
31
+ report?: ValidationReport;
32
+ propertiesWithoutErrors: { message: string }[];
33
+ propertiesWithErrors: (
34
+ | {
35
+ message: string;
36
+ subject: string | undefined;
37
+ }
38
+ // TODO get rid of this?
39
+ | undefined
40
+ )[];
41
+ }
42
+ export interface DocumentValidationTransactionMeta
43
+ extends DocumentValidationResult {
44
+ type: string;
45
+ }
46
+ export interface DocumentValidationPluginState
47
+ extends DocumentValidationResult {
48
+ documentShape: string;
49
+ validationCallback: typeof validationCallback;
50
+ }
51
+
52
+ export const documentValidationPlugin = (
53
+ options: DocumentValidationPluginArgs,
54
+ ) =>
55
+ new ProsePlugin<DocumentValidationPluginState>({
56
+ key: documentValidationPluginKey,
57
+ state: {
58
+ init() {
59
+ return {
60
+ validationCallback: validationCallback,
61
+ documentShape: options.documentShape,
62
+ propertiesWithoutErrors: [],
63
+ propertiesWithErrors: [],
64
+ };
65
+ },
66
+ apply(tr, state) {
67
+ const pluginTransaction = tr.getMeta(documentValidationPluginKey) as
68
+ | DocumentValidationTransactionMeta
69
+ | undefined;
70
+ if (pluginTransaction && pluginTransaction.type === 'setNewReport') {
71
+ return {
72
+ ...state,
73
+ report: pluginTransaction.report,
74
+ propertiesWithoutErrors: pluginTransaction.propertiesWithoutErrors,
75
+ propertiesWithErrors: pluginTransaction.propertiesWithErrors,
76
+ };
77
+ }
78
+
79
+ return state;
80
+ },
81
+ },
82
+ });
83
+
84
+ async function validationCallback(view: EditorView, documentHtml: string) {
85
+ const documentValidationState = documentValidationPluginKey.getState(
86
+ view.state,
87
+ );
88
+ if (!documentValidationState) {
89
+ console.warn('No shape found in the document validation plugin');
90
+ return;
91
+ }
92
+ const { documentShape } = documentValidationState;
93
+ const rdf = await htmlToRdf(documentHtml);
94
+
95
+ const shacl = await parse(documentShape);
96
+
97
+ const validator = new SHACLValidator(shacl, {
98
+ // @ts-expect-error ts doesn't recognize the configuration parameter not sure why
99
+ allowNamedNodeInList: true,
100
+ });
101
+ const report = validator.validate(rdf);
102
+ const sayFactory = new SayDataFactory();
103
+ const propertyPred = sayFactory.namedNode(
104
+ 'http://www.w3.org/ns/shacl#property',
105
+ );
106
+ const propertyNodes = [
107
+ ...shacl.match(undefined, propertyPred, undefined),
108
+ ].map((quad: Quad) => quad.object);
109
+
110
+ const propertiesWithErrors: {
111
+ sourceShape: BlankNode | NamedNode<string>;
112
+ focusNode: BlankNode | NamedNode<string> | null;
113
+ }[] = [];
114
+ for (const r of report.results) {
115
+ const sourceShape = r.sourceShape;
116
+ if (sourceShape)
117
+ propertiesWithErrors.push({ sourceShape, focusNode: r.focusNode });
118
+ }
119
+ const errorMessagePred = sayFactory.namedNode(
120
+ 'http://www.w3.org/ns/shacl#resultMessage',
121
+ );
122
+ const propertiesWithErrorsMessages = propertiesWithErrors
123
+ .map(({ sourceShape, focusNode }) => {
124
+ const match = shacl.match(sourceShape, errorMessagePred, undefined);
125
+ const message = [...match][0]?.object.value;
126
+ return message
127
+ ? { message: removeQuotes(message), subject: focusNode?.value }
128
+ : undefined;
129
+ })
130
+ .filter((message) => message);
131
+ const propertiesWithoutErrorsArray = propertyNodes.filter((propertyNode) =>
132
+ propertiesWithErrors.some((propertyWithError) => {
133
+ return propertyWithError.sourceShape.value !== propertyNode.value;
134
+ }),
135
+ );
136
+
137
+ const successMessagePred = sayFactory.namedNode(
138
+ 'http://mu.semte.ch/vocabularies/ext/successMessage',
139
+ );
140
+ const propertiesWithoutErrors = propertiesWithoutErrorsArray
141
+ .map((propertyNode) => {
142
+ const match = shacl.match(propertyNode, successMessagePred, undefined);
143
+ const message = [...match][0]?.object.value;
144
+ return message ? { message: removeQuotes(message) } : undefined;
145
+ })
146
+ .filter((message) => message);
147
+ const transaction = view.state.tr;
148
+ transaction.setMeta(documentValidationPluginKey, {
149
+ type: 'setNewReport',
150
+ report,
151
+ propertiesWithoutErrors,
152
+ propertiesWithErrors: propertiesWithErrorsMessages,
153
+ });
154
+ transaction.setMeta('addToHistory', false);
155
+ view.dispatch(transaction);
156
+ }
157
+
158
+ interface N3Parser {
159
+ parse: (
160
+ triples: string,
161
+ callback: (error: string, quad: Quad) => void,
162
+ ) => void;
163
+ }
164
+
165
+ async function parse(triples: string): Promise<DatasetCore<Quad>> {
166
+ return new Promise((resolve, reject) => {
167
+ // @ts-expect-error we have to use a custom type to make the quads compatible or else ts will complain
168
+ const parser: N3Parser = new ParserN3();
169
+ const dataset = factory.dataset();
170
+ parser.parse(triples, (error, quad) => {
171
+ if (error) {
172
+ console.warn(error);
173
+ reject(error);
174
+ } else if (quad) {
175
+ dataset.add(quad);
176
+ } else {
177
+ resolve(dataset);
178
+ }
179
+ });
180
+ });
181
+ }
182
+
183
+ function htmlToRdf(html: string): Promise<DatasetCore<Quad>> {
184
+ return new Promise((res, rej) => {
185
+ const myParser = new RdfaParser({ contentType: 'text/html' });
186
+ const dataset = factory.dataset();
187
+ myParser
188
+ .on('data', (data) => {
189
+ dataset.add(data);
190
+ })
191
+ .on('error', rej)
192
+ .on('end', () => res(dataset));
193
+ myParser.write(html);
194
+ myParser.end();
195
+ });
196
+ }