@wizzlethorpe/vaults 0.13.5 → 0.15.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/README.md +2 -2
- package/dist/asset-refs.js +282 -0
- package/dist/asset-refs.js.map +1 -0
- package/dist/auth.js.map +1 -1
- package/dist/build.js +393 -544
- package/dist/build.js.map +1 -1
- package/dist/commands/build.js +0 -4
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/preview.js +0 -4
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/push.js +4 -9
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/role.js +55 -14
- package/dist/commands/role.js.map +1 -1
- package/dist/config.js +25 -5
- package/dist/config.js.map +1 -1
- package/dist/escape.js +20 -0
- package/dist/escape.js.map +1 -1
- package/dist/foundry-adventure.js +86 -0
- package/dist/foundry-adventure.js.map +1 -0
- package/dist/foundry-defaults.js +65 -0
- package/dist/foundry-defaults.js.map +1 -0
- package/dist/foundry-grafts.js +610 -0
- package/dist/foundry-grafts.js.map +1 -0
- package/dist/foundry-html.js +196 -0
- package/dist/foundry-html.js.map +1 -0
- package/dist/foundry-importer.bundle.js +1192 -322
- package/dist/foundry-importer.js +2 -7
- package/dist/foundry-importer.js.map +1 -1
- package/dist/foundry-meta.js +56 -0
- package/dist/foundry-meta.js.map +1 -0
- package/dist/foundry-module-journal.js +133 -0
- package/dist/foundry-module-journal.js.map +1 -0
- package/dist/foundry-module-render.js +75 -0
- package/dist/foundry-module-render.js.map +1 -0
- package/dist/foundry-module.js +1082 -0
- package/dist/foundry-module.js.map +1 -0
- package/dist/foundry-types.js +28 -0
- package/dist/foundry-types.js.map +1 -0
- package/dist/foundry-version.js +30 -0
- package/dist/foundry-version.js.map +1 -0
- package/dist/frontmatter-defaults.js +68 -0
- package/dist/frontmatter-defaults.js.map +1 -0
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/manifest.js +115 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrate/0.15-foundry-patch-keys.js +51 -0
- package/dist/migrate/0.15-foundry-patch-keys.js.map +1 -0
- package/dist/migrate/0.15-foundry-pinned-id.js +68 -0
- package/dist/migrate/0.15-foundry-pinned-id.js.map +1 -0
- package/dist/migrate/files.js +66 -0
- package/dist/migrate/files.js.map +1 -0
- package/dist/migrate/registry.js +4 -0
- package/dist/migrate/registry.js.map +1 -1
- package/dist/migrate/run.js +36 -2
- package/dist/migrate/run.js.map +1 -1
- package/dist/render/auth-template.js +331 -42
- package/dist/render/auth-template.js.map +1 -1
- package/dist/render/bases.js +22 -38
- package/dist/render/bases.js.map +1 -1
- package/dist/render/cover.js +23 -1
- package/dist/render/cover.js.map +1 -1
- package/dist/render/handlers/assets.js +5 -34
- package/dist/render/handlers/assets.js.map +1 -1
- package/dist/render/handlers/builtin/battlemap.js +4 -1
- package/dist/render/handlers/builtin/battlemap.js.map +1 -1
- package/dist/render/handlers/builtin/download.js +90 -0
- package/dist/render/handlers/builtin/download.js.map +1 -0
- package/dist/render/handlers/builtin/fm-code.js +2 -2
- package/dist/render/handlers/builtin/fm-code.js.map +1 -1
- package/dist/render/handlers/builtin/foundry-manifest.js +158 -0
- package/dist/render/handlers/builtin/foundry-manifest.js.map +1 -0
- package/dist/render/handlers/builtin/fvtt-link.js +39 -0
- package/dist/render/handlers/builtin/fvtt-link.js.map +1 -0
- package/dist/render/handlers/builtin/index.js +4 -1
- package/dist/render/handlers/builtin/index.js.map +1 -1
- package/dist/render/handlers/builtin/statblock.js +0 -4
- package/dist/render/handlers/builtin/statblock.js.map +1 -1
- package/dist/render/handlers/types.js.map +1 -1
- package/dist/render/pipeline.js +4 -1
- package/dist/render/pipeline.js.map +1 -1
- package/dist/render/slug.js +0 -5
- package/dist/render/slug.js.map +1 -1
- package/dist/settings.js +156 -21
- package/dist/settings.js.map +1 -1
- package/dist/zip.js +78 -0
- package/dist/zip.js.map +1 -0
- package/package.json +4 -3
package/dist/foundry-importer.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
// Build helper: the Foundry-side importer is pre-bundled at CLI build time
|
|
2
2
|
// (see scripts/bundle-importer.mjs) into `dist/foundry-importer.bundle.js`,
|
|
3
3
|
// which ships inside the npm package. At deploy time we copy that bundle to
|
|
4
|
-
// `_foundry/importer.js
|
|
5
|
-
// `{ version, sha256 }` so the Foundry host can detect skew before evaluating.
|
|
4
|
+
// `_foundry/importer.js`, which the Foundry host fetches and evaluates.
|
|
6
5
|
//
|
|
7
6
|
// Bundling ahead of publish (not here) means the installed CLI never runs
|
|
8
7
|
// esbuild on the user's machine and doesn't need the foundry/ source tree,
|
|
9
8
|
// which isn't part of the npm package.
|
|
10
|
-
import { createHash } from "node:crypto";
|
|
11
9
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
12
10
|
import { basename, dirname, join } from "node:path";
|
|
13
11
|
import { fileURLToPath } from "node:url";
|
|
14
|
-
import { CLI_VERSION } from "./version.js";
|
|
15
12
|
// scripts/bundle-importer.mjs always emits the bundle into dist/. This module
|
|
16
13
|
// runs from dist/ once published, but from src/ under tsx (tests) — resolve to
|
|
17
14
|
// dist/ either way.
|
|
@@ -19,17 +16,15 @@ const here = dirname(fileURLToPath(import.meta.url));
|
|
|
19
16
|
const distDir = basename(here) === "src" ? join(here, "..", "dist") : here;
|
|
20
17
|
const BUNDLE_PATH = join(distDir, "foundry-importer.bundle.js");
|
|
21
18
|
/**
|
|
22
|
-
* Write `_foundry/importer.js`
|
|
19
|
+
* Write `_foundry/importer.js` into the deploy.
|
|
23
20
|
* Called from build.ts after the variant outputs are in place — the
|
|
24
21
|
* bundle is a shared root-level asset (not per-variant), since it has
|
|
25
22
|
* no role-gated content.
|
|
26
23
|
*/
|
|
27
24
|
export async function writeFoundryImporter(outputDir) {
|
|
28
25
|
const source = await readFile(BUNDLE_PATH, "utf8");
|
|
29
|
-
const sha256 = createHash("sha256").update(source).digest("hex");
|
|
30
26
|
const dir = join(outputDir, "_foundry");
|
|
31
27
|
await mkdir(dir, { recursive: true });
|
|
32
28
|
await writeFile(join(dir, "importer.js"), source);
|
|
33
|
-
await writeFile(join(dir, "version.json"), JSON.stringify({ version: CLI_VERSION, sha256 }, null, 2));
|
|
34
29
|
}
|
|
35
30
|
//# sourceMappingURL=foundry-importer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundry-importer.js","sourceRoot":"","sources":["../src/foundry-importer.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,
|
|
1
|
+
{"version":3,"file":"foundry-importer.js","sourceRoot":"","sources":["../src/foundry-importer.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,wEAAwE;AACxE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,uCAAuC;AAEvC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,8EAA8E;AAC9E,+EAA+E;AAC/E,oBAAoB;AACpB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,4BAA4B,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,SAAiB;IAC1D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACxC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// What the CLI knows about the `foundry:` frontmatter block: which document a
|
|
2
|
+
// `source` names, and whether two pages are fighting over the same one.
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { DOC_TYPES } from "./foundry-types.js";
|
|
6
|
+
import { documentFolder, documentTypeOf, firstBase } from "./foundry-grafts.js";
|
|
7
|
+
export function warnFoundryDocCollisions(pages) {
|
|
8
|
+
const seen = new Map(); // key → first page path
|
|
9
|
+
for (const p of pages) {
|
|
10
|
+
const fo = p.frontmatter?.["foundry"];
|
|
11
|
+
if (!fo || typeof fo !== "object" || Array.isArray(fo))
|
|
12
|
+
continue;
|
|
13
|
+
if (fo["sync"] === false)
|
|
14
|
+
continue;
|
|
15
|
+
const spec = firstBase(fo["source"]);
|
|
16
|
+
if (!spec)
|
|
17
|
+
continue;
|
|
18
|
+
// The same reading the emitter uses, so a warning never describes a
|
|
19
|
+
// document that will not exist: a type with no pack produces nothing.
|
|
20
|
+
const docType = documentTypeOf(spec);
|
|
21
|
+
if (!docType || !DOC_TYPES[docType])
|
|
22
|
+
continue;
|
|
23
|
+
const folder = documentFolder({ path: p.path, foundry: fo });
|
|
24
|
+
const name = p.title || p.path.split("/").pop().replace(/\.md$/i, "");
|
|
25
|
+
const key = `${docType}\u0000${folder}\u0000${name}`;
|
|
26
|
+
const previous = seen.get(key);
|
|
27
|
+
if (previous === undefined) {
|
|
28
|
+
seen.set(key, p.path);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
console.warn(` ${p.path}: would create a ${docType} named '${name}' in the same Foundry `
|
|
32
|
+
+ `folder ('${folder || "(vault root)"}') as '${previous}'. Rename one, or `
|
|
33
|
+
+ `separate them with foundry.folder.`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Read + parse a vault-relative JSON file referenced by `foundry.patch_json`.
|
|
37
|
+
* Warns on missing / unparseable file and returns null so the page renders
|
|
38
|
+
* without the overlay rather than failing the build. */
|
|
39
|
+
export async function loadDataJson(vaultPath, relPath, pagePath) {
|
|
40
|
+
const abs = join(vaultPath, relPath);
|
|
41
|
+
try {
|
|
42
|
+
const raw = await readFile(abs, "utf8");
|
|
43
|
+
return JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
const code = err.code;
|
|
47
|
+
if (code === "ENOENT") {
|
|
48
|
+
console.warn(` ${pagePath}: foundry.patch_json "${relPath}" not found, skipping`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.warn(` ${pagePath}: foundry.patch_json "${relPath}" failed to parse: ${err.message}`);
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=foundry-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundry-meta.js","sourceRoot":"","sources":["../src/foundry-meta.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AAExE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhF,MAAM,UAAU,wBAAwB,CAAC,KAAiB;IACxD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,wBAAwB;IAChE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAAE,SAAS;QACjE,IAAK,EAA8B,CAAC,MAAM,CAAC,KAAK,KAAK;YAAE,SAAS;QAChE,MAAM,IAAI,GAAG,SAAS,CAAE,EAA8B,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,oEAAoE;QACpE,sEAAsE;QACtE,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAAE,SAAS;QAE9C,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAyB,EAAE,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,GAAG,OAAO,SAAS,MAAM,SAAS,IAAI,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YACtB,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,CAAC,IAAI,oBAAoB,OAAO,WAAW,IAAI,wBAAwB;cAC3E,YAAY,MAAM,IAAI,cAAc,UAAU,QAAQ,oBAAoB;cAC1E,oCAAoC,CACvC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;yDAEyD;AACzD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EACjB,OAAe,EACf,QAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,yBAAyB,OAAO,uBAAuB,CAAC,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,KAAK,QAAQ,yBAAyB,OAAO,sBAAuB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5G,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Build a module's JournalEntry pack from the pages the wiki already rendered.
|
|
2
|
+
//
|
|
3
|
+
// Mirrors the sync model exactly: one JournalEntry per vault directory, every
|
|
4
|
+
// .md file in that directory an embedded JournalEntryPage. Matching it is the
|
|
5
|
+
// point — a document's description embeds a journal page, and if the module
|
|
6
|
+
// laid its journals out differently, the same vault would produce two
|
|
7
|
+
// different-shaped things depending on how a reader got it.
|
|
8
|
+
//
|
|
9
|
+
// The HTML is the wiki's own rendered body, not a second rendering of the
|
|
10
|
+
// markdown. That matters: a page's battlemap, statblock and `fm:` values only
|
|
11
|
+
// exist in the rendered output, so re-rendering the source with a plain
|
|
12
|
+
// markdown parser would quietly ship a different article than the one on the
|
|
13
|
+
// site.
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
/** The sync path's id scheme, namespaced to the module instead of the vault. */
|
|
16
|
+
function det(kind, key) {
|
|
17
|
+
return createHash("sha1").update(`vaults:${kind}:${key}`).digest("hex").slice(0, 16);
|
|
18
|
+
}
|
|
19
|
+
export function folderOfPath(path) {
|
|
20
|
+
const i = path.lastIndexOf("/");
|
|
21
|
+
return i < 0 ? "" : path.slice(0, i);
|
|
22
|
+
}
|
|
23
|
+
/** One entry per directory, so every page in a folder shares an id. */
|
|
24
|
+
export const journalEntryId = (ns, path) => det("entry", `${ns}:${folderOfPath(path)}`);
|
|
25
|
+
export const journalPageId = (ns, path) => det("page", `${ns}:${path}`);
|
|
26
|
+
/**
|
|
27
|
+
* Rewrite the wiki's HTML into something a Foundry journal can render.
|
|
28
|
+
*
|
|
29
|
+
* Two things have to change and the rest is already fine. An internal link is
|
|
30
|
+
* a site path that means nothing inside Foundry, so it becomes a `@UUID`
|
|
31
|
+
* enricher pointing at the compendium page. A media src is a deploy-absolute
|
|
32
|
+
* path, so it becomes a module-relative one and the file is bundled.
|
|
33
|
+
*
|
|
34
|
+
* Deliberately narrower than the sync path's transform, which also converts
|
|
35
|
+
* role-gated callouts into Foundry secret blocks. A module carries only one
|
|
36
|
+
* role's pages, so there is no gated content inside them to convert.
|
|
37
|
+
*/
|
|
38
|
+
export function transformForModule(html, moduleId, targets, assets) {
|
|
39
|
+
// An internal link the renderer marked. Attribute order is not fixed — the
|
|
40
|
+
// renderer emits `class` before `href` in some cases and after in others —
|
|
41
|
+
// so match the whole tag and read the attributes out of it rather than
|
|
42
|
+
// assuming a shape. Anchoring on `href` first silently missed every link
|
|
43
|
+
// that happened to be written the other way round.
|
|
44
|
+
let out = html.replace(/<a\s+([^>]*)>([\s\S]*?)<\/a>/g, (whole, attrs, label) => {
|
|
45
|
+
if (!/\bclass="[^"]*\binternal\b/.test(attrs))
|
|
46
|
+
return whole;
|
|
47
|
+
const href = /href="([^"]*)"/.exec(attrs)?.[1];
|
|
48
|
+
if (!href || !href.startsWith("/"))
|
|
49
|
+
return whole;
|
|
50
|
+
const key = decodeURIComponent(href.replace(/^\//, "").split("#")[0] ?? "");
|
|
51
|
+
const target = targets.get(key) ?? targets.get(`${key}.md`);
|
|
52
|
+
if (!target)
|
|
53
|
+
return label; // page not in the module: keep the words, drop the dead link
|
|
54
|
+
// Strip tags from the label: an enricher's {…} is plain text.
|
|
55
|
+
const text = label.replace(/<[^>]+>/g, "").trim();
|
|
56
|
+
return `@UUID[${target.uuid}]{${text}}`;
|
|
57
|
+
});
|
|
58
|
+
// src="/attachments/x.webp" — deploy-absolute, meaningless in a module.
|
|
59
|
+
out = out.replace(/(\ssrc=")\/([^"]+)"/g, (_whole, prefix, path) => {
|
|
60
|
+
const rel = decodeURIComponent(path);
|
|
61
|
+
assets.add(rel);
|
|
62
|
+
return `${prefix}modules/${moduleId}/assets/${rel}"`;
|
|
63
|
+
});
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Group pages into one JournalEntry per directory.
|
|
68
|
+
*
|
|
69
|
+
* The entry's name is the directory's own name, and a root-level page lands in
|
|
70
|
+
* an entry named for the module — the same shape the sync path produces, where
|
|
71
|
+
* a directory becomes an entry and its files become that entry's pages.
|
|
72
|
+
*/
|
|
73
|
+
/** Deep-merge an overlay onto page data, arrays and scalars replacing. */
|
|
74
|
+
function deepMergePage(target, patch) {
|
|
75
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
76
|
+
const cur = target[k];
|
|
77
|
+
if (v && typeof v === "object" && !Array.isArray(v)
|
|
78
|
+
&& cur && typeof cur === "object" && !Array.isArray(cur)) {
|
|
79
|
+
deepMergePage(cur, v);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
target[k] = v;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return target;
|
|
86
|
+
}
|
|
87
|
+
export function buildJournalEntries(sources, ns, rootName, stats) {
|
|
88
|
+
const byFolder = new Map();
|
|
89
|
+
for (const s of sources) {
|
|
90
|
+
const folder = folderOfPath(s.path);
|
|
91
|
+
const list = byFolder.get(folder) ?? [];
|
|
92
|
+
list.push(s);
|
|
93
|
+
byFolder.set(folder, list);
|
|
94
|
+
}
|
|
95
|
+
const entries = [];
|
|
96
|
+
for (const [folder, pages] of [...byFolder].sort(([a], [b]) => a.localeCompare(b))) {
|
|
97
|
+
const id = journalEntryId(ns, pages[0].path);
|
|
98
|
+
entries.push({
|
|
99
|
+
_id: id,
|
|
100
|
+
name: folder ? folder.split("/").pop() : rootName,
|
|
101
|
+
pages: pages.map((p, i) => {
|
|
102
|
+
const pid = journalPageId(ns, p.path);
|
|
103
|
+
const type = p.spec?.type ?? "text";
|
|
104
|
+
const page = {
|
|
105
|
+
_id: pid,
|
|
106
|
+
name: p.title,
|
|
107
|
+
type,
|
|
108
|
+
title: { show: true, level: 1 },
|
|
109
|
+
// A page whose content is its `src` has nowhere to put an article.
|
|
110
|
+
// Unlike sync, the compiler cannot degrade an unknown type: it does
|
|
111
|
+
// not know the system of the world this module will be installed in.
|
|
112
|
+
...(type === "text" ? { text: { format: 1, content: p.html } } : {}),
|
|
113
|
+
sort: (i + 1) * 100000,
|
|
114
|
+
ownership: { default: -1 },
|
|
115
|
+
flags: {},
|
|
116
|
+
_stats: stats,
|
|
117
|
+
_key: `!journal.pages!${id}.${pid}`,
|
|
118
|
+
};
|
|
119
|
+
if (p.spec && Object.keys(p.spec.overlay).length > 0)
|
|
120
|
+
deepMergePage(page, p.spec.overlay);
|
|
121
|
+
return page;
|
|
122
|
+
}),
|
|
123
|
+
folder: null,
|
|
124
|
+
sort: 0,
|
|
125
|
+
flags: {},
|
|
126
|
+
ownership: { default: 0 },
|
|
127
|
+
_stats: stats,
|
|
128
|
+
_key: `!journal!${id}`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return entries;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=foundry-module-journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundry-module-journal.js","sourceRoot":"","sources":["../src/foundry-module-journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Render a vault page's markdown body into Foundry-flavoured description HTML,
|
|
2
|
+
// and build a pack's compendium folders.
|
|
3
|
+
//
|
|
4
|
+
// Ported from the standalone compiler this replaced, so `vaults build --module` can
|
|
5
|
+
// replace it. A vault body is Obsidian/vaults markdown; a Foundry sheet wants
|
|
6
|
+
// HTML with native inline rolls and Compendium @UUID cross-links.
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { marked } from "marked";
|
|
9
|
+
// Fenced blocks that are wiki chrome: the Foundry sheet renders the same
|
|
10
|
+
// mechanics natively, so carrying the block's source into a description would
|
|
11
|
+
// show the reader a code listing of something already on their screen.
|
|
12
|
+
const HANDLER_FENCES = new Set([
|
|
13
|
+
"spell-card", "item-card", "statblock", "statblock-fm", "gallery", "battlemap",
|
|
14
|
+
"rolltable", "dice", "download", "foundry-manifest",
|
|
15
|
+
]);
|
|
16
|
+
function dropHandlerFences(md) {
|
|
17
|
+
return md.replace(/^```([\w-]+)[^\n]*\n[\s\S]*?^```[ \t]*$/gm, (block, lang) => HANDLER_FENCES.has(lang) ? "" : block);
|
|
18
|
+
}
|
|
19
|
+
/** `dice: 2d6+1` in backticks becomes dnd5e's native inline roll. */
|
|
20
|
+
function diceToRolls(md) {
|
|
21
|
+
return md.replace(/`dice:\s*([^`]+?)`/gi, (_m, f) => `[[/r ${f.trim()}]]`);
|
|
22
|
+
}
|
|
23
|
+
function rewriteWikilinks(md, index) {
|
|
24
|
+
return md.replace(/\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|([^\]]+))?\]\]/g, (_m, target, label) => {
|
|
25
|
+
const entry = index.get(target.trim().toLowerCase());
|
|
26
|
+
const text = (label ?? target).trim();
|
|
27
|
+
return entry ? `@UUID[${entry.uuid}]{${text}}` : text;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wikilinks are rewritten before dice, not after: at that point a `dice:` span
|
|
32
|
+
* is still inside backticks, so the wikilink pass cannot mistake the `[[/r …]]`
|
|
33
|
+
* this would otherwise have produced for a link of its own.
|
|
34
|
+
*/
|
|
35
|
+
export function renderBody(md, index) {
|
|
36
|
+
let out = dropHandlerFences(md);
|
|
37
|
+
out = rewriteWikilinks(out, index);
|
|
38
|
+
out = diceToRolls(out);
|
|
39
|
+
return marked.parse(out, { async: false }).trim();
|
|
40
|
+
}
|
|
41
|
+
function folderId(packName, pathStr) {
|
|
42
|
+
return createHash("sha1").update(`folder:${packName}:${pathStr}`).digest("base64")
|
|
43
|
+
.replace(/[^A-Za-z0-9]/g, "").slice(0, 16).padEnd(16, "0");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build `!folders!` documents for a pack, plus the leaf folder each entry
|
|
47
|
+
* belongs in. `fvtt package pack` turns these keys into real compendium
|
|
48
|
+
* folders, so a pack of 500 items is browsable rather than one flat list.
|
|
49
|
+
*/
|
|
50
|
+
export function buildFolders(entries, packName, docType, stats) {
|
|
51
|
+
const docs = new Map();
|
|
52
|
+
const leafFor = new Map();
|
|
53
|
+
const ensure = (segments) => {
|
|
54
|
+
let parent = null;
|
|
55
|
+
let pathStr = "";
|
|
56
|
+
for (const seg of segments) {
|
|
57
|
+
pathStr = pathStr ? `${pathStr}/${seg}` : seg;
|
|
58
|
+
if (!docs.has(pathStr)) {
|
|
59
|
+
const id = folderId(packName, pathStr);
|
|
60
|
+
docs.set(pathStr, {
|
|
61
|
+
_id: id, name: seg, type: docType, folder: parent,
|
|
62
|
+
sort: 0, color: null, sorting: "a", flags: {},
|
|
63
|
+
_stats: stats, _key: `!folders!${id}`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
parent = docs.get(pathStr)._id;
|
|
67
|
+
}
|
|
68
|
+
return parent;
|
|
69
|
+
};
|
|
70
|
+
for (const e of entries) {
|
|
71
|
+
leafFor.set(e.key, ensure(e.folderPath.split("/").map((s) => s.trim()).filter(Boolean)));
|
|
72
|
+
}
|
|
73
|
+
return { folderDocs: [...docs.values()], leafFor };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=foundry-module-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundry-module-render.js","sourceRoot":"","sources":["../src/foundry-module-render.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,yCAAyC;AACzC,EAAE;AACF,oFAAoF;AACpF,8EAA8E;AAC9E,kEAAkE;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQhC,yEAAyE;AACzE,8EAA8E;AAC9E,uEAAuE;AACvE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW;IAC9E,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB;CACpD,CAAC,CAAC;AAEH,SAAS,iBAAiB,CAAC,EAAU;IACnC,OAAO,EAAE,CAAC,OAAO,CAAC,2CAA2C,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CACrF,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CACtC,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,SAAS,WAAW,CAAC,EAAU;IAC7B,OAAO,EAAE,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,EAAE,EAAE,CAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAU,EAAE,KAA6B;IACjE,OAAO,EAAE,CAAC,OAAO,CAAC,iDAAiD,EAAE,CAAC,EAAE,EAAE,MAAc,EAAE,KAAc,EAAE,EAAE;QAC1G,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,EAAU,EAAE,KAA6B;IAClE,IAAI,GAAG,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAChC,GAAG,GAAG,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IACvB,OAAQ,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAY,CAAC,IAAI,EAAE,CAAC;AAChE,CAAC;AAeD,SAAS,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACjD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,UAAU,QAAQ,IAAI,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;SAC/E,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,OAA8C,EAC9C,QAAgB,EAChB,OAAe,EACf,KAAc;IAEd,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE5C,MAAM,MAAM,GAAG,CAAC,QAAkB,EAAiB,EAAE;QACnD,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YAC9C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvB,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;oBAChB,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;oBACjD,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;oBAC7C,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE;iBACtC,CAAC,CAAC;YACL,CAAC;YACD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,GAAG,CAAC;QAClC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC"}
|