@erudit-js/prose 4.0.0 → 4.1.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 (129) hide show
  1. package/dist/app/composables/context.d.ts +6 -1
  2. package/dist/app/default/Inliners.vue +11 -11
  3. package/dist/app/default/Mix.vue +11 -11
  4. package/dist/app/default/Text.vue +25 -25
  5. package/dist/app/language/element.d.ts +1 -1
  6. package/dist/app/shared/Prose.vue +40 -40
  7. package/dist/app/shared/Render.vue +51 -51
  8. package/dist/app/shared/assets/block.svg +2 -2
  9. package/dist/app/shared/assets/check.svg +2 -2
  10. package/dist/app/shared/assets/inliner.svg +2 -2
  11. package/dist/app/shared/assets/plus.svg +2 -2
  12. package/dist/app/shared/block/AsideMenu.vue +44 -44
  13. package/dist/app/shared/block/AsideMenuButton.vue +51 -51
  14. package/dist/app/shared/block/AsideMenuCopyLink.vue +40 -40
  15. package/dist/app/shared/block/AsideMenuSeparator.vue +3 -3
  16. package/dist/app/shared/block/Block.vue +270 -270
  17. package/dist/app/shared/inliner/Inliner.vue +11 -11
  18. package/dist/app/shared/photoswipe/style.css +22 -22
  19. package/dist/elements/accent/Accent.vue +89 -88
  20. package/dist/elements/accent/AccentColumnSection.vue +61 -61
  21. package/dist/elements/accent/AccentRowSections.vue +64 -64
  22. package/dist/elements/callout/Callout.vue +81 -81
  23. package/dist/elements/callout/_global.d.ts +15 -15
  24. package/dist/elements/caption/Caption.vue +44 -44
  25. package/dist/elements/caption/_global.d.ts +26 -26
  26. package/dist/elements/details/Details.vue +49 -49
  27. package/dist/elements/details/_global.d.ts +27 -27
  28. package/dist/elements/details/icon.svg +2 -2
  29. package/dist/elements/diagram/Diagram.vue +356 -360
  30. package/dist/elements/diagram/_global.d.ts +19 -19
  31. package/dist/elements/emphasis/Emphasis.vue +25 -25
  32. package/dist/elements/emphasis/_global.d.ts +18 -18
  33. package/dist/elements/flex/Flex.vue +36 -36
  34. package/dist/elements/flex/_global.d.ts +23 -23
  35. package/dist/elements/gallery/Gallery.vue +56 -56
  36. package/dist/elements/gallery/_global.d.ts +18 -18
  37. package/dist/elements/heading/Heading.vue +44 -44
  38. package/dist/elements/heading/_global.d.ts +42 -42
  39. package/dist/elements/heading/icon.svg +2 -2
  40. package/dist/elements/horizontalLine/HorizontalLine.vue +6 -6
  41. package/dist/elements/horizontalLine/_global.d.ts +17 -17
  42. package/dist/elements/image/Image.vue +15 -15
  43. package/dist/elements/image/ImageElement.vue +80 -80
  44. package/dist/elements/image/_global.d.ts +18 -18
  45. package/dist/elements/lineBreak/LineBreak.vue +3 -3
  46. package/dist/elements/lineBreak/_global.d.ts +18 -18
  47. package/dist/elements/link/BlockLink.vue +159 -108
  48. package/dist/elements/link/Link.vue +119 -92
  49. package/dist/elements/link/core.js +1 -1
  50. package/dist/elements/link/dependency/_global.d.ts +47 -47
  51. package/dist/elements/link/dependency/app.d.ts +2 -2
  52. package/dist/elements/link/dependency/core.d.ts +12 -18
  53. package/dist/elements/link/dependency/core.js +1 -17
  54. package/dist/elements/link/reference/_global.d.ts +49 -49
  55. package/dist/elements/link/reference/languages/en.d.ts +2 -3
  56. package/dist/elements/link/reference/languages/en.js +5 -1
  57. package/dist/elements/link/reference/languages/ru.d.ts +2 -3
  58. package/dist/elements/link/reference/languages/ru.js +5 -1
  59. package/dist/elements/link/reference/phrases.d.ts +5 -0
  60. package/dist/elements/link/reference/phrases.js +1 -0
  61. package/dist/elements/link/step.d.ts +16 -0
  62. package/dist/elements/link/step.js +36 -0
  63. package/dist/elements/link/storage.d.ts +9 -5
  64. package/dist/elements/link/storage.js +4 -4
  65. package/dist/elements/list/List.vue +58 -58
  66. package/dist/elements/list/_global.d.ts +50 -50
  67. package/dist/elements/math/_global.d.ts +79 -72
  68. package/dist/elements/math/_global.ts +3 -3
  69. package/dist/elements/math/block.d.ts +2 -0
  70. package/dist/elements/math/block.js +42 -29
  71. package/dist/elements/math/components/BlockMath.vue +30 -30
  72. package/dist/elements/math/components/InlinerMath.vue +65 -65
  73. package/dist/elements/math/components/Katex.vue +88 -88
  74. package/dist/elements/math/components/MathGroup.vue +58 -41
  75. package/dist/elements/paragraph/Paragraph.vue +25 -25
  76. package/dist/elements/paragraph/_global.d.ts +27 -27
  77. package/dist/elements/paragraph/icon.svg +3 -3
  78. package/dist/elements/problem/_global.d.ts +257 -112
  79. package/dist/elements/problem/app.d.ts +7 -7
  80. package/dist/elements/problem/app.js +13 -12
  81. package/dist/elements/problem/assets/actions/answer.svg +2 -2
  82. package/dist/elements/problem/assets/actions/check.svg +2 -2
  83. package/dist/elements/problem/assets/actions/generate.svg +2 -2
  84. package/dist/elements/problem/assets/actions/hint.svg +2 -2
  85. package/dist/elements/problem/assets/actions/note.svg +2 -2
  86. package/dist/elements/problem/assets/actions/solution.svg +2 -2
  87. package/dist/elements/problem/assets/icon.svg +2 -2
  88. package/dist/elements/problem/components/Problem.vue +22 -22
  89. package/dist/elements/problem/components/ProblemButton.vue +20 -20
  90. package/dist/elements/problem/components/ProblemButtonGenerate.vue +96 -0
  91. package/dist/elements/problem/components/ProblemContainer.vue +8 -8
  92. package/dist/elements/problem/components/ProblemContent.vue +266 -356
  93. package/dist/elements/problem/components/ProblemExpander.vue +7 -7
  94. package/dist/elements/problem/components/ProblemExpanderSection.vue +57 -57
  95. package/dist/elements/problem/components/ProblemHeader.vue +100 -100
  96. package/dist/elements/problem/components/Problems.vue +83 -83
  97. package/dist/elements/problem/components/SubProblem.vue +14 -14
  98. package/dist/elements/problem/components/expanders/Check.vue +200 -153
  99. package/dist/elements/problem/components/expanders/Checks.vue +146 -146
  100. package/dist/elements/problem/components/expanders/DefaultPlusSections.vue +36 -38
  101. package/dist/elements/problem/components/expanders/Hint.vue +26 -26
  102. package/dist/elements/problem/core.d.ts +55 -28
  103. package/dist/elements/problem/core.js +2 -1
  104. package/dist/elements/problem/languages/{en.d.ts → problem/en.d.ts} +1 -1
  105. package/dist/elements/problem/languages/problem/en.js +6 -0
  106. package/dist/elements/problem/languages/{ru.d.ts → problem/ru.d.ts} +1 -1
  107. package/dist/elements/problem/languages/problem/ru.js +6 -0
  108. package/dist/elements/problem/languages/problems/en.d.ts +3 -0
  109. package/dist/elements/problem/languages/problems/en.js +6 -0
  110. package/dist/elements/problem/languages/problems/ru.d.ts +3 -0
  111. package/dist/elements/problem/languages/problems/ru.js +6 -0
  112. package/dist/elements/problem/languages/shared/en.d.ts +3 -0
  113. package/dist/elements/problem/languages/{en.js → shared/en.js} +12 -3
  114. package/dist/elements/problem/languages/shared/ru.d.ts +3 -0
  115. package/dist/elements/problem/languages/{ru.js → shared/ru.js} +12 -3
  116. package/dist/elements/problem/phrases.d.ts +4 -0
  117. package/dist/elements/problem/problemCheck.d.ts +166 -0
  118. package/dist/elements/problem/problemCheck.js +203 -0
  119. package/dist/elements/problem/problemContent.d.ts +2 -120
  120. package/dist/elements/problem/problemContent.js +2 -127
  121. package/dist/elements/problem/problemScript.d.ts +6 -1
  122. package/dist/elements/table/Table.vue +100 -100
  123. package/dist/elements/table/_global.d.ts +36 -36
  124. package/dist/elements/video/Video.vue +110 -110
  125. package/dist/elements/video/_global.d.ts +18 -18
  126. package/dist/resolve.d.ts +2 -1
  127. package/dist/resolve.js +8 -5
  128. package/package.json +4 -4
  129. package/types.d.ts +4 -4
