@heroiclands/package-build 23.13.0 → 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 +36 -0
- package/README.md +2 -1
- package/assets/preview/gitea.ini +12 -7
- package/assets/styles/content-base.css +150 -1
- package/bin/content-commands.mjs +356 -210
- 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 +93 -72
- package/docs/authoring/links-and-markup.md +316 -78
- package/docs/commands.md +244 -78
- package/docs/configuration.md +210 -102
- package/docs/content-format.md +2 -2
- package/docs/diagnostics.md +2 -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 +589 -308
- package/docs/reference/note-types.md +40 -10
- package/docs/reference/theme-pages.md +127 -108
- package/docs/source-preview.md +15 -1
- package/engine/asset-shipping.mjs +22 -10
- package/engine/base-compiler.mjs +62 -104
- package/engine/changelog-lint.mjs +1 -1
- package/engine/content-address.mjs +1 -1
- package/engine/content-alerts.mjs +8 -4
- package/engine/content-blocks.mjs +26 -11
- package/engine/content-embeds.mjs +1 -1
- package/engine/content-expand.mjs +376 -0
- package/engine/content-figures.mjs +13 -6
- package/engine/content-format.yaml +8 -0
- package/engine/content-glyphs.mjs +213 -0
- package/engine/content-images.mjs +6 -7
- 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 +326 -27
- package/engine/content-spans.mjs +4 -1
- package/engine/content-styles.mjs +91 -0
- package/engine/content-symbols.mjs +186 -0
- package/engine/content-verse.mjs +6 -18
- package/engine/core-report.mjs +169 -0
- package/engine/core-vocabulary.mjs +208 -0
- package/engine/dictionary-html.mjs +119 -0
- package/engine/field-reference.mjs +1 -1
- 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/language-rows.mjs +8 -2
- package/engine/language-terms.mjs +115 -14
- package/engine/language-words.mjs +12 -0
- package/engine/logographic.mjs +255 -0
- package/engine/map-lexicon.mjs +221 -25
- 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/note-matter.mjs +2 -2
- package/engine/note-vocabulary.mjs +187 -3
- package/engine/pdf-build.mjs +68 -133
- package/engine/pdf-render.mjs +102 -44
- 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/run-words.mjs +3 -2
- 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 +259 -314
- 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 +50 -523
- 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/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 +39 -24
- package/engine/word-rows.mjs +12 -2
- package/engine/word-terms.mjs +29 -4
- package/manifest.mjs +3 -4
- package/package.json +10 -7
- 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 +14 -0
- 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/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 +62 -0
- 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/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/field-reference.d.mts +1 -1
- 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/language-terms.d.mts +24 -2
- package/types/engine/logographic.d.mts +45 -0
- package/types/engine/map-lexicon.d.mts +48 -8
- 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/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/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/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 +3 -2
- 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/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/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
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The syllables of a word, each as the vowel group that makes it.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} word - The word.
|
|
5
|
+
* @param {Iterable<string>} pairs - The vowel pairs that are one syllable.
|
|
6
|
+
* @returns {string[]} The nuclei, in order; none for a word with no vowel.
|
|
7
|
+
*/
|
|
8
|
+
export function nucleiOf(word: string, pairs: Iterable<string>): string[];
|
|
9
|
+
/**
|
|
10
|
+
* The index of the stressed syllable of a word.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} word - The word.
|
|
13
|
+
* @param {{two: string, longer: string, mark?: string}} rule - The language's
|
|
14
|
+
* `data.sounds.stress`.
|
|
15
|
+
* @param {Iterable<string>} pairs - The vowel pairs that are one syllable.
|
|
16
|
+
* @returns {number} The 0-based syllable; 0 for a word of one syllable or none.
|
|
17
|
+
*/
|
|
18
|
+
export function stressIndex(word: string, rule: {
|
|
19
|
+
two: string;
|
|
20
|
+
longer: string;
|
|
21
|
+
mark?: string;
|
|
22
|
+
}, pairs: Iterable<string>): number;
|
|
23
|
+
/**
|
|
24
|
+
* Each configured language's metre book: one per language whose `note` names a
|
|
25
|
+
* language note stating a complete `data.sounds.stress`.
|
|
26
|
+
*
|
|
27
|
+
* @param {Iterable<Record<string, any>>|undefined} records - Index records.
|
|
28
|
+
* @param {{languages?: Readonly<Record<string, {tag: string, note?: string}>>, contentPackage?: string}} config -
|
|
29
|
+
* The resolved configuration.
|
|
30
|
+
* @returns {Map<string, MetreBook>} The books by language name.
|
|
31
|
+
*/
|
|
32
|
+
export function metreBooksFromRecords(records: Iterable<Record<string, any>> | undefined, config?: {
|
|
33
|
+
languages?: Readonly<Record<string, {
|
|
34
|
+
tag: string;
|
|
35
|
+
note?: string;
|
|
36
|
+
}>>;
|
|
37
|
+
contentPackage?: string;
|
|
38
|
+
}): Map<string, MetreBook>;
|
|
39
|
+
/**
|
|
40
|
+
* Every metre the index's `doc` notes declare, by name. The first note to
|
|
41
|
+
* declare a name keeps it.
|
|
42
|
+
*
|
|
43
|
+
* @param {Iterable<Record<string, any>>|undefined} records - Index records.
|
|
44
|
+
* @returns {Map<string, import("./metre-declaration.mjs").Metre>} The metres.
|
|
45
|
+
*/
|
|
46
|
+
export function metresFromRecords(records: Iterable<Record<string, any>> | undefined): Map<string, import("./metre-declaration.mjs").Metre>;
|
|
47
|
+
/**
|
|
48
|
+
* The beats a line of verse can have.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} text - The line.
|
|
51
|
+
* @param {MetreBook} book - The line's language's book.
|
|
52
|
+
* @returns {{min: number, max: number}} The beats without the second beats a
|
|
53
|
+
* long word may take, and with all of them.
|
|
54
|
+
*/
|
|
55
|
+
export function lineBeats(text: string, book: MetreBook): {
|
|
56
|
+
min: number;
|
|
57
|
+
max: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* The warning for a line that cannot have its metre's beats.
|
|
61
|
+
*
|
|
62
|
+
* @param {{min: number, max: number}} beats - The line's beats.
|
|
63
|
+
* @param {import("./metre-declaration.mjs").Metre} metre - The fence's metre.
|
|
64
|
+
* @returns {string} The message.
|
|
65
|
+
*/
|
|
66
|
+
export function metreMessage({ min, max }: {
|
|
67
|
+
min: number;
|
|
68
|
+
max: number;
|
|
69
|
+
}, metre: import("./metre-declaration.mjs").Metre): string;
|
|
70
|
+
/**
|
|
71
|
+
* Check the verse fences that state `scan=`.
|
|
72
|
+
*
|
|
73
|
+
* @param {ReadonlyArray<{start: number, end: number, indent: string, attributes: Record<string, string>, classes: string[]}>} blocks -
|
|
74
|
+
* The fences, from {@link module:engine/content-verse.scanVerse}.
|
|
75
|
+
* @param {string[]} lines - The source's lines.
|
|
76
|
+
* @param {{metres?: ReadonlyMap<string, import("./metre-declaration.mjs").Metre>, metreBooks?: ReadonlyMap<string, MetreBook>, lexicons?: ReadonlyMap<string, unknown>, columnsClass: string, columnKeys: readonly string[], attributeColumns: (line: string, key: string) => {key: number, value: number}}} ctx -
|
|
77
|
+
* The metres and books, and how the fence says its columns and where its
|
|
78
|
+
* keys sit.
|
|
79
|
+
* @returns {{errors: object[], warnings: object[]}} The findings at 1-based
|
|
80
|
+
* positions.
|
|
81
|
+
*/
|
|
82
|
+
export function metreFindings(blocks: ReadonlyArray<{
|
|
83
|
+
start: number;
|
|
84
|
+
end: number;
|
|
85
|
+
indent: string;
|
|
86
|
+
attributes: Record<string, string>;
|
|
87
|
+
classes: string[];
|
|
88
|
+
}>, lines: string[], ctx: {
|
|
89
|
+
metres?: ReadonlyMap<string, import("./metre-declaration.mjs").Metre>;
|
|
90
|
+
metreBooks?: ReadonlyMap<string, MetreBook>;
|
|
91
|
+
lexicons?: ReadonlyMap<string, unknown>;
|
|
92
|
+
columnsClass: string;
|
|
93
|
+
columnKeys: readonly string[];
|
|
94
|
+
attributeColumns: (line: string, key: string) => {
|
|
95
|
+
key: number;
|
|
96
|
+
value: number;
|
|
97
|
+
};
|
|
98
|
+
}): {
|
|
99
|
+
errors: object[];
|
|
100
|
+
warnings: object[];
|
|
101
|
+
};
|
|
102
|
+
/** The bases whose one-syllable words carry a beat. */
|
|
103
|
+
export const BEAT_BASES: readonly string[];
|
|
104
|
+
/**
|
|
105
|
+
* What a language's lines are counted by.
|
|
106
|
+
*/
|
|
107
|
+
export type MetreBook = {
|
|
108
|
+
/**
|
|
109
|
+
* - The language's configured name.
|
|
110
|
+
*/
|
|
111
|
+
language: string;
|
|
112
|
+
/**
|
|
113
|
+
* - Its stress rule.
|
|
114
|
+
*/
|
|
115
|
+
rule: {
|
|
116
|
+
two: string;
|
|
117
|
+
longer: string;
|
|
118
|
+
mark?: string;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* - Its vowel pairs.
|
|
122
|
+
*/
|
|
123
|
+
pairs: ReadonlySet<string>;
|
|
124
|
+
/**
|
|
125
|
+
* - Each lexicon
|
|
126
|
+
* form, and each form its rules derive, folded, with the class bases of its
|
|
127
|
+
* entries.
|
|
128
|
+
*/
|
|
129
|
+
classes: ReadonlyMap<string, ReadonlySet<string>>;
|
|
130
|
+
};
|
|
131
|
+
export { METRE_KINDS, METRE_NAME, checkMetresField } from "./metre-declaration.mjs";
|
|
@@ -36,12 +36,8 @@ export function parseWikilink(rawInner: string, literal?: string): ParsedWikilin
|
|
|
36
36
|
* `[[x|]]` is labelled and `[[x]]` is not, and only the first addresses
|
|
37
37
|
* anything.
|
|
38
38
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* the web tested `??` — which falls through on `null` only — and emitted
|
|
42
|
-
* `[](/url/)`, a link with no clickable text, through every build. That
|
|
43
|
-
* is the same drift this module exists to prevent, in the case its own
|
|
44
|
-
* {@link ParsedWikilink} docstring calls out. One reading, one place.
|
|
39
|
+
* Read with `??`, which falls through on `null` only, an empty label would
|
|
40
|
+
* emit `[](/url/)`: a link with no clickable text. One reading, one place.
|
|
45
41
|
*
|
|
46
42
|
* @param {{display: string|null}} parsed - A parsed wikilink, or anything
|
|
47
43
|
* carrying its `display`.
|
|
@@ -53,7 +49,7 @@ export function authoredLabel({ display }: {
|
|
|
53
49
|
/**
|
|
54
50
|
* What an author writing an unlabelled link is told, in one place.
|
|
55
51
|
*
|
|
56
|
-
* Shared by the link checker
|
|
52
|
+
* Shared by the link checker and the resolver, on every target, because
|
|
57
53
|
* an author meets whichever runs first and they should read the same. It names
|
|
58
54
|
* the form to write rather than a value to correct: there is no value that
|
|
59
55
|
* makes an unlabelled link resolve.
|
|
@@ -99,7 +95,7 @@ export function isEventAnchor(hit: {
|
|
|
99
95
|
*
|
|
100
96
|
* An address naming no note is a typo or an omission: the intent of a
|
|
101
97
|
* placeholder for a note nobody has written yet is spelled as a `draft`-tagged
|
|
102
|
-
* note that exists, resolves and renders marked. Both want fixing, and
|
|
98
|
+
* note that exists, resolves and renders marked. Both want fixing, and every build says so.
|
|
103
99
|
*
|
|
104
100
|
* @param {string} target - The address as authored, named in the message.
|
|
105
101
|
* @returns {string} The message, unpunctuated at the end as a finding is.
|
|
@@ -143,9 +139,9 @@ export function ambiguousAddressMessage(target: string, packages?: Iterable<stri
|
|
|
143
139
|
/**
|
|
144
140
|
* The message for one link finding, whichever resolver found it.
|
|
145
141
|
*
|
|
146
|
-
* The single table the checker
|
|
147
|
-
*
|
|
148
|
-
*
|
|
142
|
+
* The single table the checker and the resolver report through, on every
|
|
143
|
+
* target, so one authored link cannot get different explanations of the same
|
|
144
|
+
* mistake depending on which build the author ran first. Callers
|
|
149
145
|
* add their own context around it — the note's name, the file it sits in — and
|
|
150
146
|
* never their own wording for the defect.
|
|
151
147
|
*
|
|
@@ -181,8 +177,9 @@ export function linkFindingMessage({ reason, target, packages, anchor, type, stu
|
|
|
181
177
|
/**
|
|
182
178
|
* Whether a parsed link addresses a section of the page it is written on.
|
|
183
179
|
*
|
|
184
|
-
* `[[#some-heading]]` — no target, only an anchor.
|
|
185
|
-
* it before consulting any index, because there is nothing to look
|
|
180
|
+
* `[[#some-heading]]` — no target, only an anchor. The resolver and the checker
|
|
181
|
+
* special-case it before consulting any index, because there is nothing to look
|
|
182
|
+
* up.
|
|
186
183
|
*
|
|
187
184
|
* @param {ParsedWikilink} parsed - A parsed wikilink.
|
|
188
185
|
* @returns {boolean} True when the link is same-page.
|
|
@@ -212,36 +209,23 @@ export function presentWikilink(reference: string, parsed: object, destination:
|
|
|
212
209
|
/**
|
|
213
210
|
* What a `[[…]]` **is**, before anything decides where it points.
|
|
214
211
|
*
|
|
215
|
-
* One authored link
|
|
216
|
-
*
|
|
217
|
-
* *only* thing that legitimately differs. The syntax is the
|
|
218
|
-
* the same syntax whichever build is reading it.
|
|
212
|
+
* One authored link is written three ways — a Foundry `@UUID` content link for
|
|
213
|
+
* the packs, a URL for the web, a cross-reference for the book — and those
|
|
214
|
+
* forms are the *only* thing that legitimately differs. The syntax is the
|
|
215
|
+
* author's, and it is the same syntax whichever build is reading it.
|
|
219
216
|
*
|
|
220
|
-
*
|
|
217
|
+
* So the parse lives here, once, and two readers take it: the link checker
|
|
218
|
+
* (`content-links.mjs`) and the resolver (`wikilinks.mjs`). Each receives the
|
|
219
|
+
* parts and decides only what it is for: which document the address names.
|
|
221
220
|
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* The web side's pattern omitted `\n` from the excluded set, so an unclosed
|
|
228
|
-
* bracket consumed everything up to the next `]]` anywhere in the document —
|
|
229
|
-
* the same shape of corruption a hand-rolled code-fence regex caused on the one
|
|
230
|
-
* page whose subject is link syntax. It was also internally
|
|
231
|
-
* inconsistent: its *frontmatter* scan excluded newlines while its body scan did
|
|
232
|
-
* not.
|
|
233
|
-
*
|
|
234
|
-
* So the parse lives here, once. A resolver receives the parts and decides only
|
|
235
|
-
* what it is actually for: which document the address names.
|
|
236
|
-
*
|
|
237
|
-
* The one rule about a link's *shape* that both resolvers share also lives here
|
|
238
|
-
* — **a link carries a label** ({@link unlabelledLinkMessage}) — because the
|
|
239
|
-
* two state it through one message and the author reads the same words
|
|
240
|
-
* whichever ran first.
|
|
221
|
+
* The one rule about a link's *shape* also lives here — **a link carries a
|
|
222
|
+
* label** ({@link unlabelledLinkMessage}) — because every build states it
|
|
223
|
+
* through one message and the author reads the same words whichever ran
|
|
224
|
+
* first.
|
|
241
225
|
*
|
|
242
226
|
* For the same reason, so does the **vocabulary of link findings**
|
|
243
227
|
* ({@link LINK_FINDING_REASONS}) and the message each one reports through
|
|
244
|
-
* ({@link linkFindingMessage}).
|
|
228
|
+
* ({@link linkFindingMessage}). Every build reads one authored link; an author
|
|
245
229
|
* meets whichever ran first, and a consumer switching on a `reason` should not
|
|
246
230
|
* be switching on which build produced it.
|
|
247
231
|
*
|
|
@@ -258,20 +242,18 @@ export function presentWikilink(reference: string, parsed: object, destination:
|
|
|
258
242
|
* **A leading `!` makes it an embed, not a link**, and the lookbehind is what
|
|
259
243
|
* keeps every reader from seeing one as the other. Stated here rather than in
|
|
260
244
|
* each reader for the reason the rest of this module exists: the checker, the
|
|
261
|
-
*
|
|
262
|
-
*
|
|
245
|
+
* resolver and the embed reader all match on this pattern, and a copy of the
|
|
246
|
+
* exclusion in each is a place for it to be forgotten. An embed's
|
|
263
247
|
* own grammar is {@link module:engine/content-embeds}.
|
|
264
248
|
*/
|
|
265
249
|
export const WIKILINK: RegExp;
|
|
266
250
|
/**
|
|
267
|
-
* Every way a link can fail, named once for
|
|
268
|
-
*
|
|
269
|
-
* A link is read
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* consumer switching on a `reason` was switching on which build had produced
|
|
274
|
-
* it. The set is closed and lives here, beside the syntax the three share.
|
|
251
|
+
* Every way a link can fail, named once for every reader of a link.
|
|
252
|
+
*
|
|
253
|
+
* A link is read by the checker (`content-links.mjs`) and by the resolver
|
|
254
|
+
* (`wikilinks.mjs`) for every target, and each names a failure by one of these
|
|
255
|
+
* reasons, so a consumer switching on a `reason` never switches on which build
|
|
256
|
+
* produced it. The set is closed and lives here, beside the syntax they share.
|
|
275
257
|
*
|
|
276
258
|
* - `unlabelled` — no `|`, so the link addresses nothing.
|
|
277
259
|
* - `not-an-address` — labelled, but the target does not parse as an address.
|
|
@@ -69,19 +69,86 @@ export function buildWikilinkIndex(docs: Array<{
|
|
|
69
69
|
types: Set<string>;
|
|
70
70
|
};
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* Resolve every wikilink in a markdown body, and write each in one target's
|
|
73
|
+
* form.
|
|
73
74
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
75
|
+
* The one link resolver. The two indexes a link is read against differ, and
|
|
76
|
+
* only that differs, so the index is a {@link LinkView} and the target a
|
|
77
|
+
* writer: {@link convertWikilinks} and {@link resolveWebWikilinks} are this,
|
|
78
|
+
* with their own view and writer.
|
|
77
79
|
*
|
|
78
80
|
* **Code is verbatim.** A `[[…]]` inside a fenced or indented code block, or
|
|
79
81
|
* inside an inline code span, is source text an author wrote to be read as
|
|
80
|
-
* written, so it is left alone and not reported. Without that, a
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* written, so it is left alone and not reported. Without that, a script sample
|
|
83
|
+
* containing `grid[[0]]` would become a link — and only for some array shapes,
|
|
84
|
+
* `[[1,2],[3,4]]` having an inner `]` the pattern cannot cross.
|
|
85
|
+
*
|
|
86
|
+
* **Every failure is a finding**, classified into the vocabulary
|
|
87
|
+
* {@link LINK_FINDING_REASONS} names for every reader of a link. A finding
|
|
88
|
+
* keeps the link's `offset` in `markdown` and its `occurrence` — the how-many-th
|
|
89
|
+
* finding on that literal — so a caller can report the line and column it sits
|
|
90
|
+
* on by either.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} markdown - The body.
|
|
93
|
+
* @param {object} opts
|
|
94
|
+
* @param {LinkView} opts.view - The index the links resolve against.
|
|
95
|
+
* @param {(link: ResolvedLink) => string} opts.write - The target's writer,
|
|
96
|
+
* from {@link LINK_WRITERS}.
|
|
97
|
+
* @param {Map<string, string>} [opts.captionLabels] - Numbered caption labels.
|
|
98
|
+
* @returns {{markdown: string, links: ResolvedLink[], findings: Array<{link:
|
|
99
|
+
* string, offset: number, occurrence: number, target: string, reason:
|
|
100
|
+
* string}>, resolved: object[]}} The written body; every link in body order;
|
|
101
|
+
* the findings; and every destination a link outside its own page resolved
|
|
102
|
+
* to, in body order, repeats included — the page's edges.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveWikilinks(markdown: string, { view, write, captionLabels }: {
|
|
105
|
+
view: LinkView;
|
|
106
|
+
write: (link: ResolvedLink) => string;
|
|
107
|
+
captionLabels?: Map<string, string> | undefined;
|
|
108
|
+
}): {
|
|
109
|
+
markdown: string;
|
|
110
|
+
links: ResolvedLink[];
|
|
111
|
+
findings: Array<{
|
|
112
|
+
link: string;
|
|
113
|
+
offset: number;
|
|
114
|
+
occurrence: number;
|
|
115
|
+
target: string;
|
|
116
|
+
reason: string;
|
|
117
|
+
}>;
|
|
118
|
+
resolved: object[];
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* The pack compile's view of a link: {@link buildWikilinkIndex}'s index,
|
|
122
|
+
* answered with compendium UUIDs.
|
|
123
|
+
*
|
|
124
|
+
* `[[type-shortcode|Text]]` defaults to the readable `note` Address. A stated
|
|
125
|
+
* game system names an Actor or Item; `none` names a systemless document.
|
|
126
|
+
* `doc<type>` names the readable note of an item. A journal link may carry a
|
|
127
|
+
* heading anchor, which addresses the journal's page for it; an Actor, Item or
|
|
128
|
+
* Macro link opens a sheet, which has no sections, so its anchor addresses
|
|
129
|
+
* nothing and is dropped.
|
|
130
|
+
*
|
|
131
|
+
* @param {object} index - From {@link buildWikilinkIndex}.
|
|
132
|
+
* @param {object} source - The note the links are written on.
|
|
133
|
+
* @param {string} source.type - Its type.
|
|
134
|
+
* @param {string} source.id - Its document id.
|
|
135
|
+
* @param {string} [source.pack] - The pack its own document lands in.
|
|
136
|
+
* @param {string} [source.docPack] - The pack its documentation entry lands in.
|
|
137
|
+
* @returns {LinkView} The view.
|
|
138
|
+
*/
|
|
139
|
+
export function packLinkView(index: object, { type, id, pack, docPack }: {
|
|
140
|
+
type: string;
|
|
141
|
+
id: string;
|
|
142
|
+
pack?: string | undefined;
|
|
143
|
+
docPack?: string | undefined;
|
|
144
|
+
}): LinkView;
|
|
145
|
+
/**
|
|
146
|
+
* Rewrites every wikilink in a markdown body as a Foundry UUID enricher — see
|
|
147
|
+
* {@link resolveWikilinks}, with the pack compile's {@link packLinkView} and
|
|
148
|
+
* the `foundry` {@link LINK_WRITERS} entry.
|
|
149
|
+
*
|
|
150
|
+
* A link that cannot be resolved renders marked and is reported in
|
|
151
|
+
* `unresolved`.
|
|
85
152
|
*
|
|
86
153
|
* @param {string} markdown - The note body (frontmatter already stripped).
|
|
87
154
|
* @param {object} ctx
|
|
@@ -96,10 +163,10 @@ export function buildWikilinkIndex(docs: Array<{
|
|
|
96
163
|
* @param {{byShortcode: Map, types: Set}} ctx.index - From
|
|
97
164
|
* {@link buildWikilinkIndex}.
|
|
98
165
|
* @param {Map<string, string>} [ctx.captionLabels] - Numbered caption references.
|
|
99
|
-
* @returns {{markdown: string, unresolved: Array<{link:
|
|
100
|
-
* offset: number, reason: string, packages?:
|
|
101
|
-
* Each `reason` is one of
|
|
102
|
-
*
|
|
166
|
+
* @returns {{markdown: string, links: ResolvedLink[], unresolved: Array<{link:
|
|
167
|
+
* string, target: string, offset: number, reason: string, packages?:
|
|
168
|
+
* string[], anchor?: string}>}} Each `reason` is one of
|
|
169
|
+
* {@link LINK_FINDING_REASONS} — `ambiguous` carries the claiming `packages`
|
|
103
170
|
* and `unknown-anchor` the section it named. `offset` is the link's 0-based
|
|
104
171
|
* position in `markdown`, which is what lets a caller report the line and
|
|
105
172
|
* column it sits on.
|
|
@@ -116,6 +183,7 @@ export function convertWikilinks(markdown: string, { type, id, pack, docPack, in
|
|
|
116
183
|
captionLabels?: Map<string, string> | undefined;
|
|
117
184
|
}): {
|
|
118
185
|
markdown: string;
|
|
186
|
+
links: ResolvedLink[];
|
|
119
187
|
unresolved: Array<{
|
|
120
188
|
link: string;
|
|
121
189
|
target: string;
|
|
@@ -148,9 +216,257 @@ export function resolveReference(index: object, ref: unknown, hint?: object): {
|
|
|
148
216
|
subType?: string;
|
|
149
217
|
standings?: object;
|
|
150
218
|
} | undefined;
|
|
219
|
+
/**
|
|
220
|
+
* The website's and the book's view of a link: the site index, answered with
|
|
221
|
+
* URLs.
|
|
222
|
+
*
|
|
223
|
+
* The site index is keyed case-insensitively by the canonical
|
|
224
|
+
* `package-system-type-shortcode` address, by `type/shortcode` and by the
|
|
225
|
+
* site's own `section/slug`; a fully qualified address another package
|
|
226
|
+
* publishes is looked up in its fetched index. Local wins: a live build is
|
|
227
|
+
* authoritative and a fetched index can only be staler. A short address two
|
|
228
|
+
* packages claim is in the index's `ambiguous` set, and is a finding of its
|
|
229
|
+
* own.
|
|
230
|
+
*
|
|
231
|
+
* A target that **resolved** to an entry with no page is not unresolved: a
|
|
232
|
+
* pack-only package publishes Foundry addresses and no web pages, so the
|
|
233
|
+
* author wrote a real address and there is simply nothing to link to.
|
|
234
|
+
*
|
|
235
|
+
* @param {object} ctx - What {@link module:engine/site-index.wikiContext}
|
|
236
|
+
* returns, with the page's own `anchors` and `eventAnchors`.
|
|
237
|
+
* @param {string} body - The page's text, which a link to its own section is
|
|
238
|
+
* concealed by when the section is secret.
|
|
239
|
+
* @returns {LinkView} The view.
|
|
240
|
+
*/
|
|
241
|
+
export function siteLinkView(ctx: object, body: string): LinkView;
|
|
242
|
+
/**
|
|
243
|
+
* Every wikilink authored inside a frontmatter value.
|
|
244
|
+
*
|
|
245
|
+
* Wikilinks are resolved in a note's **body**. Frontmatter is not markdown and
|
|
246
|
+
* is never walked by the resolver, so a link written in one would be copied
|
|
247
|
+
* through verbatim and reach the reader as literal `[[…]]` text, in whatever the
|
|
248
|
+
* theme renders that field as (an infobox row, a description, a card
|
|
249
|
+
* subtitle). Nothing downstream notices: the value is a valid string, the page
|
|
250
|
+
* builds, and the defect is visible only to someone who looks at it.
|
|
251
|
+
*
|
|
252
|
+
* So the form is refused rather than resolved. Resolving it would mean choosing
|
|
253
|
+
* an output syntax for a field whose renderer is unknown to this build — a
|
|
254
|
+
* markdown link is inert in a template that prints the value as text, and an
|
|
255
|
+
* `<a>` is unusable in one that escapes it — and would quietly bless an
|
|
256
|
+
* authoring habit that the pack build has no way to honour at all. Frontmatter
|
|
257
|
+
* carries data; a link belongs in prose.
|
|
258
|
+
*
|
|
259
|
+
* Values are read from the *parsed* frontmatter, so a `[[` inside a YAML comment
|
|
260
|
+
* is not a hit, and every hit can be named by the path a reader would look at.
|
|
261
|
+
*
|
|
262
|
+
* @param {unknown} fm - Parsed frontmatter, as `readMatter` returns it.
|
|
263
|
+
* @returns {Array<{path: string, link: string}>} In reading order; `path` is the
|
|
264
|
+
* dotted key path of the offending value (`government.summary`, `aliases.1`).
|
|
265
|
+
*/
|
|
266
|
+
export function frontmatterWikilinks(fm: unknown): Array<{
|
|
267
|
+
path: string;
|
|
268
|
+
link: string;
|
|
269
|
+
}>;
|
|
270
|
+
/**
|
|
271
|
+
* Rewrites the embeds and wikilinks in a markdown body for the website or the
|
|
272
|
+
* book — see {@link resolveWikilinks}, with {@link siteLinkView} and the `web`
|
|
273
|
+
* or `book` {@link LINK_WRITERS} entry.
|
|
274
|
+
*
|
|
275
|
+
* `[[type-shortcode|Text]]` → `[Text](/section/slug/)`
|
|
276
|
+
* `[[type-shortcode|]]` → the same, showing the target's own name
|
|
277
|
+
* `[[type-shortcode#slug|Text]]` → `[Text](/section/slug/#slug)`
|
|
278
|
+
* `[[#slug|Text]]` → `[Text](#slug)`
|
|
279
|
+
*
|
|
280
|
+
* **Every target that resolves nowhere fails the build.** Failures are
|
|
281
|
+
* collected in `ctx.errors`, each carrying the authored `link` and its
|
|
282
|
+
* `occurrence` so a caller can report the line and column it sits on. The
|
|
283
|
+
* link still renders, marked: the mark is for whoever reads the page, the
|
|
284
|
+
* failure for its author.
|
|
285
|
+
*
|
|
286
|
+
* ## Embeds first, and they are not links
|
|
287
|
+
*
|
|
288
|
+
* `![[address|label]]` names a file rather than a note, so it is resolved into
|
|
289
|
+
* an ordinary markdown image before anything looks for a link — which is what
|
|
290
|
+
* stops the link pass reading an embed's interior as a link to a note nobody
|
|
291
|
+
* wrote. The image the rewrite leaves behind is what
|
|
292
|
+
* {@link module:engine/content-images.renderImageFigures} turns into a figure
|
|
293
|
+
* for the website, and what the book reads its staging list out of.
|
|
294
|
+
*
|
|
295
|
+
* ## Every hit is recorded, so the page's edges come out of one pass
|
|
296
|
+
*
|
|
297
|
+
* A caller that hands in `ctx.resolved` is given every index entry a link on
|
|
298
|
+
* the page resolved to, in body order, repeats included. Nothing is recorded
|
|
299
|
+
* for a same-page anchor or for a target that resolved nowhere.
|
|
300
|
+
*
|
|
301
|
+
* @param {string} body - The markdown body.
|
|
302
|
+
* @param {object} ctx - `{ index, assets, collide, contentTypes, packages,
|
|
303
|
+
* noIndexPackages, foreign, errors, src, file, resolved, output, anchors,
|
|
304
|
+
* eventAnchors, captionLabels }`, as
|
|
305
|
+
* {@link module:engine/site-index.wikiContext} builds it. `output` is
|
|
306
|
+
* `"book"` for the book and defaults to the website. `anchors` and
|
|
307
|
+
* `eventAnchors` are what *this* page declares, which a `[[#slug]]`
|
|
308
|
+
* self-link is checked against; absent, a self-link is not checked. `src`
|
|
309
|
+
* is the page's display path and `file` the source file a diagnostic names
|
|
310
|
+
* — absent, `src` stands in.
|
|
311
|
+
* @returns {string} The body with embeds and wikilinks rewritten.
|
|
312
|
+
*/
|
|
313
|
+
export function resolveWebWikilinks(body: string, ctx: object): string;
|
|
314
|
+
/**
|
|
315
|
+
* How each target writes a {@link ResolvedLink}.
|
|
316
|
+
*
|
|
317
|
+
* | | `foundry` | `web` | `book` |
|
|
318
|
+
* | --- | --- | --- | --- |
|
|
319
|
+
* | a link | `@UUID[…]{text}`, a content link that survives import into a world | `[text](url)`, the page's relative URL | `[text](url)`, which the book sets as a cross-reference to the entry it prints, or as the page's address where it prints none |
|
|
320
|
+
* | a draft target | the link in a `sohl-draft-link` span | the same span | the link, then `(draft)` |
|
|
321
|
+
* | nothing to open | the text | the text, marked when the target is a draft | the text, then `(draft)` when the target is one |
|
|
322
|
+
* | unresolved | the text in a `sohl-unresolved-link` span | the same span | the text, then `(unresolved link)` |
|
|
323
|
+
*
|
|
324
|
+
* A link to a GM-only note, or to a secret section, is concealed by
|
|
325
|
+
* {@link presentWikilink} on every target alike.
|
|
326
|
+
*
|
|
327
|
+
* Foundry does not mark a link to a note another package publishes as a
|
|
328
|
+
* draft: its `@UUID` names the document the dependency installed, and the
|
|
329
|
+
* dependency's journal is what the reader opens.
|
|
330
|
+
*
|
|
331
|
+
* @type {Readonly<Record<"foundry"|"web"|"book", (link: ResolvedLink) => string>>}
|
|
332
|
+
*/
|
|
333
|
+
export const LINK_WRITERS: Readonly<Record<"foundry" | "web" | "book", (link: ResolvedLink) => string>>;
|
|
334
|
+
/**
|
|
335
|
+
* A wikilink once it is resolved, before any target writes it.
|
|
336
|
+
*
|
|
337
|
+
* This is the link's **neutral form**: what it names and how it reads, with no
|
|
338
|
+
* target's syntax in it. Each target writes it through its own
|
|
339
|
+
* {@link LINK_WRITERS} entry, so one authored link reaches a Foundry journal as
|
|
340
|
+
* an `@UUID` content link, a web page as a relative URL and the book as a
|
|
341
|
+
* cross-reference, from the same resolution.
|
|
342
|
+
*/
|
|
343
|
+
export type ResolvedLink = {
|
|
344
|
+
/**
|
|
345
|
+
* - `link`: the target has a
|
|
346
|
+
* destination the reader can open. `text`: the address is real and names a
|
|
347
|
+
* note with nothing to open — a note with no single Foundry document, or one
|
|
348
|
+
* a package publishing no pages holds — so the reader gets the words.
|
|
349
|
+
* `unresolved`: the link is a finding, and the words are kept, marked.
|
|
350
|
+
*/
|
|
351
|
+
kind: "link" | "text" | "unresolved";
|
|
352
|
+
/**
|
|
353
|
+
* - What the reader sees.
|
|
354
|
+
*/
|
|
355
|
+
text: string;
|
|
356
|
+
/**
|
|
357
|
+
* - The link exactly as authored.
|
|
358
|
+
*/
|
|
359
|
+
literal: string;
|
|
360
|
+
/**
|
|
361
|
+
* - The target as authored, `""` for a link to a
|
|
362
|
+
* section of the same page.
|
|
363
|
+
*/
|
|
364
|
+
target: string;
|
|
365
|
+
/**
|
|
366
|
+
* - The `#section` named, `""` when none.
|
|
367
|
+
*/
|
|
368
|
+
anchor: string;
|
|
369
|
+
/**
|
|
370
|
+
* - Whether it names a section of its own page.
|
|
371
|
+
*/
|
|
372
|
+
samePage: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* - The canonical address it names, the
|
|
375
|
+
* same on every target; `undefined` for a same-page link and for a target
|
|
376
|
+
* that is not an address.
|
|
377
|
+
*/
|
|
378
|
+
address: string | undefined;
|
|
379
|
+
/**
|
|
380
|
+
* - The Foundry document or page it opens.
|
|
381
|
+
*/
|
|
382
|
+
uuid?: string | undefined;
|
|
383
|
+
/**
|
|
384
|
+
* - The URL it opens on the web and in the book,
|
|
385
|
+
* fragment included.
|
|
386
|
+
*/
|
|
387
|
+
href?: string | undefined;
|
|
388
|
+
/**
|
|
389
|
+
* - Whether it names a note tagged `draft`.
|
|
390
|
+
*/
|
|
391
|
+
draft: boolean;
|
|
392
|
+
/**
|
|
393
|
+
* - What it resolved to: an index entry,
|
|
394
|
+
* which decides whether the reference is concealed.
|
|
395
|
+
*/
|
|
396
|
+
destination?: object | undefined;
|
|
397
|
+
/**
|
|
398
|
+
* - The link's parts, from {@link readWikilink}.
|
|
399
|
+
*/
|
|
400
|
+
parsed: object;
|
|
401
|
+
/**
|
|
402
|
+
* - For `unresolved`, what is wrong: a `reason`
|
|
403
|
+
* from {@link LINK_FINDING_REASONS}, the `target` the message names, and the
|
|
404
|
+
* fields that reason carries.
|
|
405
|
+
*/
|
|
406
|
+
finding?: object | undefined;
|
|
407
|
+
};
|
|
408
|
+
/**
|
|
409
|
+
* What one index answers a link with: the half of resolution that depends on
|
|
410
|
+
* which index is read. A pack compile reads {@link buildWikilinkIndex}'s
|
|
411
|
+
* index and answers with UUIDs ({@link packLinkView}); the website and the
|
|
412
|
+
* book read the site index and answer with URLs ({@link siteLinkView}).
|
|
413
|
+
* Everything else — the syntax, the label rule, which failure is which, and
|
|
414
|
+
* the order the checks run in — is {@link resolveWikilinks}'s, once.
|
|
415
|
+
*/
|
|
416
|
+
export type LinkView = {
|
|
417
|
+
/**
|
|
418
|
+
* - The Address context a target is read in:
|
|
419
|
+
* `{package, system, types, packages, noIndexPackages}`.
|
|
420
|
+
*/
|
|
421
|
+
context: object;
|
|
422
|
+
/**
|
|
423
|
+
* - The page the link is written
|
|
424
|
+
* on, as a destination.
|
|
425
|
+
*/
|
|
426
|
+
self: (markdown: string) => object;
|
|
427
|
+
/**
|
|
428
|
+
* - What an address names: a destination, which
|
|
429
|
+
* may be an item's readable note or another package's note; a claim by more
|
|
430
|
+
* than one package; or nothing.
|
|
431
|
+
*/
|
|
432
|
+
find: (read: object, target: string) => ({
|
|
433
|
+
destination: object;
|
|
434
|
+
itemDoc?: boolean;
|
|
435
|
+
foreign?: boolean;
|
|
436
|
+
} | {
|
|
437
|
+
ambiguous: true;
|
|
438
|
+
packages?: string[];
|
|
439
|
+
} | undefined);
|
|
440
|
+
/**
|
|
441
|
+
* - Whether a
|
|
442
|
+
* target that is not an address is a short address two packages claim.
|
|
443
|
+
*/
|
|
444
|
+
collides: (read: object, target: string) => boolean;
|
|
445
|
+
/**
|
|
446
|
+
* - Whether a lowercase
|
|
447
|
+
* spelling of the shortcode names a note.
|
|
448
|
+
*/
|
|
449
|
+
declared: (read: object) => boolean;
|
|
450
|
+
/**
|
|
451
|
+
* - Where a destination opens: a finding reason
|
|
452
|
+
* when the anchor does not belong to it, the UUID or URL it opens, or
|
|
453
|
+
* neither when there is nothing to open.
|
|
454
|
+
*/
|
|
455
|
+
locate: (destination: object, anchor: string, how: {
|
|
456
|
+
samePage: boolean;
|
|
457
|
+
itemDoc?: boolean;
|
|
458
|
+
foreign?: boolean;
|
|
459
|
+
}) => {
|
|
460
|
+
reason?: string;
|
|
461
|
+
uuid?: string;
|
|
462
|
+
href?: string;
|
|
463
|
+
draft?: boolean;
|
|
464
|
+
};
|
|
465
|
+
};
|
|
466
|
+
import { slugify } from "./content-slug.mjs";
|
|
151
467
|
import { ITEM_PACK } from "./ids.mjs";
|
|
152
468
|
import { PACK_BY_TYPE } from "./ids.mjs";
|
|
153
469
|
import { packForType } from "./ids.mjs";
|
|
154
470
|
import { readQualifier } from "./address.mjs";
|
|
155
471
|
import { resolveItemDocType } from "./address.mjs";
|
|
156
|
-
export { ITEM_PACK, PACK_BY_TYPE, packForType, readQualifier, resolveItemDocType };
|
|
472
|
+
export { slugify, ITEM_PACK, PACK_BY_TYPE, packForType, readQualifier, resolveItemDocType };
|
|
@@ -20,8 +20,9 @@ export function addWords(set: Set<string>, text: string): void;
|
|
|
20
20
|
* @property {Record<string, any>} word - The `data.words` entry it comes from.
|
|
21
21
|
*/
|
|
22
22
|
/**
|
|
23
|
-
* Every form the language's rules derive from its lexicon words,
|
|
24
|
-
* `data.words` order, each once, leaving out a
|
|
23
|
+
* Every form the language's rules derive from its lexicon words, and each
|
|
24
|
+
* declared variant of a word, in `data.words` order, each once, leaving out a
|
|
25
|
+
* form that is a lexicon word.
|
|
25
26
|
*
|
|
26
27
|
* @param {Record<string, any>|undefined} data - The language note's `data`.
|
|
27
28
|
* @returns {DerivedForm[]} The forms.
|
package/types/manifest.d.mts
CHANGED
|
@@ -27,10 +27,9 @@ export function normalizeRepoUrl(repository: string | {
|
|
|
27
27
|
* to drift — and the one that drifts is this one, because nothing fetches `url`
|
|
28
28
|
* the way Foundry fetches `manifest`, so a wrong value is never reported.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
* source: it
|
|
32
|
-
*
|
|
33
|
-
* repository keeps its site configuration.
|
|
30
|
+
* `package.json`'s `homepage` says the same thing, and is deliberately not the
|
|
31
|
+
* source: reading it would mean the packaging half depending on the site's
|
|
32
|
+
* configuration.
|
|
34
33
|
*
|
|
35
34
|
* @param {string} contentPackage - The package's content-package name.
|
|
36
35
|
* @returns {string} The homepage URL, with its trailing slash.
|