@heroiclands/package-build 23.12.8 → 24.0.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 +84 -0
- package/README.md +3 -2
- package/assets/preview/gitea.ini +12 -7
- package/assets/styles/content-base.css +293 -24
- package/bin/content-commands.mjs +370 -213
- package/bin/package-build-preview.mjs +2 -2
- package/bin/package-build.mjs +3 -2
- package/ci/check-banners.mjs +7 -7
- package/config.mjs +21 -6
- package/content-config.mjs +199 -80
- package/docs/api.md +110 -89
- package/docs/authoring/links-and-markup.md +469 -97
- package/docs/commands.md +259 -78
- package/docs/configuration.md +211 -103
- package/docs/content-format.md +4 -4
- package/docs/diagnostics.md +44 -2
- package/docs/getting-started.md +1 -1
- package/docs/guides/icons.md +1 -1
- package/docs/guides/module-project.md +5 -8
- package/docs/guides/release-and-deploy.md +2 -2
- package/docs/guides/site.md +112 -23
- package/docs/guides/system-project.md +1 -1
- package/docs/guides/writing-in-invented-scripts.md +1247 -0
- package/docs/index.md +1 -0
- package/docs/project-setup.md +28 -30
- package/docs/reference/format-details.md +677 -319
- package/docs/reference/note-types.md +47 -10
- package/docs/reference/theme-pages.md +178 -108
- package/docs/source-preview.md +16 -2
- package/engine/anchors.mjs +2 -2
- package/engine/asset-shipping.mjs +22 -10
- package/engine/base-compiler.mjs +62 -104
- package/engine/changelog-lint.mjs +1 -1
- package/engine/code-fences.mjs +3 -3
- package/engine/content-address.mjs +1 -1
- package/engine/content-alerts.mjs +8 -4
- package/engine/content-blocks.mjs +29 -14
- package/engine/content-embeds.mjs +1 -1
- package/engine/content-expand.mjs +376 -0
- package/engine/content-figures.mjs +18 -11
- package/engine/content-format.yaml +8 -0
- package/engine/content-glyphs.mjs +213 -0
- package/engine/content-images.mjs +6 -7
- package/engine/content-index.mjs +1 -1
- package/engine/content-links.mjs +3 -3
- package/engine/content-lint.mjs +1 -1
- package/engine/content-render.mjs +453 -0
- package/engine/content-scripts.mjs +376 -43
- package/engine/content-spans.mjs +6 -3
- package/engine/content-styles.mjs +91 -0
- package/engine/content-symbols.mjs +186 -0
- package/engine/content-verse.mjs +738 -0
- package/engine/core-report.mjs +169 -0
- package/engine/core-vocabulary.mjs +208 -0
- package/engine/dictionary-html.mjs +119 -0
- package/engine/dictionary-rows.mjs +15 -4
- package/engine/field-reference.mjs +5 -5
- package/engine/first-use.mjs +17 -27
- package/engine/frontmatter-lint.mjs +1 -1
- package/engine/heading-attributes.mjs +89 -0
- package/engine/helpers.mjs +61 -101
- package/engine/homepage.mjs +17 -29
- package/engine/html-minify.mjs +70 -0
- package/engine/index.mjs +8 -5
- package/engine/key-case-collisions.mjs +136 -0
- package/engine/language-data.mjs +203 -6
- package/engine/language-rows.mjs +8 -2
- package/engine/language-terms.mjs +186 -16
- package/engine/language-words.mjs +12 -0
- package/engine/logographic.mjs +255 -0
- package/engine/map-lexicon.mjs +262 -47
- package/engine/map-places.mjs +5 -4
- package/engine/markdown-expressions.mjs +0 -2
- package/engine/markdownlint-run.mjs +9 -3
- package/engine/markup-validation.mjs +21 -0
- package/engine/metre-declaration.mjs +134 -0
- package/engine/names.mjs +36 -9
- package/engine/note-matter.mjs +66 -0
- package/engine/note-vocabulary.mjs +187 -3
- package/engine/pdf-build.mjs +69 -133
- package/engine/pdf-render.mjs +205 -58
- package/engine/post-fields.mjs +157 -0
- package/engine/preview-index.mjs +130 -0
- package/engine/preview-source.mjs +450 -0
- package/engine/project-init.mjs +5 -12
- package/engine/prose-config.mjs +3 -3
- package/engine/read-stdin.mjs +29 -0
- package/engine/run-rows.mjs +2 -2
- package/engine/run-words.mjs +6 -112
- package/engine/script-emphasis-terms.mjs +38 -0
- package/engine/script-emphasis.mjs +295 -0
- package/engine/script-font-delivery.mjs +4 -4
- package/engine/site-build.mjs +260 -315
- package/engine/site-config.mjs +26 -238
- package/engine/site-files.mjs +175 -0
- package/engine/site-index.mjs +9 -4
- package/engine/site-preview.mjs +52 -525
- package/engine/site-render.mjs +593 -0
- package/engine/site-root.mjs +22 -13
- package/engine/site-search.mjs +161 -0
- package/engine/site-serve.mjs +273 -0
- package/engine/site-theme-banner.mjs +154 -0
- package/engine/site-theme-urls.mjs +125 -0
- package/engine/site-theme.mjs +926 -0
- package/engine/sql-tables.mjs +20 -3
- package/engine/text-maps.mjs +57 -10
- package/engine/typographer.mjs +248 -0
- package/engine/verse-metre.mjs +357 -0
- package/engine/wikilink-syntax.mjs +29 -47
- package/engine/wikilinks.mjs +758 -279
- package/engine/word-forms.mjs +364 -0
- package/engine/word-rows.mjs +12 -2
- package/engine/word-terms.mjs +38 -4
- package/manifest.mjs +3 -4
- package/package.json +11 -8
- package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
- package/site-theme/layouts/base.hbs +31 -0
- package/site-theme/layouts/blog-list.hbs +30 -0
- package/site-theme/layouts/blog-post.hbs +40 -0
- package/site-theme/layouts/home.hbs +35 -0
- package/site-theme/layouts/list.hbs +20 -0
- package/site-theme/layouts/not-found.hbs +31 -0
- package/site-theme/layouts/page.hbs +7 -0
- package/site-theme/partials/copy-buttons.hbs +37 -0
- package/site-theme/partials/draft-notice.hbs +5 -0
- package/site-theme/partials/exturl.hbs +2 -0
- package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
- package/site-theme/partials/header.hbs +44 -0
- package/site-theme/partials/hero-banner.hbs +11 -0
- package/site-theme/partials/infobox-entry.hbs +2 -0
- package/site-theme/partials/infobox-section.hbs +31 -0
- package/site-theme/partials/infobox-value.hbs +2 -0
- package/site-theme/partials/infobox.hbs +18 -0
- package/site-theme/partials/list-members.hbs +9 -0
- package/site-theme/partials/nav-links.hbs +5 -0
- package/site-theme/partials/page-body.hbs +48 -0
- package/site-theme/partials/page-list.hbs +14 -0
- package/site-theme/partials/related.hbs +24 -0
- package/site-theme/partials/search-meta.hbs +6 -0
- package/site-theme/partials/search-names.hbs +2 -0
- package/site-theme/partials/search.hbs +52 -0
- package/site-theme/partials/tags.hbs +4 -0
- package/site-theme/partials/toc.hbs +7 -0
- package/{hugo-theme → site-theme}/static/css/style.css +106 -14
- package/stage.mjs +1 -2
- package/types/config.d.mts +8 -4
- package/types/content-config.d.mts +15 -15
- package/types/engine/asset-shipping.d.mts +5 -2
- package/types/engine/base-compiler.d.mts +20 -2
- package/types/engine/code-fences.d.mts +3 -3
- package/types/engine/content-address.d.mts +1 -1
- package/types/engine/content-alerts.d.mts +8 -2
- package/types/engine/content-blocks.d.mts +11 -4
- package/types/engine/content-expand.d.mts +288 -0
- package/types/engine/content-figures.d.mts +11 -3
- package/types/engine/content-glyphs.d.mts +85 -0
- package/types/engine/content-images.d.mts +6 -7
- package/types/engine/content-links.d.mts +1 -1
- package/types/engine/content-render.d.mts +199 -0
- package/types/engine/content-scripts.d.mts +70 -4
- package/types/engine/content-spans.d.mts +1 -1
- package/types/engine/content-styles.d.mts +33 -0
- package/types/engine/content-symbols.d.mts +35 -0
- package/types/engine/content-verse.d.mts +240 -0
- package/types/engine/core-report.d.mts +45 -0
- package/types/engine/core-vocabulary.d.mts +53 -0
- package/types/engine/dictionary-html.d.mts +8 -0
- package/types/engine/dictionary-rows.d.mts +10 -0
- package/types/engine/field-reference.d.mts +2 -2
- package/types/engine/heading-attributes.d.mts +20 -0
- package/types/engine/helpers.d.mts +3 -10
- package/types/engine/homepage.d.mts +11 -24
- package/types/engine/html-minify.d.mts +9 -0
- package/types/engine/index.d.mts +2 -1
- package/types/engine/key-case-collisions.d.mts +28 -0
- package/types/engine/language-data.d.mts +0 -2
- package/types/engine/language-terms.d.mts +24 -2
- package/types/engine/logographic.d.mts +45 -0
- package/types/engine/map-lexicon.d.mts +66 -13
- package/types/engine/map-places.d.mts +8 -0
- package/types/engine/markdown-expressions.d.mts +0 -2
- package/types/engine/metre-declaration.d.mts +39 -0
- package/types/engine/names.d.mts +34 -3
- package/types/engine/note-matter.d.mts +48 -0
- package/types/engine/pdf-render.d.mts +6 -2
- package/types/engine/post-fields.d.mts +44 -0
- package/types/engine/preview-index.d.mts +72 -0
- package/types/engine/preview-source.d.mts +51 -0
- package/types/engine/read-stdin.d.mts +11 -0
- package/types/engine/run-rows.d.mts +2 -2
- package/types/engine/run-words.d.mts +0 -15
- package/types/engine/script-emphasis-terms.d.mts +21 -0
- package/types/engine/script-emphasis.d.mts +84 -0
- package/types/engine/script-font-delivery.d.mts +4 -4
- package/types/engine/site-build.d.mts +71 -113
- package/types/engine/site-config.d.mts +14 -134
- package/types/engine/site-files.d.mts +73 -0
- package/types/engine/site-index.d.mts +11 -3
- package/types/engine/site-preview.d.mts +15 -19
- package/types/engine/site-render.d.mts +171 -0
- package/types/engine/site-root.d.mts +12 -4
- package/types/engine/site-search.d.mts +54 -0
- package/types/engine/site-serve.d.mts +44 -0
- package/types/engine/site-theme-banner.d.mts +51 -0
- package/types/engine/site-theme-urls.d.mts +60 -0
- package/types/engine/site-theme.d.mts +127 -0
- package/types/engine/sql-tables.d.mts +4 -1
- package/types/engine/text-maps.d.mts +17 -3
- package/types/engine/typographer.d.mts +11 -0
- package/types/engine/verse-metre.d.mts +131 -0
- package/types/engine/wikilink-syntax.d.mts +30 -48
- package/types/engine/wikilinks.d.mts +330 -14
- package/types/engine/word-forms.d.mts +83 -0
- package/types/manifest.d.mts +3 -4
- package/types/stage.d.mts +1 -2
- package/types/vendor/markdownlint.d.mts +8 -0
- package/vendor/markdownlint.mjs +20388 -0
- package/engine/content-poetry.mjs +0 -240
- package/engine/web-wikilinks.mjs +0 -594
- package/hugo-theme/layouts/404.html +0 -85
- package/hugo-theme/layouts/_default/baseof.html +0 -67
- package/hugo-theme/layouts/_default/list.html +0 -139
- package/hugo-theme/layouts/_default/single.html +0 -4
- package/hugo-theme/layouts/blog/list.html +0 -54
- package/hugo-theme/layouts/blog-post/single.html +0 -36
- package/hugo-theme/layouts/index.html +0 -75
- package/hugo-theme/layouts/partials/banner-url.html +0 -141
- package/hugo-theme/layouts/partials/cdn-url.html +0 -36
- package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
- package/hugo-theme/layouts/partials/draft-notice.html +0 -41
- package/hugo-theme/layouts/partials/draft-state.html +0 -26
- package/hugo-theme/layouts/partials/header.html +0 -35
- package/hugo-theme/layouts/partials/hero-banner.html +0 -85
- package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
- package/hugo-theme/layouts/partials/infobox/items.html +0 -26
- package/hugo-theme/layouts/partials/infobox/section.html +0 -56
- package/hugo-theme/layouts/partials/infobox/value.html +0 -43
- package/hugo-theme/layouts/partials/infobox.html +0 -57
- package/hugo-theme/layouts/partials/page-body.html +0 -152
- package/hugo-theme/layouts/partials/related.html +0 -138
- package/hugo-theme/layouts/partials/search.html +0 -84
- package/hugo-theme/layouts/partials/site-url.html +0 -32
- package/hugo-theme/layouts/partials/tags.html +0 -30
- package/hugo-theme/layouts/partials/toc.html +0 -28
- package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
- package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
- package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
- package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
- package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
- package/hugo-theme/theme.toml +0 -11
- package/types/engine/content-poetry.d.mts +0 -58
- package/types/engine/web-wikilinks.d.mts +0 -107
- /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
- /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
- /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
- /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
- /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
- /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
package/engine/map-lexicon.mjs
CHANGED
|
@@ -37,6 +37,9 @@
|
|
|
37
37
|
* over one with none.
|
|
38
38
|
* - **Derived forms take the rows**: a plural or a verb ending of an exception
|
|
39
39
|
* word is spelled by the rows, and only the word as cited is looked up.
|
|
40
|
+
* - **A logographic map** spells no word by its rows: every word is written
|
|
41
|
+
* from the lexicon, by its own writing or its parts' (see
|
|
42
|
+
* {@link module:engine/logographic}), and a word with neither is a finding.
|
|
40
43
|
*
|
|
41
44
|
* {@link mappingFor} is the one path from a map, a face and a language to the
|
|
42
45
|
* function that rewrites text: the build's runs, `package-build transliterate`
|
|
@@ -51,9 +54,12 @@ import { parseAddress, renderAddress } from "./address.mjs";
|
|
|
51
54
|
import { positionOfFrontmatterPath, positionOfYamlPath } from "./diagnostics.mjs";
|
|
52
55
|
import { isNoteRecord } from "./index-records.mjs";
|
|
53
56
|
import { nearest } from "./near-miss.mjs";
|
|
57
|
+
import { WRITTEN_ENDINGS } from "./language-terms.mjs";
|
|
58
|
+
import { writingsOf } from "./logographic.mjs";
|
|
54
59
|
import { FONTS_PACKAGE } from "./script-fonts.mjs";
|
|
55
60
|
import { GENERIC_FAMILIES, applyMap } from "./text-maps.mjs";
|
|
56
61
|
import { isLanguageRecord, noteAddressOf } from "./word-rows.mjs";
|
|
62
|
+
import { derivedForms } from "./word-forms.mjs";
|
|
57
63
|
import { LANGUAGE_SUBTYPE, glossText } from "./word-terms.mjs";
|
|
58
64
|
|
|
59
65
|
/** The configuration file a language is declared in. */
|
|
@@ -103,6 +109,11 @@ function said(names) {
|
|
|
103
109
|
* @property {readonly LexiconWord[]} words - Its words, in `data.words` order.
|
|
104
110
|
* @property {ReadonlyMap<string, readonly NativeForm[]>} byForm - The native
|
|
105
111
|
* forms by the word's form, NFC; the first word of a form keeps it.
|
|
112
|
+
* @property {ReadonlyArray<{form: string, from: LexiconWord}>} derived - The
|
|
113
|
+
* forms the language's rules derive from its words, folded, as the mapped-run
|
|
114
|
+
* word check accepts them (see {@link module:engine/word-forms.derivedForms}).
|
|
115
|
+
* @property {Record<string, any>} data - The language note's `data`, which a
|
|
116
|
+
* logographic map writes words from.
|
|
106
117
|
*/
|
|
107
118
|
|
|
108
119
|
/**
|
|
@@ -134,21 +145,31 @@ function readNatives(value) {
|
|
|
134
145
|
function lexiconOf(language, data) {
|
|
135
146
|
const words = [];
|
|
136
147
|
const byForm = new Map();
|
|
148
|
+
const bySource = new Map();
|
|
137
149
|
for (const word of listOf(data?.words)) {
|
|
138
150
|
if (!isMap(word) || typeof word.form !== "string") continue;
|
|
139
151
|
const natives = readNatives(word.native);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
);
|
|
152
|
+
const read = Object.freeze({
|
|
153
|
+
form: word.form,
|
|
154
|
+
class: typeof word.class === "string" ? word.class : null,
|
|
155
|
+
gloss: glossText(word.gloss),
|
|
156
|
+
natives,
|
|
157
|
+
});
|
|
158
|
+
words.push(read);
|
|
159
|
+
bySource.set(word, read);
|
|
148
160
|
const key = word.form.normalize("NFC");
|
|
149
161
|
if (!byForm.has(key)) byForm.set(key, natives);
|
|
150
162
|
}
|
|
151
|
-
|
|
163
|
+
const derived = derivedForms(data).map(({ form, word }) =>
|
|
164
|
+
Object.freeze({ form, from: bySource.get(word) }),
|
|
165
|
+
);
|
|
166
|
+
return Object.freeze({
|
|
167
|
+
language,
|
|
168
|
+
words: Object.freeze(words),
|
|
169
|
+
byForm,
|
|
170
|
+
derived: Object.freeze(derived),
|
|
171
|
+
data: isMap(data) ? data : {},
|
|
172
|
+
});
|
|
152
173
|
}
|
|
153
174
|
|
|
154
175
|
/**
|
|
@@ -317,7 +338,10 @@ export function nativeLookup(lexicon, map, font) {
|
|
|
317
338
|
* @property {import("./text-maps.mjs").TextMap} map - The map.
|
|
318
339
|
* @property {string|undefined} font - The face, whose own rows come first.
|
|
319
340
|
* @property {((word: string) => string|undefined)|undefined} native - The
|
|
320
|
-
* language's native forms under the map in the face
|
|
341
|
+
* language's native forms under the map in the face, for a map that spells
|
|
342
|
+
* by its rows.
|
|
343
|
+
* @property {((word: string) => import("./logographic.mjs").Writing)|undefined} writing -
|
|
344
|
+
* Each word's writing, for a logographic map.
|
|
321
345
|
*/
|
|
322
346
|
|
|
323
347
|
/**
|
|
@@ -333,7 +357,20 @@ export function mappingFor(ctx, { map, font, lang }) {
|
|
|
333
357
|
const textMap = ctx?.maps?.get(map);
|
|
334
358
|
if (!textMap) return undefined;
|
|
335
359
|
const lexicon = lang === undefined ? undefined : ctx.lexicons?.get(lang);
|
|
336
|
-
|
|
360
|
+
if (!textMap.logographic)
|
|
361
|
+
return {
|
|
362
|
+
map: textMap,
|
|
363
|
+
font,
|
|
364
|
+
native: nativeLookup(lexicon, textMap.name, font),
|
|
365
|
+
writing: undefined,
|
|
366
|
+
};
|
|
367
|
+
const writings = lexicon ? writingsOf(lexicon.data, textMap.name, font) : undefined;
|
|
368
|
+
return {
|
|
369
|
+
map: textMap,
|
|
370
|
+
font,
|
|
371
|
+
native: undefined,
|
|
372
|
+
writing: writings ? writings.word : () => ({ missing: true, noLexicon: true }),
|
|
373
|
+
};
|
|
337
374
|
}
|
|
338
375
|
|
|
339
376
|
/**
|
|
@@ -411,6 +448,52 @@ export function uncapitalisedMessage(word, lower, lang, map) {
|
|
|
411
448
|
);
|
|
412
449
|
}
|
|
413
450
|
|
|
451
|
+
/**
|
|
452
|
+
* What is wrong with a word a logographic map gives no writing.
|
|
453
|
+
*
|
|
454
|
+
* @param {string} word - The word as written.
|
|
455
|
+
* @param {object} unwritten - Why it has none, as
|
|
456
|
+
* {@link module:engine/logographic.writingsOf} says.
|
|
457
|
+
* @param {string|undefined} lang - The run's language.
|
|
458
|
+
* @param {string} map - The map's name.
|
|
459
|
+
* @returns {string} The message.
|
|
460
|
+
*/
|
|
461
|
+
export function unwrittenMessage(word, unwritten, lang, map) {
|
|
462
|
+
const why = /** @type {{noLexicon?: true, ambiguous?: {form: string, glosses: string[]}}} */ (
|
|
463
|
+
unwritten
|
|
464
|
+
);
|
|
465
|
+
if (why.noLexicon)
|
|
466
|
+
return lang === undefined ?
|
|
467
|
+
`\`${word}\` has no \`${map}\` writing: the map \`${map}\` is logographic, and the run ` +
|
|
468
|
+
"names no `lang=` whose lexicon writes it; mark the run with its language, or " +
|
|
469
|
+
"write the word directly in signs"
|
|
470
|
+
: `\`${word}\` has no \`${map}\` writing: the map \`${map}\` is logographic, and \`${lang}\` ` +
|
|
471
|
+
`has no lexicon (\`languages.${lang}.note\`) to write it from; write the word ` +
|
|
472
|
+
"directly in signs";
|
|
473
|
+
if (why.ambiguous) {
|
|
474
|
+
const { form, glosses } = why.ambiguous;
|
|
475
|
+
const quoted = glosses.map((gloss) => `“${gloss}”`);
|
|
476
|
+
const listed =
|
|
477
|
+
quoted.length < 2 ?
|
|
478
|
+
quoted.join("")
|
|
479
|
+
: `${quoted.slice(0, -1).join(", ")} and ${quoted.at(-1)}`;
|
|
480
|
+
const stands =
|
|
481
|
+
`stands for ${glosses.length} words of the \`${lang}\` lexicon that the map ` +
|
|
482
|
+
`\`${map}\` writes differently, ${listed}`;
|
|
483
|
+
return (
|
|
484
|
+
(form === word ?
|
|
485
|
+
`\`${word}\` ${stands}`
|
|
486
|
+
: `\`${word}\` is written from its part \`${form}\`, which ${stands}`) +
|
|
487
|
+
"; write the word directly in signs, choosing by its sense in " +
|
|
488
|
+
`\`package-build lexicon ${lang} --map ${map}\``
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return (
|
|
492
|
+
`\`${word}\` has no \`${map}\` writing in the \`${lang}\` lexicon, and its parts do not ` +
|
|
493
|
+
"give one; state one, or write the word directly in signs"
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
414
497
|
/**
|
|
415
498
|
* Map a passage exactly as the build maps a run with the same keys.
|
|
416
499
|
*
|
|
@@ -423,8 +506,14 @@ export function uncapitalisedMessage(word, lower, lang, map) {
|
|
|
423
506
|
export function transliterate(ctx, keys, text) {
|
|
424
507
|
const found = commandMapping(ctx, keys);
|
|
425
508
|
if ("problem" in found) return { problem: found.problem, about: found.about };
|
|
426
|
-
const { map, font, native } = found.mapping;
|
|
427
|
-
const mapped = applyMap(map, text, { font, native });
|
|
509
|
+
const { map, font, native, writing } = found.mapping;
|
|
510
|
+
const mapped = applyMap(map, text, { font, native, writing });
|
|
511
|
+
const unwritten = mapped.pieces.find((one) => one.unwritten !== undefined);
|
|
512
|
+
if (unwritten)
|
|
513
|
+
return {
|
|
514
|
+
about: "word",
|
|
515
|
+
problem: unwrittenMessage(unwritten.from, unwritten.unwritten, keys.lang, map.name),
|
|
516
|
+
};
|
|
428
517
|
const piece = mapped.pieces.find((one) => one.uncapitalised !== undefined);
|
|
429
518
|
if (piece)
|
|
430
519
|
return {
|
|
@@ -442,15 +531,24 @@ export function transliterate(ctx, keys, text) {
|
|
|
442
531
|
/**
|
|
443
532
|
* Every word of a language's lexicon with its native form under a map: the
|
|
444
533
|
* stated exception, else the rows' spelling, each exactly as the build gives
|
|
445
|
-
* it.
|
|
534
|
+
* it. With `derived`, the forms the language's rules derive follow the words,
|
|
535
|
+
* each case folded and naming the word it comes from in `from`, so the list
|
|
536
|
+
* is what the mapped-run word check accepts of the lexicon.
|
|
537
|
+
*
|
|
538
|
+
* Under a logographic map an entry carries `source` in place of `exception`:
|
|
539
|
+
* `own` for a writing it states, `parts` for one its parts give, and `none`,
|
|
540
|
+
* with an empty `native`, where it has none. A word whose form a run cannot
|
|
541
|
+
* write, because the form stands for entries written differently, or a part
|
|
542
|
+
* does, also carries `ambiguous: true`; its `native` is still its own
|
|
543
|
+
* writing, the signs a run writes directly for that sense.
|
|
446
544
|
*
|
|
447
545
|
* @param {object} ctx - The run context.
|
|
448
|
-
* @param {{lang: string, map: string, font?: string}} keys -
|
|
449
|
-
* map and
|
|
450
|
-
* @returns {{entries: Array<{form: string, native: string, exception
|
|
451
|
-
* The words in `data.words` order, or the problem.
|
|
546
|
+
* @param {{lang: string, map: string, font?: string, derived?: boolean}} keys -
|
|
547
|
+
* The language, the map, the face, and whether to list derived forms.
|
|
548
|
+
* @returns {{entries: Array<{form: string, native: string, exception?: boolean, source?: "own"|"parts"|"none", ambiguous?: true, class: string|null, gloss: string|null, from?: string}>}|{problem: string, about: string}}
|
|
549
|
+
* The words in `data.words` order, then any derived forms, or the problem.
|
|
452
550
|
*/
|
|
453
|
-
export function lexiconEntries(ctx, { lang, map, font }) {
|
|
551
|
+
export function lexiconEntries(ctx, { lang, map, font, derived = false }) {
|
|
454
552
|
const found = commandMapping(ctx, { map, font, lang });
|
|
455
553
|
if ("problem" in found) return { problem: found.problem, about: found.about };
|
|
456
554
|
const lexicon = ctx.lexicons?.get(lang);
|
|
@@ -462,9 +560,14 @@ export function lexiconEntries(ctx, { lang, map, font }) {
|
|
|
462
560
|
"in its `note`",
|
|
463
561
|
};
|
|
464
562
|
const { map: textMap, font: face, native } = found.mapping;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
563
|
+
if (textMap.logographic) return { entries: writtenEntries(lexicon, textMap, face, derived) };
|
|
564
|
+
const listed = [
|
|
565
|
+
...lexicon.words.map((word) => ({ word, form: word.form, from: undefined })),
|
|
566
|
+
...(derived ?
|
|
567
|
+
lexicon.derived.map((one) => ({ word: one.from, form: one.form, from: one.from.form }))
|
|
568
|
+
: []),
|
|
569
|
+
];
|
|
570
|
+
const mapped = listed.map((one) => applyMap(textMap, one.form, { font: face, native }));
|
|
468
571
|
const unsound = mapped.flatMap((one) => one.pieces).find((one) => one.uncapitalised);
|
|
469
572
|
if (unsound)
|
|
470
573
|
return {
|
|
@@ -477,19 +580,64 @@ export function lexiconEntries(ctx, { lang, map, font }) {
|
|
|
477
580
|
),
|
|
478
581
|
};
|
|
479
582
|
return {
|
|
480
|
-
entries:
|
|
481
|
-
form
|
|
583
|
+
entries: listed.map(({ word, form, from }, i) => ({
|
|
584
|
+
form,
|
|
482
585
|
native: mapped[i].text,
|
|
483
586
|
exception:
|
|
484
|
-
native?.(
|
|
485
|
-
(
|
|
486
|
-
native?.(word.form.toLowerCase()) !== undefined),
|
|
587
|
+
native?.(form) !== undefined ||
|
|
588
|
+
(form.toLowerCase() !== form && native?.(form.toLowerCase()) !== undefined),
|
|
487
589
|
class: word.class,
|
|
488
590
|
gloss: word.gloss,
|
|
591
|
+
...(from === undefined ? {} : { from }),
|
|
489
592
|
})),
|
|
490
593
|
};
|
|
491
594
|
}
|
|
492
595
|
|
|
596
|
+
/**
|
|
597
|
+
* Every word of a lexicon with its writing under a logographic map, as
|
|
598
|
+
* {@link lexiconEntries} lists them.
|
|
599
|
+
*
|
|
600
|
+
* @param {Lexicon} lexicon - The lexicon.
|
|
601
|
+
* @param {import("./text-maps.mjs").TextMap} map - The map.
|
|
602
|
+
* @param {string|undefined} font - The face.
|
|
603
|
+
* @param {boolean} derived - Whether to list derived forms.
|
|
604
|
+
* @returns {Array<Record<string, any>>} The entries.
|
|
605
|
+
*/
|
|
606
|
+
function writtenEntries(lexicon, map, font, derived) {
|
|
607
|
+
const writings = writingsOf(lexicon.data, map.name, font);
|
|
608
|
+
// The `data.words` index of each lexicon word, which reads the same entries.
|
|
609
|
+
const indexes = [];
|
|
610
|
+
listOf(lexicon.data.words).forEach((word, index) => {
|
|
611
|
+
if (isMap(word) && typeof word.form === "string") indexes.push(index);
|
|
612
|
+
});
|
|
613
|
+
const shaped = (form, writing, word, from) => {
|
|
614
|
+
// Whether a run of the form, written as the build writes it, meets an
|
|
615
|
+
// ambiguity: another entry of the form, or of a part, written otherwise.
|
|
616
|
+
const run = applyMap(map, form, { font, writing: writings.word }).pieces.some(
|
|
617
|
+
(piece) => piece.unwritten?.ambiguous !== undefined,
|
|
618
|
+
);
|
|
619
|
+
return {
|
|
620
|
+
form,
|
|
621
|
+
native: "text" in writing ? writing.text : "",
|
|
622
|
+
source:
|
|
623
|
+
"text" in writing ? writing.source
|
|
624
|
+
: "ambiguous" in writing ? "parts"
|
|
625
|
+
: "none",
|
|
626
|
+
...("ambiguous" in writing || run ? { ambiguous: true } : {}),
|
|
627
|
+
class: word.class,
|
|
628
|
+
gloss: word.gloss,
|
|
629
|
+
...(from === undefined ? {} : { from }),
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
const entries = lexicon.words.map((word, at) =>
|
|
633
|
+
shaped(word.form, writings.entry(indexes[at]), word, undefined),
|
|
634
|
+
);
|
|
635
|
+
if (derived)
|
|
636
|
+
for (const one of lexicon.derived)
|
|
637
|
+
entries.push(shaped(one.form, writings.word(one.form), one.from, one.from.form));
|
|
638
|
+
return entries;
|
|
639
|
+
}
|
|
640
|
+
|
|
493
641
|
/**
|
|
494
642
|
* Whether a shared row can be reached in a face: no plain row of the face's
|
|
495
643
|
* own matches at the start of its `from`, which would win there first.
|
|
@@ -588,10 +736,16 @@ export function checkMapFonts(note, ctx) {
|
|
|
588
736
|
}
|
|
589
737
|
|
|
590
738
|
/**
|
|
591
|
-
* Check a language note's native forms against the maps and faces:
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
739
|
+
* Check a language note's native forms against the maps and faces: a word's
|
|
740
|
+
* `native`, an affix's, and the endings' in `data.grammar.native`. Each is
|
|
741
|
+
* checked for an unknown map, a face the map is not for, a second form for one
|
|
742
|
+
* map and face (and one ending), and a code point a face it applies in does
|
|
743
|
+
* not draw. A word's form under a map that spells by its rows is also checked
|
|
744
|
+
* for stating what the rows already give; under a logographic map the rows
|
|
745
|
+
* spell no word, so that check does not apply. An affix's and an ending's
|
|
746
|
+
* writings mean something only under a logographic map, and an ending of a
|
|
747
|
+
* person is written only where `data.grammar.verbs` states `persons`. The
|
|
748
|
+
* shape of each entry is the data-key check's.
|
|
595
749
|
*
|
|
596
750
|
* @param {{file: string, raw?: string, fm?: Record<string, any>}} note - The note.
|
|
597
751
|
* @param {{faces?: ReadonlyMap<string, import("./script-fonts.mjs").Face>, maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap>}} ctx -
|
|
@@ -604,35 +758,47 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
604
758
|
const raw = note.raw ?? "";
|
|
605
759
|
const finding = (keyPath, message, key = false) => ({
|
|
606
760
|
file: note.file,
|
|
607
|
-
...positionOfFrontmatterPath(raw, ["data",
|
|
761
|
+
...positionOfFrontmatterPath(raw, ["data", ...keyPath], { key }),
|
|
608
762
|
severity: "error",
|
|
609
763
|
message,
|
|
610
764
|
});
|
|
611
765
|
const maps = ctx?.maps ?? new Map();
|
|
612
766
|
const faces = ctx?.faces ?? new Map();
|
|
613
767
|
const findings = [];
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Check one `native` list.
|
|
771
|
+
*
|
|
772
|
+
* @param {unknown[]} list - The list as authored.
|
|
773
|
+
* @param {Array<string|number>} keyPath - Its path under `data`.
|
|
774
|
+
* @param {object} as - What it belongs to.
|
|
775
|
+
* @param {"word"|"affix"|"ending"} as.kind - A word's, an affix's or the
|
|
776
|
+
* endings' list.
|
|
777
|
+
* @param {string} [as.form] - The word's form, for the rows' check.
|
|
778
|
+
*/
|
|
779
|
+
const checkList = (list, keyPath, { kind, form = "" }) => {
|
|
780
|
+
const base = `data.${keyPath.join(".").replace(/\.(\d+)/g, "[$1]")}`;
|
|
617
781
|
const stated = new Map();
|
|
618
|
-
const entries =
|
|
782
|
+
const entries = list.map((entry) =>
|
|
619
783
|
isMap(entry) && typeof entry.map === "string" && typeof entry.text === "string" ?
|
|
620
784
|
{
|
|
621
785
|
map: entry.map,
|
|
622
786
|
font: typeof entry.font === "string" ? entry.font : undefined,
|
|
623
787
|
text: entry.text,
|
|
788
|
+
ending: typeof entry.ending === "string" ? entry.ending : undefined,
|
|
624
789
|
}
|
|
625
790
|
: undefined,
|
|
626
791
|
);
|
|
792
|
+
const persons = isMap(fm.data.grammar?.verbs?.persons);
|
|
627
793
|
entries.forEach((entry, j) => {
|
|
628
794
|
if (!entry) return;
|
|
629
|
-
const label =
|
|
795
|
+
const label = `${base}[${j}]`;
|
|
630
796
|
const map = maps.get(entry.map);
|
|
631
797
|
if (!map) {
|
|
632
798
|
const near = nearest(entry.map, [...maps.keys()]);
|
|
633
799
|
findings.push(
|
|
634
800
|
finding(
|
|
635
|
-
[
|
|
801
|
+
[...keyPath, j, "map"],
|
|
636
802
|
`\`${label}.map\` is \`${entry.map}\`, which is not a map: a native form names ` +
|
|
637
803
|
"the `data.map.name` of a mapping note" +
|
|
638
804
|
(near ? `; did you mean \`${near}\`?` : ""),
|
|
@@ -640,24 +806,51 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
640
806
|
);
|
|
641
807
|
return;
|
|
642
808
|
}
|
|
809
|
+
if (kind !== "word" && !map.logographic) {
|
|
810
|
+
findings.push(
|
|
811
|
+
finding(
|
|
812
|
+
[...keyPath, j],
|
|
813
|
+
`\`${label}\` names the map \`${map.name}\`, which is not logographic; ` +
|
|
814
|
+
`${kind === "affix" ? "an affix" : "an ending"} is written by a native ` +
|
|
815
|
+
"form only under a logographic map",
|
|
816
|
+
),
|
|
817
|
+
);
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
643
820
|
if (entry.font !== undefined && map.fonts.size && !map.fonts.has(entry.font)) {
|
|
644
821
|
findings.push(
|
|
645
822
|
finding(
|
|
646
|
-
[
|
|
823
|
+
[...keyPath, j, "font"],
|
|
647
824
|
`\`${label}.font\` is \`${entry.font}\`, which is not a font of the map ` +
|
|
648
825
|
`\`${map.name}\`; it is for ${said([...map.fonts.keys()])}`,
|
|
649
826
|
),
|
|
650
827
|
);
|
|
651
828
|
return;
|
|
652
829
|
}
|
|
653
|
-
|
|
830
|
+
if (
|
|
831
|
+
kind === "ending" &&
|
|
832
|
+
entry.ending !== undefined &&
|
|
833
|
+
entry.ending !== WRITTEN_ENDINGS[0] &&
|
|
834
|
+
WRITTEN_ENDINGS.includes(entry.ending) &&
|
|
835
|
+
!persons
|
|
836
|
+
)
|
|
837
|
+
findings.push(
|
|
838
|
+
finding(
|
|
839
|
+
[...keyPath, j],
|
|
840
|
+
`\`${label}\` writes the ending \`${entry.ending}\`, and \`data.grammar.verbs\` ` +
|
|
841
|
+
"states no `persons`",
|
|
842
|
+
),
|
|
843
|
+
);
|
|
844
|
+
const slot = `${entry.ending ?? ""}\u0000${entry.map}\u0000${entry.font ?? ""}`;
|
|
654
845
|
if (stated.has(slot))
|
|
655
846
|
findings.push(
|
|
656
847
|
finding(
|
|
657
|
-
[
|
|
658
|
-
`\`${label}\` states a second native form
|
|
848
|
+
[...keyPath, j],
|
|
849
|
+
`\`${label}\` states a second native form` +
|
|
850
|
+
(kind === "ending" ? ` of the ending \`${entry.ending}\`` : "") +
|
|
851
|
+
` for the map \`${map.name}\`` +
|
|
659
852
|
(entry.font === undefined ? "" : ` in the font \`${entry.font}\``) +
|
|
660
|
-
`; the first is
|
|
853
|
+
`; the first is \`${base}[${stated.get(slot)}]\``,
|
|
661
854
|
),
|
|
662
855
|
);
|
|
663
856
|
else stated.set(slot, j);
|
|
@@ -665,10 +858,14 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
665
858
|
entry.font !== undefined ? [entry.font]
|
|
666
859
|
: map.fonts.size ? [...map.fonts.keys()]
|
|
667
860
|
: [undefined];
|
|
668
|
-
if (
|
|
861
|
+
if (
|
|
862
|
+
kind === "word" &&
|
|
863
|
+
!map.logographic &&
|
|
864
|
+
fonts.every((font) => applyMap(map, form, { font }).text === entry.text)
|
|
865
|
+
)
|
|
669
866
|
findings.push(
|
|
670
867
|
finding(
|
|
671
|
-
[
|
|
868
|
+
[...keyPath, j],
|
|
672
869
|
`\`${label}\` states what the rows already give: the map \`${map.name}\` ` +
|
|
673
870
|
`spells \`${form}\` so ` +
|
|
674
871
|
(entry.font !== undefined ? `in the font \`${entry.font}\``
|
|
@@ -686,7 +883,11 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
686
883
|
: [...map.fonts.keys()].filter(
|
|
687
884
|
(font) =>
|
|
688
885
|
!entries.some(
|
|
689
|
-
(other) =>
|
|
886
|
+
(other) =>
|
|
887
|
+
other &&
|
|
888
|
+
other.map === entry.map &&
|
|
889
|
+
other.ending === entry.ending &&
|
|
890
|
+
other.font === font,
|
|
690
891
|
),
|
|
691
892
|
);
|
|
692
893
|
for (const slug of applies) {
|
|
@@ -699,7 +900,7 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
699
900
|
seen.add(point);
|
|
700
901
|
findings.push(
|
|
701
902
|
finding(
|
|
702
|
-
[
|
|
903
|
+
[...keyPath, j],
|
|
703
904
|
`\`${label}\` holds ${codeName(point)}, which the font \`${slug}\`, ` +
|
|
704
905
|
`listed in the map \`${map.name}\`, does not draw`,
|
|
705
906
|
),
|
|
@@ -707,7 +908,21 @@ export function checkLexiconNatives(note, ctx) {
|
|
|
707
908
|
}
|
|
708
909
|
}
|
|
709
910
|
});
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
listOf(fm.data.words).forEach((word, i) => {
|
|
914
|
+
if (!isMap(word) || !Array.isArray(word.native)) return;
|
|
915
|
+
checkList(word.native, ["words", i, "native"], {
|
|
916
|
+
kind: "word",
|
|
917
|
+
form: typeof word.form === "string" ? word.form : "",
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
listOf(fm.data.affixes).forEach((affix, i) => {
|
|
921
|
+
if (isMap(affix) && Array.isArray(affix.native))
|
|
922
|
+
checkList(affix.native, ["affixes", i, "native"], { kind: "affix" });
|
|
710
923
|
});
|
|
924
|
+
if (isMap(fm.data.grammar) && Array.isArray(fm.data.grammar.native))
|
|
925
|
+
checkList(fm.data.grammar.native, ["grammar", "native"], { kind: "ending" });
|
|
711
926
|
return findings;
|
|
712
927
|
}
|
|
713
928
|
|
package/engine/map-places.mjs
CHANGED
|
@@ -131,12 +131,13 @@ function parentShortcode(parent) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
* A `parents
|
|
134
|
+
* A list of places — `parents`, a being's `homes`, a scenario's `locations` —
|
|
135
|
+
* as their shortcodes.
|
|
135
136
|
*
|
|
136
137
|
* @param {unknown} value - The authored value, a list or a lone entry.
|
|
137
138
|
* @returns {string[]} Shortcodes, lower case, empties dropped.
|
|
138
139
|
*/
|
|
139
|
-
function
|
|
140
|
+
export function placeShortcodes(value) {
|
|
140
141
|
const list =
|
|
141
142
|
Array.isArray(value) ? value
|
|
142
143
|
: value ? [value]
|
|
@@ -198,7 +199,7 @@ export function placesFromRecords(records, { contentBase, base }) {
|
|
|
198
199
|
name,
|
|
199
200
|
type: "place",
|
|
200
201
|
subType: record.subType === undefined ? undefined : String(record.subType),
|
|
201
|
-
parents:
|
|
202
|
+
parents: placeShortcodes(data.parents),
|
|
202
203
|
borders: relationList(data.borders),
|
|
203
204
|
routes: relationList(data.routes),
|
|
204
205
|
address: record.address?.canonical,
|
|
@@ -251,7 +252,7 @@ function addForeignPlaces(world, foreignIndex) {
|
|
|
251
252
|
name: String(entry.name ?? shortcode),
|
|
252
253
|
type: "place",
|
|
253
254
|
subType: entry.subType === undefined ? undefined : String(entry.subType),
|
|
254
|
-
parents:
|
|
255
|
+
parents: placeShortcodes(entry.parents),
|
|
255
256
|
borders: relationList(entry.borders),
|
|
256
257
|
routes: relationList(entry.routes),
|
|
257
258
|
address: canonical,
|
|
@@ -25,8 +25,6 @@ import { noteCalendar } from "./note-calendars.mjs";
|
|
|
25
25
|
/**
|
|
26
26
|
* An inline expression, as an author writes one.
|
|
27
27
|
*
|
|
28
|
-
* Hugo shortcodes begin `{{<` or `{{%` and stay in the source for Hugo.
|
|
29
|
-
*
|
|
30
28
|
* Exported because a renderer that meets one has met a body this pass never ran
|
|
31
29
|
* over, and has to be able to say so.
|
|
32
30
|
*
|
|
@@ -51,11 +51,16 @@ import {
|
|
|
51
51
|
printParseErrorCode,
|
|
52
52
|
} from "jsonc-parser";
|
|
53
53
|
import markdownIt from "markdown-it";
|
|
54
|
-
import { applyFixes, resolveModule } from "markdownlint";
|
|
55
|
-
import { extendConfig, lint, readConfig } from "markdownlint/promise";
|
|
56
54
|
import { minimatch } from "minimatch";
|
|
57
55
|
import { LineCounter, parse as parseYaml, parseDocument } from "yaml";
|
|
58
56
|
|
|
57
|
+
import {
|
|
58
|
+
applyFixes,
|
|
59
|
+
extendConfig,
|
|
60
|
+
lint,
|
|
61
|
+
readConfig,
|
|
62
|
+
resolveModule,
|
|
63
|
+
} from "../vendor/markdownlint.mjs";
|
|
59
64
|
import { walkFiles } from "./walk-files.mjs";
|
|
60
65
|
|
|
61
66
|
/** Option-file names, in the order the first existing one is taken. */
|
|
@@ -313,7 +318,8 @@ async function validateOptions(file, text, raw, isRoot) {
|
|
|
313
318
|
*/
|
|
314
319
|
async function extendRules(file, config) {
|
|
315
320
|
try {
|
|
316
|
-
|
|
321
|
+
// `extendConfig`, unlike `readConfig`, has no default file system.
|
|
322
|
+
return await extendConfig(config, file, [...CONFIG_PARSERS], fs);
|
|
317
323
|
} catch (err) {
|
|
318
324
|
throw new MarkdownConfigError(file, `cannot resolve \`extends\`: ${err.message}`);
|
|
319
325
|
}
|
|
@@ -14,6 +14,26 @@
|
|
|
14
14
|
import { scanBlocks } from "./content-blocks.mjs";
|
|
15
15
|
import { scanAlerts } from "./content-alerts.mjs";
|
|
16
16
|
import { scanRuns } from "./content-scripts.mjs";
|
|
17
|
+
import { matchAllOutsideCode } from "./code-fences.mjs";
|
|
18
|
+
|
|
19
|
+
/** The opening of a shortcode: `{{<` or `{{%`. */
|
|
20
|
+
const SHORTCODE = /\{\{[<%]/g;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Locate every shortcode outside code.
|
|
24
|
+
* @param {string} body - Markdown with its frontmatter masked.
|
|
25
|
+
* @returns {Array<{line: number, column: number, message: string}>} One error per shortcode.
|
|
26
|
+
*/
|
|
27
|
+
function shortcodeErrors(body) {
|
|
28
|
+
return matchAllOutsideCode(body, SHORTCODE).map((match) => {
|
|
29
|
+
const before = body.slice(0, match.index);
|
|
30
|
+
return {
|
|
31
|
+
line: before.split("\n").length,
|
|
32
|
+
column: match.index - before.lastIndexOf("\n"),
|
|
33
|
+
message: "A shortcode is not supported; write `[x]{.glyph}` or `[signs]{.cartouche}`",
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
17
37
|
|
|
18
38
|
/**
|
|
19
39
|
* Validate authored block syntax with positions in the original file.
|
|
@@ -39,6 +59,7 @@ export function markupFindings(source, file, syntax, runs) {
|
|
|
39
59
|
...(scanned?.blocks ?? scanBlocks(body)).errors,
|
|
40
60
|
...(scanned?.alerts ?? scanAlerts(body)).errors,
|
|
41
61
|
...(marked?.errors ?? []),
|
|
62
|
+
...shortcodeErrors(body),
|
|
42
63
|
].map((error) => ({
|
|
43
64
|
file,
|
|
44
65
|
...error,
|