@kensio/colophon 2.2.0 → 2.3.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 +560 -24
- package/dist/cli/args.d.ts +14 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +67 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config.d.ts +12 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +43 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli.js +34 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/defaults.d.ts +64 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +64 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +22 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +52 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/resolve.d.ts +24 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +66 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/config/size.d.ts +20 -0
- package/dist/config/size.d.ts.map +1 -0
- package/dist/config/size.js +46 -0
- package/dist/config/size.js.map +1 -0
- package/dist/config.d.ts +27 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +78 -2
- package/dist/config.js.map +1 -1
- package/dist/content/index.d.ts +5 -51
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +3 -115
- package/dist/content/index.js.map +1 -1
- package/dist/content/props.d.ts +15 -0
- package/dist/content/props.d.ts.map +1 -0
- package/dist/content/props.js +71 -0
- package/dist/content/props.js.map +1 -0
- package/dist/content/slug.d.ts +23 -0
- package/dist/content/slug.d.ts.map +1 -0
- package/dist/content/slug.js +52 -0
- package/dist/content/slug.js.map +1 -0
- package/dist/content/walk.d.ts +17 -0
- package/dist/content/walk.d.ts.map +1 -0
- package/dist/content/walk.js +57 -0
- package/dist/content/walk.js.map +1 -0
- package/dist/fonts/index.d.ts +10 -0
- package/dist/fonts/index.d.ts.map +1 -0
- package/dist/fonts/index.js +11 -0
- package/dist/fonts/index.js.map +1 -0
- package/dist/fonts/materialise.d.ts +7 -0
- package/dist/fonts/materialise.d.ts.map +1 -0
- package/dist/fonts/materialise.js +47 -0
- package/dist/fonts/materialise.js.map +1 -0
- package/dist/fonts/resolve.d.ts +7 -0
- package/dist/fonts/resolve.d.ts.map +1 -0
- package/dist/fonts/resolve.js +50 -0
- package/dist/fonts/resolve.js.map +1 -0
- package/dist/fonts.d.ts +18 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +102 -0
- package/dist/fonts.js.map +1 -0
- package/dist/generate/extra.d.ts +16 -0
- package/dist/generate/extra.d.ts.map +1 -0
- package/dist/generate/extra.js +60 -0
- package/dist/generate/extra.js.map +1 -0
- package/dist/generate/index.d.ts +19 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +46 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate/job.d.ts +35 -0
- package/dist/generate/job.d.ts.map +1 -0
- package/dist/generate/job.js +2 -0
- package/dist/generate/job.js.map +1 -0
- package/dist/generate/options.d.ts +56 -0
- package/dist/generate/options.d.ts.map +1 -0
- package/dist/generate/options.js +17 -0
- package/dist/generate/options.js.map +1 -0
- package/dist/generate/output-path.d.ts +12 -0
- package/dist/generate/output-path.d.ts.map +1 -0
- package/dist/generate/output-path.js +18 -0
- package/dist/generate/output-path.js.map +1 -0
- package/dist/generate/outputs.d.ts +28 -0
- package/dist/generate/outputs.d.ts.map +1 -0
- package/dist/generate/outputs.js +71 -0
- package/dist/generate/outputs.js.map +1 -0
- package/dist/generate/plan.d.ts +21 -0
- package/dist/generate/plan.d.ts.map +1 -0
- package/dist/generate/plan.js +72 -0
- package/dist/generate/plan.js.map +1 -0
- package/dist/generate/render-image.d.ts +11 -0
- package/dist/generate/render-image.d.ts.map +1 -0
- package/dist/generate/render-image.js +27 -0
- package/dist/generate/render-image.js.map +1 -0
- package/dist/generate.d.ts +27 -6
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +69 -15
- package/dist/generate.js.map +1 -1
- package/dist/highlight/color.d.ts +9 -0
- package/dist/highlight/color.d.ts.map +1 -0
- package/dist/highlight/color.js +15 -0
- package/dist/highlight/color.js.map +1 -0
- package/dist/highlight/grid.d.ts +14 -0
- package/dist/highlight/grid.d.ts.map +1 -0
- package/dist/highlight/grid.js +36 -0
- package/dist/highlight/grid.js.map +1 -0
- package/dist/highlight/index.d.ts +12 -0
- package/dist/highlight/index.d.ts.map +1 -0
- package/dist/highlight/index.js +31 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/highlight/language.d.ts +14 -0
- package/dist/highlight/language.d.ts.map +1 -0
- package/dist/highlight/language.js +42 -0
- package/dist/highlight/language.js.map +1 -0
- package/dist/highlight/normalise.d.ts +17 -0
- package/dist/highlight/normalise.d.ts.map +1 -0
- package/dist/highlight/normalise.js +37 -0
- package/dist/highlight/normalise.js.map +1 -0
- package/dist/highlight/types.d.ts +40 -0
- package/dist/highlight/types.d.ts.map +1 -0
- package/dist/highlight/types.js +2 -0
- package/dist/highlight/types.js.map +1 -0
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/manifest/build.d.ts +14 -0
- package/dist/manifest/build.d.ts.map +1 -0
- package/dist/manifest/build.js +43 -0
- package/dist/manifest/build.js.map +1 -0
- package/dist/manifest/index.d.ts +27 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +31 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/order.d.ts +12 -0
- package/dist/manifest/order.d.ts.map +1 -0
- package/dist/manifest/order.js +17 -0
- package/dist/manifest/order.js.map +1 -0
- package/dist/manifest/page.d.ts +24 -0
- package/dist/manifest/page.d.ts.map +1 -0
- package/dist/manifest/page.js +55 -0
- package/dist/manifest/page.js.map +1 -0
- package/dist/meta/html.d.ts +14 -0
- package/dist/meta/html.d.ts.map +1 -0
- package/dist/meta/html.js +24 -0
- package/dist/meta/html.js.map +1 -0
- package/dist/meta/index.d.ts +11 -0
- package/dist/meta/index.d.ts.map +1 -0
- package/dist/meta/index.js +11 -0
- package/dist/meta/index.js.map +1 -0
- package/dist/meta/tags.d.ts +21 -0
- package/dist/meta/tags.d.ts.map +1 -0
- package/dist/meta/tags.js +72 -0
- package/dist/meta/tags.js.map +1 -0
- package/dist/meta/url.d.ts +15 -0
- package/dist/meta/url.d.ts.map +1 -0
- package/dist/meta/url.js +34 -0
- package/dist/meta/url.js.map +1 -0
- package/dist/placement/check.d.ts +16 -0
- package/dist/placement/check.d.ts.map +1 -0
- package/dist/placement/check.js +40 -0
- package/dist/placement/check.js.map +1 -0
- package/dist/placement/index.d.ts +29 -0
- package/dist/placement/index.d.ts.map +1 -0
- package/dist/placement/index.js +61 -0
- package/dist/placement/index.js.map +1 -0
- package/dist/placement/relative.d.ts +31 -0
- package/dist/placement/relative.d.ts.map +1 -0
- package/dist/placement/relative.js +53 -0
- package/dist/placement/relative.js.map +1 -0
- package/dist/pool.d.ts +18 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +56 -0
- package/dist/pool.js.map +1 -0
- package/dist/render/index.d.ts +10 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +27 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/png.d.ts +10 -0
- package/dist/render/png.d.ts.map +1 -0
- package/dist/render/png.js +30 -0
- package/dist/render/png.js.map +1 -0
- package/dist/render/svg.d.ts +10 -0
- package/dist/render/svg.d.ts.map +1 -0
- package/dist/render/svg.js +20 -0
- package/dist/render/svg.js.map +1 -0
- package/dist/render/template.d.ts +9 -0
- package/dist/render/template.d.ts.map +1 -0
- package/dist/render/template.js +17 -0
- package/dist/render/template.js.map +1 -0
- package/dist/render.d.ts +6 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +31 -10
- package/dist/render.js.map +1 -1
- package/dist/stamp/chunk.d.ts +16 -0
- package/dist/stamp/chunk.d.ts.map +1 -0
- package/dist/stamp/chunk.js +46 -0
- package/dist/stamp/chunk.js.map +1 -0
- package/dist/stamp/config-digest.d.ts +11 -0
- package/dist/stamp/config-digest.d.ts.map +1 -0
- package/dist/stamp/config-digest.js +43 -0
- package/dist/stamp/config-digest.js.map +1 -0
- package/dist/stamp/digest.d.ts +8 -0
- package/dist/stamp/digest.d.ts.map +1 -0
- package/dist/stamp/digest.js +20 -0
- package/dist/stamp/digest.js.map +1 -0
- package/dist/stamp/index.d.ts +20 -0
- package/dist/stamp/index.d.ts.map +1 -0
- package/dist/stamp/index.js +40 -0
- package/dist/stamp/index.js.map +1 -0
- package/dist/stamp/read.d.ts +7 -0
- package/dist/stamp/read.d.ts.map +1 -0
- package/dist/stamp/read.js +62 -0
- package/dist/stamp/read.js.map +1 -0
- package/dist/stamp.d.ts +29 -0
- package/dist/stamp.d.ts.map +1 -0
- package/dist/stamp.js +198 -0
- package/dist/stamp.js.map +1 -0
- package/dist/templates/banner/badge.d.ts +7 -0
- package/dist/templates/banner/badge.d.ts.map +1 -0
- package/dist/templates/banner/badge.js +24 -0
- package/dist/templates/banner/badge.js.map +1 -0
- package/dist/templates/banner/index.d.ts +9 -0
- package/dist/templates/banner/index.d.ts.map +1 -0
- package/dist/templates/banner/index.js +66 -0
- package/dist/templates/banner/index.js.map +1 -0
- package/dist/templates/banner/lines.d.ts +27 -0
- package/dist/templates/banner/lines.d.ts.map +1 -0
- package/dist/templates/banner/lines.js +46 -0
- package/dist/templates/banner/lines.js.map +1 -0
- package/dist/templates/card/index.d.ts +7 -0
- package/dist/templates/card/index.d.ts.map +1 -0
- package/dist/templates/card/index.js +43 -0
- package/dist/templates/card/index.js.map +1 -0
- package/dist/templates/card/lines.d.ts +17 -0
- package/dist/templates/card/lines.d.ts.map +1 -0
- package/dist/templates/card/lines.js +32 -0
- package/dist/templates/card/lines.js.map +1 -0
- package/dist/templates/code/chrome.d.ts +9 -0
- package/dist/templates/code/chrome.d.ts.map +1 -0
- package/dist/templates/code/chrome.js +32 -0
- package/dist/templates/code/chrome.js.map +1 -0
- package/dist/templates/code/clip.d.ts +18 -0
- package/dist/templates/code/clip.d.ts.map +1 -0
- package/dist/templates/code/clip.js +44 -0
- package/dist/templates/code/clip.js.map +1 -0
- package/dist/templates/code/ellipsis.d.ts +3 -0
- package/dist/templates/code/ellipsis.d.ts.map +1 -0
- package/dist/templates/code/ellipsis.js +3 -0
- package/dist/templates/code/ellipsis.js.map +1 -0
- package/dist/templates/code/fit.d.ts +27 -0
- package/dist/templates/code/fit.d.ts.map +1 -0
- package/dist/templates/code/fit.js +59 -0
- package/dist/templates/code/fit.js.map +1 -0
- package/dist/templates/code/index.d.ts +12 -0
- package/dist/templates/code/index.d.ts.map +1 -0
- package/dist/templates/code/index.js +64 -0
- package/dist/templates/code/index.js.map +1 -0
- package/dist/templates/code/layout.d.ts +21 -0
- package/dist/templates/code/layout.d.ts.map +1 -0
- package/dist/templates/code/layout.js +21 -0
- package/dist/templates/code/layout.js.map +1 -0
- package/dist/templates/code/panel.d.ts +17 -0
- package/dist/templates/code/panel.d.ts.map +1 -0
- package/dist/templates/code/panel.js +20 -0
- package/dist/templates/code/panel.js.map +1 -0
- package/dist/templates/code/plate.d.ts +15 -0
- package/dist/templates/code/plate.d.ts.map +1 -0
- package/dist/templates/code/plate.js +32 -0
- package/dist/templates/code/plate.js.map +1 -0
- package/dist/templates/code/spans.d.ts +19 -0
- package/dist/templates/code/spans.d.ts.map +1 -0
- package/dist/templates/code/spans.js +36 -0
- package/dist/templates/code/spans.js.map +1 -0
- package/dist/templates/code/warn.d.ts +11 -0
- package/dist/templates/code/warn.d.ts.map +1 -0
- package/dist/templates/code/warn.js +24 -0
- package/dist/templates/code/warn.js.map +1 -0
- package/dist/templates/footer.d.ts +21 -0
- package/dist/templates/footer.d.ts.map +1 -0
- package/dist/templates/footer.js +25 -0
- package/dist/templates/footer.js.map +1 -0
- package/dist/templates/index.d.ts +3 -3
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +6 -6
- package/dist/templates/index.js.map +1 -1
- package/dist/text/element.d.ts +18 -0
- package/dist/text/element.d.ts.map +1 -0
- package/dist/text/element.js +19 -0
- package/dist/text/element.js.map +1 -0
- package/dist/text/escape.d.ts +5 -0
- package/dist/text/escape.d.ts.map +1 -0
- package/dist/text/escape.js +12 -0
- package/dist/text/escape.js.map +1 -0
- package/dist/text/index.d.ts +7 -0
- package/dist/text/index.d.ts.map +1 -0
- package/dist/text/index.js +5 -0
- package/dist/text/index.js.map +1 -0
- package/dist/text/stack.d.ts +24 -0
- package/dist/text/stack.d.ts.map +1 -0
- package/dist/text/stack.js +18 -0
- package/dist/text/stack.js.map +1 -0
- package/dist/text/wrap.d.ts +12 -0
- package/dist/text/wrap.d.ts.map +1 -0
- package/dist/text/wrap.js +33 -0
- package/dist/text/wrap.js.map +1 -0
- package/dist/types.d.ts +326 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/check.d.ts +13 -0
- package/dist/validate/check.d.ts.map +1 -0
- package/dist/validate/check.js +34 -0
- package/dist/validate/check.js.map +1 -0
- package/dist/validate/index.d.ts +15 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +41 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/keys.d.ts +58 -0
- package/dist/validate/keys.d.ts.map +1 -0
- package/dist/validate/keys.js +166 -0
- package/dist/validate/keys.js.map +1 -0
- package/dist/validate/overrides.d.ts +5 -0
- package/dist/validate/overrides.d.ts.map +1 -0
- package/dist/validate/overrides.js +43 -0
- package/dist/validate/overrides.js.map +1 -0
- package/dist/validate/placement.d.ts +10 -0
- package/dist/validate/placement.d.ts.map +1 -0
- package/dist/validate/placement.js +38 -0
- package/dist/validate/placement.js.map +1 -0
- package/dist/validate/sizes.d.ts +9 -0
- package/dist/validate/sizes.d.ts.map +1 -0
- package/dist/validate/sizes.js +27 -0
- package/dist/validate/sizes.js.map +1 -0
- package/dist/validate/suggest.d.ts +10 -0
- package/dist/validate/suggest.d.ts.map +1 -0
- package/dist/validate/suggest.js +55 -0
- package/dist/validate/suggest.js.map +1 -0
- package/dist/validate/values.d.ts +21 -0
- package/dist/validate/values.d.ts.map +1 -0
- package/dist/validate/values.js +57 -0
- package/dist/validate/values.js.map +1 -0
- package/dist/validate.d.ts +15 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +300 -0
- package/dist/validate.js.map +1 -0
- package/package.json +13 -6
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import matter from "gray-matter";
|
|
4
|
+
import { coerceString, extractProps } from "./props.js";
|
|
5
|
+
import { assertSlugStaysInside, slugFromPath } from "./slug.js";
|
|
6
|
+
const defaultSlugField = "slug";
|
|
7
|
+
const defaultSlugStrategy = "basename";
|
|
8
|
+
const defaultExtensions = [".md", ".markdown"];
|
|
9
|
+
async function collectContentFiles(dir, extensions) {
|
|
10
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
11
|
+
const nested = await Promise.all(entries.map(async (entry) => {
|
|
12
|
+
const entryPath = path.join(dir, entry.name);
|
|
13
|
+
if (entry.isDirectory()) {
|
|
14
|
+
return collectContentFiles(entryPath, extensions);
|
|
15
|
+
}
|
|
16
|
+
if (entry.isFile() &&
|
|
17
|
+
extensions.some((extension) => entry.name.endsWith(extension))) {
|
|
18
|
+
return [entryPath];
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
}));
|
|
22
|
+
return nested.flat();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Walk a content tree, read each file's frontmatter with `gray-matter`, and
|
|
26
|
+
* return the files that image props can be built for. This is the host-project
|
|
27
|
+
* concern — finding content and reading frontmatter — kept separate from
|
|
28
|
+
* rendering.
|
|
29
|
+
*/
|
|
30
|
+
export async function walkContent(options) {
|
|
31
|
+
const extensions = options.extensions ?? defaultExtensions;
|
|
32
|
+
const filePaths = await collectContentFiles(options.dir, extensions);
|
|
33
|
+
const slugField = options.slugField ?? defaultSlugField;
|
|
34
|
+
const slugStrategy = options.slugStrategy ?? defaultSlugStrategy;
|
|
35
|
+
const files = await Promise.all(filePaths.map(async (filePath) => {
|
|
36
|
+
const raw = await readFile(filePath, "utf8");
|
|
37
|
+
const frontmatter = matter(raw).data;
|
|
38
|
+
const props = extractProps(frontmatter, options);
|
|
39
|
+
if (props === undefined) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const contentPath = path.relative(options.dir, filePath);
|
|
43
|
+
const declaredSlug = coerceString(frontmatter[slugField])?.trim();
|
|
44
|
+
const slug = declaredSlug !== undefined && declaredSlug !== ""
|
|
45
|
+
? declaredSlug
|
|
46
|
+
: slugFromPath(contentPath, slugStrategy);
|
|
47
|
+
assertSlugStaysInside(slug, contentPath);
|
|
48
|
+
return {
|
|
49
|
+
contentPath,
|
|
50
|
+
absolutePath: filePath,
|
|
51
|
+
slug,
|
|
52
|
+
props,
|
|
53
|
+
};
|
|
54
|
+
}));
|
|
55
|
+
return files.filter((file) => file !== undefined);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/content/walk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FontSource } from "../types.js";
|
|
2
|
+
export { fontFilePaths } from "./materialise.js";
|
|
3
|
+
export { resolveFonts } from "./resolve.js";
|
|
4
|
+
/**
|
|
5
|
+
* The family the rasteriser should fall back to when a `font-family` names
|
|
6
|
+
* something it has not loaded — the first declared family, so the fallback is
|
|
7
|
+
* the same wherever the build runs rather than whichever font loaded first.
|
|
8
|
+
*/
|
|
9
|
+
export declare function fallbackFamily(fonts: readonly FontSource[]): string | undefined;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fonts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,MAAM,GAAG,SAAS,CAEpB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { fontFilePaths } from "./materialise.js";
|
|
2
|
+
export { resolveFonts } from "./resolve.js";
|
|
3
|
+
/**
|
|
4
|
+
* The family the rasteriser should fall back to when a `font-family` names
|
|
5
|
+
* something it has not loaded — the first declared family, so the fallback is
|
|
6
|
+
* the same wherever the build runs rather than whichever font loaded first.
|
|
7
|
+
*/
|
|
8
|
+
export function fallbackFamily(fonts) {
|
|
9
|
+
return fonts.find((font) => font.family !== undefined)?.family;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fonts/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,KAA4B;IAE5B,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,MAAM,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FontSource } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* File paths for the configured fonts, in order, writing any supplied as
|
|
4
|
+
* bytes to a temp file first.
|
|
5
|
+
*/
|
|
6
|
+
export declare function fontFilePaths(fonts: readonly FontSource[]): Promise<string[]>;
|
|
7
|
+
//# sourceMappingURL=materialise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialise.d.ts","sourceRoot":"","sources":["../../src/fonts/materialise.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA4C9C;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
/**
|
|
7
|
+
* Directory in-memory fonts are written to. The rasteriser takes file paths
|
|
8
|
+
* only, so a font supplied as bytes has to land on disk somewhere; the temp
|
|
9
|
+
* directory keeps it out of the user's project.
|
|
10
|
+
*/
|
|
11
|
+
const materialisedDir = path.join(os.tmpdir(), "colophon-fonts");
|
|
12
|
+
/**
|
|
13
|
+
* In-flight and completed writes of in-memory fonts, keyed by content hash.
|
|
14
|
+
* A build renders many images from one config, so the same bytes would
|
|
15
|
+
* otherwise be written once per image.
|
|
16
|
+
*/
|
|
17
|
+
const materialised = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Write font bytes to a temp file and return its path, reusing the file for
|
|
20
|
+
* identical bytes. The name is the content hash, so a rebuild reuses whatever
|
|
21
|
+
* an earlier run left behind and nothing has to be cleaned up.
|
|
22
|
+
*/
|
|
23
|
+
async function materialise(data) {
|
|
24
|
+
const hash = createHash("sha256").update(data).digest("hex").slice(0, 32);
|
|
25
|
+
const pending = materialised.get(hash);
|
|
26
|
+
if (pending !== undefined) {
|
|
27
|
+
return pending;
|
|
28
|
+
}
|
|
29
|
+
const write = (async () => {
|
|
30
|
+
const file = path.join(materialisedDir, `${hash}.font`);
|
|
31
|
+
if (!existsSync(file)) {
|
|
32
|
+
await mkdir(materialisedDir, { recursive: true });
|
|
33
|
+
await writeFile(file, data);
|
|
34
|
+
}
|
|
35
|
+
return file;
|
|
36
|
+
})();
|
|
37
|
+
materialised.set(hash, write);
|
|
38
|
+
return write;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* File paths for the configured fonts, in order, writing any supplied as
|
|
42
|
+
* bytes to a temp file first.
|
|
43
|
+
*/
|
|
44
|
+
export async function fontFilePaths(fonts) {
|
|
45
|
+
return Promise.all(fonts.map(async (font) => "data" in font ? materialise(font.data) : font.path));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=materialise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialise.js","sourceRoot":"","sources":["../../src/fonts/materialise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B;;;;GAIG;AACH,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;AAExD;;;;GAIG;AACH,KAAK,UAAU,WAAW,CAAC,IAAgB;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,KAAK,IAAqB,EAAE;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;QAExD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,KAAK,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,EAAE,CAAC;IAEL,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA4B;IAE5B,OAAO,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACvB,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CACpD,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FontSource } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate the configured fonts and make their paths absolute. Safe to call
|
|
4
|
+
* with no fonts, which is the default.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveFonts(fonts: readonly FontSource[] | undefined): readonly FontSource[];
|
|
7
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/fonts/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA0D9C;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GACvC,SAAS,UAAU,EAAE,CAMvB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
function label(index) {
|
|
4
|
+
return `fonts[${String(index)}]`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validate one font source and make its path absolute.
|
|
8
|
+
*
|
|
9
|
+
* The rasteriser ignores a font file it cannot read and renders the text in
|
|
10
|
+
* whatever else it has loaded — or, with system fonts off, renders no text at
|
|
11
|
+
* all. A typo in a path would therefore show up as a blank image rather than
|
|
12
|
+
* an error, so the path is checked here instead.
|
|
13
|
+
*/
|
|
14
|
+
function resolveFont(font, index) {
|
|
15
|
+
const source = font;
|
|
16
|
+
const hasPath = source.path !== undefined;
|
|
17
|
+
const hasData = source.data !== undefined;
|
|
18
|
+
if (hasPath && hasData) {
|
|
19
|
+
throw new Error(`${label(index)} has both "path" and "data"; give one or the other.`);
|
|
20
|
+
}
|
|
21
|
+
if (source.data !== undefined) {
|
|
22
|
+
if (source.data.byteLength === 0) {
|
|
23
|
+
throw new Error(`${label(index)} has empty font data.`);
|
|
24
|
+
}
|
|
25
|
+
return font;
|
|
26
|
+
}
|
|
27
|
+
if (source.path === undefined || source.path === "") {
|
|
28
|
+
throw new Error(`${label(index)} needs a "path" to a font file, or its bytes as "data".`);
|
|
29
|
+
}
|
|
30
|
+
const absolute = path.resolve(source.path);
|
|
31
|
+
if (!existsSync(absolute) || !statSync(absolute).isFile()) {
|
|
32
|
+
throw new Error(`${label(index)}: font file not found at ${absolute}` +
|
|
33
|
+
` (from "${source.path}"). Relative paths resolve from the working directory.`);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
...(source.family !== undefined && { family: source.family }),
|
|
37
|
+
path: absolute,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate the configured fonts and make their paths absolute. Safe to call
|
|
42
|
+
* with no fonts, which is the default.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveFonts(fonts) {
|
|
45
|
+
if (fonts === undefined || fonts.length === 0) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return fonts.map((font, index) => resolveFont(font, index));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/fonts/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,SAAS,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,IAAgB,EAAE,KAAa;IAClD,MAAM,MAAM,GAAG,IAId,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IAE1C,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,KAAK,CAAC,qDAAqD,CACrE,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,KAAK,CAAC,yDAAyD,CACzE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,KAAK,CAAC,4BAA4B,QAAQ,EAAE;YACnD,WAAW,MAAM,CAAC,IAAI,wDAAwD,CACjF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7D,IAAI,EAAE,QAAQ;KACf,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAwC;IAExC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AAC9D,CAAC"}
|
package/dist/fonts.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FontSource } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate the configured fonts and make their paths absolute. Safe to call
|
|
4
|
+
* with no fonts, which is the default.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveFonts(fonts: readonly FontSource[] | undefined): readonly FontSource[];
|
|
7
|
+
/**
|
|
8
|
+
* File paths for the configured fonts, in order, writing any supplied as
|
|
9
|
+
* bytes to a temp file first.
|
|
10
|
+
*/
|
|
11
|
+
export declare function fontFilePaths(fonts: readonly FontSource[]): Promise<string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* The family the rasteriser should fall back to when a `font-family` names
|
|
14
|
+
* something it has not loaded — the first declared family, so the fallback is
|
|
15
|
+
* the same wherever the build runs rather than whichever font loaded first.
|
|
16
|
+
*/
|
|
17
|
+
export declare function fallbackFamily(fonts: readonly FontSource[]): string | undefined;
|
|
18
|
+
//# sourceMappingURL=fonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAwE7C;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,GACvC,SAAS,UAAU,EAAE,CAMvB;AA8BD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC,CAMnB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,MAAM,GAAG,SAAS,CAEpB"}
|
package/dist/fonts.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
/**
|
|
7
|
+
* Directory in-memory fonts are written to. The rasteriser takes file paths
|
|
8
|
+
* only, so a font supplied as bytes has to land on disk somewhere; the temp
|
|
9
|
+
* directory keeps it out of the user's project.
|
|
10
|
+
*/
|
|
11
|
+
const materialisedDir = path.join(os.tmpdir(), "colophon-fonts");
|
|
12
|
+
/**
|
|
13
|
+
* In-flight and completed writes of in-memory fonts, keyed by content hash.
|
|
14
|
+
* A build renders many images from one config, so the same bytes would
|
|
15
|
+
* otherwise be written once per image.
|
|
16
|
+
*/
|
|
17
|
+
const materialised = new Map();
|
|
18
|
+
function label(index) {
|
|
19
|
+
return `fonts[${String(index)}]`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate one font source and make its path absolute.
|
|
23
|
+
*
|
|
24
|
+
* The rasteriser ignores a font file it cannot read and renders the text in
|
|
25
|
+
* whatever else it has loaded — or, with system fonts off, renders no text at
|
|
26
|
+
* all. A typo in a path would therefore show up as a blank image rather than
|
|
27
|
+
* an error, so the path is checked here instead.
|
|
28
|
+
*/
|
|
29
|
+
function resolveFont(font, index) {
|
|
30
|
+
const source = font;
|
|
31
|
+
const hasPath = source.path !== undefined;
|
|
32
|
+
const hasData = source.data !== undefined;
|
|
33
|
+
if (hasPath && hasData) {
|
|
34
|
+
throw new Error(`${label(index)} has both "path" and "data"; give one or the other.`);
|
|
35
|
+
}
|
|
36
|
+
if (source.data !== undefined) {
|
|
37
|
+
if (source.data.byteLength === 0) {
|
|
38
|
+
throw new Error(`${label(index)} has empty font data.`);
|
|
39
|
+
}
|
|
40
|
+
return font;
|
|
41
|
+
}
|
|
42
|
+
if (source.path === undefined || source.path === "") {
|
|
43
|
+
throw new Error(`${label(index)} needs a "path" to a font file, or its bytes as "data".`);
|
|
44
|
+
}
|
|
45
|
+
const absolute = path.resolve(source.path);
|
|
46
|
+
if (!existsSync(absolute) || !statSync(absolute).isFile()) {
|
|
47
|
+
throw new Error(`${label(index)}: font file not found at ${absolute}` +
|
|
48
|
+
` (from "${source.path}"). Relative paths resolve from the working directory.`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...(source.family !== undefined && { family: source.family }),
|
|
52
|
+
path: absolute,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate the configured fonts and make their paths absolute. Safe to call
|
|
57
|
+
* with no fonts, which is the default.
|
|
58
|
+
*/
|
|
59
|
+
export function resolveFonts(fonts) {
|
|
60
|
+
if (fonts === undefined || fonts.length === 0) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return fonts.map((font, index) => resolveFont(font, index));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Write font bytes to a temp file and return its path, reusing the file for
|
|
67
|
+
* identical bytes. The name is the content hash, so a rebuild reuses whatever
|
|
68
|
+
* an earlier run left behind and nothing has to be cleaned up.
|
|
69
|
+
*/
|
|
70
|
+
async function materialise(data) {
|
|
71
|
+
const hash = createHash("sha256").update(data).digest("hex").slice(0, 32);
|
|
72
|
+
const pending = materialised.get(hash);
|
|
73
|
+
if (pending !== undefined) {
|
|
74
|
+
return pending;
|
|
75
|
+
}
|
|
76
|
+
const write = (async () => {
|
|
77
|
+
const file = path.join(materialisedDir, `${hash}.font`);
|
|
78
|
+
if (!existsSync(file)) {
|
|
79
|
+
await mkdir(materialisedDir, { recursive: true });
|
|
80
|
+
await writeFile(file, data);
|
|
81
|
+
}
|
|
82
|
+
return file;
|
|
83
|
+
})();
|
|
84
|
+
materialised.set(hash, write);
|
|
85
|
+
return write;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* File paths for the configured fonts, in order, writing any supplied as
|
|
89
|
+
* bytes to a temp file first.
|
|
90
|
+
*/
|
|
91
|
+
export async function fontFilePaths(fonts) {
|
|
92
|
+
return Promise.all(fonts.map(async (font) => "data" in font ? materialise(font.data) : font.path));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The family the rasteriser should fall back to when a `font-family` names
|
|
96
|
+
* something it has not loaded — the first declared family, so the fallback is
|
|
97
|
+
* the same wherever the build runs rather than whichever font loaded first.
|
|
98
|
+
*/
|
|
99
|
+
export function fallbackFamily(fonts) {
|
|
100
|
+
return fonts.find((font) => font.family !== undefined)?.family;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Stamper } from "../stamp/index.js";
|
|
2
|
+
import type { ColophonConfig, ResolvedConfig } from "../types.js";
|
|
3
|
+
import type { RenderJob } from "./job.js";
|
|
4
|
+
/**
|
|
5
|
+
* The jobs for the images a config declares outright, rather than finding in
|
|
6
|
+
* the content tree.
|
|
7
|
+
*
|
|
8
|
+
* An extra image is a size like any other as far as the renderer is concerned,
|
|
9
|
+
* so it goes through `resolveConfigForSize` too and gets the same override
|
|
10
|
+
* rules rather than a second set that would have to agree with the first.
|
|
11
|
+
* Each resolves its own: there are a handful of these at most, and one
|
|
12
|
+
* carrying overrides is the normal case rather than the exception, so caching
|
|
13
|
+
* them by name the way the content jobs do would save nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extraJobs(config: ColophonConfig | undefined, resolved: ResolvedConfig, stamper: Stamper): RenderJob[];
|
|
16
|
+
//# sourceMappingURL=extra.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extra.d.ts","sourceRoot":"","sources":["../../src/generate/extra.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAc,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA4B1C;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,OAAO,GACf,SAAS,EAAE,CA0Bb"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SIZE_PRESETS } from "../config/defaults.js";
|
|
2
|
+
import { resolveConfigForSize } from "../config/size.js";
|
|
3
|
+
import { isRecord } from "../validate/check.js";
|
|
4
|
+
/**
|
|
5
|
+
* Reject an extra image that says too little to be rendered or written.
|
|
6
|
+
*
|
|
7
|
+
* The type requires both fields, but a CLI user's config module is plain
|
|
8
|
+
* JavaScript with nothing checking it, and neither omission fails anywhere
|
|
9
|
+
* near the config: a missing `output` surfaces as a complaint about an
|
|
10
|
+
* argument to `path`, and missing props as a property read on `undefined`.
|
|
11
|
+
* Key validation is no help either — it is the option that is not there.
|
|
12
|
+
*/
|
|
13
|
+
function checkImage(image, index) {
|
|
14
|
+
// The types say what should be here; this exists for when it is not.
|
|
15
|
+
const declared = image;
|
|
16
|
+
const label = `extra[${String(index)}]`;
|
|
17
|
+
if (typeof declared.output !== "string" || declared.output === "") {
|
|
18
|
+
throw new Error(`${label} needs an "output" path to write the image to.`);
|
|
19
|
+
}
|
|
20
|
+
if (!isRecord(declared.props)) {
|
|
21
|
+
throw new Error(`${label} needs a "props" object describing the image.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The jobs for the images a config declares outright, rather than finding in
|
|
26
|
+
* the content tree.
|
|
27
|
+
*
|
|
28
|
+
* An extra image is a size like any other as far as the renderer is concerned,
|
|
29
|
+
* so it goes through `resolveConfigForSize` too and gets the same override
|
|
30
|
+
* rules rather than a second set that would have to agree with the first.
|
|
31
|
+
* Each resolves its own: there are a handful of these at most, and one
|
|
32
|
+
* carrying overrides is the normal case rather than the exception, so caching
|
|
33
|
+
* them by name the way the content jobs do would save nothing.
|
|
34
|
+
*/
|
|
35
|
+
export function extraJobs(config, resolved, stamper) {
|
|
36
|
+
// `resolveSizes` never returns an empty list; the default is for the type.
|
|
37
|
+
const [firstSize = SIZE_PRESETS.og] = resolved.sizes;
|
|
38
|
+
return (config?.extra ?? []).map((image, index) => {
|
|
39
|
+
checkImage(image, index);
|
|
40
|
+
const size = image.size ?? firstSize;
|
|
41
|
+
return {
|
|
42
|
+
contentPath: undefined,
|
|
43
|
+
// Not a page, so not something the manifest can key by.
|
|
44
|
+
slug: undefined,
|
|
45
|
+
props: image.props,
|
|
46
|
+
size,
|
|
47
|
+
// Left as written rather than made absolute: the file system resolves a
|
|
48
|
+
// relative path against the working directory anyway, and the build log
|
|
49
|
+
// reads better saying what the config said.
|
|
50
|
+
outputPath: image.output,
|
|
51
|
+
// An extra names its own path, so the placement — which maps posts to
|
|
52
|
+
// paths — has nothing to say about where this one is served, nor about
|
|
53
|
+
// hashing a filename it did not choose.
|
|
54
|
+
url: undefined,
|
|
55
|
+
stamp: stamper.stamp(image.props, size),
|
|
56
|
+
config: resolveConfigForSize(config, size),
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=extra.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extra.js","sourceRoot":"","sources":["../../src/generate/extra.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,KAAiB,EAAE,KAAa;IAClD,qEAAqE;IACrE,MAAM,QAAQ,GAAG,KAGhB,CAAC;IACF,MAAM,KAAK,GAAG,SAAS,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;IAExC,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,gDAAgD,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,+CAA+C,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CACvB,MAAkC,EAClC,QAAwB,EACxB,OAAgB;IAEhB,2EAA2E;IAC3E,MAAM,CAAC,SAAS,GAAG,YAAY,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAErD,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAChD,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;QAErC,OAAO;YACL,WAAW,EAAE,SAAS;YACtB,wDAAwD;YACxD,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI;YACJ,wEAAwE;YACxE,wEAAwE;YACxE,4CAA4C;YAC5C,UAAU,EAAE,KAAK,CAAC,MAAM;YACxB,sEAAsE;YACtE,uEAAuE;YACvE,wCAAwC;YACxC,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC;YACvC,MAAM,EAAE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC;SAC3C,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GeneratedImage, GenerateOptions } from "./options.js";
|
|
2
|
+
export { defaultOutputPath } from "./output-path.js";
|
|
3
|
+
export type { GeneratedImage, GenerateOptions } from "./options.js";
|
|
4
|
+
/**
|
|
5
|
+
* Walk a content tree and render meta images for every file that declares
|
|
6
|
+
* props, writing PNGs to disk. Images the config declares outright under
|
|
7
|
+
* `extra` are rendered by the same pass, on the same terms.
|
|
8
|
+
*
|
|
9
|
+
* Each image is stamped with a digest of the props, config and size it came
|
|
10
|
+
* from, so a rebuild renders only what has actually changed: an image whose
|
|
11
|
+
* stamp still matches is left alone, and one whose title, colours or template
|
|
12
|
+
* has moved on is rendered again. `overwrite` ignores the stamps and renders
|
|
13
|
+
* everything. Sizes with no image to render are never rasterised.
|
|
14
|
+
*
|
|
15
|
+
* Rendering runs `concurrency` images at a time rather than all of them, so a
|
|
16
|
+
* large tree does not start hundreds of rasterisations at once.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generate(options: GenerateOptions): Promise<GeneratedImage[]>;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generate/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAKpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CA6B3B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { writeManifest } from "../manifest/index.js";
|
|
2
|
+
import { mapConcurrent } from "../pool.js";
|
|
3
|
+
import { readPngStamp } from "../stamp/index.js";
|
|
4
|
+
import { resolveConcurrency } from "./options.js";
|
|
5
|
+
import { planBuild } from "./plan.js";
|
|
6
|
+
import { renderImage } from "./render-image.js";
|
|
7
|
+
export { defaultOutputPath } from "./output-path.js";
|
|
8
|
+
/**
|
|
9
|
+
* Walk a content tree and render meta images for every file that declares
|
|
10
|
+
* props, writing PNGs to disk. Images the config declares outright under
|
|
11
|
+
* `extra` are rendered by the same pass, on the same terms.
|
|
12
|
+
*
|
|
13
|
+
* Each image is stamped with a digest of the props, config and size it came
|
|
14
|
+
* from, so a rebuild renders only what has actually changed: an image whose
|
|
15
|
+
* stamp still matches is left alone, and one whose title, colours or template
|
|
16
|
+
* has moved on is rendered again. `overwrite` ignores the stamps and renders
|
|
17
|
+
* everything. Sizes with no image to render are never rasterised.
|
|
18
|
+
*
|
|
19
|
+
* Rendering runs `concurrency` images at a time rather than all of them, so a
|
|
20
|
+
* large tree does not start hundreds of rasterisations at once.
|
|
21
|
+
*/
|
|
22
|
+
export async function generate(options) {
|
|
23
|
+
const concurrency = resolveConcurrency(options.concurrency);
|
|
24
|
+
const plan = await planBuild(options);
|
|
25
|
+
const results = await mapConcurrent(plan.jobs, concurrency, async (job) => {
|
|
26
|
+
const isSkipped = options.overwrite !== true &&
|
|
27
|
+
(await readPngStamp(job.outputPath)) === job.stamp;
|
|
28
|
+
if (!isSkipped) {
|
|
29
|
+
await renderImage(job, job.stamp);
|
|
30
|
+
}
|
|
31
|
+
const result = {
|
|
32
|
+
contentPath: job.contentPath,
|
|
33
|
+
size: job.size,
|
|
34
|
+
outputPath: job.outputPath,
|
|
35
|
+
url: job.url,
|
|
36
|
+
skipped: isSkipped,
|
|
37
|
+
};
|
|
38
|
+
options.onResult?.(result);
|
|
39
|
+
return result;
|
|
40
|
+
});
|
|
41
|
+
// Written last, and only once every image is on disk: a manifest naming a
|
|
42
|
+
// file that failed to render would outlive the build that failed.
|
|
43
|
+
await writeManifest(plan.manifest);
|
|
44
|
+
return results;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAwB;IAExB,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACxE,MAAM,SAAS,GACb,OAAO,CAAC,SAAS,KAAK,IAAI;YAC1B,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC;QAErD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,MAAM,GAAmB;YAC7B,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,OAAO,EAAE,SAAS;SACnB,CAAC;QACF,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEnC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { MetaImageProps, OutputSize, ResolvedConfig } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* One image to render: what to draw, how big, where it goes, and the config it
|
|
4
|
+
* is drawn with. A content file becomes one job per size; a config `extra`
|
|
5
|
+
* becomes a single job of its own.
|
|
6
|
+
*
|
|
7
|
+
* Working the paths and configs out while planning is what lets the two
|
|
8
|
+
* sources meet: by the time anything is rendered there are only jobs, and
|
|
9
|
+
* nothing downstream has to ask which kind of image it is holding.
|
|
10
|
+
*/
|
|
11
|
+
export interface RenderJob {
|
|
12
|
+
/**
|
|
13
|
+
* The content file this image came from, relative to the content root.
|
|
14
|
+
* `undefined` for an extra image, which has no content file.
|
|
15
|
+
*/
|
|
16
|
+
readonly contentPath: string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* The slug the page is addressed by, and the key it appears under in the
|
|
19
|
+
* manifest. `undefined` for an extra image, which is not a page.
|
|
20
|
+
*/
|
|
21
|
+
readonly slug: string | undefined;
|
|
22
|
+
readonly props: MetaImageProps;
|
|
23
|
+
readonly size: OutputSize;
|
|
24
|
+
readonly outputPath: string;
|
|
25
|
+
/** Where the image is served, if the placement knows. */
|
|
26
|
+
readonly url: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The digest of everything this image is drawn from. An image on disk
|
|
29
|
+
* carrying the same one is already up to date, and a placement that hashes
|
|
30
|
+
* filenames names the file after it.
|
|
31
|
+
*/
|
|
32
|
+
readonly stamp: string;
|
|
33
|
+
readonly config: ResolvedConfig;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../src/generate/job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9E;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job.js","sourceRoot":"","sources":["../../src/generate/job.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ContentFile, WalkOptions } from "../content/index.js";
|
|
2
|
+
import type { ColophonConfig, OutputSize } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Outcome for one generated (or skipped) image.
|
|
5
|
+
*/
|
|
6
|
+
export interface GeneratedImage {
|
|
7
|
+
/**
|
|
8
|
+
* The content file this image came from, relative to the content root.
|
|
9
|
+
* `undefined` for a config `extra` image: there is no post behind it, and
|
|
10
|
+
* naming one — the output path, say — would quietly break anything grouping
|
|
11
|
+
* results by the post they belong to.
|
|
12
|
+
*/
|
|
13
|
+
readonly contentPath: string | undefined;
|
|
14
|
+
readonly size: OutputSize;
|
|
15
|
+
readonly outputPath: string;
|
|
16
|
+
/**
|
|
17
|
+
* Where the image is served, from the configured placement. `undefined`
|
|
18
|
+
* when nothing says: no `urlBase`, an image placed by `outputPath`, or an
|
|
19
|
+
* `extra` that named its own path.
|
|
20
|
+
*/
|
|
21
|
+
readonly url: string | undefined;
|
|
22
|
+
/** True when an up-to-date image was left in place (no `overwrite`). */
|
|
23
|
+
readonly skipped: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for `generate`.
|
|
27
|
+
*/
|
|
28
|
+
export interface GenerateOptions {
|
|
29
|
+
/** Root content directory to walk. */
|
|
30
|
+
readonly contentDir: string;
|
|
31
|
+
readonly config?: ColophonConfig;
|
|
32
|
+
/** Extra walk options (props key, template field, slug field, extensions). */
|
|
33
|
+
readonly walk?: Omit<WalkOptions, "dir">;
|
|
34
|
+
/** Override where each image is written. */
|
|
35
|
+
readonly outputPath?: (file: ContentFile, size: OutputSize) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Re-render every image, ignoring the stamps that would otherwise mark them
|
|
38
|
+
* as up to date. Default `false`.
|
|
39
|
+
*/
|
|
40
|
+
readonly overwrite?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* How many images to render at once. Defaults to the number of CPUs the
|
|
43
|
+
* process can use. Must be a positive integer.
|
|
44
|
+
*/
|
|
45
|
+
readonly concurrency?: number;
|
|
46
|
+
/** Called after each image is written or skipped. */
|
|
47
|
+
readonly onResult?: (result: GeneratedImage) => void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* How many images to render at once when nothing is configured: one per CPU
|
|
51
|
+
* the process can actually use. Rasterising is CPU-bound, so starting more
|
|
52
|
+
* than that only queues the work up while holding every pending image in
|
|
53
|
+
* memory.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveConcurrency(concurrency: number | undefined): number;
|
|
56
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/generate/options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACzC,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;IACtE;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CACtD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAY1E"}
|