@heroiclands/package-build 25.2.0 → 25.2.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 +7 -0
- package/docs/content-format.md +1 -1
- package/docs/source-preview.md +2 -1
- package/engine/journals.mjs +14 -14
- package/engine/preview-source.mjs +15 -8
- package/package.json +1 -1
- package/types/engine/journals.d.mts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 25.2.1
|
|
4
|
+
|
|
5
|
+
**Rendering and sites**
|
|
6
|
+
|
|
7
|
+
- Preview tables display linked names cleanly and keep their following columns aligned.
|
|
8
|
+
- Foundry journal page names show the readable text of headings containing names, links or emphasis.
|
|
9
|
+
|
|
3
10
|
## 25.2.0
|
|
4
11
|
|
|
5
12
|
**Content and notes**
|
package/docs/content-format.md
CHANGED
|
@@ -25,7 +25,7 @@ Start with [your first note](authoring/first-note.md). It explains the smallest
|
|
|
25
25
|
|
|
26
26
|
## The shared note
|
|
27
27
|
|
|
28
|
-
A nonempty note body creates one system-agnostic Foundry JournalEntry. Content before the first H1 becomes an introduction page; every H1 starts another JournalEntryPage. A lower-level heading with an explicit `{#anchor}` starts a page too, so a link can address it. The same prose becomes a web page and can be selected for a book. The content index records the note and its frontmatter for queries and navigation.
|
|
28
|
+
A nonempty note body creates one system-agnostic Foundry JournalEntry. Content before the first H1 becomes an introduction page; every H1 starts another JournalEntryPage. A lower-level heading with an explicit `{#anchor}` starts a page too, so a link can address it. Each page name is its heading's visible text: spans, links and emphasis contribute their text without their markup. The same prose becomes a web page and can be selected for a book. The content index records the note and its frontmatter for queries and navigation.
|
|
29
29
|
|
|
30
30
|
Leading `:` captions describe the next supported block; `:@` captions also number it. The optional type accepts `figure`, `table`, `verse`, `code`, `prose`, and `example`. Captions support identifiers, classes and named attributes; unsupported following blocks are errors. See [captions and numbered references](authoring/links-and-markup.md#captions-and-numbered-references).
|
|
31
31
|
|
package/docs/source-preview.md
CHANGED
|
@@ -37,7 +37,8 @@ source. A host that holds the package's content index builds an index with
|
|
|
37
37
|
wikilink is a link, a link to a concealed note is concealed, an embed draws its
|
|
38
38
|
picture, marked text is mapped and set in its face, an icon is drawn, and a
|
|
39
39
|
caption is numbered with its asset's role, so a map is a **Map**. A query, which
|
|
40
|
-
a buffer cannot run, stays highlighted source in both views.
|
|
40
|
+
a buffer cannot run, stays highlighted source in both views. Table cells keep
|
|
41
|
+
wikilinks and their labels together, including links inside marked spans.
|
|
41
42
|
|
|
42
43
|
With an index, a marked-text run that cannot be set produces an error finding
|
|
43
44
|
and sets the result's `ok` to `false`. The preview still returns recoverable
|
package/engine/journals.mjs
CHANGED
|
@@ -116,9 +116,9 @@ function namedBlockLines(markdown, syntax) {
|
|
|
116
116
|
* code blocks are respected so `# foo` inside ``` or ~~~ blocks doesn't
|
|
117
117
|
* trigger a split. Content before the first H1 (if non-empty) becomes a
|
|
118
118
|
* leading page. Each H1 yields a page whose name is the heading
|
|
119
|
-
* text (with any `{#anchor-id}` suffix stripped out and
|
|
120
|
-
* `anchorSlug`). The classes the heading declares come along as
|
|
121
|
-
* a surface that honours one has it without reading the suffix again.
|
|
119
|
+
* text without inline markup (with any `{#anchor-id}` suffix stripped out and
|
|
120
|
+
* surfaced as `anchorSlug`). The classes the heading declares come along as
|
|
121
|
+
* `classes`, so a surface that honours one has it without reading the suffix again.
|
|
122
122
|
*
|
|
123
123
|
* `leadName` names that leading page. A journal note's is "Introduction",
|
|
124
124
|
* because it introduces the pages that follow. An item doc's is the item — a
|
|
@@ -220,7 +220,7 @@ export function splitPages(body, leadName = "Introduction", resolveRole, syntax)
|
|
|
220
220
|
anchorSlug: null,
|
|
221
221
|
level: section.level,
|
|
222
222
|
classes: section.classes,
|
|
223
|
-
continues: item.slug || item.label ||
|
|
223
|
+
continues: item.slug || item.label || pageNameText(item.caption),
|
|
224
224
|
lines: [],
|
|
225
225
|
};
|
|
226
226
|
}
|
|
@@ -231,7 +231,7 @@ export function splitPages(body, leadName = "Introduction", resolveRole, syntax)
|
|
|
231
231
|
if (figure) {
|
|
232
232
|
closeCurrent();
|
|
233
233
|
current = {
|
|
234
|
-
name: figure.label ||
|
|
234
|
+
name: figure.label || pageNameText(figure.caption),
|
|
235
235
|
anchorSlug: figure.id || null,
|
|
236
236
|
level: 1,
|
|
237
237
|
classes: section.classes.includes(WITHHELD_CLASS) ? [WITHHELD_CLASS] : [],
|
|
@@ -243,7 +243,7 @@ export function splitPages(body, leadName = "Introduction", resolveRole, syntax)
|
|
|
243
243
|
if (opening) {
|
|
244
244
|
closeCurrent();
|
|
245
245
|
current = {
|
|
246
|
-
name: opening.text,
|
|
246
|
+
name: pageNameText(opening.text),
|
|
247
247
|
anchorSlug: opening.id || null,
|
|
248
248
|
level: opening.level,
|
|
249
249
|
classes: opening.classes,
|
|
@@ -384,20 +384,20 @@ export function journalPageId(entryId, page) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
/**
|
|
387
|
-
* The name of
|
|
387
|
+
* The name of a page a heading or caption begins: its visible text.
|
|
388
388
|
*
|
|
389
|
-
* Foundry shows a page name as plain text, so
|
|
389
|
+
* Foundry shows a page name as plain text, so inline markup — emphasis, a
|
|
390
390
|
* code span, a Markdown link, or the `@UUID[...]{label}` a resolved wikilink
|
|
391
391
|
* has already become, inside its wrapping `<span>` — reduces to the text a
|
|
392
392
|
* reader sees, the same text a reference to the caption displays. The markup
|
|
393
393
|
* itself stays in the page's content, where it renders.
|
|
394
394
|
*
|
|
395
|
-
* @param {string}
|
|
395
|
+
* @param {string} markdown - A heading or caption, as the journal pass sees it.
|
|
396
396
|
* @returns {string} Its visible text, whitespace collapsed.
|
|
397
397
|
*/
|
|
398
|
-
function
|
|
399
|
-
if (!
|
|
400
|
-
const [inline] = md.parseInline(
|
|
398
|
+
function pageNameText(markdown) {
|
|
399
|
+
if (!markdown) return "";
|
|
400
|
+
const [inline] = md.parseInline(markdown, {});
|
|
401
401
|
const text = (inline?.children ?? [])
|
|
402
402
|
.map((token) =>
|
|
403
403
|
token.type === "text" || token.type === "code_inline" ? token.content
|
|
@@ -501,7 +501,7 @@ function buildFigurePageFields(figure, page, pageId, footnoteNumbers, resolveRol
|
|
|
501
501
|
// image's own render takes when no configuration resolves it.
|
|
502
502
|
}
|
|
503
503
|
return {
|
|
504
|
-
name: figure.label ||
|
|
504
|
+
name: figure.label || pageNameText(figure.caption),
|
|
505
505
|
type: "image",
|
|
506
506
|
src,
|
|
507
507
|
image: figure.hasCaption ? { caption: figure.caption } : {},
|
|
@@ -520,7 +520,7 @@ function buildFigurePageFields(figure, page, pageId, footnoteNumbers, resolveRol
|
|
|
520
520
|
runs,
|
|
521
521
|
);
|
|
522
522
|
return {
|
|
523
|
-
name: figure.label ||
|
|
523
|
+
name: figure.label || pageNameText(figure.caption),
|
|
524
524
|
type: "text",
|
|
525
525
|
text: {
|
|
526
526
|
format: 1,
|
|
@@ -67,7 +67,8 @@ export const PREVIEW_HELPERS = Object.freeze({
|
|
|
67
67
|
*/
|
|
68
68
|
export const INERT_BRACKET = "\uE000";
|
|
69
69
|
|
|
70
|
-
const
|
|
70
|
+
const syntax = new MarkdownIt();
|
|
71
|
+
const escapeHtml = syntax.utils.escapeHtml;
|
|
71
72
|
// An authored `<` stands as a private-use character until the HTML is written;
|
|
72
73
|
// source is shown as it was authored.
|
|
73
74
|
const escape = (value) => escapeHtml(String(value ?? "").replaceAll(INERT_BRACKET, "<"));
|
|
@@ -185,16 +186,16 @@ function withTrailingAttributes(rest, raw) {
|
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
/**
|
|
188
|
-
* The cells of one table row, keeping
|
|
189
|
-
*
|
|
189
|
+
* The cells of one table row, keeping pipes inside balanced brackets, code
|
|
190
|
+
* spans and extension braces in their cell.
|
|
190
191
|
*
|
|
191
192
|
* @param {string} line - One table line.
|
|
192
193
|
* @returns {string[]} The trimmed cells, without the empty edges.
|
|
193
194
|
*/
|
|
194
195
|
function tableCells(line) {
|
|
195
196
|
const result = [];
|
|
197
|
+
const state = new syntax.inline.State(line, syntax, {}, []);
|
|
196
198
|
let cell = "",
|
|
197
|
-
wiki = false,
|
|
198
199
|
code = "",
|
|
199
200
|
quote = false,
|
|
200
201
|
braces = 0;
|
|
@@ -204,7 +205,15 @@ function tableCells(line) {
|
|
|
204
205
|
cell += char + line[++at];
|
|
205
206
|
continue;
|
|
206
207
|
}
|
|
207
|
-
if (char === "
|
|
208
|
+
if (char === "[" && !code && !braces) {
|
|
209
|
+
const end = syntax.helpers.parseLinkLabel(state, at, false);
|
|
210
|
+
if (end >= 0) {
|
|
211
|
+
cell += line.slice(at, end + 1);
|
|
212
|
+
at = end;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (char === "`") {
|
|
208
217
|
const marks = /^`+/.exec(line.slice(at))[0];
|
|
209
218
|
if (!code) code = marks;
|
|
210
219
|
else if (code === marks) code = "";
|
|
@@ -213,13 +222,11 @@ function tableCells(line) {
|
|
|
213
222
|
continue;
|
|
214
223
|
}
|
|
215
224
|
if (!code) {
|
|
216
|
-
if (line.slice(at, at + 2) === "[[") wiki = true;
|
|
217
|
-
if (line.slice(at - 1, at + 1) === "]]") wiki = false;
|
|
218
225
|
if (char === '"' && braces) quote = !quote;
|
|
219
226
|
if (!quote && char === "{") braces++;
|
|
220
227
|
if (!quote && char === "}" && braces) braces--;
|
|
221
228
|
}
|
|
222
|
-
if (char === "|" && !
|
|
229
|
+
if (char === "|" && !code && !braces) {
|
|
223
230
|
result.push(cell.trim());
|
|
224
231
|
cell = "";
|
|
225
232
|
} else cell += char;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heroiclands/package-build",
|
|
3
|
-
"version": "25.2.
|
|
3
|
+
"version": "25.2.1",
|
|
4
4
|
"description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package \u2014 content compilation, manifest, localization, staging, bundle, release and deployment.",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* code blocks are respected so `# foo` inside ``` or ~~~ blocks doesn't
|
|
4
4
|
* trigger a split. Content before the first H1 (if non-empty) becomes a
|
|
5
5
|
* leading page. Each H1 yields a page whose name is the heading
|
|
6
|
-
* text (with any `{#anchor-id}` suffix stripped out and
|
|
7
|
-
* `anchorSlug`). The classes the heading declares come along as
|
|
8
|
-
* a surface that honours one has it without reading the suffix again.
|
|
6
|
+
* text without inline markup (with any `{#anchor-id}` suffix stripped out and
|
|
7
|
+
* surfaced as `anchorSlug`). The classes the heading declares come along as
|
|
8
|
+
* `classes`, so a surface that honours one has it without reading the suffix again.
|
|
9
9
|
*
|
|
10
10
|
* `leadName` names that leading page. A journal note's is "Introduction",
|
|
11
11
|
* because it introduces the pages that follow. An item doc's is the item — a
|