@@ -0,0 +1,203 @@
1
+ import { defineRegistryItem, defineSchema, ensureTagChildren, ProseError } from "@jsprose/core";
2
+ import { defineEruditTag } from "../../tag.js";
3
+ import { defineEruditProseCoreElement } from "../../coreElement.js";
4
+ export const problemCheckSchema = defineSchema({
5
+ name: "problemCheck",
6
+ type: "block",
7
+ linkable: false
8
+ })();
9
+ export const ProblemCheck = defineEruditTag({
10
+ tagName: "ProblemCheck",
11
+ schema: problemCheckSchema
12
+ })(({ element, tagName, props, children }) => {
13
+ //
14
+ // Info
15
+ //
16
+ const checkInfo = {
17
+ label: props.label,
18
+ hint: props.hint,
19
+ placeholder: props.placeholder
20
+ };
21
+ //
22
+ // Children
23
+ //
24
+ if (children && children.length > 0) {
25
+ ensureTagChildren(tagName, children, problemCheckSchema);
26
+ element.children = children;
27
+ }
28
+ //
29
+ // Validator
30
+ //
31
+ let validator;
32
+ if ("yes" in props) {
33
+ validator = {
34
+ type: "boolean",
35
+ answer: true
36
+ };
37
+ } else if ("no" in props) {
38
+ validator = {
39
+ type: "boolean",
40
+ answer: false
41
+ };
42
+ } else if ("answer" in props) {
43
+ validator = {
44
+ type: "value",
45
+ answer: props.answer
46
+ };
47
+ } else if ("answers" in props) {
48
+ const answersProp = props.answers;
49
+ let ordered = false;
50
+ let separator = ",";
51
+ let answers;
52
+ if (Array.isArray(answersProp)) {
53
+ answers = answersProp;
54
+ } else {
55
+ ordered = answersProp.ordered ?? false;
56
+ separator = answersProp.separator ?? ",";
57
+ answers = answersProp.values;
58
+ }
59
+ validator = {
60
+ type: "array",
61
+ ordered,
62
+ separator,
63
+ answers
64
+ };
65
+ } else if ("script" in props) {
66
+ validator = {
67
+ type: "script",
68
+ name: props.script
69
+ };
70
+ }
71
+ element.data = {
72
+ ...checkInfo,
73
+ serializedValidator: toSerializableValidator(validator)
74
+ };
75
+ });
76
+ export const problemCheckRegistryItem = defineRegistryItem({
77
+ schema: problemCheckSchema,
78
+ tags: [ProblemCheck]
79
+ });
80
+ export const problemCheckCoreElement = defineEruditProseCoreElement({ registryItem: problemCheckRegistryItem });
81
+ export function toSerializableValidator(validator) {
82
+ if (validator.type === "boolean") {
83
+ return validator;
84
+ }
85
+ const toSerializableValue = (value) => {
86
+ if (value instanceof RegExp) {
87
+ return {
88
+ type: "regexp",
89
+ source: value.source,
90
+ flags: value.flags
91
+ };
92
+ }
93
+ return value;
94
+ };
95
+ if (validator.type === "value") {
96
+ return {
97
+ type: "value",
98
+ answer: toSerializableValue(validator.answer)
99
+ };
100
+ }
101
+ if (validator.type === "array") {
102
+ return {
103
+ type: "array",
104
+ ordered: validator.ordered,
105
+ separator: validator.separator,
106
+ answers: validator.answers.map((answer) => {
107
+ if (Array.isArray(answer)) {
108
+ return answer.map(toSerializableValue);
109
+ }
110
+ return toSerializableValue(answer);
111
+ })
112
+ };
113
+ }
114
+ if (validator.type === "script") {
115
+ return validator;
116
+ }
117
+ throw new Error(`Unknown ProblemCheckData type "${validator.type}"!`);
118
+ }
119
+ export function fromSerializableValidator(serializedValidator) {
120
+ if (serializedValidator.type === "boolean") {
121
+ return serializedValidator;
122
+ }
123
+ const fromSerializableValue = (value) => {
124
+ if (value && value.type === "regexp") {
125
+ return new RegExp(value.source, value.flags);
126
+ }
127
+ return value;
128
+ };
129
+ if (serializedValidator.type === "value") {
130
+ return {
131
+ type: "value",
132
+ answer: fromSerializableValue(serializedValidator.answer)
133
+ };
134
+ }
135
+ if (serializedValidator.type === "array") {
136
+ return {
137
+ type: "array",
138
+ ordered: serializedValidator.ordered,
139
+ separator: serializedValidator.separator,
140
+ answers: serializedValidator.answers.map((answer) => {
141
+ if (Array.isArray(answer)) {
142
+ return answer.map(fromSerializableValue);
143
+ }
144
+ return fromSerializableValue(answer);
145
+ })
146
+ };
147
+ }
148
+ if (serializedValidator.type === "script") {
149
+ return serializedValidator;
150
+ }
151
+ throw new Error(`Unknown ProblemCheckData type "${serializedValidator.type}"!`);
152
+ }
153
+ export function checkProblemAnswer(answer, yesRegexp, noRegexp, validator) {
154
+ if (validator.type === "boolean") {
155
+ return validator.answer === true ? yesRegexp.test(answer) : noRegexp.test(answer);
156
+ }
157
+ const checkDefinedAnswer = (expected, answer) => {
158
+ if (typeof expected === "number") {
159
+ return Number(answer) === expected;
160
+ }
161
+ if (expected instanceof RegExp) {
162
+ return expected.test(answer);
163
+ }
164
+ return answer === String(expected);
165
+ };
166
+ const checkAnswer = (expect, answer) => {
167
+ if (expect === undefined) {
168
+ return answer.trim() === "";
169
+ }
170
+ return checkDefinedAnswer(expect, answer);
171
+ };
172
+ if (validator.type === "value") {
173
+ return checkAnswer(validator.answer, answer);
174
+ }
175
+ if (validator.type === "array") {
176
+ const separatorRegexp = new RegExp(`\\s*${validator.separator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*`, "g");
177
+ const parts = answer.split(separatorRegexp).map((p) => p.trim());
178
+ const checkExpected = (expected, actual) => {
179
+ if (Array.isArray(expected)) {
180
+ // any-of logic
181
+ return expected.some((e) => checkDefinedAnswer(e, actual));
182
+ }
183
+ return checkDefinedAnswer(expected, actual);
184
+ };
185
+ if (parts.length !== validator.answers.length) {
186
+ return false;
187
+ }
188
+ if (validator.ordered) {
189
+ return validator.answers.every((expected, i) => checkExpected(expected, parts[i]));
190
+ }
191
+ // unordered matching (multiset semantics)
192
+ const remaining = [...parts];
193
+ for (const expected of validator.answers) {
194
+ const index = remaining.findIndex((actual) => checkExpected(expected, actual));
195
+ if (index === -1) {
196
+ return false;
197
+ }
198
+ remaining.splice(index, 1);
199
+ }
200
+ return true;
201
+ }
202
+ throw new ProseError(`"checkProblemAnswer" not implemented for type "${validator.type}"!`);
203
+ }
@@ -1,4 +1,5 @@
1
- import { type AnySchema, type BlockSchema, type NormalizedChildren, type NoTagChildren, type TagChildren } from '@jsprose/core';
1
+ import { type AnySchema, type NormalizedChildren, type TagChildren } from '@jsprose/core';
2
+ import { problemCheckSchema } from './problemCheck.js';
2
3
  export declare const problemDescription: {
3
4
  schema: {
4
5
  name: "problemDescription";
@@ -425,124 +426,5 @@ export declare const problemAnswer: {
425
426
  }, undefined>;
426
427
  };
427
428
  };
