@lernapps/app-templates 0.1.0 → 0.2.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.
- package/README.md +2 -2
- package/dist/{assessment-By2GGTJC.mjs → assessment-Dy359O1O.mjs} +1 -1
- package/dist/{blocks-BmRrD7UY.mjs → blocks-CxtCPAa5.mjs} +2 -2
- package/dist/blocks.mjs +2 -2
- package/dist/{check-BkEl-m-F.mjs → check-CteIFN96.mjs} +1 -1
- package/dist/{content-cYBPYg_J.mjs → content-DO6oEJxj.mjs} +1 -1
- package/dist/{e2e-BiMI-pCL.mjs → e2e-CU0n_unV.mjs} +1 -1
- package/dist/{engine-BqF2Vffn.mjs → engine-CArxqizW.mjs} +1 -1
- package/dist/explainer-e2e.mjs +54 -19
- package/dist/explainer-plugin.mjs +6 -5
- package/dist/explainer.mjs +4 -4
- package/dist/interactive-e2e.mjs +1 -1
- package/dist/interactive-plugin.mjs +2 -2
- package/dist/{load-C-0hUaSC.mjs → load-RosvaPZf.mjs} +37 -8
- package/dist/questions-e2e.mjs +1 -1
- package/dist/questions-engine.mjs +2 -2
- package/dist/questions.mjs +2 -2
- package/dist/{quiz-BKc8JYtC.mjs → quiz-DnW-xtCh.mjs} +1 -1
- package/dist/quiz-e2e.mjs +52 -28
- package/dist/quiz-plugin.mjs +4 -4
- package/dist/quiz.mjs +3 -3
- package/dist/{render-BL6fV_NI.mjs → render-D5kwkNt1.mjs} +2 -2
- package/dist/{render-DpRO_RKm.mjs → render-DqHOJyHK.mjs} +3 -3
- package/dist/{render-BJey0bwl.mjs → render-GS1Htlu8.mjs} +9 -4
- package/dist/{result-_eQcamoz.mjs → result-D_mmCVwN.mjs} +2 -2
- package/dist/{validate-COaZso7u.mjs → validate-BDwL7Su3.mjs} +6 -2
- package/dist/{validate-CxtdeQ5S.mjs → validate-Bxy9NfB8.mjs} +1 -1
- package/docs/arc42/09-decisions.arc42.md +24 -0
- package/explainer/docs/arc42/05-explainer-building-blocks.arc42.md +7 -3
- package/explainer/e2e/runtime.e2e.ts +6 -0
- package/explainer/package.json +2 -1
- package/interactive/package.json +2 -1
- package/package.json +38 -2
- package/quiz/docs/arc42/05-quiz-building-blocks.arc42.md +7 -3
- package/quiz/e2e/runtime.e2e.ts +5 -0
- package/quiz/package.json +2 -1
- package/runtime/explainer/assessment-page.ts +2 -0
- package/runtime/explainer/e2e.ts +204 -149
- package/runtime/explainer/exercises.ts +2 -0
- package/runtime/explainer/outline.ts +8 -1
- package/runtime/quiz/e2e.ts +172 -135
- package/runtime/shared/questions/question.ts +3 -0
- package/runtime/shared/questions/question.v1.schema.json +4 -0
- package/runtime/shared/questions/render.ts +14 -6
- package/runtime/shared/text/markdown.ts +1 -1
- package/runtime/shared/text/speech.ts +39 -0
- package/scaffold/explainer/src/app.yaml +5 -0
- package/scaffold/explainer/src/thema/chapter.yaml +4 -0
- package/scaffold/explainer/src/thema/einstieg.yaml +28 -0
- package/scaffold/interactive/src/app.yaml +8 -0
- package/scaffold/interactive/src/core/index.ts +23 -0
- package/scaffold/interactive/src/messages/de.json +6 -0
- package/scaffold/interactive/src/playthroughs/zaehlen.yaml +12 -0
- package/scaffold/interactive/src/ui/App.vue +27 -0
- package/scaffold/quiz/src/quiz.json +31 -0
package/dist/quiz.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S as shuffled, g as questionId, u as isCorrect } from "./render-
|
|
2
|
-
import { n as startQuestion } from "./engine-
|
|
3
|
-
import { a as de_default, i as en_default, r as solutionId } from "./quiz-
|
|
1
|
+
import { S as shuffled, g as questionId, u as isCorrect } from "./render-GS1Htlu8.mjs";
|
|
2
|
+
import { n as startQuestion } from "./engine-CArxqizW.mjs";
|
|
3
|
+
import { a as de_default, i as en_default, r as solutionId } from "./quiz-DnW-xtCh.mjs";
|
|
4
4
|
import { translator } from "@lernapps/tooling/i18n";
|
|
5
5
|
import { announce, moveFocus } from "@lernapps/tooling/a11y";
|
|
6
6
|
import { createStorage } from "@lernapps/tooling/storage";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as inLanguage, l as textsIn, o as languageListProblems, r as LANGUAGES } from "./html-mffkHGHh.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { c as renderMarkdown, o as plain } from "./check-CteIFN96.mjs";
|
|
3
3
|
import { a as pageFooter, o as pageHeader, r as languageRoot, s as relative, t as alternateLinks } from "./pages-9RaaomoO.mjs";
|
|
4
|
-
import { c as schemaProblems, n as Texts, s as readYaml, t as Problems } from "./content-
|
|
4
|
+
import { c as schemaProblems, n as Texts, s as readYaml, t as Problems } from "./content-DO6oEJxj.mjs";
|
|
5
5
|
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
6
6
|
import { existsSync, readdirSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { l as textsIn, s as localeOf, t as escape } from "./html-mffkHGHh.mjs";
|
|
2
|
-
import { n as renderMaterial } from "./blocks-
|
|
3
|
-
import { a as renderQuestion, g as questionId, o as renderSolution, r as external, t as QUESTION_MESSAGES } from "./render-
|
|
4
|
-
import { a as de_default, i as en_default, r as solutionId } from "./quiz-
|
|
2
|
+
import { n as renderMaterial } from "./blocks-CxtCPAa5.mjs";
|
|
3
|
+
import { a as renderQuestion, g as questionId, o as renderSolution, r as external, t as QUESTION_MESSAGES } from "./render-GS1Htlu8.mjs";
|
|
4
|
+
import { a as de_default, i as en_default, r as solutionId } from "./quiz-DnW-xtCh.mjs";
|
|
5
5
|
import { a as pageFooter, o as pageHeader, r as languageRoot, s as relative, t as alternateLinks } from "./pages-9RaaomoO.mjs";
|
|
6
6
|
import { translator } from "@lernapps/tooling/i18n";
|
|
7
7
|
// runtime/quiz/render.ts
|
|
@@ -199,6 +199,7 @@ function questionIn(question, lang) {
|
|
|
199
199
|
text: t(option.text),
|
|
200
200
|
correct: option.correct,
|
|
201
201
|
info: t(option.info),
|
|
202
|
+
...option.alt === void 0 ? {} : { alt: t(option.alt) },
|
|
202
203
|
...option.link === void 0 ? {} : { link: link(option.link) }
|
|
203
204
|
}))
|
|
204
205
|
};
|
|
@@ -415,13 +416,17 @@ function questionWords(lang = "de") {
|
|
|
415
416
|
}
|
|
416
417
|
return found;
|
|
417
418
|
}
|
|
418
|
-
function controls(question, { t }, format) {
|
|
419
|
+
function controls(question, { t }, format, describe) {
|
|
419
420
|
const name = questionId(question);
|
|
420
421
|
switch (question.type) {
|
|
421
422
|
case "single-choice":
|
|
422
423
|
case "multiple-choice": {
|
|
423
424
|
const type = question.type === "single-choice" ? "radio" : "checkbox";
|
|
424
|
-
return question.options.map((option, index) =>
|
|
425
|
+
return question.options.map((option, index) => {
|
|
426
|
+
const spoken = option.alt ?? describe?.(option.text);
|
|
427
|
+
const label = spoken === void 0 ? "" : ` aria-label="${escape(spoken)}"`;
|
|
428
|
+
return `<label class="question-option"><input type="${type}" name="${name}" value="${index}"${label}> <span>${format(option.text)}</span></label>`;
|
|
429
|
+
}).join("\n");
|
|
425
430
|
}
|
|
426
431
|
case "true-false": return [true, false].map((value) => `<label class="question-option"><input type="radio" name="${name}" value="${value}"> <span>${t(value ? "true" : "false")}</span></label>`).join("\n");
|
|
427
432
|
case "number": return [
|
|
@@ -456,7 +461,7 @@ function controls(question, { t }, format) {
|
|
|
456
461
|
* what the learner learns about it (the same as its solution). The engine's startQuestion makes it live; without
|
|
457
462
|
* JavaScript the button stays hidden.
|
|
458
463
|
*/
|
|
459
|
-
function renderQuestion(question, { element = "div", next = false, lang = "de", textHtml, materialHtml, explanationHtml, format = escape } = {}) {
|
|
464
|
+
function renderQuestion(question, { element = "div", next = false, lang = "de", textHtml, materialHtml, explanationHtml, format = escape, describe } = {}) {
|
|
460
465
|
const words = questionWords(lang);
|
|
461
466
|
const { t } = words;
|
|
462
467
|
const id = questionId(question);
|
|
@@ -467,7 +472,7 @@ function renderQuestion(question, { element = "div", next = false, lang = "de",
|
|
|
467
472
|
`<fieldset>`,
|
|
468
473
|
`<legend class="question-text">${textHtml ?? format(question.text)}</legend>`,
|
|
469
474
|
...materialHtml === void 0 || materialHtml === "" ? [] : [`<div class="question-material">${materialHtml}</div>`],
|
|
470
|
-
controls(question, words, format),
|
|
475
|
+
controls(question, words, format, describe),
|
|
471
476
|
`</fieldset>`,
|
|
472
477
|
`<div class="question-feedback" role="status"></div>`,
|
|
473
478
|
`<div class="question-reveal" hidden>`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as rightEntries } from "./render-
|
|
2
|
-
import { w as message } from "./assessment-
|
|
1
|
+
import { x as rightEntries } from "./render-GS1Htlu8.mjs";
|
|
2
|
+
import { w as message } from "./assessment-Dy359O1O.mjs";
|
|
3
3
|
// runtime/explainer/result.ts
|
|
4
4
|
const key = (id, n) => n === void 0 ? id : `${id}=${n}`;
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as textLanguages } from "./html-mffkHGHh.mjs";
|
|
2
|
-
import { n as checkMaterial, t as MATERIAL_DEFINITIONS } from "./validate-
|
|
3
|
-
import { _ as questionIn, h as questionAddresses, l as isComplete, m as parseNumber, u as isCorrect, v as questionTexts, x as rightEntries } from "./render-
|
|
2
|
+
import { n as checkMaterial, t as MATERIAL_DEFINITIONS } from "./validate-Bxy9NfB8.mjs";
|
|
3
|
+
import { _ as questionIn, h as questionAddresses, l as isComplete, m as parseNumber, u as isCorrect, v as questionTexts, x as rightEntries } from "./render-GS1Htlu8.mjs";
|
|
4
4
|
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
5
5
|
// runtime/shared/examples.ts
|
|
6
6
|
/**
|
|
@@ -591,6 +591,10 @@ var question_v1_schema_default = {
|
|
|
591
591
|
"description": "One to three sentences of background on this option itself, true whether or not it is the right answer, e.g. \"Der Uluru ist ein Inselberg in der Wüste Zentralaustraliens ...\". After an answer it shows for every option. For a wrong option it is also the reason a learner who chose it reads with the feedback, so say there why it does not fit.",
|
|
592
592
|
"$ref": "urn:lernapps:schema:text.v1#/$defs/text"
|
|
593
593
|
},
|
|
594
|
+
"alt": {
|
|
595
|
+
"description": "Optional: the option as it is spoken, for the name of its radio button or checkbox, when its text is only a formula, e.g. \"zwei hoch sieben\" for \"$2^7$\". Without it the name is made from the formula in the page's language (\"2 hoch 7\"); write it where that reads badly, e.g. for a chemical formula. Not needed when the text has words.",
|
|
596
|
+
"$ref": "urn:lernapps:schema:text.v1#/$defs/text"
|
|
597
|
+
},
|
|
594
598
|
"link": {
|
|
595
599
|
"description": "Further reading on this option.",
|
|
596
600
|
"$ref": "#/$defs/link"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as inLanguage } from "./html-mffkHGHh.mjs";
|
|
2
2
|
import { n as markerOf } from "./block-BK_ohsH1.mjs";
|
|
3
|
-
import { t as checkText } from "./check-
|
|
3
|
+
import { t as checkText } from "./check-CteIFN96.mjs";
|
|
4
4
|
// runtime/shared/blocks/validate.ts
|
|
5
5
|
/** The definition of each type of block in the schema of the blocks (blocks.v1.schema.json). */
|
|
6
6
|
const MATERIAL_DEFINITIONS = {
|
|
@@ -228,6 +228,30 @@ addresses: qg-understandable
|
|
|
228
228
|
:::
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
+
## A New App Gets the Scaffold, Not the Example
|
|
232
|
+
|
|
233
|
+
`lernapps create` copies only the scaffold of the archetype into a new app: the paths that `lernapps.scaffold.<archetype>`
|
|
234
|
+
in this package's `package.json` lists (the entry, the configuration, the e2e entry) and a placeholder as start content
|
|
235
|
+
(`scaffold/<archetype>/`: one question, one page with one exercise, or a counter as the core). The template folder
|
|
236
|
+
stays a complete example app, which this repo checks; an app does not copy it, the creator's assistant looks it up in
|
|
237
|
+
`node_modules/@lernapps/app-templates/<archetype>/`. A copied example shaped the new app too much: its structure,
|
|
238
|
+
its topic and its tone stayed long after the plan said otherwise. The list is data in this package, which alone knows
|
|
239
|
+
what is configuration and what is example; the tooling only reads it. The CI job `scaffold` checks the scaffold as an
|
|
240
|
+
app, so that a new app passes `lernapps check` from its first commit. `lernapps update` never writes the scaffold
|
|
241
|
+
again: it moves libraries, not content. Rejected: a function `scaffold()` exported by the package, which would need the
|
|
242
|
+
built package even in a clone given to `create --templates`; start content inside the template folder, which the
|
|
243
|
+
template's own checks would read as part of the example.
|
|
244
|
+
|
|
245
|
+
```arc42
|
|
246
|
+
:::decision
|
|
247
|
+
id: dec-scaffold
|
|
248
|
+
title: A new app gets the scaffold and a placeholder, not the example app
|
|
249
|
+
status: accepted
|
|
250
|
+
date: 2026-11-02
|
|
251
|
+
addresses: qg-understandable
|
|
252
|
+
:::
|
|
253
|
+
```
|
|
254
|
+
|
|
231
255
|
## Tutor Variant
|
|
232
256
|
|
|
233
257
|
The optional tutor is a handoff to the learner's own assistant: after a click, a prompt (copied or passed to a chosen
|
|
@@ -488,8 +488,12 @@ path: runtime/explainer/assessment.ts
|
|
|
488
488
|
|
|
489
489
|
### End-to-end tests
|
|
490
490
|
|
|
491
|
-
Built. `explainerTests()` derives from the content what every page must
|
|
492
|
-
|
|
491
|
+
Built, in two parts. `explainerTests()` checks the app's content: it derives from the content what every page must
|
|
492
|
+
show and checks it without JavaScript in every language, previous and next, and with JavaScript the app's own
|
|
493
|
+
components and the checks of its exercise components. `explainerRuntimeTests()` checks the runtime, the same in every
|
|
494
|
+
app: one exercise per type and page, the videos, the tutor ways, the start page, the self-assessments, what is stored.
|
|
495
|
+
Only this repo runs the second part, on the template and its fixtures (`explainer/e2e/runtime.e2e.ts`, not in the
|
|
496
|
+
scaffold).
|
|
493
497
|
|
|
494
498
|
```arc42
|
|
495
499
|
:::building-block
|
|
@@ -504,7 +508,7 @@ requires: if-archetype-content, if-runtime-texts, if-questions
|
|
|
504
508
|
|
|
505
509
|
#### Tests interface
|
|
506
510
|
|
|
507
|
-
The app's `e2e/explainer.e2e.ts
|
|
511
|
+
The app's `e2e/explainer.e2e.ts`, part of the scaffold, only calls `explainerTests()`.
|
|
508
512
|
|
|
509
513
|
```arc42
|
|
510
514
|
:::interface
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { explainerRuntimeTests } from "@lernapps/app-templates/explainer/e2e";
|
|
2
|
+
|
|
3
|
+
// The tests of the explainer runtime, which this repo runs on the template and its fixtures. Not part of the scaffold
|
|
4
|
+
// (lernapps.scaffold in the package.json of @lernapps/app-templates): a new app runs only explainerTests(), on its
|
|
5
|
+
// content.
|
|
6
|
+
explainerRuntimeTests();
|
package/explainer/package.json
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@lernapps/app-templates": "file:..",
|
|
12
|
-
"@lernapps/tooling": "
|
|
12
|
+
"@lernapps/tooling": "^0.1.2",
|
|
13
13
|
"vite-plus": "1.4.0"
|
|
14
14
|
},
|
|
15
15
|
"overrides": {
|
|
16
|
+
"@lernapps/app-templates": "file:..",
|
|
16
17
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
|
|
17
18
|
}
|
|
18
19
|
}
|
package/interactive/package.json
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@lernapps/app-templates": "file:..",
|
|
12
|
-
"@lernapps/tooling": "
|
|
12
|
+
"@lernapps/tooling": "^0.1.2",
|
|
13
13
|
"vite-plus": "1.4.0"
|
|
14
14
|
},
|
|
15
15
|
"overrides": {
|
|
16
|
+
"@lernapps/app-templates": "file:..",
|
|
16
17
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
|
|
17
18
|
}
|
|
18
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lernapps/app-templates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "The templates of the archetypes of lernapps.net apps, and the runtime of each archetype that apps depend on (the quiz: engine, build step, styles, end-to-end tests, the schema of the question bank, the questions it shares with the explainer are in ./questions; the explainer: build step, client module with its exercises, the islands of its Vue components, styles, end-to-end tests, the schema of its content; the interactive archetype: build step, the start page and the app page around the app's own Vue components and core, its playthroughs, styles, end-to-end tests, the schemas of its start page and its playthroughs)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"explainer",
|
|
15
15
|
"interactive",
|
|
16
16
|
"quiz",
|
|
17
|
+
"scaffold",
|
|
17
18
|
"!**/package-lock.json",
|
|
18
19
|
"!**/node_modules"
|
|
19
20
|
],
|
|
@@ -100,6 +101,7 @@
|
|
|
100
101
|
"highlight.js": "11.12.0",
|
|
101
102
|
"marked": "18.1.2",
|
|
102
103
|
"source-map-js": "1.2.2",
|
|
104
|
+
"speech-rule-engine": "4.1.5",
|
|
103
105
|
"temml": "0.14.0",
|
|
104
106
|
"vue": "3.5.44",
|
|
105
107
|
"yaml": "2.9.1"
|
|
@@ -141,6 +143,40 @@
|
|
|
141
143
|
"explainer",
|
|
142
144
|
"interactive",
|
|
143
145
|
"quiz"
|
|
144
|
-
]
|
|
146
|
+
],
|
|
147
|
+
"scaffold": {
|
|
148
|
+
"explainer": [
|
|
149
|
+
".gitignore",
|
|
150
|
+
"index.html",
|
|
151
|
+
"package.json",
|
|
152
|
+
"tsconfig.json",
|
|
153
|
+
"vite.config.ts",
|
|
154
|
+
"playwright.config.ts",
|
|
155
|
+
"src/main.ts",
|
|
156
|
+
"e2e/explainer.e2e.ts"
|
|
157
|
+
],
|
|
158
|
+
"interactive": [
|
|
159
|
+
".arc42ignore",
|
|
160
|
+
".gitignore",
|
|
161
|
+
"index.html",
|
|
162
|
+
"package.json",
|
|
163
|
+
"tsconfig.json",
|
|
164
|
+
"vite.config.ts",
|
|
165
|
+
"playwright.config.ts",
|
|
166
|
+
"src/main.ts",
|
|
167
|
+
"src/env.d.ts",
|
|
168
|
+
"e2e/interactive.e2e.ts"
|
|
169
|
+
],
|
|
170
|
+
"quiz": [
|
|
171
|
+
".gitignore",
|
|
172
|
+
"index.html",
|
|
173
|
+
"package.json",
|
|
174
|
+
"tsconfig.json",
|
|
175
|
+
"vite.config.ts",
|
|
176
|
+
"playwright.config.ts",
|
|
177
|
+
"src/main.ts",
|
|
178
|
+
"e2e/quiz.e2e.ts"
|
|
179
|
+
]
|
|
180
|
+
}
|
|
145
181
|
}
|
|
146
182
|
}
|
|
@@ -196,8 +196,12 @@ path: runtime/quiz/engine.ts
|
|
|
196
196
|
|
|
197
197
|
### End-to-end tests
|
|
198
198
|
|
|
199
|
-
Built. `quizTests()` checks
|
|
200
|
-
|
|
199
|
+
Built, in two parts. `quizTests()` checks the app's content: each question's deep link with what it shows, the page
|
|
200
|
+
without JavaScript with every question and its solution, and each further language. `quizRuntimeTests()` checks the
|
|
201
|
+
runtime, the same in every app: right and wrong answer with the feedback in view and the focus, the seed and the order,
|
|
202
|
+
the run to the full score, the number of questions, what is stored. Only this repo runs the second part, on the
|
|
203
|
+
template and its fixtures (`quiz/e2e/runtime.e2e.ts`, not in the scaffold): its time grows with the bank, and it tests
|
|
204
|
+
nothing an app writes.
|
|
201
205
|
|
|
202
206
|
```arc42
|
|
203
207
|
:::building-block
|
|
@@ -212,7 +216,7 @@ requires: if-archetype-content, if-runtime-texts
|
|
|
212
216
|
|
|
213
217
|
#### Tests interface
|
|
214
218
|
|
|
215
|
-
The app's `e2e/quiz.e2e.ts
|
|
219
|
+
The app's `e2e/quiz.e2e.ts`, part of the scaffold, only calls `quizTests()`.
|
|
216
220
|
|
|
217
221
|
```arc42
|
|
218
222
|
:::interface
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { quizRuntimeTests } from "@lernapps/app-templates/quiz/e2e";
|
|
2
|
+
|
|
3
|
+
// The tests of the quiz runtime, which this repo runs on the template and its fixtures. Not part of the scaffold
|
|
4
|
+
// (lernapps.scaffold in the package.json of @lernapps/app-templates): a new app runs only quizTests(), on its content.
|
|
5
|
+
quizRuntimeTests();
|
package/quiz/package.json
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@lernapps/app-templates": "file:..",
|
|
12
|
-
"@lernapps/tooling": "
|
|
12
|
+
"@lernapps/tooling": "^0.1.2",
|
|
13
13
|
"vite-plus": "1.4.0"
|
|
14
14
|
},
|
|
15
15
|
"overrides": {
|
|
16
|
+
"@lernapps/app-templates": "file:..",
|
|
16
17
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
|
|
17
18
|
}
|
|
18
19
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { renderQuestion } from "../shared/questions/render.ts";
|
|
13
13
|
import { type MaterialContext, renderMaterial } from "../shared/blocks/index.ts";
|
|
14
14
|
import { plain, renderWithFormulas } from "../shared/text/markdown.ts";
|
|
15
|
+
import { formulaAlternative } from "../shared/text/speech.ts";
|
|
15
16
|
import {
|
|
16
17
|
assessments,
|
|
17
18
|
drawsTasks,
|
|
@@ -117,6 +118,7 @@ function itemHtml(context: AssessmentContext, data: AssessmentItemData, n: numbe
|
|
|
117
118
|
return `${label}${renderQuestion(question, {
|
|
118
119
|
lang,
|
|
119
120
|
format: (text) => rendered[text] ?? renderWithFormulas(text),
|
|
121
|
+
describe: (text) => formulaAlternative(text, lang),
|
|
120
122
|
...(question.material === undefined ? {} : { materialHtml: renderMaterial(question.material, context.material) }),
|
|
121
123
|
})}`;
|
|
122
124
|
}
|