@erudit-js/prose 4.0.1 → 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 (55) hide show
  1. package/dist/app/composables/context.d.ts +6 -1
  2. package/dist/app/language/element.d.ts +1 -1
  3. package/dist/elements/accent/Accent.vue +1 -0
  4. package/dist/elements/diagram/Diagram.vue +6 -10
  5. package/dist/elements/link/BlockLink.vue +117 -66
  6. package/dist/elements/link/Link.vue +38 -11
  7. package/dist/elements/link/core.js +1 -1
  8. package/dist/elements/link/dependency/app.d.ts +2 -2
  9. package/dist/elements/link/dependency/core.d.ts +12 -18
  10. package/dist/elements/link/dependency/core.js +1 -17
  11. package/dist/elements/link/reference/languages/en.d.ts +2 -3
  12. package/dist/elements/link/reference/languages/en.js +5 -1
  13. package/dist/elements/link/reference/languages/ru.d.ts +2 -3
  14. package/dist/elements/link/reference/languages/ru.js +5 -1
  15. package/dist/elements/link/reference/phrases.d.ts +5 -0
  16. package/dist/elements/link/reference/phrases.js +1 -0
  17. package/dist/elements/link/step.d.ts +16 -0
  18. package/dist/elements/link/step.js +36 -0
  19. package/dist/elements/link/storage.d.ts +9 -5
  20. package/dist/elements/link/storage.js +4 -4
  21. package/dist/elements/math/_global.d.ts +7 -0
  22. package/dist/elements/math/block.d.ts +2 -0
  23. package/dist/elements/math/block.js +42 -29
  24. package/dist/elements/math/components/MathGroup.vue +20 -3
  25. package/dist/elements/problem/_global.d.ts +174 -29
  26. package/dist/elements/problem/app.d.ts +7 -7
  27. package/dist/elements/problem/app.js +13 -12
  28. package/dist/elements/problem/components/ProblemButtonGenerate.vue +96 -0
  29. package/dist/elements/problem/components/ProblemContent.vue +14 -104
  30. package/dist/elements/problem/components/expanders/Check.vue +58 -11
  31. package/dist/elements/problem/components/expanders/Checks.vue +5 -5
  32. package/dist/elements/problem/components/expanders/DefaultPlusSections.vue +0 -2
  33. package/dist/elements/problem/core.d.ts +55 -28
  34. package/dist/elements/problem/core.js +2 -1
  35. package/dist/elements/problem/languages/{en.d.ts → problem/en.d.ts} +1 -1
  36. package/dist/elements/problem/languages/problem/en.js +6 -0
  37. package/dist/elements/problem/languages/{ru.d.ts → problem/ru.d.ts} +1 -1
  38. package/dist/elements/problem/languages/problem/ru.js +6 -0
  39. package/dist/elements/problem/languages/problems/en.d.ts +3 -0
  40. package/dist/elements/problem/languages/problems/en.js +6 -0
  41. package/dist/elements/problem/languages/problems/ru.d.ts +3 -0
  42. package/dist/elements/problem/languages/problems/ru.js +6 -0
  43. package/dist/elements/problem/languages/shared/en.d.ts +3 -0
  44. package/dist/elements/problem/languages/{en.js → shared/en.js} +12 -3
  45. package/dist/elements/problem/languages/shared/ru.d.ts +3 -0
  46. package/dist/elements/problem/languages/{ru.js → shared/ru.js} +12 -3
  47. package/dist/elements/problem/phrases.d.ts +4 -0
  48. package/dist/elements/problem/problemCheck.d.ts +166 -0
  49. package/dist/elements/problem/problemCheck.js +203 -0
  50. package/dist/elements/problem/problemContent.d.ts +2 -120
  51. package/dist/elements/problem/problemContent.js +2 -127
  52. package/dist/elements/problem/problemScript.d.ts +6 -1
  53. package/dist/resolve.d.ts +2 -1
  54. package/dist/resolve.js +8 -5
  55. package/package.json +2 -2
