@erudit-js/prose 3.0.0-dev.30 → 4.0.0-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/app/composables/context.d.ts +2 -1
  2. package/dist/app/composables/formatText.d.ts +5 -1
  3. package/dist/app/composables/formatText.js +5 -0
  4. package/dist/app/default/Text.vue +6 -2
  5. package/dist/app/shared/Prose.vue +4 -0
  6. package/dist/app/shared/block/Block.vue +5 -0
  7. package/dist/app/shared/invert.d.ts +2 -2
  8. package/dist/app/shared/invert.js +2 -2
  9. package/dist/app/shared/photoswipe/composable.js +1 -1
  10. package/dist/elements/accent/Accent.vue +2 -2
  11. package/dist/elements/accent/AccentColumnSection.vue +2 -2
  12. package/dist/elements/accent/AccentRowSections.vue +1 -1
  13. package/dist/elements/accent/core.d.ts +2 -2
  14. package/dist/elements/callout/Callout.vue +6 -9
  15. package/dist/elements/callout/core.d.ts +3 -3
  16. package/dist/elements/caption/Caption.vue +1 -1
  17. package/dist/elements/details/Details.vue +2 -3
  18. package/dist/elements/diagram/Diagram.vue +12 -2
  19. package/dist/elements/diagram/core.d.ts +3 -3
  20. package/dist/elements/emphasis/Emphasis.vue +1 -1
  21. package/dist/elements/emphasis/core.d.ts +6 -6
  22. package/dist/elements/flex/Flex.vue +8 -2
  23. package/dist/elements/flex/core.d.ts +7 -3
  24. package/dist/elements/flex/core.js +4 -0
  25. package/dist/elements/gallery/core.d.ts +3 -3
  26. package/dist/elements/heading/Heading.vue +1 -1
  27. package/dist/elements/heading/core.d.ts +9 -9
  28. package/dist/elements/heading/core.js +14 -10
  29. package/dist/elements/horizontalLine/HorizontalLine.vue +1 -1
  30. package/dist/elements/image/core.d.ts +3 -3
  31. package/dist/elements/link/BlockLink.vue +1 -2
  32. package/dist/elements/link/Link.vue +6 -3
  33. package/dist/elements/list/List.vue +10 -8
  34. package/dist/elements/list/core.d.ts +3 -3
  35. package/dist/elements/math/block.d.ts +9 -6
  36. package/dist/elements/math/block.js +2 -1
  37. package/dist/elements/math/components/BlockMath.vue +1 -1
  38. package/dist/elements/math/components/MathGroup.vue +5 -3
  39. package/dist/elements/math/core.d.ts +2 -2
  40. package/dist/elements/math/inliner.d.ts +2 -2
  41. package/dist/elements/paragraph/Paragraph.vue +1 -1
  42. package/dist/elements/paragraph/core.d.ts +3 -3
  43. package/dist/elements/problem/components/ProblemButton.vue +2 -2
  44. package/dist/elements/problem/components/ProblemContainer.vue +1 -2
  45. package/dist/elements/problem/components/ProblemExpander.vue +1 -1
  46. package/dist/elements/problem/components/ProblemExpanderSection.vue +2 -3
  47. package/dist/elements/problem/components/ProblemHeader.vue +2 -6
  48. package/dist/elements/problem/components/Problems.vue +3 -3
  49. package/dist/elements/problem/components/expanders/Check.vue +2 -3
  50. package/dist/elements/problem/components/expanders/Checks.vue +1 -1
  51. package/dist/elements/problem/core.d.ts +44 -8
  52. package/dist/elements/problem/problem.d.ts +3 -3
  53. package/dist/elements/problem/problem.js +3 -4
  54. package/dist/elements/problem/problemContent.d.ts +42 -37
  55. package/dist/elements/problem/problemContent.js +86 -2
  56. package/dist/elements/problem/problems.d.ts +3 -3
  57. package/dist/elements/problem/problems.js +3 -4
  58. package/dist/elements/table/Table.vue +2 -4
  59. package/dist/elements/table/core.d.ts +3 -3
  60. package/dist/elements/video/core.d.ts +3 -3
  61. package/dist/include.js +0 -1
  62. package/dist/snippet.d.ts +24 -34
  63. package/dist/snippet.js +60 -31
  64. package/dist/tag.d.ts +3 -3
  65. package/dist/tag.js +1 -1
  66. package/package.json +2 -2