428
- export type CheckFunction = (args: {
429
- answer: string | undefined;
430
- name: string;
431
- answers: Record<string, string | undefined>;
432
- }) => boolean;
433
- export interface ProblemCheckRegex {
434
- pattern: string;
435
- flags: string;
436
- }
437
- export type ProblemCheckValue = string | ProblemCheckRegex | undefined;
438
- export type ProblemCheckSetValue = string | ProblemCheckRegex;
439
- export interface ProblemCheckData {
440
- label?: string;
441
- hint?: string;
442
- placeholder?: string;
443
- answers?: ProblemCheckValue[];
444
- set?: {
445
- separator: string;
446
- values: (ProblemCheckSetValue | ProblemCheckSetValue[])[];
447
- };
448
- script?: string;
449
- }
450
- type Answer = string | number | RegExp | undefined;
451
- export declare function checkValue(input: string | undefined, data: ProblemCheckData): boolean;
452
- export declare const problemCheckSchema: {
453
- name: "problemCheck";
454
- type: "block";
455
- linkable: false;
456
- Data: ProblemCheckData;
457
- Storage: undefined;
458
- Children: BlockSchema[];
459
- };
460
- type UndefinedOnly<T> = {
461
- [K in keyof T]?: undefined;
462
- };
463
- type OneOf<T extends Record<string, any>> = {
464
- [K in keyof T]: Pick<T, K> & UndefinedOnly<Omit<T, K>>;
465
- }[keyof T];
466
- export declare const ProblemCheck: import("@jsprose/core").Tag<"ProblemCheck", {
467
- name: "problemCheck";
468
- type: "block";
469
- linkable: false;
470
- Data: ProblemCheckData;
471
- Storage: undefined;
472
- Children: BlockSchema[];
473
- }, ({
474
- label?: string;
475
- hint?: string;
476
- placeholder?: string;
477
- } & (OneOf<{
478
- answer: Answer;
479
- answers: Answer[];
480
- set: (Answer | Answer[])[] | {
481
- separator: string;
482
- values: (Answer | Answer[])[];
483
- };
484
- script: string;
485
- }> & (TagChildren | NoTagChildren))) & {}>;
486
- export declare const problemCheckRegistryItem: import("@jsprose/core").RegistryItem<{
487
- name: "problemCheck";
488
- type: "block";
489
- linkable: false;
490
- Data: ProblemCheckData;
491
- Storage: undefined;
492
- Children: BlockSchema[];
493
- }, {
494
- ProblemCheck: import("@jsprose/core").Tag<"ProblemCheck", {
495
- name: "problemCheck";
496
- type: "block";
497
- linkable: false;
498
- Data: ProblemCheckData;
499
- Storage: undefined;
500
- Children: BlockSchema[];
501
- }, ({
502
- label?: string;
503
- hint?: string;
504
- placeholder?: string;
505
- } & (OneOf<{
506
- answer: Answer;
507
- answers: Answer[];
508
- set: (Answer | Answer[])[] | {
509
- separator: string;
510
- values: (Answer | Answer[])[];
511
- };
512
- script: string;
513
- }> & (TagChildren | NoTagChildren))) & {}>;
514
- }, undefined>;
515
- export declare const problemCheckCoreElement: {
516
- registryItem: import("@jsprose/core").RegistryItem<{
517
- name: "problemCheck";
518
- type: "block";
519
- linkable: false;
520
- Data: ProblemCheckData;
521
- Storage: undefined;
522
- Children: BlockSchema[];
523
- }, {
524
- ProblemCheck: import("@jsprose/core").Tag<"ProblemCheck", {
525
- name: "problemCheck";
526
- type: "block";
527
- linkable: false;
528
- Data: ProblemCheckData;
529
- Storage: undefined;
530
- Children: BlockSchema[];
531
- }, ({
532
- label?: string;
533
- hint?: string;
534
- placeholder?: string;
535
- } & (OneOf<{
536
- answer: Answer;
537
- answers: Answer[];
538
- set: (Answer | Answer[])[] | {
539
- separator: string;
540
- values: (Answer | Answer[])[];
541
- };
542
- script: string;
543
- }> & (TagChildren | NoTagChildren))) & {}>;
544
- }, undefined>;
545
- };
546
429
  export type ProblemContentChild = typeof problemDescriptionSchema | typeof problemHintSchema | typeof problemNote.schema | typeof problemSolution.schema | typeof problemAnswer.schema | typeof problemCheckSchema;