@@ -0,0 +1,36 @@
1
+ import { isRawElement } from "@jsprose/core";
2
+ import { defineResolveStep } from "../../resolveStep.js";
3
+ import { dependencySchema, depSchema } from "./dependency/core.js";
4
+ import { referenceSchema, refSchema } from "./reference/core.js";
5
+ export const contentLinkStep = defineResolveStep(({ rawElement, proseElement }) => {
6
+ if (!proseElement.id || !rawElement.storageKey) {
7
+ return;
8
+ }
9
+ const checks = [
10
+ {
11
+ schema: depSchema,
12
+ key: "Dep"
13
+ },
14
+ {
15
+ schema: dependencySchema,
16
+ key: "Dependency"
17
+ },
18
+ {
19
+ schema: refSchema,
20
+ key: "Ref"
21
+ },
22
+ {
23
+ schema: referenceSchema,
24
+ key: "Reference"
25
+ }
26
+ ];
27
+ for (const { schema, key } of checks) {
28
+ if (isRawElement(rawElement, schema)) {
29
+ return {
30
+ storageKey: rawElement.storageKey,
31
+ label: rawElement.data.label.trim(),
32
+ type: key
33
+ };
34
+ }
35
+ }
36
+ });
@@ -2,7 +2,7 @@ import type { TopicPart } from '@erudit-js/core/content/topic';
2
2
  import type { ContentType } from '@erudit-js/core/content/type';
3
3
  import type { PreviewRequest } from '@erudit-js/core/preview/request';
4
4
  import type { LinkToProp } from './core.js';
5
- export type LinkStorageType = 'direct' | 'contentItem' | 'unique';
5
+ export type LinkStorageType = 'external' | 'contentItem' | 'unique';
6
6
  interface LinkStorageBase {
7
7
  type: LinkStorageType;
8
8
  resolvedHref: string;
@@ -16,8 +16,8 @@ export type LinkStorageContent = {
16
16
  } | {
17
17
  contentType: Exclude<ContentType, 'topic'>;
18
18
  });
