@lblod/ember-rdfa-editor-lblod-plugins 11.1.0 → 11.3.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 (45) hide show
  1. package/.woodpecker/.changelog.yml +9 -0
  2. package/.woodpecker/.test.yml +0 -8
  3. package/CHANGELOG.md +14 -1
  4. package/README.md +14 -12
  5. package/addon/components/citation-plugin/citation-card.ts +22 -18
  6. package/addon/components/citation-plugin/citation-insert.hbs +0 -1
  7. package/addon/components/citation-plugin/citation-insert.ts +5 -7
  8. package/addon/components/citation-plugin/citations/decision-detail.ts +4 -5
  9. package/addon/components/citation-plugin/citations/decision-preview.hbs +61 -15
  10. package/addon/components/citation-plugin/citations/decision-preview.ts +19 -0
  11. package/addon/components/citation-plugin/citations/search-modal.hbs +49 -47
  12. package/addon/components/citation-plugin/citations/search-modal.ts +28 -17
  13. package/addon/components/variable-plugin/codelist/edit.ts +6 -1
  14. package/addon/components/variable-plugin/codelist/insert.hbs +16 -6
  15. package/addon/components/variable-plugin/codelist/insert.ts +40 -9
  16. package/addon/plugins/citation-plugin/index.ts +8 -2
  17. package/addon/plugins/citation-plugin/utils/article.ts +193 -0
  18. package/addon/plugins/citation-plugin/utils/cache.ts +7 -0
  19. package/addon/plugins/citation-plugin/utils/legal-documents.ts +133 -0
  20. package/addon/plugins/citation-plugin/utils/process-match.ts +60 -44
  21. package/addon/plugins/citation-plugin/utils/public-decisions.ts +228 -0
  22. package/addon/plugins/citation-plugin/utils/{legislation-types.ts → types.ts} +24 -18
  23. package/addon/plugins/citation-plugin/utils/utils.ts +14 -0
  24. package/addon/plugins/citation-plugin/utils/vlaamse-codex.ts +29 -390
  25. package/addon/plugins/variable-plugin/utils/attribute-parsers.ts +4 -0
  26. package/addon/plugins/variable-plugin/variables/codelist.ts +15 -2
  27. package/components/citation-plugin/citation-card.d.ts +11 -14
  28. package/components/citation-plugin/citation-insert.d.ts +4 -3
  29. package/components/citation-plugin/citations/decision-detail.d.ts +3 -3
  30. package/components/citation-plugin/citations/decision-preview.d.ts +10 -0
  31. package/components/citation-plugin/citations/search-modal.d.ts +15 -16
  32. package/components/variable-plugin/codelist/insert.d.ts +18 -4
  33. package/package.json +4 -3
  34. package/plugins/citation-plugin/index.d.ts +2 -1
  35. package/plugins/citation-plugin/utils/article.d.ts +29 -0
  36. package/plugins/citation-plugin/utils/cache.d.ts +1 -0
  37. package/plugins/citation-plugin/utils/legal-documents.d.ts +48 -0
  38. package/plugins/citation-plugin/utils/public-decisions.d.ts +8 -0
  39. package/plugins/citation-plugin/utils/types.d.ts +28 -0
  40. package/plugins/citation-plugin/utils/utils.d.ts +1 -0
  41. package/plugins/citation-plugin/utils/vlaamse-codex.d.ts +7 -69
  42. package/plugins/variable-plugin/utils/attribute-parsers.d.ts +1 -0
  43. package/translations/en-US.yaml +7 -1
  44. package/translations/nl-BE.yaml +7 -1
  45. package/plugins/citation-plugin/utils/legislation-types.d.ts +0 -24
@@ -1,12 +1,22 @@
1
1
  <PowerSelect
2
2
  @allowClear={{false}}
3
3
  @searchEnabled={{false}}
4
- @options={{this.subtypes.value}}
5
- @selected={{this.selectedSubtype}}
6
- @onChange={{this.updateSubtype}}
7
- as |subtype|
4
+ @options={{this.codelistData.value}}
5
+ @selected={{this.selectedCodelist}}
6
+ @onChange={{this.selectCodelist}}
7
+ as |codelist|
8
8
  >