547
430
  export declare function validateProblemContent(source: string, children: NormalizedChildren): void;
548
- export {};
@@ -1,20 +1,9 @@
1
- //
2
- // <Problem>
3
- // <ProblemDescription />
4
- // <ProblemHint />
5
- // <ProblemNote>
6
- // <ProblemSection title="..." />
7
- // </ProblemNote>
8
- // <ProblemSolution />
9
- // <ProblemAnswer />
10
- // <ProblemCheck />
11
- // </Problem>
12
- //
13
- import { defineRegistryItem, defineSchema, ensureTagChildren, ensureTagNoChildren, isRawElement, ProseError } from "@jsprose/core";
1
+ import { defineRegistryItem, defineSchema, ensureTagChildren, isRawElement, ProseError } from "@jsprose/core";
14
2
  import { defineEruditTag } from "../../tag.js";
15
3
  import { defineEruditProseCoreElement } from "../../coreElement.js";
16
4
  import { uppercaseFirst } from "../../utils/case.js";
17
5
  import { tryParagraphWrap } from "../../shared/paragraphWrap.js";
6
+ import { problemCheckSchema } from "./problemCheck.js";
18
7
  /* --------------------------------------------------------- */
19
8
  /* shared helpers */
20
9
  /* --------------------------------------------------------- */