19
- export interface DirectLinkStorage extends LinkStorageBase {
20
- type: 'direct';
19
+ export interface ExternalLinkStorage extends LinkStorageBase {
20
+ type: 'external';
21
21
  }
22
22
  export interface ContentItemLinkStorage extends LinkStorageBase {
23
23
  type: 'contentItem';
@@ -29,6 +29,10 @@ export interface UniqueLinkStorage extends LinkStorageBase {
29
29
  elementTitle?: string;
30
30
  content: LinkStorageContent;
31
31
  }
32
- export type LinkStorage = DirectLinkStorage | ContentItemLinkStorage | UniqueLinkStorage;
33
- export declare function createLinkStorageKey(to: LinkToProp, tagName: string): string;
32
+ export interface ErrorLinkStorage {
33
+ type: 'error';
34
+ error: string;
35
+ }
36
+ export type LinkStorage = ExternalLinkStorage | ContentItemLinkStorage | UniqueLinkStorage | ErrorLinkStorage;
37
+ export declare function createLinkStorageKey(to: LinkToProp): string;
34
38
  export {};
@@ -1,7 +1,7 @@
1
- import { isUnique, ProseError } from "@jsprose/core";
1
+ import { isUnique } from "@jsprose/core";
2
2
  import { parseDocumentId } from "@erudit-js/core/prose/documentId";
3
3
  import { getGlobalContentPath, isGlobalContent } from "@erudit-js/core/content/global";
4
- export function createLinkStorageKey(to, tagName) {
4
+ export function createLinkStorageKey(to) {
5
5
  if (isUnique(to)) {
6
6
  const documentId = parseDocumentId(to.documentId);
7
7
  if (documentId.type === "contentPage") {
@@ -14,7 +14,7 @@ export function createLinkStorageKey(to, tagName) {
14
14
  return `<link:global>/${getGlobalContentPath(to)}`;
15
15
  }
16
16
  if (typeof to === "string") {
17
- return `<link:direct>/${to}`;
17
+ return `<link:external>/${to}`;
18
18
  }
19
- throw new ProseError(`<${tagName}> is unable to resolve "to" prop value!`);
19
+ return `<link:unknown>/${JSON.stringify(to)}`;
20
20
  }
@@ -43,6 +43,9 @@ export const M = '_tag_';
43
43
  *
44
44
  * Use `freeze` prop to prevent line breaks in the rendered math (scrollbars will appear if the content overflows).
45
45
  *
46
+ * You can also create flexible "breaking" gaps between expressions using `>>`, `>>{0|small|big|100px}` delimiters.
47
+ * Also you can specify the vertical aligment of such gaps using `>>{top|center|bottom}`.
48
+ *
46
49
  * @title Block Math
47
50
  * @layout block
48
51
  * @example
@@ -54,6 +57,10 @@ export const M = '_tag_';
54
57
  * <BlockMath freeze>{math`
55
58
  * \lim\limits_{x \to \infty} \frac{1}{x} = 0
56
59
  * `}</BlockMath>
60
+ *
61
+ * <BlockMath>{math`
62
+ * a^2 >> b^2 >>{big} c^2 >>{top} \sqrt{a^2 + b^2} >>{small}{bottom} \frac{a^2 + b^2}{c^2}
63
+ * `}</BlockMath>
57
64
  * ```
58
65
  */
59
66
  export const BlockMath = '_tag_';
@@ -1,6 +1,7 @@
1
1
  import { type TagChildren } from '@jsprose/core';
2
2
  export declare const mathGroupTypes: readonly ["0", "small", "normal", "big"];
3
3
  export type MathGroupGapType = (typeof mathGroupTypes)[number] | 'custom';
4
+ export type MathGroupAlignItems = 'top' | 'center' | 'bottom';
4
5
  export interface MathGroupGapTemplate {
5
6
  type: MathGroupGapType;
6
7
  }
@@ -24,6 +25,7 @@ export type MathGroupGap = MathGroupGapZero | MathGroupGapSmall | MathGroupGapNo
24
25
  export type MathGroupPart = string | MathGroup;
25
26
  export interface MathGroup {
26
27
  gap: MathGroupGap;
28
+ alignItems?: MathGroupAlignItems;
27
29
  parts: MathGroupPart[];
28
30
  }
29
31
  export declare function resolveMathGroups(katex: string, isTopLevel?: boolean): Promise<MathGroup | string>;
@@ -7,71 +7,84 @@ export const mathGroupTypes = [
7
7
  "normal",
8
8
  "big"
9
9
  ];
10
- function gapFromString(strGap) {
11
- if (mathGroupTypes.includes(strGap)) {
12
- return { type: strGap };
10
+ const alignValues = [
11
+ "top",
12
+ "center",
13
+ "bottom"
14
+ ];
15
+ function isAlignValue(value) {
16
+ return alignValues.includes(value);
17
+ }
18
+ function gapFromString(str) {
19
+ if (mathGroupTypes.includes(str)) {
20
+ return { type: str };
13
21
  }
14
22
  return {
15
23
  type: "custom",
16
- size: strGap
24
+ size: str
17
25
  };
18
26
  }
19
27
  function gapsEqual(gap1, gap2) {
20
- if (gap1.type !== gap2.type) {
21
- return false;
22
- }
28
+ if (gap1.type !== gap2.type) return false;
23
29
  if (gap1.type === "custom" && gap2.type === "custom") {
24
30
  return gap1.size === gap2.size;
25
31
  }
26
32
  return true;
27
33
  }
28
34
  export async function resolveMathGroups(katex, isTopLevel = true) {
29
- // If whole string does not contain any groups, return default group with rendered math
30
35
  if (!katex.includes(">>")) {
31
36
  const rendered = await latexToHtml(katex, "block");
32
37
  if (isTopLevel) {
33
- // Only top-level should return a group
34
38
  return {
35
39
  gap: { type: "normal" },
36
40
  parts: [rendered]
37
41
  };
38
42
  }
39
- // Recursive left side should return a plain string
40
43
  return rendered;
41
44
  }
42
- // Find the rightmost delimiter and its gap specification
43
- const delimiterRegex = />>(?:\{([^}]+)\})?/g;
45
+ const delimiterRegex = />>(?:\{([^}]+)\})?(?:\{([^}]+)\})?/g;
44
46
  let match;
45
- let lastDelimiterMatch;
47
+ let last;
46
48
  while ((match = delimiterRegex.exec(katex)) !== null) {
47
- lastDelimiterMatch = match;
49
+ last = match;
50
+ }
51
+ const raw1 = last[1];
52
+ const raw2 = last[2];
53
+ let gap = { type: "normal" };
54
+ let alignItems;
55
+ // ---- Resolution rules ----
56
+ if (raw1 && raw2) {
57
+ // >>{gap}{align}
58
+ gap = gapFromString(raw1);
59
+ if (isAlignValue(raw2)) alignItems = raw2;
60
+ } else if (raw1) {
61
+ // >>{something}
62
+ if (isAlignValue(raw1)) {
63
+ // >>{center}
64
+ alignItems = raw1;
65
+ } else {
66
+ // >>{small} or custom gap
67
+ gap = gapFromString(raw1);
68
+ }
48
69
  }
49
- // Extract gap
50
- const gap = gapFromString(lastDelimiterMatch[1] || "normal");
51
- // Calculate positions
52
- const lastDelimiterPos = lastDelimiterMatch.index;
53
- const lastDelimiterLen = lastDelimiterMatch[0].length;
54
- // Split the katex string
55
- const leftPart = katex.slice(0, lastDelimiterPos);
56
- const rightPart = katex.slice(lastDelimiterPos + lastDelimiterLen);
57
- // Pushing rendered right part
58
- const parts = [await latexToHtml(rightPart, "block")];
59
- // Resolving left part
60
- const leftGroup = await resolveMathGroups(leftPart, false);
70
+ const delimiterPos = last.index;
71
+ const delimiterLen = last[0].length;
72
+ const left = katex.slice(0, delimiterPos);
73
+ const right = katex.slice(delimiterPos + delimiterLen);
74
+ const parts = [await latexToHtml(right, "block")];
75
+ const leftGroup = await resolveMathGroups(left, false);
61
76
  if (typeof leftGroup === "string") {
62
77
  parts.unshift(leftGroup);
63
78
  } else {
64
- // Left part is a group, meaning it contains gaps
65
79
  if (gapsEqual(leftGroup.gap, gap)) {
66
- // If gaps are equal, we can merge the two groups into (current) one
67
80
  parts.unshift(...leftGroup.parts);
68
81
  } else {
69
- // Gaps are different, we need to keep the left group as is
70
82
  parts.unshift(leftGroup);
71
83
  }
72
84
  }
73
85
  return {
74
86
  gap,
87
+ ...alignItems ? { alignItems } : {},
75
88
  parts
76
89
  };
77
90
  }
@@ -7,7 +7,7 @@ const { mathGroup } = defineProps<{
7
7
  freeze: boolean;
8
8
  }>();
9
9
 
10
- const columnGap = (() => {
10
+ const gap = (() => {
11
11
  switch (mathGroup.gap.type) {
12
12
  case '0':
13
13
  return '0px';
@@ -21,12 +21,29 @@ const columnGap = (() => {
21
21
  return mathGroup.gap.size;
22
22
  }
23
23
  })();
24
+
25
+ const alignItems = (() => {
26
+ switch (mathGroup.alignItems ?? 'center') {
27
+ case 'top':
28
+ return 'flex-start';
29
+ case 'bottom':
30
+ return 'flex-end';
31
+ case 'center':
32
+ default:
33
+ return 'center';
34
+ }
35
+ })();
24
36
  </script>
25
37
 
26
38
  <template>
27
39
  <div
28
- :style="{ columnGap }"
29
- class="flex flex-wrap items-center justify-center gap-y-(--mathRowGap)"
40
+ :style="{
41
+ '--mathGroupGap': gap,
42
+ gap: 'var(--mathGroupGap)',
43
+ rowGap: 'calc(var(--mathGroupGap)/2)',
44
+ alignItems,
45
+ }"
46
+ class="flex flex-wrap justify-center"
30
47
  >
31
48
  <template v-for="part of mathGroup.parts">
32
49
  <Katex
@@ -1,16 +1,21 @@
1
1
  import type { ProblemCustomAttribute as PAC } from './shared.js';
2
+ import type { ProblemRandom as _ProblemRandom } from './rng.js';
2
3
 
3
4
  /**
4
5
  * Problems are used to present exercises and questions to the reader.
5
- * See the example for a full breakdown of the sub-elements available.
6
6
  *
7
- * All problems are added to TOC and search by default (can be disabled via tag properties).
7
+ * Allowed children inside `<Problem>`:
8
+ * - `<ProblemDescription>`
9
+ * - `<ProblemCheck>` (repeatable)
10
+ * - `<ProblemHint>` (repeatable)
11
+ * - `<ProblemAnswer>` (optionally with `<ProblemSection>`)
12
+ * - `<ProblemSolution>` (optionally with `<ProblemSection>`)
13
+ * - `<ProblemNote>` (optionally with `<ProblemSection>`)
8
14
  *
9
15
  * @title Problem
10
16
  * @layout block
11
17
  * @example
12
18
  * ```tsx
13
- * // Static problem
14
19
  * <Problem title="Find the square" level="easy">
15
20
  * <ProblemDescription>
16
21
  * <P>What is the square of 2?</P>
@@ -40,52 +45,162 @@ import type { ProblemCustomAttribute as PAC } from './shared.js';
40
45
  * </ProblemAnswer>
41
46
  *
42
47
  * <ProblemCheck label="The square of 2 is" answer={4} />
43
- * // More checks...
44
48
  *
45
49
  * <ProblemNote>
46
50
  * In fact, you can find the square of any number by multiplying it by itself!
47
51
  * </ProblemNote>
48
52
  * </Problem>
49
- *
50
- * // Script problem
51
- * export const fooScript = defineProblemScript({
52
- * isGenerator: true,
53
- * })(({ initial, random }) => {
54
- * const a = initial.nextInt(1, 10);
55
- * const b = initial.nextInt(1, 10);
56
- *
57
- * return (
58
- * <>
59
- * <ProblemDescription>
60
- * What is <M>{a} + {b}</M>?
61
- * </ProblemDescription>
62
- * <ProblemAnswer>
63
- * <M>{a + b}</M>
64
- * </ProblemAnswer>
65
- * <ProblemCheck label="The answer is" answer={a + b} />
66
- * </>
67
- * );
68
- * });
69
- *
70
- * <Problem title="Addition Problem" level="medium" script={fooScript} />
71
53
  * ```
72
54
  */
73
55
  export const Problem = '_tag_';
56
+
57
+ /**
58
+ * Problem description.
59
+ *
60
+ * Can be used inside `<Problem>` or `<SubProblem>`.
61
+ *
62
+ * @title ProblemDescription
63
+ * @layout block
64
+ * @example
65
+ * ```tsx
66
+ * <ProblemDescription>
67
+ * <P>State the problem in your own words.</P>
68
+ * </ProblemDescription>
69
+ * ```
70
+ */
74
71
  export const ProblemDescription = '_tag_';
72
+
73
+ /**
74
+ * A hint for the problem. Multiple hints can be provided.
75
+ *
76
+ * Can be used inside `<Problem>` or `<SubProblem>`.
77
+ *
78
+ * @title ProblemHint
79
+ * @layout block
80
+ * @example
81
+ * ```tsx
82
+ * <ProblemHint>
83
+ * <P>Try rewriting the expression in a simpler form.</P>
84
+ * </ProblemHint>
85
+ * ```
86
+ */
75
87
  export const ProblemHint = '_tag_';
88
+
89
+ /**
90
+ * A titled section used inside `<ProblemSolution>` or `<ProblemAnswer>`.
91
+ *
92
+ * @title ProblemSection
93
+ * @layout block
94
+ * @example
95
+ * ```tsx
96
+ * <ProblemSection title="Method">
97
+ * <P>Show the steps.</P>
98
+ * </ProblemSection>
99
+ * ```
100
+ */
76
101
  export const ProblemSection = '_tag_';
102
+
103
+ /**
104
+ * The problem solution.
105
+ *
106
+ * Can contain plain content and `<ProblemSection>` blocks.
107
+ * Can be used inside `<Problem>` or `<SubProblem>`.
108
+ *
109
+ * @title ProblemSolution
110
+ * @layout block
111
+ * @example
112
+ * ```tsx
113
+ * <ProblemSolution>
114
+ * <P>Start with the key idea.</P>
115
+ *
116
+ * <ProblemSection title="Details">
117
+ * <P>Then provide the full derivation.</P>
118
+ * </ProblemSection>
119
+ * </ProblemSolution>
120
+ * ```
121
+ */
77
122
  export const ProblemSolution = '_tag_';
123
+
124
+ /**
125
+ * The final answer (usually concise).
126
+ *
127
+ * Can contain plain content and `<ProblemSection>` blocks.
128
+ * Can be used inside `<Problem>` or `<SubProblem>`.
129
+ *
130
+ * @title ProblemAnswer
131
+ * @layout block
132
+ * @example
133
+ * ```tsx
134
+ * <ProblemAnswer>
135
+ * <P><M>42</M></P>
136
+ * </ProblemAnswer>
137
+ * ```
138
+ */
78
139
  export const ProblemAnswer = '_tag_';
140
+
141
+ /**
142
+ * A note shown after the checks/solution.
143
+ *
144
+ * Can be used inside `<Problem>` or `<SubProblem>`.
145
+ *
146
+ * @title ProblemNote
147
+ * @layout block
148
+ * @example
149
+ * ```tsx
150
+ * <ProblemNote>
151
+ * Remember to double-check units.
152
+ * </ProblemNote>
153
+ * ```
154
+ */
79
155
  export const ProblemNote = '_tag_';
156
+
157
+ /**
158
+ * Defines an answer check for a problem.
159
+ *
160
+ * Can be used inside `<Problem>` or `<SubProblem>`.
161
+ *
162
+ * Validator props (exactly one per `<ProblemCheck>`):
163
+ * - `yes`: boolean-like answer, validated via locale yes/no patterns.
164
+ * - `no`: boolean-like answer, validated via locale yes/no patterns.
165
+ * - `answer`: exact expected value.
166
+ * - `number` -> numeric equality
167
+ * - `string` -> exact string match
168
+ * - `RegExp` -> `test()` match
169
+ * - `undefined` -> expects an empty answer
170
+ * - `answers`: multi-part answer (split by `separator`, default `,`, unordered by default).
171
+ * - Use `{ ordered, separator, values }` to configure matching.
172
+ * - Each position in `values` can be a single expected value or an array of expected values (any-of).
173
+ * - `script`: named script validator.
174
+ *
175
+ * You can nest `<ProblemCheck>` inside another `<ProblemCheck>` to group multiple checks.
176
+ *
177
+ * @title ProblemCheck
178
+ * @layout block
179
+ * @example
180
+ * ```tsx
181
+ * <ProblemCheck label="2 is even" yes />
182
+ * <ProblemCheck label="Enter nothing" answer={undefined} />
183
+ * <ProblemCheck label="The square of 2 is" answer={4} />
184
+ * <ProblemCheck
185
+ * label="Enter roots"
186
+ * answers={{ ordered: false, separator: ',', values: [2, [-2, /-?2/]] }}
187
+ * />
188
+ * <ProblemCheck script="myCustomValidator" />
189
+ *
190
+ * <ProblemCheck label="Grouped checks" yes>
191
+ * <ProblemCheck label="Also accept 42" answer={42} />
192
+ * </ProblemCheck>
193
+ * ```
194
+ */
80
195
  export const ProblemCheck = '_tag_';
81
196
 
82
197
  /**
83
198
  * Problem set is a collection of related problems presented together.
84
- * `<Problems>` tag contains general problem information and insude can have multiple `<SubProblem>` tags.
85
199
  *
86
- * Each `<SubProblem>` contains the same problem content tags as single `<Problem>` tag.
200
+ * Allowed children inside `<Problems>`:
201
+ * - `<SubProblem>` (repeatable)
87
202
  *
88
- * All problems are added to TOC and search by default (can be disabled via tag properties).
203
+ * Each `<SubProblem>` can contain the same child tags as `<Problem>`.
89
204
  *
90
205
  * @title Problems
91
206
  * @layout block
@@ -104,9 +219,39 @@ export const ProblemCheck = '_tag_';
104
219
  * ```
105
220
  */
106
221
  export const Problems = '_tag_';
222
+
223
+ /**
224
+ * A single problem inside a `<Problems>` set.
225
+ *
226
+ * Allowed children inside `<SubProblem>`:
227
+ * - `<ProblemDescription>`
228
+ * - `<ProblemHint>` (repeatable)
229
+ * - `<ProblemSolution>` (optionally with `<ProblemSection>`)
230
+ * - `<ProblemAnswer>` (optionally with `<ProblemSection>`)
231
+ * - `<ProblemCheck>` (repeatable)
232
+ * - `<ProblemNote>`
233
+ *
234
+ * @title SubProblem
235
+ * @layout block
236
+ * @example
237
+ * ```tsx
238
+ * <SubProblem label="A">
239
+ * <ProblemDescription>
240
+ * <P>Solve for <M>x</M>.</P>
241
+ * </ProblemDescription>
242
+ *
243
+ * <ProblemCheck answer={42} />
244
+ * </SubProblem>
245
+ * ```
246
+ */
107
247
  export const SubProblem = '_tag_';
108
248
 
109
249
  /**
110
250
  * Typeguard for creating custom problem attributes.
111
251
  */
112
252
  export type ProblemCustomAttribute = PAC;
253
+
254
+ /**
255
+ * Typeguard for problem RNG.
256
+ */
257
+ export type ProblemRandom = _ProblemRandom;
@@ -5,13 +5,6 @@ declare const _default: (import("../../app/appElement.js").AppElement<{
5
5
  Data: import("./problem.js").ProblemData;
6
6
  Storage: import("./storage.js").ProblemScriptStorage;
7
7
  Children: import("./problemContent.js").ProblemContentChild[];
8
- }> | import("../../app/appElement.js").AppElement<{
9
- name: "subProblem";
10
- type: "block";
11
- linkable: false;
12
- Data: import("./problems.js").SubProblemData;
13
- Storage: import("./storage.js").ProblemScriptStorage;
14
- Children: import("./problemContent.js").ProblemContentChild[];
15
8
  }> | import("../../app/appElement.js").AppElement<{
16
9
  name: "problems";
17
10
  type: "block";
@@ -26,5 +19,12 @@ declare const _default: (import("../../app/appElement.js").AppElement<{
26
19
  Storage: import("./storage.js").ProblemScriptStorage;
27
20
  Children: import("./problemContent.js").ProblemContentChild[];
28
21
  })[];
22
+ }> | import("../../app/appElement.js").AppElement<{
23
+ name: "subProblem";
24
+ type: "block";
25
+ linkable: false;
26
+ Data: import("./problems.js").SubProblemData;
27
+ Storage: import("./storage.js").ProblemScriptStorage;
28
+ Children: import("./problemContent.js").ProblemContentChild[];
29
29
  }>)[];
30
30
  export default _default;
@@ -1,27 +1,28 @@
1
1
  import { defineEruditProseAppElement } from "../../app/appElement.js";
2
2
  import { problemSchema } from "./problem.js";
3
3
  import { problemsSchema, subProblemSchema } from "./problems.js";
4
+ const icon = () => import("./assets/icon.svg?raw");
4
5
  export default [
5
6
  defineEruditProseAppElement({
6
7
  schema: problemSchema,
7
8
  component: () => import("./components/Problem.vue"),
9
+ icon,
8
10
  languages: {
9
- en: () => import("./languages/en.js"),
10
- ru: () => import("./languages/ru.js")
11
- },
12
- icon: () => import("./assets/icon.svg?raw")
13
- }),
14
- defineEruditProseAppElement({
15
- schema: subProblemSchema,
16
- component: () => import("./components/SubProblem.vue")
11
+ en: () => import("./languages/problem/en.js"),
12
+ ru: () => import("./languages/problem/ru.js")
13
+ }
17
14
  }),
18
15
  defineEruditProseAppElement({
19
16
  schema: problemsSchema,
20
17
  component: () => import("./components/Problems.vue"),
18
+ icon,
21
19
  languages: {
22
- en: () => import("./languages/en.js"),
23
- ru: () => import("./languages/ru.js")
24
- },
25
- icon: () => import("./assets/icon.svg?raw")
20
+ en: () => import("./languages/problems/en.js"),
21
+ ru: () => import("./languages/problems/ru.js")
22
+ }
23
+ }),
24
+ defineEruditProseAppElement({
25
+ schema: subProblemSchema,
26
+ component: () => import("./components/SubProblem.vue")
26
27
  })
27
28
  ];