@heroiclands/package-build 22.22.0 → 22.24.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/CHANGELOG.md +46 -0
- package/README.md +1 -0
- package/bin/content-commands.mjs +51 -14
- package/ci/content-format-reference.mjs +1 -1
- package/content-config.mjs +80 -2
- package/docs/api.md +85 -72
- package/docs/authoring/assets.md +29 -0
- package/docs/authoring/dates-and-calendars.md +37 -1
- package/docs/authoring/links-and-markup.md +112 -31
- package/docs/commands.md +30 -29
- package/docs/configuration.md +92 -19
- package/docs/content-format.md +1 -1
- package/docs/guides/book.md +5 -4
- package/docs/guides/module-project.md +2 -2
- package/docs/guides/site.md +41 -0
- package/docs/project-setup.md +4 -4
- package/docs/reference/format-details.md +323 -60
- package/docs/reference/note-types.md +9 -9
- package/docs/reference/theme-pages.md +496 -0
- package/engine/anchors.mjs +16 -10
- package/engine/art-fields.mjs +118 -0
- package/engine/art-slots.mjs +9 -2
- package/engine/asset-index.mjs +160 -10
- package/engine/asset-replacement.mjs +93 -0
- package/engine/asset-types.mjs +240 -0
- package/engine/base-compiler.mjs +54 -2
- package/engine/bundles.mjs +13 -1
- package/engine/content-blocks.mjs +4 -4
- package/engine/content-embeds.mjs +19 -0
- package/engine/content-figures.mjs +468 -0
- package/engine/content-footnotes.mjs +10 -2
- package/engine/content-format.yaml +1 -1
- package/engine/content-images.mjs +126 -25
- package/engine/content-index.mjs +36 -10
- package/engine/field-reference.mjs +31 -10
- package/engine/field-spec.mjs +10 -8
- package/engine/foreign-catalog.mjs +145 -19
- package/engine/frontmatter-lint.mjs +73 -1
- package/engine/heading-attributes.mjs +31 -18
- package/engine/helpers.mjs +102 -33
- package/engine/infobox-registry.mjs +4 -1
- package/engine/infobox.mjs +47 -8
- package/engine/itinerary-scenes.mjs +4 -10
- package/engine/journals.mjs +264 -39
- package/engine/lore-events.mjs +197 -0
- package/engine/markdown-expressions.mjs +257 -7
- package/engine/note-dates.mjs +305 -12
- package/engine/note-vocabulary.mjs +11 -5
- package/engine/pathnames.mjs +36 -0
- package/engine/pdf-build.mjs +357 -34
- package/engine/pdf-images.mjs +64 -0
- package/engine/pdf-render.mjs +160 -36
- package/engine/scenes.mjs +16 -4
- package/engine/site-build.mjs +127 -13
- package/engine/site-config.mjs +19 -24
- package/engine/site-index.mjs +72 -1
- package/engine/site-preview.mjs +2 -0
- package/engine/system-block.mjs +44 -16
- package/hm3/actors.mjs +2 -2
- package/hugo-theme/data/banners.yaml +69 -0
- package/hugo-theme/layouts/404.html +85 -0
- package/hugo-theme/layouts/_default/baseof.html +64 -0
- package/hugo-theme/layouts/_default/list.html +139 -0
- package/hugo-theme/layouts/_default/single.html +4 -0
- package/hugo-theme/layouts/blog/list.html +54 -0
- package/hugo-theme/layouts/blog-post/single.html +36 -0
- package/hugo-theme/layouts/index.html +75 -0
- package/hugo-theme/layouts/partials/banner-url.html +117 -0
- package/hugo-theme/layouts/partials/cdn-url.html +36 -0
- package/hugo-theme/layouts/partials/draft-notice.html +41 -0
- package/hugo-theme/layouts/partials/draft-state.html +26 -0
- package/hugo-theme/layouts/partials/footer.html +29 -0
- package/hugo-theme/layouts/partials/header.html +35 -0
- package/hugo-theme/layouts/partials/hero-banner.html +86 -0
- package/hugo-theme/layouts/partials/holdings/entry.html +21 -0
- package/hugo-theme/layouts/partials/holdings/kind-groups.html +71 -0
- package/hugo-theme/layouts/partials/holdings.html +61 -0
- package/hugo-theme/layouts/partials/infobox/entry.html +15 -0
- package/hugo-theme/layouts/partials/infobox/items.html +26 -0
- package/hugo-theme/layouts/partials/infobox/section.html +56 -0
- package/hugo-theme/layouts/partials/infobox/value.html +43 -0
- package/hugo-theme/layouts/partials/infobox.html +57 -0
- package/hugo-theme/layouts/partials/page-body.html +154 -0
- package/hugo-theme/layouts/partials/place-map.html +9 -0
- package/hugo-theme/layouts/partials/related.html +121 -0
- package/hugo-theme/layouts/partials/search.html +84 -0
- package/hugo-theme/layouts/partials/site-url.html +32 -0
- package/hugo-theme/layouts/partials/tags.html +30 -0
- package/hugo-theme/layouts/partials/toc.html +28 -0
- package/hugo-theme/layouts/partials/warn-missing-banner.html +3 -0
- package/hugo-theme/layouts/shortcodes/cartouche.html +64 -0
- package/hugo-theme/layouts/shortcodes/exturl.html +12 -0
- package/hugo-theme/layouts/shortcodes/glyph.html +43 -0
- package/hugo-theme/layouts/shortcodes/pagelist.html +63 -0
- package/hugo-theme/static/css/sohl-icons.css +57 -0
- package/hugo-theme/static/css/style.css +2953 -0
- package/hugo-theme/static/fonts/game-icons-kb.woff2 +0 -0
- package/hugo-theme/static/img/banners/takheperu-hieroglyphs.svg +1 -0
- package/hugo-theme/static/img/cartouches/takheperu.svg +1 -0
- package/hugo-theme/theme.toml +11 -0
- package/manifest.mjs +30 -24
- package/package.json +2 -1
- package/packagebuild-metadata.jsonl +13 -13
- package/sohl/item-fields.mjs +4 -3
- package/types/content-config.d.mts +48 -1
- package/types/engine/anchors.d.mts +9 -4
- package/types/engine/art-fields.d.mts +64 -0
- package/types/engine/art-slots.d.mts +2 -1
- package/types/engine/asset-index.d.mts +43 -0
- package/types/engine/asset-replacement.d.mts +22 -0
- package/types/engine/asset-types.d.mts +18 -0
- package/types/engine/base-compiler.d.mts +0 -17
- package/types/engine/content-embeds.d.mts +16 -0
- package/types/engine/content-figures.d.mts +101 -0
- package/types/engine/content-footnotes.d.mts +7 -0
- package/types/engine/content-images.d.mts +78 -12
- package/types/engine/content-index.d.mts +8 -2
- package/types/engine/field-reference.d.mts +21 -0
- package/types/engine/field-spec.d.mts +20 -16
- package/types/engine/foreign-catalog.d.mts +39 -0
- package/types/engine/heading-attributes.d.mts +13 -8
- package/types/engine/helpers.d.mts +28 -10
- package/types/engine/infobox-registry.d.mts +4 -1
- package/types/engine/infobox.d.mts +6 -0
- package/types/engine/journals.d.mts +31 -9
- package/types/engine/lore-events.d.mts +14 -0
- package/types/engine/markdown-expressions.d.mts +23 -2
- package/types/engine/note-dates.d.mts +64 -1
- package/types/engine/pathnames.d.mts +26 -0
- package/types/engine/pdf-build.d.mts +28 -6
- package/types/engine/pdf-images.d.mts +52 -0
- package/types/engine/pdf-render.d.mts +12 -0
- package/types/engine/site-build.d.mts +14 -3
- package/types/engine/site-config.d.mts +9 -9
- package/types/engine/site-index.d.mts +54 -0
- package/types/engine/system-block.d.mts +26 -2
- package/types/hm3/actors.d.mts +18 -0
- package/types/manifest.d.mts +19 -23
- package/engine/content-captions.mjs +0 -230
- package/types/engine/content-captions.d.mts +0 -58
package/engine/pdf-render.mjs
CHANGED
|
@@ -67,7 +67,14 @@ import deflistPlugin from "markdown-it-deflist";
|
|
|
67
67
|
|
|
68
68
|
import { bookDraftNoticePreamble } from "./draft-notice.mjs";
|
|
69
69
|
import { iconPlugin, ICON_PATTERN, ICON_SIZES } from "./content-icons.mjs";
|
|
70
|
-
import {
|
|
70
|
+
import {
|
|
71
|
+
IMAGE_CLASSES,
|
|
72
|
+
IMAGE_FLOATS,
|
|
73
|
+
IMAGE_PATTERN,
|
|
74
|
+
checkImages,
|
|
75
|
+
imagePlugin,
|
|
76
|
+
} from "./content-images.mjs";
|
|
77
|
+
import { bookImageWidthIn } from "./pdf-images.mjs";
|
|
71
78
|
|
|
72
79
|
/** Requested print width for every named image size. */
|
|
73
80
|
export const BOOK_IMAGE_WIDTHS = Object.freeze({
|
|
@@ -79,7 +86,7 @@ export const BOOK_IMAGE_WIDTHS = Object.freeze({
|
|
|
79
86
|
"full-width": '"full-width"',
|
|
80
87
|
});
|
|
81
88
|
import { slugify } from "./content-slug.mjs";
|
|
82
|
-
import {
|
|
89
|
+
import { scanFigures } from "./content-figures.mjs";
|
|
83
90
|
import { BLOCK_CONTAINERS, scanBlocks, BLOCK_NAMES } from "./content-blocks.mjs";
|
|
84
91
|
import { matchAllOutsideCode, replaceOutsideCode } from "./code-fences.mjs";
|
|
85
92
|
import { HTML_TAG, htmlMessage } from "./content-html.mjs";
|
|
@@ -290,7 +297,7 @@ function offsetPosition(source, offset, opts = {}) {
|
|
|
290
297
|
* those passes did not run — `opts.prepared` — because each of them leaves the
|
|
291
298
|
* markup as written when it fails and has already said so in its own words.
|
|
292
299
|
*
|
|
293
|
-
* A `:::` block and a `:::
|
|
300
|
+
* A `:::` block and a `:::figure` are the pair this pass does handle, and their
|
|
294
301
|
* own scanners decide what is well formed; their findings are reported here so
|
|
295
302
|
* that a front-matter file, a prose file and a note body all get them.
|
|
296
303
|
*
|
|
@@ -341,8 +348,15 @@ function reportUnrenderable(source, definitions, opts, original) {
|
|
|
341
348
|
);
|
|
342
349
|
}
|
|
343
350
|
}
|
|
344
|
-
for (const error of
|
|
351
|
+
for (const error of scanFigures(source).errors)
|
|
345
352
|
report(linePosition(error.line, error.column, opts), "error", error.message);
|
|
353
|
+
// An image sharing its paragraph with other text, or an address or title
|
|
354
|
+
// the website's own lint already refuses — asked here too, so the book
|
|
355
|
+
// fails on the same input rather than typesetting the directive as
|
|
356
|
+
// though it were absent. `checkImages` resolves `opts.bodyLine` and
|
|
357
|
+
// `opts.bodyColumn` itself.
|
|
358
|
+
for (const error of checkImages(source, opts.file ?? "", opts))
|
|
359
|
+
report({ line: error.line, column: error.column }, error.severity, error.message);
|
|
346
360
|
for (const error of scanHeadingAttributes(source).errors)
|
|
347
361
|
report(linePosition(error.line, error.column, opts), "error", error.message);
|
|
348
362
|
for (const error of withheldSections(source).errors)
|
|
@@ -408,6 +422,12 @@ function reportUnrenderable(source, definitions, opts, original) {
|
|
|
408
422
|
* the staged file's path, relative to the `.typ`. An address this does not
|
|
409
423
|
* carry has no file the compiler can open, so the figure prints its caption
|
|
410
424
|
* alone — see {@link renderImage}.
|
|
425
|
+
* @param {Map<string, {type: string, role?: string, width: number|"", height: number|""}>}
|
|
426
|
+
* [opts.assets] - An image's address as authored → what
|
|
427
|
+
* {@link module:engine/art-fields.assetImageInfoByPathname} records for it,
|
|
428
|
+
* which is what sizes a picture carrying no named `size=` — see
|
|
429
|
+
* {@link module:engine/pdf-images.bookImageWidthIn}. An address missing from
|
|
430
|
+
* this map draws at the medium's ordinary size, the same as today.
|
|
411
431
|
* @param {number} [opts.headingOffset] - Added to every heading level, so a
|
|
412
432
|
* note's own `##` nests beneath the entry heading the book gave it.
|
|
413
433
|
* @param {string} [opts.anchorPrefix] - The entry's anchor, which namespaces
|
|
@@ -440,6 +460,7 @@ export function markdownToTypst(markdown, opts = {}) {
|
|
|
440
460
|
links = new Map(),
|
|
441
461
|
glyphs = new Map(),
|
|
442
462
|
images = new Map(),
|
|
463
|
+
assets = new Map(),
|
|
443
464
|
headingOffset = 0,
|
|
444
465
|
anchorPrefix = "",
|
|
445
466
|
} = opts;
|
|
@@ -466,6 +487,7 @@ export function markdownToTypst(markdown, opts = {}) {
|
|
|
466
487
|
links,
|
|
467
488
|
glyphs,
|
|
468
489
|
images,
|
|
490
|
+
assets,
|
|
469
491
|
headingOffset,
|
|
470
492
|
anchorPrefix,
|
|
471
493
|
url: opts.url,
|
|
@@ -544,18 +566,18 @@ export function markdownToTypst(markdown, opts = {}) {
|
|
|
544
566
|
}
|
|
545
567
|
}
|
|
546
568
|
const lines = source.split("\n");
|
|
547
|
-
const
|
|
569
|
+
const localFigures = scanFigures(source, { resolveRole: opts.resolveRole }).figures;
|
|
548
570
|
// Numbered by the caller, which counts across the whole book, and placed by
|
|
549
571
|
// the scan above, which is the only reading of *this* body. Paired by
|
|
550
|
-
// position: two
|
|
551
|
-
// anyway — and keying on one would give the second
|
|
552
|
-
// first, printing its
|
|
553
|
-
const provided = opts.captions ??
|
|
554
|
-
const numbered = new Map(provided.map((
|
|
555
|
-
const captions =
|
|
572
|
+
// position: two figures may share an id — a finding, and the book is built
|
|
573
|
+
// anyway — and keying on one would give the second figure's lines to the
|
|
574
|
+
// first, printing its contents twice and losing its label.
|
|
575
|
+
const provided = opts.captions ?? localFigures;
|
|
576
|
+
const numbered = new Map(provided.map((figure) => [figure.id, figure]));
|
|
577
|
+
const captions = localFigures.map((figure, at) => {
|
|
556
578
|
const counted =
|
|
557
|
-
provided[at]?.id ===
|
|
558
|
-
return { ...
|
|
579
|
+
provided[at]?.id === figure.id ? provided[at] : (numbered.get(figure.id) ?? figure);
|
|
580
|
+
return { ...figure, label: counted.label, number: counted.number };
|
|
559
581
|
});
|
|
560
582
|
if (!captions.length) return renderMarkdownSegment(source, md, ctx, definitions);
|
|
561
583
|
const out = [];
|
|
@@ -569,14 +591,29 @@ export function markdownToTypst(markdown, opts = {}) {
|
|
|
569
591
|
definitions,
|
|
570
592
|
),
|
|
571
593
|
);
|
|
572
|
-
const block = lines.slice(caption.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
594
|
+
const block = lines.slice(caption.bodyStart, caption.bodyEnd).join("\n");
|
|
595
|
+
// A grouped figure's images are rendered through the same call that
|
|
596
|
+
// reads `ctx.caption`, so `renderImage` needs to know which one is
|
|
597
|
+
// last — see the counter it decrements, set only for a `figure`-kind
|
|
598
|
+
// fence, where more than one image can share the one caption.
|
|
599
|
+
const captioned =
|
|
600
|
+
caption.kind === "figure" || caption.kind === "map" ?
|
|
601
|
+
{ ...caption, imagesRemaining: { n: countImages(block) } }
|
|
602
|
+
: caption;
|
|
603
|
+
const segments = [
|
|
604
|
+
renderMarkdownSegment(block, md, { ...ctx, caption: captioned }, definitions),
|
|
605
|
+
];
|
|
606
|
+
if (caption.kind !== "table" && caption.kind !== "figure" && caption.kind !== "map") {
|
|
607
|
+
segments.push(
|
|
608
|
+
`\n#block(below: 0.6em)[#text(size: 7.6pt, style: "italic")[${captionMarkup(caption, ctx)}]]${typstAnchor(anchorPrefix, caption)}\n\n`,
|
|
577
609
|
);
|
|
578
610
|
}
|
|
579
|
-
|
|
611
|
+
out.push(
|
|
612
|
+
caption.classes.includes("border") ?
|
|
613
|
+
figureBorder(segments.join(""))
|
|
614
|
+
: segments.join(""),
|
|
615
|
+
);
|
|
616
|
+
cursor = caption.close + 1;
|
|
580
617
|
}
|
|
581
618
|
out.push(renderMarkdownSegment(lines.slice(cursor).join("\n"), md, ctx, definitions));
|
|
582
619
|
return out.filter(Boolean).join("\n\n");
|
|
@@ -885,9 +922,63 @@ function inlineMarkup(text, ctx) {
|
|
|
885
922
|
return inline ? renderInline(inline, ctx) : "";
|
|
886
923
|
}
|
|
887
924
|
|
|
888
|
-
/**
|
|
925
|
+
/**
|
|
926
|
+
* A figure's label, with its caption when it carries one.
|
|
927
|
+
*
|
|
928
|
+
* The caption's inline Markdown is handled the way the surrounding prose is. A
|
|
929
|
+
* figure with no caption draws its label alone.
|
|
930
|
+
*
|
|
931
|
+
* @param {object} caption - A figure record.
|
|
932
|
+
* @param {object} ctx - Render context.
|
|
933
|
+
* @returns {string} Typst markup.
|
|
934
|
+
*/
|
|
889
935
|
function captionMarkup(caption, ctx) {
|
|
890
|
-
|
|
936
|
+
const label = escapeTypst(caption.label);
|
|
937
|
+
return caption.hasCaption ? `${label}: ${inlineMarkup(caption.caption, ctx)}` : label;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* How many markdown images a figure's contents carry.
|
|
942
|
+
*
|
|
943
|
+
* A grouped figure's `///` caption describes the whole plate, not any one
|
|
944
|
+
* picture in it, so {@link renderImage} needs to know which image is the
|
|
945
|
+
* last — the one that carries the group's single label and anchor — and this
|
|
946
|
+
* is the count it counts down from.
|
|
947
|
+
*
|
|
948
|
+
* @param {string} contents - The figure's captioned contents, as authored.
|
|
949
|
+
* @returns {number} How many images the contents hold.
|
|
950
|
+
*/
|
|
951
|
+
function countImages(contents) {
|
|
952
|
+
return (String(contents ?? "").match(IMAGE_PATTERN) ?? []).length;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* `.border` draws the whole figure — its content and its label together —
|
|
957
|
+
* inside a hairline box. A thin stroke is print's equivalent of a border and
|
|
958
|
+
* padding on the web and in a Foundry journal: a figure already sits inside
|
|
959
|
+
* its own column or float, so the book's version of a border is the lightest
|
|
960
|
+
* mark that still reads as one rather than a second, heavier frame around a
|
|
961
|
+
* frame.
|
|
962
|
+
*
|
|
963
|
+
* @param {string} body - The figure's own rendered Typst, content and label.
|
|
964
|
+
* @returns {string} Typst markup.
|
|
965
|
+
*/
|
|
966
|
+
function figureBorder(body) {
|
|
967
|
+
return `\n#block(width: 100%, stroke: 0.4pt + luma(60%), inset: 8pt, above: 0.6em, below: 0.6em)[\n${body}\n]\n\n`;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* The Typst label a figure is referenced by, or `""` when it declares no id.
|
|
972
|
+
*
|
|
973
|
+
* A figure with no id is numbered and drawn and nothing addresses it, so it is
|
|
974
|
+
* given no label: an empty one would collide with every other idless figure.
|
|
975
|
+
*
|
|
976
|
+
* @param {string} prefix - The entry's anchor prefix.
|
|
977
|
+
* @param {object} caption - A figure record.
|
|
978
|
+
* @returns {string} A ` <label>` to append, or `""`.
|
|
979
|
+
*/
|
|
980
|
+
function typstAnchor(prefix, caption) {
|
|
981
|
+
return caption.id ? ` <${sectionLabel(prefix, slugify(caption.id))}>` : "";
|
|
891
982
|
}
|
|
892
983
|
|
|
893
984
|
/**
|
|
@@ -966,7 +1057,7 @@ function renderTable(tokens, ctx) {
|
|
|
966
1057
|
const caption = ctx.caption;
|
|
967
1058
|
const labelled =
|
|
968
1059
|
caption ?
|
|
969
|
-
`#text(size: 7.6pt, style: "italic")[${captionMarkup(caption, ctx)}]
|
|
1060
|
+
`#text(size: 7.6pt, style: "italic")[${captionMarkup(caption, ctx)}]${typstAnchor(ctx.anchorPrefix, caption)}\n${drawn}`
|
|
970
1061
|
: drawn;
|
|
971
1062
|
// Wide content is given an explicit span rather than left to overflow the
|
|
972
1063
|
// measure: past three columns a table is set across the page, and
|
|
@@ -1186,6 +1277,16 @@ function renderLink(href, inner, ctx) {
|
|
|
1186
1277
|
return `#link("${escapeTypstString(absolutePageUrl(url, ctx.url))}")[${inner}]`;
|
|
1187
1278
|
}
|
|
1188
1279
|
|
|
1280
|
+
/**
|
|
1281
|
+
* A width in inches, as a Typst length literal.
|
|
1282
|
+
*
|
|
1283
|
+
* @param {number} inches - The width.
|
|
1284
|
+
* @returns {string} A Typst length, rounded to a thousandth of an inch.
|
|
1285
|
+
*/
|
|
1286
|
+
function typstInches(inches) {
|
|
1287
|
+
return `${Math.round(inches * 1000) / 1000}in`;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1189
1290
|
/**
|
|
1190
1291
|
* One image, as the figure the book prints.
|
|
1191
1292
|
*
|
|
@@ -1221,32 +1322,55 @@ function renderLink(href, inner, ctx) {
|
|
|
1221
1322
|
* `#image` on a path Typst cannot open is a compile error, and a compile error
|
|
1222
1323
|
* in a 2,500-entry book is fatal at the very end of a run that otherwise
|
|
1223
1324
|
* succeeded — over an illustration, which is the least important thing on the
|
|
1224
|
-
* page. An address the build could not stage prints its caption alone
|
|
1225
|
-
* and
|
|
1325
|
+
* page. An address the build could not stage prints its authored caption alone
|
|
1326
|
+
* instead, if it has one, and nothing at all if it does not; the build reports
|
|
1327
|
+
* the address it could not find either way.
|
|
1328
|
+
*
|
|
1329
|
+
* ## A grouped figure's one label belongs to the last picture
|
|
1330
|
+
*
|
|
1331
|
+
* Only a figure-kind fence labels an image inline — a fence holding anything
|
|
1332
|
+
* besides pictures is prose, and gets its label from the generic block-level
|
|
1333
|
+
* print in {@link markdownToTypst} instead, the same as a code or a table
|
|
1334
|
+
* fence. Within a figure-kind fence, `ctx.caption.imagesRemaining` counts down
|
|
1335
|
+
* one picture at a time; the picture that brings it to zero is the last one in
|
|
1336
|
+
* document order, and only that one carries the caption and the anchor. Every
|
|
1337
|
+
* other picture in the group draws with no caption at all. Attaching the label
|
|
1338
|
+
* to each of them would print the same text under every picture and emit the
|
|
1339
|
+
* same Typst label more than once, which Typst refuses to compile.
|
|
1226
1340
|
*
|
|
1227
1341
|
* @param {object} token - An `image` token.
|
|
1228
1342
|
* @param {object} ctx - Render context.
|
|
1229
1343
|
* @returns {string} Typst markup.
|
|
1230
1344
|
*/
|
|
1231
1345
|
function renderImage(token, ctx) {
|
|
1232
|
-
const
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
const figureCaption = ctx.caption?.kind === "figure" ? ctx.caption : null;
|
|
1239
|
-
const captionText = figureCaption ? captionMarkup(figureCaption, ctx) : escapeTypst(alt);
|
|
1346
|
+
const figureCaption =
|
|
1347
|
+
ctx.caption?.kind === "figure" || ctx.caption?.kind === "map" ? ctx.caption : null;
|
|
1348
|
+
const remaining = figureCaption?.imagesRemaining;
|
|
1349
|
+
const isLastImage = !remaining || --remaining.n <= 0;
|
|
1350
|
+
const labelled = Boolean(figureCaption) && isLastImage;
|
|
1351
|
+
const captionText = labelled ? captionMarkup(figureCaption, ctx) : "";
|
|
1240
1352
|
const caption = captionText ? `[${captionText}]` : "none";
|
|
1241
|
-
const anchor =
|
|
1242
|
-
|
|
1243
|
-
const staged = ctx.images.get(
|
|
1353
|
+
const anchor = labelled ? typstAnchor(ctx.anchorPrefix, figureCaption) : "";
|
|
1354
|
+
const src = token.attrGet?.("src") ?? "";
|
|
1355
|
+
const staged = ctx.images.get(src);
|
|
1244
1356
|
if (!staged)
|
|
1245
1357
|
return captionText ?
|
|
1246
1358
|
`\n#block(below: 0.6em)[#text(size: 7.6pt, style: "italic", fill: luma(45%))${caption}]${anchor}\n\n`
|
|
1247
1359
|
: "";
|
|
1248
1360
|
|
|
1249
|
-
|
|
1361
|
+
// A named `size=` is the author's own statement and wins outright. Left
|
|
1362
|
+
// unstated — `auto`, written or implied — the picture's role or its icon
|
|
1363
|
+
// type decides instead, and only a picture declaring neither falls back to
|
|
1364
|
+
// the natural-pixel `auto` Typst resolves for itself.
|
|
1365
|
+
const requestedSize = token.meta?.size;
|
|
1366
|
+
const roleWidthIn =
|
|
1367
|
+
requestedSize && requestedSize !== "auto" ?
|
|
1368
|
+
undefined
|
|
1369
|
+
: bookImageWidthIn(ctx.assets?.get(src));
|
|
1370
|
+
const size =
|
|
1371
|
+
roleWidthIn !== undefined ?
|
|
1372
|
+
typstInches(roleWidthIn)
|
|
1373
|
+
: (BOOK_IMAGE_WIDTHS[requestedSize] ?? BOOK_IMAGE_WIDTHS.auto);
|
|
1250
1374
|
const figure = `#book-image("${escapeTypstString(staged)}", requested: ${size}, caption: ${caption})${anchor}`;
|
|
1251
1375
|
|
|
1252
1376
|
const width = token.meta?.classes?.[0];
|
package/engine/scenes.mjs
CHANGED
|
@@ -80,7 +80,7 @@ import { behaviorDocId, buildScene, isMapType, regionDocId } from "./map-notes.m
|
|
|
80
80
|
import { buildItineraryScenes } from "./itinerary-scenes.mjs";
|
|
81
81
|
import { emitDiagnostic } from "./diagnostics.mjs";
|
|
82
82
|
import { rasterizeMapSvg } from "./map-raster.mjs";
|
|
83
|
-
import { artPathname, artSlot } from "./art-fields.mjs";
|
|
83
|
+
import { artPathname, artSlot, pathnameRoles } from "./art-fields.mjs";
|
|
84
84
|
import { buildExportedScene } from "./exported-scene.mjs";
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -395,11 +395,15 @@ export class Scenes extends BasePackCompiler {
|
|
|
395
395
|
* @param {string} markdown - The converted body.
|
|
396
396
|
* @param {string} entryId - The JournalEntry's id.
|
|
397
397
|
* @param {string} name - The map's name (its lead page).
|
|
398
|
+
* @param {(address: string) => string|undefined} resolveRole - See
|
|
399
|
+
* {@link module:engine/journals.splitPages}; threaded through so an
|
|
400
|
+
* unanchored map figure's page key agrees with the journal this pass
|
|
401
|
+
* derives it against.
|
|
398
402
|
* @returns {Map<string, string>} heading key → page id.
|
|
399
403
|
*/
|
|
400
|
-
#pageIds(markdown, entryId, name) {
|
|
404
|
+
#pageIds(markdown, entryId, name, resolveRole) {
|
|
401
405
|
const pageIds = new Map();
|
|
402
|
-
splitPages(markdown, name).forEach((page) => {
|
|
406
|
+
splitPages(markdown, name, resolveRole).forEach((page) => {
|
|
403
407
|
const id = journalPageId(entryId, page);
|
|
404
408
|
if (page.anchorSlug) pageIds.set(page.anchorSlug, id);
|
|
405
409
|
const slug = slugify(page.name);
|
|
@@ -439,6 +443,12 @@ export class Scenes extends BasePackCompiler {
|
|
|
439
443
|
compileNote(fm, markdown) {
|
|
440
444
|
const name = resolveName(fm);
|
|
441
445
|
const hasBody = Boolean(String(markdown).trim());
|
|
446
|
+
// The markdown this pass reads has already had its embeds rewritten
|
|
447
|
+
// into ordinary images, each `src` the pathname `pathnameRoles` keys
|
|
448
|
+
// its roles by — see {@link module:engine/journals.Journals#buildEntry},
|
|
449
|
+
// which derives this same journal's pages the same way.
|
|
450
|
+
const roles = pathnameRoles(this.linkIndex);
|
|
451
|
+
const resolveRole = (pathname) => roles.get(pathname);
|
|
442
452
|
// The same doc-entry id the journals pass derives, from the
|
|
443
453
|
// shared `docEntryTypes` arrangement — so neither
|
|
444
454
|
// pass has to read the other's output.
|
|
@@ -511,7 +521,8 @@ export class Scenes extends BasePackCompiler {
|
|
|
511
521
|
hasBody ?
|
|
512
522
|
this.#packRouter.resolve(fm, "JournalEntry")
|
|
513
523
|
: this.#packRouter.defaultOf("JournalEntry"),
|
|
514
|
-
pageIds:
|
|
524
|
+
pageIds:
|
|
525
|
+
hasBody ? this.#pageIds(markdown, entryId, name, resolveRole) : new Map(),
|
|
515
526
|
knownActions: this.knownActions,
|
|
516
527
|
warnings,
|
|
517
528
|
...this.#resolvers(this.index, this.effectsByAddress, fm.shortcode),
|
|
@@ -535,6 +546,7 @@ export class Scenes extends BasePackCompiler {
|
|
|
535
546
|
name,
|
|
536
547
|
markdown,
|
|
537
548
|
leadName: name,
|
|
549
|
+
resolveRole,
|
|
538
550
|
// As in the journals pass: an address resolves in the
|
|
539
551
|
// pack that emits it, which is what makes the folder
|
|
540
552
|
// materialise there too. The id spelling that used
|
package/engine/site-build.mjs
CHANGED
|
@@ -64,12 +64,18 @@ import { renderMarkdownExpressions } from "./markdown-expressions.mjs";
|
|
|
64
64
|
import { expandContentTables } from "./content-tables.mjs";
|
|
65
65
|
import { renderBlocks, renderWithheldSections, scanBlocks } from "./content-blocks.mjs";
|
|
66
66
|
import { scanHeadingAttributes, withheldSections } from "./heading-attributes.mjs";
|
|
67
|
-
import {
|
|
67
|
+
import { renderFigureBlocks, scanFigures } from "./content-figures.mjs";
|
|
68
68
|
import { footnoteFindings } from "./content-footnotes.mjs";
|
|
69
69
|
import { collectAnchors } from "./anchors.mjs";
|
|
70
|
-
import { renderImageFigures } from "./content-images.mjs";
|
|
71
|
-
import { pathnameProblem, resolvePathname } from "./pathnames.mjs";
|
|
72
|
-
import {
|
|
70
|
+
import { checkImages, renderImageFigures } from "./content-images.mjs";
|
|
71
|
+
import { assetPathnameKey, pathnameProblem, resolvePathname } from "./pathnames.mjs";
|
|
72
|
+
import {
|
|
73
|
+
buildSiteIndex,
|
|
74
|
+
figureIndexKeys,
|
|
75
|
+
resolveCrossNoteFigures,
|
|
76
|
+
resolveInfoboxRef,
|
|
77
|
+
wikiContext,
|
|
78
|
+
} from "./site-index.mjs";
|
|
73
79
|
import { frontmatterWikilinks, resolveWebWikilinks } from "./web-wikilinks.mjs";
|
|
74
80
|
import { loadForeignIndexes, noContentIndexPackages } from "./metadata-index.mjs";
|
|
75
81
|
import { noteInfoboxes } from "./infobox-registry.mjs";
|
|
@@ -88,7 +94,8 @@ import { isNoteRecord, noteFile } from "./index-records.mjs";
|
|
|
88
94
|
// The one statement of what an empty body means, shared with the index.
|
|
89
95
|
import { isStubNote } from "./note-state.mjs";
|
|
90
96
|
import { isGmNote } from "./note-vocabulary.mjs";
|
|
91
|
-
import { ART_SLOTS, artPathname, assetAddressIndex } from "./art-fields.mjs";
|
|
97
|
+
import { ART_SLOTS, artPathname, assetAddressIndex, pathnameRoles } from "./art-fields.mjs";
|
|
98
|
+
import { embedRole } from "./content-embeds.mjs";
|
|
92
99
|
import {
|
|
93
100
|
HOMEPAGE_DESTINATION,
|
|
94
101
|
checkHomepageCount,
|
|
@@ -699,6 +706,7 @@ export function renderSitePage(
|
|
|
699
706
|
sqlTables,
|
|
700
707
|
config,
|
|
701
708
|
artIndex,
|
|
709
|
+
figuresByAddress = new Map(),
|
|
702
710
|
},
|
|
703
711
|
) {
|
|
704
712
|
const tableErrors = [];
|
|
@@ -709,6 +717,7 @@ export function renderSitePage(
|
|
|
709
717
|
const footnoteErrors = [];
|
|
710
718
|
const wikiErrors = [];
|
|
711
719
|
const imageErrors = [];
|
|
720
|
+
const embedErrors = [];
|
|
712
721
|
const resolved = [];
|
|
713
722
|
const src = page.relPath ?? page.base;
|
|
714
723
|
const ctx = wikiContext(index, {
|
|
@@ -745,10 +754,36 @@ export function renderSitePage(
|
|
|
745
754
|
return src;
|
|
746
755
|
};
|
|
747
756
|
const artSrc = (value, type, accepts) => artPathname(artIndex, value, type, accepts).pathname;
|
|
757
|
+
// The role lookup a `:::figure` fence's `map` counter reaches through —
|
|
758
|
+
// see `engine/content-figures.mjs`'s `resolveRole`. Addressed form, for
|
|
759
|
+
// the page's own scan below, which runs before an embed is rewritten into
|
|
760
|
+
// an ordinary image; `roleByWebSrc` is the same lookup keyed by the web
|
|
761
|
+
// address each picture that reaches `renderImageFigures` resolves to,
|
|
762
|
+
// recorded as it is resolved rather than built across the whole corpus —
|
|
763
|
+
// `webSrc` itself reports an image's own problems as a side effect, which
|
|
764
|
+
// a speculative call over every asset would misfire for one this page
|
|
765
|
+
// never names.
|
|
766
|
+
const resolveRole = (address) => embedRole(artIndex, address);
|
|
767
|
+
const pathRoles = pathnameRoles(artIndex);
|
|
768
|
+
const roleByWebSrc = new Map();
|
|
769
|
+
const webSrcWithRole = (src) => {
|
|
770
|
+
const result = webSrc(src);
|
|
771
|
+
const role = pathRoles.get(src);
|
|
772
|
+
if (role) roleByWebSrc.set(result, role);
|
|
773
|
+
return result;
|
|
774
|
+
};
|
|
775
|
+
// The picture's role and pixel size, by the address it resolved to — read
|
|
776
|
+
// before `webSrc` translates it to the page's own host. A body image is
|
|
777
|
+
// free to write the bare, own-package form, so the address is normalized
|
|
778
|
+
// to the pathname the asset index keys by first.
|
|
779
|
+
const lookupAsset = (src) => {
|
|
780
|
+
const key = assetPathnameKey(src, config);
|
|
781
|
+
return key ? artIndex?.byPath?.get(key) : undefined;
|
|
782
|
+
};
|
|
748
783
|
const resolve = (text) => {
|
|
749
784
|
let transformed = pass.beforeLinks ? pass.beforeLinks(text, page) : text;
|
|
750
785
|
transformed = resolveWebWikilinks(transformed, ctx);
|
|
751
|
-
return renderImageFigures(transformed,
|
|
786
|
+
return renderImageFigures(transformed, webSrcWithRole, lookupAsset);
|
|
752
787
|
};
|
|
753
788
|
|
|
754
789
|
const { markdown, errors, lineMap } = expandContentTables(page.body, {
|
|
@@ -760,8 +795,21 @@ export function renderSitePage(
|
|
|
760
795
|
self: { fm: searchableFrontmatter(page.fm, page.pkg), path: page.relPath },
|
|
761
796
|
});
|
|
762
797
|
tableErrors.push(...errors);
|
|
763
|
-
const
|
|
764
|
-
ctx.captionLabels = new Map(
|
|
798
|
+
const figureScan = scanFigures(markdown, { resolveRole });
|
|
799
|
+
ctx.captionLabels = new Map(
|
|
800
|
+
figureScan.figures.filter((figure) => figure.id).map((figure) => [figure.id, figure.label]),
|
|
801
|
+
);
|
|
802
|
+
// What the `ref` expression helper needs beyond the label: the caption
|
|
803
|
+
// text and whether one was authored, by the same id `ctx.captionLabels`
|
|
804
|
+
// keys on.
|
|
805
|
+
const figuresById = new Map(
|
|
806
|
+
figureScan.figures
|
|
807
|
+
.filter((figure) => figure.id)
|
|
808
|
+
.map((figure) => [
|
|
809
|
+
figure.id,
|
|
810
|
+
{ label: figure.label, caption: figure.caption, hasCaption: figure.hasCaption },
|
|
811
|
+
]),
|
|
812
|
+
);
|
|
765
813
|
// This page's own anchors, so a `[[#slug]]` self-link is checked against
|
|
766
814
|
// what the page actually declares rather than trusted unconditionally.
|
|
767
815
|
ctx.anchors = new Set(collectAnchors(markdown).map((anchor) => anchor.slug));
|
|
@@ -771,12 +819,29 @@ export function renderSitePage(
|
|
|
771
819
|
file: page.file,
|
|
772
820
|
bodyLine: page.bodyLine,
|
|
773
821
|
sqlResults: sqlTables?.inline?.get(page.file),
|
|
822
|
+
figures: {
|
|
823
|
+
get: (id) => figuresById.get(id),
|
|
824
|
+
// A cross-note `ref` resolves the written address exactly as a
|
|
825
|
+
// wikilink does, against every page's figures scanned before any
|
|
826
|
+
// page's expressions render — see `renderPages`.
|
|
827
|
+
note: (target) =>
|
|
828
|
+
resolveCrossNoteFigures(target, {
|
|
829
|
+
contentTypes: index.contentTypes,
|
|
830
|
+
packages: index.packages,
|
|
831
|
+
noIndexPackages: index.noIndexPackages,
|
|
832
|
+
contentPackage: index.contentPackage,
|
|
833
|
+
siteIndexMap: index.index,
|
|
834
|
+
figuresByAddress,
|
|
835
|
+
}),
|
|
836
|
+
},
|
|
774
837
|
});
|
|
775
838
|
expressionErrors.push(...expressions.findings);
|
|
776
839
|
const data = pageFrontmatter(page, { decorate, webSrc, artSrc });
|
|
777
840
|
const blocks = renderBlocks(protectCode(expressions.markdown, resolve), "web");
|
|
778
|
-
const
|
|
779
|
-
|
|
841
|
+
const figured = renderFigureBlocks(blocks.markdown, undefined, undefined, {
|
|
842
|
+
resolveRole: (address) => roleByWebSrc.get(address),
|
|
843
|
+
});
|
|
844
|
+
for (const error of figureScan.errors)
|
|
780
845
|
captionErrors.push({
|
|
781
846
|
file: page.file,
|
|
782
847
|
line: (page.bodyLine ?? 1) + (lineMap[error.line - 1]?.line ?? error.line - 1),
|
|
@@ -801,12 +866,18 @@ export function renderSitePage(
|
|
|
801
866
|
column: error.column,
|
|
802
867
|
message: error.message,
|
|
803
868
|
});
|
|
869
|
+
// An image sharing its paragraph with other text, or an address or title
|
|
870
|
+
// the lint already refuses — asked here too, so a site build run on its
|
|
871
|
+
// own fails on the same input `renderImageFigures` otherwise renders as
|
|
872
|
+
// though the directive were absent.
|
|
873
|
+
for (const error of checkImages(page.body, page.file, { bodyLine: page.bodyLine ?? 1 }))
|
|
874
|
+
embedErrors.push(error);
|
|
804
875
|
return {
|
|
805
876
|
page,
|
|
806
877
|
// The disclosure is written last, over the Markdown the page ships: the
|
|
807
878
|
// passes before this one carry line positions into their findings, and a
|
|
808
879
|
// line inserted ahead of them would move every one of them.
|
|
809
|
-
body: renderWithheldSections(
|
|
880
|
+
body: renderWithheldSections(figured.markdown),
|
|
810
881
|
data,
|
|
811
882
|
resolved,
|
|
812
883
|
tableErrors,
|
|
@@ -817,6 +888,7 @@ export function renderSitePage(
|
|
|
817
888
|
footnoteErrors,
|
|
818
889
|
wikiErrors,
|
|
819
890
|
imageErrors,
|
|
891
|
+
embedErrors,
|
|
820
892
|
};
|
|
821
893
|
}
|
|
822
894
|
|
|
@@ -855,7 +927,7 @@ export function renderSitePage(
|
|
|
855
927
|
* it by wikilink, and its own markdown links name content pages. `maps` is
|
|
856
928
|
* each drawing by the URL of the page that carries it.
|
|
857
929
|
* @returns {{written: number, byKind: Record<string, number>, tableErrors: object[],
|
|
858
|
-
* wikiErrors: object[], imageErrors: object[],
|
|
930
|
+
* wikiErrors: object[], imageErrors: object[], embedErrors: object[],
|
|
859
931
|
* related: Map<string, import("./related-pages.mjs").Related>,
|
|
860
932
|
* maps: number}} `related`
|
|
861
933
|
* is keyed by page URL, and holds the homepage's block beside every content
|
|
@@ -888,6 +960,38 @@ export function renderPages(pages, options) {
|
|
|
888
960
|
types: index?.contentTypes ?? [],
|
|
889
961
|
});
|
|
890
962
|
|
|
963
|
+
// Every page's own figures, by the address a `ref` crossing into it would
|
|
964
|
+
// write — scanned once, before any page's own expressions render, so a
|
|
965
|
+
// page citing another's figure finds it already numbered. Numbering stays
|
|
966
|
+
// per page: each `scanFigures` call here starts its own counters, exactly
|
|
967
|
+
// as the page's own render does, so the number a cross-note `ref` reports
|
|
968
|
+
// is the one the target's own page carries.
|
|
969
|
+
const figuresByAddress = new Map();
|
|
970
|
+
for (const page of pages) {
|
|
971
|
+
const shortcode = page.fm.shortcode;
|
|
972
|
+
if (typeof shortcode !== "string" || !shortcode) continue;
|
|
973
|
+
const src = page.relPath ?? page.base;
|
|
974
|
+
const { markdown } = expandContentTables(page.body, {
|
|
975
|
+
docs: universe.get(page.pkg) ?? [],
|
|
976
|
+
linkable,
|
|
977
|
+
source: src,
|
|
978
|
+
sqlTables: sqlTables?.get(page.file),
|
|
979
|
+
pageLists: sqlTables?.pageLists?.get(page.file),
|
|
980
|
+
self: { fm: searchableFrontmatter(page.fm, page.pkg), path: page.relPath },
|
|
981
|
+
});
|
|
982
|
+
const byId = new Map(
|
|
983
|
+
scanFigures(markdown)
|
|
984
|
+
.figures.filter((figure) => figure.id)
|
|
985
|
+
.map((figure) => [
|
|
986
|
+
figure.id,
|
|
987
|
+
{ label: figure.label, caption: figure.caption, hasCaption: figure.hasCaption },
|
|
988
|
+
]),
|
|
989
|
+
);
|
|
990
|
+
const type = String(page.fm.type ?? "").toLowerCase();
|
|
991
|
+
for (const key of figureIndexKeys(page.pkg, type, shortcode))
|
|
992
|
+
figuresByAddress.set(key, byId);
|
|
993
|
+
}
|
|
994
|
+
|
|
891
995
|
const tableErrors = [];
|
|
892
996
|
const expressionErrors = [];
|
|
893
997
|
const secretErrors = [];
|
|
@@ -896,6 +1000,7 @@ export function renderPages(pages, options) {
|
|
|
896
1000
|
const footnoteErrors = [];
|
|
897
1001
|
const wikiErrors = [];
|
|
898
1002
|
const imageErrors = [];
|
|
1003
|
+
const embedErrors = [];
|
|
899
1004
|
const byKind = {};
|
|
900
1005
|
// The link graph, as `(source URL, target URL)` — read off each page's
|
|
901
1006
|
// resolution below, and off the homepage's markdown links.
|
|
@@ -932,6 +1037,7 @@ export function renderPages(pages, options) {
|
|
|
932
1037
|
sqlTables,
|
|
933
1038
|
config,
|
|
934
1039
|
artIndex,
|
|
1040
|
+
figuresByAddress,
|
|
935
1041
|
});
|
|
936
1042
|
tableErrors.push(...result.tableErrors);
|
|
937
1043
|
expressionErrors.push(...result.expressionErrors);
|
|
@@ -941,6 +1047,7 @@ export function renderPages(pages, options) {
|
|
|
941
1047
|
footnoteErrors.push(...result.footnoteErrors);
|
|
942
1048
|
wikiErrors.push(...result.wikiErrors);
|
|
943
1049
|
imageErrors.push(...result.imageErrors);
|
|
1050
|
+
embedErrors.push(...result.embedErrors);
|
|
944
1051
|
rendered.push({ page, body: result.body, data: result.data });
|
|
945
1052
|
for (const hit of result.resolved) if (hit.url) edges.push([page.url, hit.url]);
|
|
946
1053
|
}
|
|
@@ -986,6 +1093,7 @@ export function renderPages(pages, options) {
|
|
|
986
1093
|
footnoteErrors,
|
|
987
1094
|
wikiErrors,
|
|
988
1095
|
imageErrors,
|
|
1096
|
+
embedErrors,
|
|
989
1097
|
related,
|
|
990
1098
|
maps: withMap,
|
|
991
1099
|
...(capture ? { ...(outputs ? { outputs } : {}), edges, entries } : {}),
|
|
@@ -1036,6 +1144,7 @@ export function sitePageDecorator(config, index) {
|
|
|
1036
1144
|
resolve: (ref, hint) => resolveInfoboxRef(index, ref, hint),
|
|
1037
1145
|
router,
|
|
1038
1146
|
dates: index.dateContext,
|
|
1147
|
+
contentPackage: index.contentPackage,
|
|
1039
1148
|
});
|
|
1040
1149
|
};
|
|
1041
1150
|
}
|
|
@@ -1057,7 +1166,8 @@ export function sitePageDecorator(config, index) {
|
|
|
1057
1166
|
* `sql` directive with none prepared is a table error: nothing here runs a
|
|
1058
1167
|
* query.
|
|
1059
1168
|
* @returns {{gates: object, stats: object|null, tableErrors: object[],
|
|
1060
|
-
* wikiErrors: object[], imageErrors: object[],
|
|
1169
|
+
* wikiErrors: object[], imageErrors: object[], embedErrors: object[],
|
|
1170
|
+
* mapFindings: object[],
|
|
1061
1171
|
* manifests: object|null}} `mapFindings` is what drawing the maps found —
|
|
1062
1172
|
* warnings, never a reason to fail the build.
|
|
1063
1173
|
*/
|
|
@@ -1156,6 +1266,7 @@ export function buildSite({ config, sqlTables } = {}) {
|
|
|
1156
1266
|
footnoteErrors: [],
|
|
1157
1267
|
wikiErrors: [],
|
|
1158
1268
|
imageErrors: [],
|
|
1269
|
+
embedErrors: [],
|
|
1159
1270
|
mapFindings: [],
|
|
1160
1271
|
stats: null,
|
|
1161
1272
|
};
|
|
@@ -1180,6 +1291,7 @@ export function buildSite({ config, sqlTables } = {}) {
|
|
|
1180
1291
|
footnoteErrors: [],
|
|
1181
1292
|
wikiErrors: [],
|
|
1182
1293
|
imageErrors: [],
|
|
1294
|
+
embedErrors: [],
|
|
1183
1295
|
mapFindings: [],
|
|
1184
1296
|
stats: {
|
|
1185
1297
|
homepages: writeHomepages(homeRoot, homepages, resolved),
|
|
@@ -1230,6 +1342,7 @@ export function buildSite({ config, sqlTables } = {}) {
|
|
|
1230
1342
|
footnoteErrors: [],
|
|
1231
1343
|
wikiErrors: [],
|
|
1232
1344
|
imageErrors: [],
|
|
1345
|
+
embedErrors: [],
|
|
1233
1346
|
mapFindings: [],
|
|
1234
1347
|
};
|
|
1235
1348
|
}
|
|
@@ -1290,6 +1403,7 @@ export function buildSite({ config, sqlTables } = {}) {
|
|
|
1290
1403
|
footnoteErrors: rendered.footnoteErrors,
|
|
1291
1404
|
wikiErrors: rendered.wikiErrors,
|
|
1292
1405
|
imageErrors: rendered.imageErrors,
|
|
1406
|
+
embedErrors: rendered.embedErrors,
|
|
1293
1407
|
mapFindings: drawn.findings,
|
|
1294
1408
|
stats: {
|
|
1295
1409
|
...rendered.byKind,
|