@hajimism/dek 0.5.1 → 0.6.1
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/CHANGELOG.md +38 -0
- package/package.json +10 -3
- package/src/cli/build.ts +3 -1
- package/src/cli/check.ts +20 -11
- package/src/cli/commands.ts +24 -10
- package/src/cli/contract.ts +28 -2
- package/src/cli/flags.ts +5 -0
- package/src/cli/lint.ts +53 -1
- package/src/cli/sync.ts +21 -6
- package/src/cli/text.ts +20 -2
- package/src/core/build.ts +4 -0
- package/src/core/config-keys.ts +7 -2
- package/src/core/config.ts +63 -0
- package/src/core/diagnostic.ts +9 -1
- package/src/core/document.ts +28 -3
- package/src/core/lint/script.ts +2 -4
- package/src/core/page.ts +1 -0
- package/src/core/plugin-host.ts +709 -0
- package/src/core/plugin.ts +442 -0
- package/src/core/sarif.ts +47 -5
- package/src/core/script-lines.ts +11 -0
- package/src/core/sync.ts +4 -2
- package/src/plugin-api.ts +126 -0
- package/src/plugins/study/check.ts +128 -0
- package/src/plugins/study/main.ts +47 -0
- package/src/plugins/study/manifest.ts +32 -0
- package/src/plugins/study/page.ts +295 -0
- package/src/plugins/study/place.ts +88 -0
- package/src/plugins/study/sarif.ts +30 -0
- package/src/plugins/study/study.ts +137 -0
- package/src/plugins/study/text.ts +55 -0
- package/src/plugins/study/yaml.ts +226 -0
- package/src/plugins/words/check.ts +109 -0
- package/src/plugins/words/lines.ts +26 -0
- package/src/plugins/words/list.ts +288 -0
- package/src/plugins/words/main.ts +50 -0
- package/src/plugins/words/manifest.ts +36 -0
- package/src/plugins/words/match.ts +60 -0
- package/src/plugins/words/sarif.ts +37 -0
- package/src/plugins/words/text.ts +352 -0
- package/src/plugins/words/yaml.ts +225 -0
- package/src/runtime/player.ts +18 -2
- package/src/runtime/plugins.ts +236 -0
- package/src/runtime/start.ts +16 -1
- package/src/runtime/window.ts +3 -0
- package/src/server/deck-snapshot.ts +32 -1
- package/src/server/dev.ts +7 -1
- package/src/server/pages.ts +9 -1
package/src/core/document.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { escapeAttr, escapeHtml } from "./escape.ts";
|
|
|
4
4
|
import { collectSlidesHtml, htmlShell } from "./html.ts";
|
|
5
5
|
import { type OgpImage, ogpHead } from "./ogp.ts";
|
|
6
6
|
import { PAGE_ID, type PageMode, pageConfigAttrs } from "./page.ts";
|
|
7
|
+
import type { PluginPage } from "./plugin.ts";
|
|
7
8
|
import {
|
|
8
9
|
nextPresenterTitle,
|
|
9
10
|
presenterSlides,
|
|
@@ -49,14 +50,19 @@ export type PageTarget =
|
|
|
49
50
|
/** The deck at `dir`, rendered for `target`. */
|
|
50
51
|
export function renderDeckHtml(
|
|
51
52
|
dir: string,
|
|
52
|
-
options: { playerScript: string; target: PageTarget },
|
|
53
|
+
options: { playerScript: string; target: PageTarget; plugins?: PluginPage[] },
|
|
53
54
|
): string {
|
|
54
55
|
return renderDeckDocument(resolveDeck(dir).deck, options);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function renderDeckDocument(
|
|
58
59
|
deck: ProjectDeck,
|
|
59
|
-
options: {
|
|
60
|
+
options: {
|
|
61
|
+
playerScript: string;
|
|
62
|
+
target: PageTarget;
|
|
63
|
+
/** Each plugin's page; only the player and the build carry them (ADR 33). */
|
|
64
|
+
plugins?: PluginPage[];
|
|
65
|
+
},
|
|
60
66
|
): string {
|
|
61
67
|
const { target } = options;
|
|
62
68
|
const mode: PageMode =
|
|
@@ -160,7 +166,8 @@ export function renderDeckDocument(
|
|
|
160
166
|
${slideScriptTags(slideScripts)}
|
|
161
167
|
<script>${options.playerScript}</script>
|
|
162
168
|
${target.kind === "dev" ? `<script>${target.liveReloadScript}</script>` : ""}
|
|
163
|
-
${target.kind === "dev" && includeNotes ? `<script>${target.annotateScript}</script>` : ""}
|
|
169
|
+
${target.kind === "dev" && includeNotes ? `<script>${target.annotateScript}</script>` : ""}
|
|
170
|
+
${pluginPagesHtml(target, options.plugins ?? [])}`,
|
|
164
171
|
});
|
|
165
172
|
}
|
|
166
173
|
|
|
@@ -225,6 +232,24 @@ function renderKeyHintHtml(lang: string): string {
|
|
|
225
232
|
return `<div id="${PAGE_ID.hint}" role="status"><span><kbd>s</kbd>${labels.rail}</span><span><kbd>p</kbd>${labels.presenter}</span></div>`;
|
|
226
233
|
}
|
|
227
234
|
|
|
235
|
+
/**
|
|
236
|
+
* The plugins' pages, after the player, which gives them `dek.plugin`: their keys and data as one
|
|
237
|
+
* JSON block, then each script in name order. Only the player and the build carry them; the
|
|
238
|
+
* presenter view and a video, like every still page, never do.
|
|
239
|
+
*/
|
|
240
|
+
function pluginPagesHtml(target: PageTarget, plugins: PluginPage[]): string {
|
|
241
|
+
const carried = target.kind === "build" || (target.kind === "dev" && target.mode === "player");
|
|
242
|
+
if (!carried || plugins.length === 0) {
|
|
243
|
+
return "";
|
|
244
|
+
}
|
|
245
|
+
const ordered = plugins.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
246
|
+
const config = Object.fromEntries(ordered.map(({ name, keys, data }) => [name, { keys, data }]));
|
|
247
|
+
return [
|
|
248
|
+
`<script type="application/json" id="${PAGE_ID.plugins}">${jsonForScript(config)}</script>`,
|
|
249
|
+
...ordered.map(({ script }) => `<script>${script.replace(/<\/(script)/gi, "<\\/$1")}</script>`),
|
|
250
|
+
].join("\n ");
|
|
251
|
+
}
|
|
252
|
+
|
|
228
253
|
function jsonForScript(value: unknown): string {
|
|
229
254
|
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
230
255
|
}
|
package/src/core/lint/script.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Diagnostic, diag } from "../diagnostic.ts";
|
|
2
2
|
import type { DekError } from "../error.ts";
|
|
3
3
|
import { ScriptError } from "../parse.ts";
|
|
4
|
-
import { scriptLines } from "../script-lines.ts";
|
|
4
|
+
import { scriptLines, slugAtLine } from "../script-lines.ts";
|
|
5
5
|
import type { LintContext } from "./context.ts";
|
|
6
6
|
|
|
7
7
|
/** DEK004: a section id or a beat id used twice. */
|
|
@@ -56,7 +56,6 @@ export function strayHeadingDiagnostics(ctx: LintContext): Diagnostic[] {
|
|
|
56
56
|
if (!script) {
|
|
57
57
|
return [];
|
|
58
58
|
}
|
|
59
|
-
const starts = deck.deck.sections.map((section) => ({ line: section.line, slug: section.slug }));
|
|
60
59
|
const diagnostics: Diagnostic[] = [];
|
|
61
60
|
// What the parser reads as text, a code block or a comment, is not a heading here either.
|
|
62
61
|
for (const [offset, { text, literal }] of scriptLines(script.body).entries()) {
|
|
@@ -65,8 +64,7 @@ export function strayHeadingDiagnostics(ctx: LintContext): Diagnostic[] {
|
|
|
65
64
|
continue;
|
|
66
65
|
}
|
|
67
66
|
const line = script.bodyStartLine + offset;
|
|
68
|
-
|
|
69
|
-
const slug = starts.filter((start) => start.line < line).at(-1)?.slug;
|
|
67
|
+
const slug = slugAtLine(deck.deck.sections, line);
|
|
70
68
|
diagnostics.push(
|
|
71
69
|
diag("DEK044", {
|
|
72
70
|
message: `${"#".repeat(level)} heading is not a slide or a beat; it is read as spoken text`,
|