@@ -328,13 +328,23 @@ export type CheckFunction = (args: {
328
328
  name: string;
329
329
  answers: Record<string, string | undefined>;
330
330
  }) => boolean;
331
+ export interface ProblemCheckRegex {
332
+ pattern: string;
333
+ flags: string;
334
+ }
335
+ export type ProblemCheckValue = string | ProblemCheckRegex;
331
336
  export interface ProblemCheckData {
332
337
  label?: string;
333
338
  hint?: string;
334
339
  placeholder?: string;
335
- answers?: (string | undefined)[];
340
+ set?: {
341
+ separator: string;
342
+ values: (ProblemCheckValue | ProblemCheckValue[])[];
343
+ };
344
+ answers?: ProblemCheckValue[];
336
345
  script?: string;
337
346
  }
347
+ export declare function checkValue(input: string | undefined, data: ProblemCheckData): boolean;
338
348
  export declare const problemCheckSchema: {
339
349
  name: "problemCheck";
340
350
  type: "block";
@@ -343,6 +353,12 @@ export declare const problemCheckSchema: {
343
353
  Storage: undefined;
344
354
  Children: BlockSchema[];
345
355
  };
356
+ type UndefinedOnly<T> = {
357
+ [K in keyof T]?: undefined;
358
+ };
359
+ type OneOf<T extends Record<string, any>> = {
360
+ [K in keyof T]: Pick<T, K> & UndefinedOnly<Omit<T, K>>;
361
+ }[keyof T];
346
362
  export declare const ProblemCheck: import("@jsprose/core").Tag<"ProblemCheck", {
347
363
  name: "problemCheck";
348
364
  type: "block";
@@ -354,19 +370,15 @@ export declare const ProblemCheck: import("@jsprose/core").Tag<"ProblemCheck", {
354
370
  label?: string;
355
371
  hint?: string;
356
372
  placeholder?: string;
357
- } & (({
358
- answer: string | number;
359
- answers?: undefined;
360
- script?: undefined;
361
- } | {
362
- answers: (string | number)[];
363
- answer?: undefined;
364
- script?: undefined;
365
- } | {
373
+ } & (OneOf<{
374
+ answer: string | number | RegExp;
375
+ answers: (string | number | RegExp)[];
376
+ set: (string | number | RegExp | (string | number | RegExp)[])[] | {
377
+ separator: string;
378
+ values: (string | number | RegExp | (string | number | RegExp)[])[];
379
+ };
366
380
  script: string;
367
- answers?: undefined;
368
- answer?: undefined;
369
- }) & NoTagChildren)) & {}>;
381
+ }> & NoTagChildren)) & {}>;
370
382
  export declare const problemCheckRegistryItem: import("@jsprose/core").RegistryItem<{
371
383
  name: "problemCheck";
372
384
  type: "block";
@@ -386,19 +398,15 @@ export declare const problemCheckRegistryItem: import("@jsprose/core").RegistryI
386
398
  label?: string;
387
399
  hint?: string;
388
400
  placeholder?: string;
389
- } & (({
390
- answer: string | number;
391
- answers?: undefined;
392
- script?: undefined;
393
- } | {
394
- answers: (string | number)[];
395
- answer?: undefined;
396
- script?: undefined;
397
- } | {
401
+ } & (OneOf<{
402
+ answer: string | number | RegExp;
403
+ answers: (string | number | RegExp)[];
404
+ set: (string | number | RegExp | (string | number | RegExp)[])[] | {
405
+ separator: string;
406
+ values: (string | number | RegExp | (string | number | RegExp)[])[];
407
+ };
398
408
  script: string;
399
- answers?: undefined;
400
- answer?: undefined;
401
- }) & NoTagChildren)) & {}>;
409
+ }> & NoTagChildren)) & {}>;
402
410
  }, undefined>;
403
411
  export declare const problemCheckCoreElement: {
404
412
  registryItem: import("@jsprose/core").RegistryItem<{
@@ -420,20 +428,17 @@ export declare const problemCheckCoreElement: {
420
428
  label?: string;
421
429
  hint?: string;
422
430
  placeholder?: string;
423
- } & (({
424
- answer: string | number;
425
- answers?: undefined;
426
- script?: undefined;
427
- } | {
428
- answers: (string | number)[];
429
- answer?: undefined;
430
- script?: undefined;
431
- } | {
431
+ } & (OneOf<{
432
+ answer: string | number | RegExp;
433
+ answers: (string | number | RegExp)[];
434
+ set: (string | number | RegExp | (string | number | RegExp)[])[] | {
435
+ separator: string;
436
+ values: (string | number | RegExp | (string | number | RegExp)[])[];
437
+ };
432
438
  script: string;
433
- answers?: undefined;
434
- answer?: undefined;
435
- }) & NoTagChildren)) & {}>;
439
+ }> & NoTagChildren)) & {}>;
436
440
  }, undefined>;