9
- {{subtype.label}}
9
+ {{codelist.label}}
10
+ </PowerSelect>
11
+ <PowerSelect
12
+ @allowClear={{false}}
13
+ @searchEnabled={{false}}
14
+ @options={{this.selectionStyles}}
15
+ @selected={{this.selectedStyle}}
16
+ @onChange={{this.selectStyle}}
17
+ as |style|
18
+ >
19
+ {{style.label}}
10
20
  </PowerSelect>
11
21
  <AuFormRow>
12
22
  <VariablePlugin::Utils::LabelInput
@@ -16,7 +26,7 @@
16
26
  </AuFormRow>
17
27
  <AuButton
18
28
  {{on 'click' this.insert}}
19
- @disabled={{not this.selectedSubtype}}
29
+ @disabled={{not this.selectedCodelist}}
20
30
  >
21
31
  {{t 'variable-plugin.button'}}
22
32
  </AuButton>
@@ -15,16 +15,22 @@ export type CodelistInsertOptions = {
15
15
  publisher?: string;
16
16
  endpoint: string;
17
17
  };
18
+
18
19
  type Args = {
19
20
  controller: SayController;
20
21
  options: CodelistInsertOptions;
21
22
  };
22
23
 
23
- export default class CodelistInsertComponent extends Component<Args> {
24
- @tracked selectedSubtype?: CodeList;
25
- @tracked label?: string;
24
+ interface SelectStyle {
25
+ label: string;
26
+ value: string;
27
+ }
26
28
 
29
+ export default class CodelistInsertComponent extends Component<Args> {
27
30
  @service declare intl: IntlService;
31
+ @tracked selectedCodelist?: CodeList;
32
+ @tracked label?: string;
33
+ @tracked selectedStyleValue = 'single';
28
34
 
29
35
  get controller() {
30
36
  return this.args.controller;
@@ -42,9 +48,28 @@ export default class CodelistInsertComponent extends Component<Args> {
42
48
  return this.args.options.endpoint;
43
49
  }
44
50
 
45
- subtypes = trackedFunction(this, async () => {
51
+ get selectionStyles() {
52
+ const singleSelect = {
53
+ label: this.intl.t('variable.codelist.single-select'),
54
+ value: 'single',
55
+ };
56
+ const multiSelect = {
57
+ label: this.intl.t('variable.codelist.multi-select'),
58
+ value: 'multi',
59
+ };
60
+ return [singleSelect, multiSelect];
61
+ }
62
+
63
+ get selectedStyle() {
64
+ return this.selectionStyles.find(
65
+ (style) => style.value === this.selectedStyleValue,
66
+ );
67
+ }
68
+
69
+ codelistData = trackedFunction(this, async () => {
46
70
  return fetchCodeListsByPublisher(this.endpoint, this.publisher);
47
71
  });
72
+
48
73
  @action
49
74
  updateLabel(event: InputEvent) {
50
75
  this.label = (event.target as HTMLInputElement).value;
@@ -58,12 +83,13 @@ export default class CodelistInsertComponent extends Component<Args> {
58
83
  {
59
84
  mappingResource,
60
85
  variableInstance,
61
- codelistResource: this.selectedSubtype?.uri,
62
- label: this.label ?? this.selectedSubtype?.label,
86
+ codelistResource: this.selectedCodelist?.uri,
87
+ label: this.label ?? this.selectedCodelist?.label,
63
88
  source: this.endpoint,
89
+ selectionStyle: this.selectedStyleValue,
64
90
  },
65
91
  this.schema.node('placeholder', {
66
- placeholderText: this.selectedSubtype?.label,
92
+ placeholderText: this.selectedCodelist?.label,
67
93
  }),
68
94
  );
69
95
 
@@ -78,7 +104,12 @@ export default class CodelistInsertComponent extends Component<Args> {
78
104
  }
79
105
 
80
106
  @action
81
- updateSubtype(subtype: CodeList) {
82
- this.selectedSubtype = subtype;
107
+ selectCodelist(codelist: CodeList) {
108
+ this.selectedCodelist = codelist;
109
+ }
110
+
111
+ @action
112
+ selectStyle(style: SelectStyle) {
113
+ this.selectedStyleValue = style.value;
83
114
  }
84
115
  }
@@ -81,12 +81,17 @@ const MINISTERIAL = `ministerieel${NNWS}?besluit`;
81
81
  */
82
82
  const ENUM_ROYAL = `genummerd${NNWS}?${ROYAL}`;
83
83
 
84
+ /**
85
+ * match for "decision of the flemish government"
86
+ */
87
+ const DECISION = 'besluit';
88
+
84
89
  /**
85
90
  * The type of citation that we need to search for
86
91
  */
87
- const TYPE = `${DECREE}|${MEMO}|${TREATY}|${CONSTITUTION_CHANGE}|${COLLAB}|${BOOK}|${PROTOCOL}|${FLEMGOV}|${COORD}|${SPECIAL}|${LAW}|${ROYAL}|${MINISTERIAL}|${ENUM_ROYAL}`;
92
+ const TYPE = `${DECREE}|${MEMO}|${TREATY}|${CONSTITUTION_CHANGE}|${COLLAB}|${BOOK}|${PROTOCOL}|${FLEMGOV}|${COORD}|${SPECIAL}|${LAW}|${ROYAL}|${MINISTERIAL}|${ENUM_ROYAL}|${DECISION}`;
88
93
  /**
89
- * The monster regex that makes the citation plugin trigger.
94
+ * The monster regex that makes the citation plugin trigger to show `CitationCard`.
90
95
  * In restructuring, I've made sure that I didn't abstract away any of the capturing groups,
91
96
  * only their content, so you can still see what's going on
92
97
  *
@@ -134,6 +139,7 @@ export type CitationPluginConfig =
134
139
 
135
140
  export type CitationPluginEmberComponentConfig = CitationPluginConfig & {
136
141
  endpoint: string;
142
+ decisionsEndpoint?: string;
137
143
  };
138
144
 
139
145
  export function citationPlugin(config: CitationPluginConfig): CitationPlugin {
@@ -0,0 +1,193 @@
1
+ import { LegalDocumentsQueryConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
2
+ import {
3
+ executeCountQuery,
4
+ executeQuery,
5
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/sparql-helpers';
6
+ import {
7
+ dateValue,
8
+ escapeValue,
9
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
10
+ import { Binding } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/types';
11
+
12
+ interface ArticleArgs {
13
+ uri: string;
14
+ number?: number;
15
+ content: string | null;
16
+ dateInForce: string | null;
17
+ dateNoLongerInForce: string | null;
18
+ }
19
+
20
+ export class Article {
21
+ uri: string;
22
+ number?: number;
23
+ content: string | null;
24
+ dateInForce: string | null;
25
+ dateNoLongerInForce: string | null;
26
+
27
+ constructor({
28
+ uri,
29
+ number,
30
+ content,
31
+ dateInForce,
32
+ dateNoLongerInForce,
33
+ }: ArticleArgs) {
34
+ this.uri = uri;
35
+ this.number = number;
36
+ this.content = content;
37
+ this.dateInForce = dateInForce;
38
+ this.dateNoLongerInForce = dateNoLongerInForce;
39
+ }
40
+ }
41
+
42
+ export const fetchArticlesCache = new Map<string, ArticleCollection>();
43
+
44
+ async function fetchArticles({
45
+ legalExpression,
46
+ pageNumber,
47
+ pageSize,
48
+ articleFilter,
49
+ config,
50
+ }: {
51
+ legalExpression: string;
52
+ pageNumber: number;
53
+ pageSize: number;
54
+ articleFilter: string;
55
+ config: LegalDocumentsQueryConfig;
56
+ }): Promise<ArticleCollection> {
57
+ //Simpler here, only one way arguments are set up
58
+ const stringArguments = JSON.stringify({
59
+ legalExpression,
60
+ pageNumber,
61
+ pageSize,
62
+ articleFilter,
63
+ });
64
+ const results = fetchArticlesCache.get(stringArguments);
65
+ if (results) {
66
+ return results;
67
+ } else {
68
+ const newResults = await fetchArticlesMemo({
69
+ legalExpression,
70
+ pageNumber,
71
+ pageSize,
72
+ articleFilter,
73
+ config,
74
+ });
75
+ fetchArticlesCache.set(stringArguments, newResults);
76
+ return newResults;
77
+ }
78
+ }
79
+
80
+ interface ArticleBinding {
81
+ count: Binding<string>;
82
+ content?: Binding<string>;
83
+ dateInForce?: Binding<string>;
84
+ dateNoLongerInForce?: Binding<string>;
85
+ article: Binding<string>;
86
+ number?: Binding<number>;
87
+ }
88
+
89
+ interface ArticleCollection {
90
+ totalCount: number;
91
+ articles: Article[];
92
+ }
93
+
94
+ async function fetchArticlesMemo({
95
+ legalExpression,
96
+ pageNumber = 0,
97
+ pageSize = 10,
98
+ articleFilter,
99
+ config,
100
+ }: {
101
+ legalExpression: string;
102
+ pageNumber: number;
103
+ pageSize: number;
104
+ articleFilter: string;
105
+ config: LegalDocumentsQueryConfig;
106
+ }): Promise<ArticleCollection> {
107
+ const numberFilter = articleFilter
108
+ ? `FILTER( !BOUND(?number) || CONTAINS(?number, "${articleFilter}"))`
109
+ : '';
110
+ const totalCount = await executeCountQuery({
111
+ query: `PREFIX eli: <http://data.europa.eu/eli/ontology#>
112
+ PREFIX dct: <http://purl.org/dc/terms/>
113
+
114
+ SELECT COUNT(DISTINCT(?article)) as ?count
115
+ WHERE {
116
+ ?legalResource eli:is_realized_by <${legalExpression}> ;
117
+ eli:has_part ?articleResource .
118
+ ?articleResource eli:is_realized_by ?article ;
119
+ dct:type <https://data.vlaanderen.be/id/concept/TypeRechtsbrononderdeel/Artikel>.
120
+ OPTIONAL {
121
+ ?article eli:first_date_entry_in_force ?dateInForce .
122
+ FILTER (?dateInForce <= NOW() )
123
+ }
124
+ OPTIONAL { ?article eli:date_no_longer_in_force ?dateNoLongerInForce }
125
+ FILTER( !BOUND(?dateNoLongerInForce) || ?dateNoLongerInForce > NOW() )
126
+ OPTIONAL { ?article eli:number ?number . }
127
+ ${numberFilter}
128
+ }`,
129
+ ...config,
130
+ });
131
+
132
+ if (totalCount > 0) {
133
+ // ?number has format like "Artikel 12." We parse the number from the string for ordering
134
+ // Second degree ordering on ?numberStr to make sure "Artikel 3/1." comes after "Artikel 3."
135
+ const response = await executeQuery<ArticleBinding>({
136
+ query: `PREFIX eli: <http://data.europa.eu/eli/ontology#>
137
+ PREFIX prov: <http://www.w3.org/ns/prov#>
138
+ PREFIX dct: <http://purl.org/dc/terms/>
139
+
140
+ SELECT DISTINCT ?article ?dateInForce ?dateNoLongerInForce ?number ?content WHERE {
141
+ ?legalResource eli:is_realized_by <${legalExpression}> ;
142
+ eli:has_part ?articleResource .
143
+ ?articleResource eli:is_realized_by ?article ;
144
+ dct:type <https://data.vlaanderen.be/id/concept/TypeRechtsbrononderdeel/Artikel>.
145
+ OPTIONAL {
146
+ ?article eli:first_date_entry_in_force ?dateInForce .
147
+ FILTER (?dateInForce <= NOW() )
148
+ }
149
+ OPTIONAL { ?article eli:date_no_longer_in_force ?dateNoLongerInForce }
150
+ FILTER( !BOUND(?dateNoLongerInForce) || ?dateNoLongerInForce > NOW() )
151
+ OPTIONAL { ?article prov:value ?content . }
152
+ OPTIONAL { ?article eli:number ?number . }
153
+ ${numberFilter}
154
+ BIND(REPLACE(?number, "Artikel ", "") as ?numberStr)
155
+ BIND(STRDT(?numberStr, xsd:integer) as ?numberInt)
156
+ } ORDER BY ?numberInt ?numberStr LIMIT ${pageSize} OFFSET ${
157
+ pageNumber * pageSize
158
+ }`,
159
+ ...config,
160
+ });
161
+
162
+ const articles = response.results.bindings.map((binding) => {
163
+ const escapedContent = escapeValue(
164
+ binding.content && binding.content.value,
165
+ );
166
+ const dateInForce = dateValue(
167
+ binding.dateInForce && binding.dateInForce.value,
168
+ );
169
+ const dateNoLongerInForce = dateValue(
170
+ binding.dateNoLongerInForce && binding.dateNoLongerInForce.value,
171
+ );
172
+ return new Article({
173
+ uri: binding.article.value,
174
+ number: binding.number && binding.number.value,
175
+ content: escapedContent,
176
+ dateInForce,
177
+ dateNoLongerInForce,
178
+ });
179
+ });
180
+
181
+ return {
182
+ totalCount,
183
+ articles,
184
+ };
185
+ } else {
186
+ return {
187
+ totalCount,
188
+ articles: [],
189
+ };
190
+ }
191
+ }
192
+
193
+ export { fetchArticles };
@@ -0,0 +1,7 @@
1
+ import { fetchLegalDocumentsCache } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
2
+ import { fetchArticlesCache } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/article';
3
+
4
+ export function cleanCaches() {
5
+ fetchLegalDocumentsCache.clear();
6
+ fetchArticlesCache.clear();
7
+ }
@@ -0,0 +1,133 @@
1
+ import {
2
+ isBesluitType,
3
+ LEGISLATION_TYPE_CONCEPTS,
4
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/types';
5
+ import { fetchVlaamseCodexLegalDocuments } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/vlaamse-codex';
6
+ import { Option } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
7
+ import { fetchPublicDecisions } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/public-decisions';
8
+
9
+ interface LegalDocumentArgs {
10
+ uri: string;
11
+ legislationTypeUri: Option<string>;
12
+ title: string | null;
13
+ publicationDate: string | null;
14
+ documentDate: string | null;
15
+ meta?: Record<string, unknown> | null;
16
+ }
17
+
18
+ export class LegalDocument {
19
+ uri: string;
20
+ legislationType: { label: string; value: string } | undefined;
21
+ title: string | null;
22
+ publicationDate: string | null;
23
+ documentDate: string | null;
24
+ meta: Record<string, unknown> | null;
25
+
26
+ constructor({
27
+ uri,
28
+ legislationTypeUri,
29
+ title,
30
+ publicationDate,
31
+ documentDate,
32
+ meta,
33
+ }: LegalDocumentArgs) {
34
+ this.uri = uri;
35
+ this.legislationType = LEGISLATION_TYPE_CONCEPTS.find(
36
+ (t) => t.value === legislationTypeUri,
37
+ );
38
+ this.title = title;
39
+ this.publicationDate = publicationDate;
40
+ this.documentDate = documentDate;
41
+ this.meta = meta ?? null;
42
+ }
43
+
44
+ get fullTitle() {
45
+ return `${this.legislationType?.label ?? ''} ${this.title ?? ''}`;
46
+ }
47
+ }
48
+
49
+ export const isBesluitLegalDocument = (legalDocument: LegalDocument) =>
50
+ isBesluitType(legalDocument.legislationType?.value ?? '');
51
+
52
+ export const fetchLegalDocumentsCache = new Map<
53
+ string,
54
+ LegalDocumentsCollection
55
+ >();
56
+
57
+ export interface LegalDocumentsCollection {
58
+ totalCount: number;
59
+ legalDocuments: LegalDocument[];
60
+ }
61
+
62
+ export interface LegalDocumentsQueryFilter {
63
+ type: string;
64
+ documentDateFrom?: Option<string>;
65
+ documentDateTo?: Option<string>;
66
+ publicationDateFrom?: Option<string>;
67
+ publicationDateTo?: Option<string>;
68
+ }
69
+
70
+ export type LegalDocumentsQueryConfig = {
71
+ endpoint: string;
72
+ decisionsEndpoint?: string;
73
+ abortSignal?: AbortSignal;
74
+ };
75
+
76
+ export async function fetchLegalDocuments({
77
+ words,
78
+ filter,
79
+ pageNumber = 0,
80
+ pageSize = 5,
81
+ config,
82
+ }: {
83
+ words: string[];
84
+ filter: LegalDocumentsQueryFilter;
85
+ pageNumber: number;
86
+ pageSize: number;
87
+ config: LegalDocumentsQueryConfig;
88
+ }) {
89
+ //This is silly, but null != undefined, so we have to be careful and include the correct value here
90
+ //Also, reconstruct the whole filter object to always have the same ordering, hopefully.
91
+ filter = {
92
+ type: filter.type,
93
+ documentDateFrom: filter.documentDateFrom || null,
94
+ documentDateTo: filter.documentDateTo || null,
95
+ publicationDateFrom: filter.publicationDateFrom || null,
96
+ publicationDateTo: filter.publicationDateTo || null,
97
+ };
98
+ const stringArguments = JSON.stringify({
99
+ words,
100
+ filter,
101
+ pageNumber,
102
+ pageSize,
103
+ });
104
+ const results = fetchLegalDocumentsCache.get(stringArguments);
105
+
106
+ if (results) {
107
+ return results;
108
+ } else {
109
+ const shouldQueryPublicDecisions =
110
+ isBesluitType(filter.type) && config.decisionsEndpoint;
111
+
112
+ const fetchConfig = {
113
+ words,
114
+ filter,
115
+ pageNumber,
116
+ pageSize,
117
+ config: {
118
+ endpoint: shouldQueryPublicDecisions
119
+ ? (config.decisionsEndpoint as string)
120
+ : config.endpoint,
121
+ abortSignal: config.abortSignal,
122
+ },
123
+ };
124
+
125
+ const newResults = shouldQueryPublicDecisions
126
+ ? await fetchPublicDecisions(fetchConfig)
127
+ : await fetchVlaamseCodexLegalDocuments(fetchConfig);
128
+
129
+ fetchLegalDocumentsCache.set(stringArguments, newResults);
130
+
131
+ return newResults;
132
+ }
133
+ }
@@ -1,5 +1,5 @@
1
1
  import { isBlank } from '@ember/utils';
2
- import { LEGISLATION_TYPES } from './legislation-types';
2
+ import { isLegislationType, LEGISLATION_TYPES } from './types';
3
3
  import { unwrap } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
4
4
 
5
5
  const STOP_WORDS = ['het', 'de', 'van', 'tot', 'dat'];
@@ -28,6 +28,44 @@ interface ProcessedMatch {
28
28
  };
29
29
  }
30
30
 
31
+ const getTypeLabel = (
32
+ type: string,
33
+ ): keyof typeof LEGISLATION_TYPES | string => {
34
+ switch (true) {
35
+ case /\w+decreet/i.test(type):
36
+ case /decreet/i.test(type):
37
+ return 'decreet';
38
+ case /\w+wetboek/i.test(type):
39
+ case /wetboek/i.test(type):
40
+ return 'wetboek';
41
+ case /geco[oö]rdineerde[^\S\n]wet(ten)?/i.test(type):
42
+ return 'gecoördineerde wetten';
43
+ case /grondwets?wijziging/i.test(type):
44
+ return 'grondwetswijziging';
45
+ case /grondwet/i.test(type):
46
+ return 'grondwet';
47
+ case /bijzondere[^\S\n]wet/i.test(type):
48
+ return 'bijzondere wet';
49
+ case /\w+wet/i.test(type):
50
+ case /wet/i.test(type):
51
+ return 'wet';
52
+ default:
53
+ return type.toLowerCase().trim();
54
+ }
55
+ };
56
+
57
+ const getAugmentedSearchTerms = (type: string, searchTerms: string) => {
58
+ if (
59
+ /\w+decreet/i.test(type) ||
60
+ /\w+wetboek/i.test(type) ||
61
+ /\w+wet/i.test(type)
62
+ ) {
63
+ return `${type} ${searchTerms}`;
64
+ }
65
+
66
+ return searchTerms;
67
+ };
68
+
31
69
  export default function processMatch(
32
70
  match: RegexpMatchArrayWithIndices,
33
71
  ): ProcessedMatch | null {
@@ -40,45 +78,23 @@ export default function processMatch(
40
78
  if (!type || !searchTerms) {
41
79
  return null;
42
80
  }
43
- let cleanedSearchTerms = cleanupText(searchTerms)
81
+
82
+ const cleanedSearchTerms = cleanupText(searchTerms)
44
83
  .split(SPACES_REGEX)
45
84
  .filter(
46
85
  (word) => !isBlank(word) && word.length > 3 && !STOP_WORDS.includes(word),
47
86
  )
48
87
  .join(' ');
88
+
49
89
  if (type) {
50
- let typeLabel: string;
51
- if (/\w+decreet/i.test(type)) {
52
- typeLabel = 'decreet';
53
- cleanedSearchTerms = `${type} ${cleanedSearchTerms}`;
54
- } else if (/decreet/i.test(type)) {
55
- typeLabel = 'decreet';
56
- } else if (/\w+wetboek/i.test(type)) {
57
- typeLabel = 'wetboek';
58
- cleanedSearchTerms = `${type} ${cleanedSearchTerms}`;
59
- } else if (/wetboek/i.test(type)) {
60
- typeLabel = 'wetboek';
61
- } else if (/geco[oö]rdineerde[^\S\n]wet(ten)?/i.test(type)) {
62
- typeLabel = 'gecoördineerde wetten';
63
- } else if (/grondwets?wijziging/i.test(type)) {
64
- typeLabel = 'grondwetswijziging';
65
- } else if (/grondwet/i.test(type)) {
66
- typeLabel = 'grondwet';
67
- } else if (/bijzondere[^\S\n]wet/i.test(type)) {
68
- typeLabel = 'bijzondere wet';
69
- } else if (/\w+wet/i.test(type)) {
70
- typeLabel = 'wet';
71
- cleanedSearchTerms = `${type} ${cleanedSearchTerms}`;
72
- } else if (/wet/i.test(type)) {
73
- typeLabel = 'wet';
74
- } else {
75
- typeLabel = type.toLowerCase().trim();
76
- }
77
- const typeUri =
78
- (LEGISLATION_TYPES as Record<string, string>)[typeLabel] ||
79
- LEGISLATION_TYPES['decreet'];
90
+ const typeLabel = getTypeLabel(type);
91
+
92
+ const typeUri = isLegislationType(typeLabel)
93
+ ? LEGISLATION_TYPES[typeLabel]
94
+ : LEGISLATION_TYPES['decreet'];
95
+
80
96
  return {
81
- text: cleanedSearchTerms,
97
+ text: getAugmentedSearchTerms(type, cleanedSearchTerms),
82
98
  legislationTypeUri: typeUri,
83
99
  typeMatch: {
84
100
  text: type,
@@ -91,18 +107,18 @@ export default function processMatch(
91
107
  end: unwrap(match.indices.groups['searchTerms'])[1],
92
108
  },
93
109
  };
94
- } else {
95
- return {
96
- text: cleanedSearchTerms,
97
- legislationTypeUri: LEGISLATION_TYPES['decreet'],
98
- typeMatch: null,
99
- searchTextMatch: {
100
- text: searchTerms,
101
- start: unwrap(match.indices.groups['searchTerms'])[0],
102
- end: unwrap(match.indices.groups['searchTerms'])[1],
103
- },
104
- };
105
110
  }
111
+
112
+ return {
113
+ text: cleanedSearchTerms,
114
+ legislationTypeUri: LEGISLATION_TYPES['decreet'],
115
+ typeMatch: null,
116
+ searchTextMatch: {
117
+ text: searchTerms,
118
+ start: unwrap(match.indices.groups['searchTerms'])[0],
119
+ end: unwrap(match.indices.groups['searchTerms'])[1],
120
+ },
121
+ };
106
122
  }
107
123
 
108
124
  function cleanupText(text?: string): string {