@@ -128,120 +117,6 @@ function defineProblemSectionContainer(name) {
128
117
  export const problemNote = defineProblemSectionContainer("note");
129
118
  export const problemSolution = defineProblemSectionContainer("solution");
130
119
  export const problemAnswer = defineProblemSectionContainer("answer");
131
- function normalizeValue(v) {
132
- if (v === undefined) return undefined;
133
- if (v instanceof RegExp) {
134
- return {
135
- pattern: v.source,
136
- flags: v.flags
137
- };
138
- }
139
- return String(v);
140
- }
141
- function safeRegexTest(re, value) {
142
- try {
143
- return new RegExp(re.pattern, re.flags).test(value);
144
- } catch {
145
- return false;
146
- }
147
- }
148
- function matchSingle(value, expected) {
149
- // Handle null as undefined (from JSON serialization)
150
- const normalizedExpected = expected === null ? undefined : expected;
151
- const normalizedValue = value === null ? undefined : value;
152
- if (normalizedExpected === undefined) return normalizedValue === undefined;
153
- if (typeof normalizedExpected === "string") return normalizedValue === normalizedExpected;
154
- if (normalizedValue === undefined) return false;
155
- return safeRegexTest(normalizedExpected, normalizedValue);
156
- }
157
- function matchSet(value, set) {
158
- const sep = new RegExp(`\\s*${set.separator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*`);
159
- const inputs = value.split(sep).filter(Boolean);
160
- if (inputs.length !== set.values.length) return false;
161
- const canMatch = (v, expected) => Array.isArray(expected) ? expected.some((e) => typeof e === "string" ? v === e : safeRegexTest(e, v)) : typeof expected === "string" ? v === expected : safeRegexTest(expected, v);
162
- const adj = inputs.map((v) => set.values.map((e, i) => canMatch(v, e) ? i : -1).filter((i) => i !== -1));
163
- const match = new Array(set.values.length).fill(-1);
164
- const dfs = (u, seen) => adj[u].some((v) => {
165
- if (seen[v]) return false;
166
- seen[v] = true;
167
- return match[v] === -1 || dfs(match[v], seen) ? (match[v] = u, true) : false;
168
- });
169
- return inputs.every((_, i) => dfs(i, new Array(set.values.length).fill(false)));
170
- }
171
- export function checkValue(input, data) {
172
- const normalized = input?.trim().replace(/\s+/g, " ") || undefined;
173
- if (data.answers) {
174
- return data.answers.some((a) => matchSingle(normalized, a));
175
- }
176
- if (data.set && normalized !== undefined) {
177
- return matchSet(normalized, data.set);
178
- }
179
- return false;
180
- }
181
- /* --------------------------------------------------------- */
182
- /* problem check tag */
183
- /* --------------------------------------------------------- */
184
- export const problemCheckSchema = defineSchema({
185
- name: "problemCheck",
186
- type: "block",
187
- linkable: false
188
- })();
189
- export const ProblemCheck = defineEruditTag({
190
- tagName: "ProblemCheck",
191
- schema: problemCheckSchema
192
- })(({ element, tagName, props, children }) => {
193
- if (children && children.length > 0) {
194
- ensureTagChildren(tagName, children, problemCheckSchema);
195
- element.children = children;
196
- } else {
197
- ensureTagNoChildren(tagName, children);
198
- }
199
- const data = {};
200
- if ("answer" in props) {
201
- data.answers = [normalizeValue(props.answer)];
202
- } else if ("answers" in props) {
203
- data.answers = props.answers.map(normalizeValue);
204
- } else if ("script" in props) {
205
- data.script = props.script;
206
- } else if ("set" in props) {
207
- const normalizeSetItem = (v) => {
208
- if (Array.isArray(v)) {
209
- return v.map((x) => {
210
- const nv = normalizeValue(x);
211
- if (!nv) {
212
- throw new ProseError(`${tagName}: undefined not allowed in set values.`);
213
- }
214
- return nv;
215
- });
216
- }
217
- const nv = normalizeValue(v);
218
- if (!nv) {
219
- throw new ProseError(`${tagName}: undefined not allowed in set values.`);
220
- }
221
- return nv;
222
- };
223
- if (Array.isArray(props.set)) {
224
- data.set = {
225
- separator: ",",
226
- values: props.set.map(normalizeSetItem)
227
- };
228
- } else {
229
- data.set = {
230
- separator: props.set.separator,
231
- values: props.set.values.map(normalizeSetItem)
232
- };
233
- }
234
- }
235
- if (props.label !== undefined) data.label = props.label;
236
- if (props.hint !== undefined) data.hint = props.hint;
237
- if (props.placeholder !== undefined) data.placeholder = props.placeholder;
238
- element.data = data;
239
- });
240
- export const problemCheckRegistryItem = defineRegistryItem({
241
- schema: problemCheckSchema,
242
- tags: [ProblemCheck]
243
- });
244
- export const problemCheckCoreElement = defineEruditProseCoreElement({ registryItem: problemCheckRegistryItem });
245
120
  export function validateProblemContent(source, children) {
246
121
  ensureTagChildren(source, children, [
247
122
  problemDescriptionSchema,
@@ -1,6 +1,11 @@
1
1
  import { type AnySchema, type AnyUnique, type AutoUnique, type LinkableTag, type RawElement, type Unique, type WrapSchemas } from '@jsprose/core';
2
2
  import { type ProblemSeed, ProblemRandom } from './rng.js';
3
- import { type CheckFunction, type ProblemContentChild } from './problemContent.js';
3
+ import { type ProblemContentChild } from './problemContent.js';
4
+ export type CheckFunction = (args: {
5
+ answer: string | undefined;
6
+ name: string;
7
+ answers: Record<string, string | undefined>;
8
+ }) => boolean;
4
9
  export declare function insertProblemScriptId(scriptSrc: string, code: string): string;
5
10
  export interface ProblemScriptDefinition {
6
11
  uniques?: Record<string, LinkableTag>;
@@ -1,100 +1,100 @@
1
- <script lang="ts" setup>
2
- import { computed } from 'vue';
3
- import { isProseElement, type ProseElement } from '@jsprose/core';
4
-
5
- import type { tableSchema } from './core.js';
6
- import { captionSchema } from '../caption/core.js';
7
- import Render from '../../app/shared/Render.vue';
8
- import Block from '../../app/shared/block/Block.vue';
9
- import Caption from '../caption/Caption.vue';
10
-
11
- const { element } = defineProps<{
12
- element: ProseElement<typeof tableSchema>;
13
- }>();
14
-
15
- const caption = computed(() => {
16
- const maybeCaption = element.children[element.children.length - 1];
17
- return isProseElement(maybeCaption, captionSchema) ? maybeCaption : undefined;
18
- });
19
-
20
- const rows = computed(() =>
21
- caption.value ? element.children.slice(0, -1) : element.children,
22
- );
23
- </script>
24
-
25
- <template>
26
- <Block :element>
27
- <div class="nice-scrollbars overflow-auto">
28
- <table
29
- :class="[
30
- $style.table,
31
- `text-main-sm bg-bg-main m-auto max-w-full border-separate
32
- border-spacing-[3px] rounded border border-(--tableBorder)`,
33
- ]"
34
- >
35
- <tbody>
36
- <tr
37
- v-for="row in rows"
38
- :key="row.id"
39
- class="odd:bg-(--oddCellBg) even:bg-(--evenCellBg)"
40
- >
41
- <td
42
- v-for="cell in row.children"
43
- :key="cell.id"
44
- class="py-small px-normal rounded"
45
- >
46
- <Render
47
- v-for="inliner of cell.children"
48
- :key="inliner.id"
49
- :element="inliner"
50
- />
51
- </td>
52
- </tr>
53
- </tbody>
54
- </table>
55
- </div>
56
- <Caption v-if="caption" :caption="caption" />
57
- </Block>
58
- </template>
59
-
60
- <style module>
61
- .table {
62
- --tableBorder: color-mix(
63
- in srgb,
64
- var(--color-brand),
65
- var(--color-border) 85%
66
- );
67
-
68
- --evenCellBg: color-mix(
69
- in srgb,
70
- light-dark(#f5f5f5, #282828),
71
- var(--color-brand) 3%
72
- );
73
-
74
- --oddCellBg: color-mix(
75
- in srgb,
76
- light-dark(#f5f5f5, #282828),
77
- var(--color-brand) 10%
78
- );
79
-
80
- [data-prose-accent] & {
81
- --tableBorder: color-mix(
82
- in srgb,
83
- var(--accentBorder),
84
- var(--color-border) 50%
85
- );
86
-
87
- --evenCellBg: color-mix(
88
- in srgb,
89
- light-dark(var(--color-bg-main), #202020),
90
- var(--accentText) 12%
91
- );
92
-
93
- --oddCellBg: color-mix(
94
- in srgb,
95
- light-dark(var(--color-bg-main), #202020),
96
- var(--accentText) 18%
97
- );
98
- }
99
- }
100
- </style>
1
+ <script lang="ts" setup>
2
+ import { computed } from 'vue';
3
+ import { isProseElement, type ProseElement } from '@jsprose/core';
4
+
5
+ import type { tableSchema } from './core.js';
6
+ import { captionSchema } from '../caption/core.js';
7
+ import Render from '../../app/shared/Render.vue';
8
+ import Block from '../../app/shared/block/Block.vue';
9
+ import Caption from '../caption/Caption.vue';
10
+
11
+ const { element } = defineProps<{
12
+ element: ProseElement<typeof tableSchema>;
13
+ }>();
14
+
15
+ const caption = computed(() => {
16
+ const maybeCaption = element.children[element.children.length - 1];
17
+ return isProseElement(maybeCaption, captionSchema) ? maybeCaption : undefined;
18
+ });
19
+
20
+ const rows = computed(() =>
21
+ caption.value ? element.children.slice(0, -1) : element.children,
22
+ );
23
+ </script>
24
+
25
+ <template>
26
+ <Block :element>
27
+ <div class="nice-scrollbars overflow-auto">
28
+ <table
29
+ :class="[
30
+ $style.table,
31
+ `text-main-sm bg-bg-main m-auto max-w-full border-separate
32
+ border-spacing-[3px] rounded border border-(--tableBorder)`,
33
+ ]"
34
+ >
35
+ <tbody>
36
+ <tr
37
+ v-for="row in rows"
38
+ :key="row.id"
39
+ class="odd:bg-(--oddCellBg) even:bg-(--evenCellBg)"
40
+ >
41
+ <td
42
+ v-for="cell in row.children"
43
+ :key="cell.id"
44
+ class="py-small px-normal rounded"
45
+ >
46
+ <Render
47
+ v-for="inliner of cell.children"
48
+ :key="inliner.id"
49
+ :element="inliner"
50
+ />
51
+ </td>
52
+ </tr>
53
+ </tbody>
54
+ </table>
55
+ </div>
56
+ <Caption v-if="caption" :caption="caption" />
57
+ </Block>
58
+ </template>
59
+
60
+ <style module>
61
+ .table {
62
+ --tableBorder: color-mix(
63
+ in srgb,
64
+ var(--color-brand),
65
+ var(--color-border) 85%
66
+ );
67
+
68
+ --evenCellBg: color-mix(
69
+ in srgb,
70
+ light-dark(#f5f5f5, #282828),
71
+ var(--color-brand) 3%
72
+ );
73
+
74
+ --oddCellBg: color-mix(
75
+ in srgb,
76
+ light-dark(#f5f5f5, #282828),
77
+ var(--color-brand) 10%
78
+ );
79
+
80
+ [data-prose-accent] & {
81
+ --tableBorder: color-mix(
82
+ in srgb,
83
+ var(--accentBorder),
84
+ var(--color-border) 50%
85
+ );
86
+
87
+ --evenCellBg: color-mix(
88
+ in srgb,
89
+ light-dark(var(--color-bg-main), #202020),
90
+ var(--accentText) 12%
91
+ );
92
+
93
+ --oddCellBg: color-mix(
94
+ in srgb,
95
+ light-dark(var(--color-bg-main), #202020),
96
+ var(--accentText) 18%
97
+ );
98
+ }
99
+ }
100
+ </style>