437
441
  };
438
442
  export type ProblemContentChild = typeof problemDescriptionSchema | typeof problemHintSchema | typeof problemNote.schema | typeof problemSolution.schema | typeof problemAnswer.schema | typeof problemCheckSchema;
439
443
  export declare function validateProblemContent(source: string, children: NormalizedChildren): void;
444
+ export {};
@@ -145,6 +145,62 @@ function defineProblemSectionContainer(name) {
145
145
  export const problemNote = defineProblemSectionContainer("note");
146
146
  export const problemSolution = defineProblemSectionContainer("solution");
147
147
  export const problemAnswer = defineProblemSectionContainer("answer");
148
+ export function checkValue(input, data) {
149
+ const normalizedInput = input?.trim().replace(/\s+/g, " ") || undefined;
150
+ const matchSingle = (val, condition) => {
151
+ const v = val || "";
152
+ if (typeof condition === "string") {
153
+ return v === condition;
154
+ }
155
+ try {
156
+ const re = new RegExp(condition.pattern, condition.flags);
157
+ return re.test(v);
158
+ } catch {
159
+ return false;
160
+ }
161
+ };
162
+ if (data.answers) {
163
+ if (!normalizedInput) return false;
164
+ return data.answers.some((ans) => matchSingle(normalizedInput, ans));
165
+ }
166
+ if (data.set) {
167
+ const { separator, values } = data.set;
168
+ const separatorRegex = new RegExp(`\\s*${separator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*`);
169
+ const inputValues = normalizedInput ? normalizedInput.split(separatorRegex).map((v) => v.trim()).filter((v) => v) : [];
170
+ if (inputValues.length !== values.length) {
171
+ return false;
172
+ }
173
+ const canMatch = (inputVal, expectedVal) => {
174
+ if (Array.isArray(expectedVal)) {
175
+ return expectedVal.some((ev) => matchSingle(inputVal, ev));
176
+ }
177
+ return matchSingle(inputVal, expectedVal);
178
+ };
179
+ const adj = inputValues.map((inputVal) => values.map((v, idx) => canMatch(inputVal, v) ? idx : -1).filter((idx) => idx !== -1));
180
+ const matchV = new Array(values.length).fill(-1);
181
+ const vis = new Array(values.length).fill(false);
182
+ const dfs = (u) => {
183
+ for (const v of adj[u]) {
184
+ if (vis[v]) continue;
185
+ vis[v] = true;
186
+ if (matchV[v] < 0 || dfs(matchV[v])) {
187
+ matchV[v] = u;
188
+ return true;
189
+ }
190
+ }
191
+ return false;
192
+ };
193
+ let matches = 0;
194
+ for (let i = 0; i < inputValues.length; i++) {
195
+ vis.fill(false);
196
+ if (dfs(i)) {
197
+ matches++;
198
+ }
199
+ }
200
+ return matches === values.length;
201
+ }
202
+ return false;
203
+ }
148
204
  export const problemCheckSchema = defineSchema({
149
205
  name: "problemCheck",
150
206
  type: "block",
@@ -155,21 +211,49 @@ export const ProblemCheck = defineEruditTag({
155
211
  schema: problemCheckSchema
156
212
  })(({ element, tagName, props, children }) => {
157
213
  ensureTagNoChildren(tagName, children);
214
+ const normalizeCheckValue = (val) => {
215
+ if (val instanceof RegExp) {
216
+ return {
217
+ pattern: val.source,
218
+ flags: val.flags
219
+ };
220
+ }
221
+ return String(val);
222
+ };
158
223
  if (props.answer !== undefined) {
159
224
  element.data = {
160
225
  ...element.data,
161
- answers: [String(props.answer)]
226
+ answers: [normalizeCheckValue(props.answer)]
162
227
  };
163
228
  } else if (props.answers !== undefined) {
164
229
  element.data = {
165
230
  ...element.data,
166
- answers: props.answers.map(String)
231
+ answers: props.answers.map(normalizeCheckValue)
167
232
  };
168
233
  } else if (props.script !== undefined) {
169
234
  element.data = {
170
235
  ...element.data,
171
236
  script: props.script
172
237
  };
238
+ } else if (props.set !== undefined) {
239
+ const normalizeSetItem = (v) => Array.isArray(v) ? v.map(normalizeCheckValue) : normalizeCheckValue(v);
240
+ if (Array.isArray(props.set)) {
241
+ element.data = {
242
+ ...element.data,
243
+ set: {
244
+ separator: ",",
245
+ values: props.set.map(normalizeSetItem)
246
+ }
247
+ };
248
+ } else {
249
+ element.data = {
250
+ ...element.data,
251
+ set: {
252
+ separator: props.set.separator,
253
+ values: props.set.values.map(normalizeSetItem)
254
+ }
255
+ };
256
+ }
173
257
  }
174
258
  if (props.label !== undefined) {
175
259
  element.data = {
@@ -127,7 +127,7 @@ export declare const Problems: import("@jsprose/core").Tag<"Problems", {
127
127
  applied?: true | undefined;
128
128
  method?: true | undefined;
129
129
  inter?: true | undefined;
130
- } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
130
+ } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
131
131
  export declare const problemsRegistryItem: import("@jsprose/core").RegistryItem<{
132
132
  name: "problems";
133
133
  type: "block";
@@ -166,7 +166,7 @@ export declare const problemsRegistryItem: import("@jsprose/core").RegistryItem<
166
166
  applied?: true | undefined;
167
167
  method?: true | undefined;
168
168
  inter?: true | undefined;
169
- } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
169
+ } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
170
170
  }, undefined>;
171
171
  export declare const problemsCoreElement: {
172
172
  registryItem: import("@jsprose/core").RegistryItem<{
@@ -207,6 +207,6 @@ export declare const problemsCoreElement: {
207
207
  applied?: true | undefined;
208
208
  method?: true | undefined;
209
209
  inter?: true | undefined;
210
- } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
210
+ } & TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
211
211
  }, undefined>;
212
212
  };
@@ -62,10 +62,9 @@ export const Problems = defineEruditTag({
62
62
  throw new ProseError(`<${tagName}> must have at least one <SubProblem> child!`);
63
63
  }
64
64
  element.children = [...otherChildren, ...subProblemChildren];
65
- element.data = problemProps2Info(props);
66
- element.title = element.data.title;
67
- element.snippet = {};
68
- element.toc = { add: true };
65
+ const problemInfo = problemProps2Info(props);
66
+ element.data = problemInfo;
67
+ element.title = problemInfo.title;
69
68
  });
70
69
  export const problemsRegistryItem = defineRegistryItem({
71
70
  schema: problemsSchema,
@@ -31,16 +31,14 @@ const rows = computed(() =>
31
31
  :class="[
32
32
  $style.table,
33
33
  `text-main-sm bg-bg-main m-auto max-w-full border-separate
34
- border-spacing-[3px] rounded border border-(--tableBorder)
35
- transition-[background,border]`,
34
+ border-spacing-[3px] rounded border border-(--tableBorder)`,
36
35
  ]"
37
36
  >
38
37
  <tbody>
39
38
  <tr
40
39
  v-for="row in rows"
41
40
  :key="row.id"
42
- class="transition-[background] odd:bg-(--oddCellBg)
43
- even:bg-(--evenCellBg)"
41
+ class="odd:bg-(--oddCellBg) even:bg-(--evenCellBg)"
44
42
  >
45
43
  <td
46
44
  v-for="cell in row.children"
@@ -150,7 +150,7 @@ export declare const Table: import("@jsprose/core").Tag<"Table", {
150
150
  Children: InlinerSchema[];
151
151
  }[];
152
152
  })[];
153
- }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
153
+ }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
154
154
  export declare const tableRegistryItem: import("@jsprose/core").RegistryItem<{
155
155
  name: "table";
156
156
  type: "block";
@@ -208,7 +208,7 @@ export declare const tableRegistryItem: import("@jsprose/core").RegistryItem<{
208
208
  Children: InlinerSchema[];
209
209
  }[];
210
210
  })[];
211
- }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
211
+ }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
212
212
  }, undefined>;
213
213
  declare const _default: [{
214
214
  registryItem: import("@jsprose/core").RegistryItem<{
@@ -318,7 +318,7 @@ declare const _default: [{
318
318
  Children: InlinerSchema[];
319
319
  }[];
320
320
  })[];
321
- }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
321
+ }, TagChildren & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
322
322
  }, undefined>;
323
323
  }];
324
324
  export default _default;
@@ -43,7 +43,7 @@ export declare const Video: import("@jsprose/core").Tag<"Video", {
43
43
  invert?: Invert;
44
44
  width?: string;
45
45
  children?: {};
46
- } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
46
+ } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
47
47
  export declare const videoRegistryItem: import("@jsprose/core").RegistryItem<{
48
48
  name: "video";
49
49
  type: "block";
@@ -79,7 +79,7 @@ export declare const videoRegistryItem: import("@jsprose/core").RegistryItem<{
79
79
  invert?: Invert;
80
80
  width?: string;
81
81
  children?: {};
82
- } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
82
+ } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
83
83
  }, undefined>;
84
84
  declare const _default: {
85
85
  registryItem: import("@jsprose/core").RegistryItem<{
@@ -117,7 +117,7 @@ declare const _default: {
117
117
  invert?: Invert;
118
118
  width?: string;
119
119
  children?: {};
120
- } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet & import("../../snippet.js").ObjPropSearch & import("../../snippet.js").ObjPropQuick & import("../../snippet.js").ObjPropSeo>;
120
+ } & import("../../toc.js").ObjPropToc & import("../../snippet.js").ObjPropSnippet>;
121
121
  }, undefined>;
122
122
  };
123
123
  export default _default;
package/dist/include.js CHANGED
@@ -25,7 +25,6 @@ export function Include(props) {
25
25
  delete element.toc;
26
26
  }
27
27
  delete element.snippet;
28
- delete element.snippetFlags;
29
28
  delete element.uniqueName;
30
29
  element[includedKey] = true;
31
30
  if (element.children) {
package/dist/snippet.d.ts CHANGED
@@ -4,60 +4,50 @@ import type { EruditRawElement } from './rawElement.js';
4
4
  /**
5
5
  * Snippet attribute - only contains title and description
6
6
  */
7
- export interface SnippetProp {
7
+ export interface SnippetData {
8
+ /** General snippet title. Used as fallback value for flags. */
8
9
  title?: string;
10
+ /** General snippet description. Used as fallback value for flags. */
9
11
  description?: string;
10
- }
11
- export type ObjPropSnippet = {
12
- /**
13
- * Compact summary of the element with title and description.
14
- */
15
- snippet?: SnippetProp;
16
- };
17
- export type ObjPropSearch = {
18
12
  /**
19
13
  * Show element in search results.
20
- * Can be a boolean to enable/disable, or an object with synonyms.
21
14
  */
22
- search?: boolean | {
23
- synonyms: string[];
15
+ search?: boolean | string | string[] | {
16
+ title?: string;
17
+ description?: string;
18
+ synonyms?: string[];
24
19
  };
25
- };
26
- export type ObjPropQuick = {
27
20
  /**
28
21
  * Show element in "Quick Links" sections at start of the page and also in TOC.
29
22
  */
30
- quick?: boolean;
31
- };
32
- export type ObjPropSeo = {
23
+ quick?: boolean | string | {
24
+ title?: string;
25
+ description?: string;
26
+ };
33
27
  /**
34
28
  * When targeting this element with '#' anchor, adjust SEO metadata (like title and description).
35
29
  * Search engines should treat it as a different "page" and therefore show it as a standalone search result.
36
30
  */
37
- seo?: boolean;
31
+ seo?: boolean | string | {
32
+ title?: string;
33
+ description?: string;
34
+ };
35
+ }
36
+ export type ObjPropSnippet = {
37
+ /**
38
+ * Compact summary of the element and where to show it (search, quick links, SEO).
39
+ */
40
+ snippet?: SnippetData;
38
41
  };
39
42
  export type ObjRawElementSnippet = {
40
- snippet?: SnippetProp;
41
- snippetFlags?: {
42
- quick?: boolean;
43
- search?: boolean | {
44
- synonyms: string[];
45
- };
46
- seo?: boolean;
47
- };
43
+ snippet?: SnippetData;
48
44
  };
49
- export declare function finalizeSnippet(processTagArgs: EruditProcessTagArgs): SnippetProp | undefined;
45
+ export declare function finalizeSnippet(processTagArgs: EruditProcessTagArgs): SnippetData | undefined;
50
46
  export interface ResolvedSnippet {
51
- title: string;
52
- description?: string;
53
- quick?: boolean;
54
- search?: boolean | {
55
- synonyms: string[];
56
- };
57
- seo?: boolean;
58
47
  schemaName: string;
59
48
  isUnique: boolean;
60
49
  elementId: string;
50
+ snippetData: SnippetData;
61
51
  }
62
52
  export declare const snippetStep: ({ rawElement, proseElement }: {
63
53
  context: import("./context.js").EruditProseContext;
package/dist/snippet.js CHANGED
@@ -1,56 +1,85 @@
1
1
  import { ProseError } from "@jsprose/core";
2
2
  import { defineResolveStep } from "./resolveStep.js";
3
3
  export function finalizeSnippet(processTagArgs) {
4
- const quick = processTagArgs.props.quick ?? processTagArgs.element.snippetFlags?.quick;
5
- const search = processTagArgs.props.search ?? processTagArgs.element.snippetFlags?.search;
6
- let seo = processTagArgs.props.seo ?? processTagArgs.element.snippetFlags?.seo;
4
+ const finalSnippet = {};
5
+ const propsSnippet = processTagArgs.props.snippet;
6
+ const builtinSnippet = processTagArgs.element.snippet;
7
+ //
8
+ const quick = propsSnippet?.quick ?? builtinSnippet?.quick;
9
+ if (quick) {
10
+ finalSnippet.quick = quick;
11
+ }
12
+ //
13
+ const search = propsSnippet?.search ?? builtinSnippet?.search;
14
+ if (search) {
15
+ finalSnippet.search = search;
16
+ }
17
+ //
18
+ let seo = propsSnippet?.seo ?? builtinSnippet?.seo;
7
19
  // If none of the flags are set to true, no snippet is created
8
20
  if (!quick && !search && !seo) {
9
21
  return undefined;
10
22
  }
11
23
  // Enable SEO if either quick or search is enabled unless SEO is explicitly disabled
12
24
  // Check both element defaults and props - if either explicitly disables seo, don't auto-enable
13
- const seoExplicitlyDisabled = processTagArgs.element.snippetFlags?.seo === false || processTagArgs.props.seo === false;
14
- if (!seoExplicitlyDisabled) {
15
- if (quick || search) {
16
- seo = true;
25
+ const seoExplicitlyDisabled = builtinSnippet?.seo === false || propsSnippet?.seo === false;
26
+ if (!seo) {
27
+ if (!seoExplicitlyDisabled) {
28
+ if (quick || search) {
29
+ seo = true;
30
+ }
17
31
  }
18
32
  }
19
- const title = finalizeTitle(processTagArgs);
20
- const description = finalizeDescription(processTagArgs);
21
- const snippet = { title };
33
+ if (seo) {
34
+ finalSnippet.seo = seo;
35
+ }
36
+ //
37
+ const title = getGenericTitle(processTagArgs);
38
+ if (title) {
39
+ finalSnippet.title = title;
40
+ }
41
+ const description = getGenericDescription(processTagArgs);
22
42
  if (description) {
23
- snippet.description = description;
24
- }
25
- // Store flags on element for later resolution
26
- processTagArgs.element.snippetFlags = {
27
- quick,
28
- search,
29
- seo
30
- };
31
- return snippet;
43
+ finalSnippet.description = description;
44
+ }
45
+ //
46
+ if (!finalSnippet.title) {
47
+ let titlessFlags = [];
48
+ if (quick && typeof quick !== "string") {
49
+ if (quick === true || !quick.title) {
50
+ titlessFlags.push("quick");
51
+ }
52
+ }
53
+ if (search && typeof search !== "string") {
54
+ if (search === true || Array.isArray(search) || !search.title) {
55
+ titlessFlags.push("search");
56
+ }
57
+ }
58
+ if (seo && typeof seo !== "string") {
59
+ if (seo === true || !seo.title) {
60
+ titlessFlags.push("seo");
61
+ }
62
+ }
63
+ throw new ProseError(`Unable to get title for snippet flags (${titlessFlags.join(", ")}) because no explicit, general inherited title was provided!`);
64
+ }
65
+ //
66
+ processTagArgs.element.snippet = finalSnippet;
67
+ return finalSnippet;
32
68
  }
33
- function finalizeTitle(processTagArgs) {
69
+ function getGenericTitle(processTagArgs) {
34
70
  const title = processTagArgs.props.snippet?.title?.trim() || processTagArgs.element.snippet?.title?.trim() || processTagArgs.element.title?.trim();
35
- if (!title) {
36
- throw new ProseError(`Unable to finalize snippet title!`);
37
- }
38
71
  return title;
39
72
  }
40
- function finalizeDescription(processTagArgs) {
73
+ function getGenericDescription(processTagArgs) {
41
74
  return processTagArgs.props.snippet?.description?.trim() || processTagArgs.element.snippet?.description?.trim();
42
75
  }
43
76
  export const snippetStep = defineResolveStep(({ rawElement, proseElement }) => {
44
- if (rawElement.snippet && proseElement.id && rawElement.snippet.title) {
77
+ if (rawElement.snippet && proseElement.id) {
45
78
  const resolvedSnippet = {
46
- title: rawElement.snippet.title,
47
- description: rawElement.snippet.description,
48
- quick: rawElement.snippetFlags?.quick,
49
- search: rawElement.snippetFlags?.search,
50
- seo: rawElement.snippetFlags?.seo,
51
79
  schemaName: rawElement.schemaName,
52
80
  isUnique: Boolean(rawElement.uniqueName),
53
- elementId: proseElement.id
81
+ elementId: proseElement.id,
82
+ snippetData: rawElement.snippet
54
83
  };
55
84
  return resolvedSnippet;
56
85
  }
package/dist/tag.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Registry, type AnySchema, type ConfigurableTagProps, type NormalizedChildren, type ProcessTagFunction, type TagDefinition } from '@jsprose/core';
2
2
  import type { EruditRawElement } from './rawElement.js';
3
- import { type ObjPropSnippet, type ObjPropSearch, type ObjPropQuick, type ObjPropSeo } from './snippet.js';
3
+ import { type ObjPropSnippet } from './snippet.js';
4
4
  import { type ObjPropToc } from './toc.js';
5
5
  declare const NoTocSymbol: unique symbol;
6
6
  declare const NoSnippetSymbol: unique symbol;
@@ -10,11 +10,11 @@ export type NoToc = {
10
10
  export type NoSnippet = {
11
11
  readonly [NoSnippetSymbol]?: never;
12
12
  };
13
- export type EruditTagProps<TProps extends Record<string, unknown>> = (TProps extends NoToc ? {} : ObjPropToc) & (TProps extends NoSnippet ? {} : ObjPropSnippet & ObjPropSearch & ObjPropQuick & ObjPropSeo);
13
+ export type EruditTagProps<TProps extends Record<string, unknown>> = (TProps extends NoToc ? {} : ObjPropToc) & (TProps extends NoSnippet ? {} : ObjPropSnippet);
14
14
  export type EruditProcessTagArgs = {
15
15
  tagName: string;
16
16
  element: EruditRawElement<AnySchema>;
17
- props: ConfigurableTagProps & ObjPropSnippet & ObjPropToc & ObjPropSearch & ObjPropQuick & ObjPropSeo;
17
+ props: ConfigurableTagProps & ObjPropSnippet & ObjPropToc;
18
18
  children: NormalizedChildren;
19
19
  registry: Registry;
20
20
  };
package/dist/tag.js CHANGED
@@ -12,7 +12,7 @@ export function defineEruditTag(definition) {
12
12
  args.element.snippet = finalizeSnippet(args);
13
13
  args.element.toc = finalizeToc(args);
14
14
  // Use every possibility to get human-readable slug whether it is set manually or taken from snippet or toc
15
- args.element.slug ||= args.element.snippet?.title || args.element.toc?.title;
15
+ args.element.slug ||= args.element.snippet?.title || args.element.toc?.title || args.element.title;
16
16
  });
17
17
  return eruditTag;
18
18
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@erudit-js/prose",
4
- "version": "3.0.0-dev.30",
4
+ "version": "4.0.0-dev.2",
5
5
  "description": "📝 JSX prose subsystem for Erudit sites",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -32,7 +32,7 @@
32
32
  "prepack": "bun run build"
33
33
  },
34
34
  "dependencies": {
35
- "@erudit-js/core": "3.0.0-dev.30",
35
+ "@erudit-js/core": "4.0.0-dev.2",
36
36
  "@jsprose/core": "^1.0.0",
37
37
  "vue": "latest",
38
38
  "@floating-ui/vue": "^1.1.9",