@kensio/colophon 2.3.0 → 2.4.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 +62 -801
- package/dist/background.d.ts +7 -2
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +44 -1
- package/dist/background.js.map +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/config.d.ts +1 -1
- package/dist/cli/config.js +1 -1
- package/dist/config/defaults.d.ts +8 -7
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +8 -8
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +5 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/resolve.d.ts +7 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +16 -0
- package/dist/config/resolve.js.map +1 -1
- package/dist/config/size.d.ts +1 -1
- package/dist/config/size.d.ts.map +1 -1
- package/dist/config/size.js +3 -2
- package/dist/config/size.js.map +1 -1
- package/dist/content/props.d.ts +2 -2
- package/dist/content/props.js +2 -2
- package/dist/content/slug.d.ts +5 -5
- package/dist/content/slug.js +6 -6
- package/dist/content/slug.js.map +1 -1
- package/dist/content/walk.d.ts +1 -1
- package/dist/content/walk.js +1 -1
- package/dist/fonts/index.d.ts +3 -2
- package/dist/fonts/index.d.ts.map +1 -1
- package/dist/fonts/index.js +3 -2
- package/dist/fonts/index.js.map +1 -1
- package/dist/fonts/resolve.js +1 -1
- package/dist/generate/extra.js +4 -4
- package/dist/generate/extra.js.map +1 -1
- package/dist/generate/options.d.ts +1 -1
- package/dist/generate/outputs.d.ts +4 -4
- package/dist/generate/outputs.js +4 -4
- package/dist/highlight/language.d.ts +2 -3
- package/dist/highlight/language.d.ts.map +1 -1
- package/dist/highlight/language.js +3 -4
- package/dist/highlight/language.js.map +1 -1
- package/dist/highlight/normalise.d.ts +2 -2
- package/dist/highlight/normalise.js +2 -2
- package/dist/image/index.d.ts +18 -0
- package/dist/image/index.d.ts.map +1 -0
- package/dist/image/index.js +42 -0
- package/dist/image/index.js.map +1 -0
- package/dist/image/jpeg.d.ts +10 -0
- package/dist/image/jpeg.d.ts.map +1 -0
- package/dist/image/jpeg.js +57 -0
- package/dist/image/jpeg.js.map +1 -0
- package/dist/image/load.d.ts +4 -0
- package/dist/image/load.d.ts.map +1 -0
- package/dist/image/load.js +60 -0
- package/dist/image/load.js.map +1 -0
- package/dist/image/media.d.ts +10 -0
- package/dist/image/media.d.ts.map +1 -0
- package/dist/image/media.js +37 -0
- package/dist/image/media.js.map +1 -0
- package/dist/image/resolve.d.ts +13 -0
- package/dist/image/resolve.d.ts.map +1 -0
- package/dist/image/resolve.js +38 -0
- package/dist/image/resolve.js.map +1 -0
- package/dist/image/size.d.ts +22 -0
- package/dist/image/size.d.ts.map +1 -0
- package/dist/image/size.js +60 -0
- package/dist/image/size.js.map +1 -0
- package/dist/image/svg.d.ts +12 -0
- package/dist/image/svg.d.ts.map +1 -0
- package/dist/image/svg.js +61 -0
- package/dist/image/svg.js.map +1 -0
- package/dist/image/uri.d.ts +9 -0
- package/dist/image/uri.d.ts.map +1 -0
- package/dist/image/uri.js +22 -0
- package/dist/image/uri.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/block.d.ts +37 -0
- package/dist/layout/block.d.ts.map +1 -0
- package/dist/layout/block.js +26 -0
- package/dist/layout/block.js.map +1 -0
- package/dist/layout/box.d.ts +20 -0
- package/dist/layout/box.d.ts.map +1 -0
- package/dist/layout/box.js +61 -0
- package/dist/layout/box.js.map +1 -0
- package/dist/layout/distribute.d.ts +15 -0
- package/dist/layout/distribute.d.ts.map +1 -0
- package/dist/layout/distribute.js +30 -0
- package/dist/layout/distribute.js.map +1 -0
- package/dist/layout/image.d.ts +42 -0
- package/dist/layout/image.d.ts.map +1 -0
- package/dist/layout/image.js +34 -0
- package/dist/layout/image.js.map +1 -0
- package/dist/layout/index.d.ts +40 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +30 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/lines.d.ts +45 -0
- package/dist/layout/lines.d.ts.map +1 -0
- package/dist/layout/lines.js +71 -0
- package/dist/layout/lines.js.map +1 -0
- package/dist/layout/measure.d.ts +11 -0
- package/dist/layout/measure.d.ts.map +1 -0
- package/dist/layout/measure.js +11 -0
- package/dist/layout/measure.js.map +1 -0
- package/dist/layout/panel.d.ts +20 -0
- package/dist/layout/panel.d.ts.map +1 -0
- package/dist/layout/panel.js +22 -0
- package/dist/layout/panel.js.map +1 -0
- package/dist/layout/row.d.ts +15 -0
- package/dist/layout/row.d.ts.map +1 -0
- package/dist/layout/row.js +20 -0
- package/dist/layout/row.js.map +1 -0
- package/dist/layout/scrim.d.ts +23 -0
- package/dist/layout/scrim.d.ts.map +1 -0
- package/dist/layout/scrim.js +38 -0
- package/dist/layout/scrim.js.map +1 -0
- package/dist/layout/stack.d.ts +14 -0
- package/dist/layout/stack.d.ts.map +1 -0
- package/dist/layout/stack.js +19 -0
- package/dist/layout/stack.js.map +1 -0
- package/dist/layout/types.d.ts +49 -0
- package/dist/layout/types.d.ts.map +1 -0
- package/dist/layout/types.js +2 -0
- package/dist/layout/types.js.map +1 -0
- package/dist/manifest/build.d.ts +1 -1
- package/dist/manifest/build.js +1 -1
- package/dist/manifest/index.d.ts +1 -1
- package/dist/manifest/index.js +1 -1
- package/dist/manifest/order.d.ts +1 -1
- package/dist/manifest/order.js +1 -1
- package/dist/manifest/page.d.ts +2 -2
- package/dist/manifest/page.js +3 -3
- package/dist/measure/estimate.d.ts +10 -0
- package/dist/measure/estimate.d.ts.map +1 -0
- package/dist/measure/estimate.js +58 -0
- package/dist/measure/estimate.js.map +1 -0
- package/dist/measure/faces.d.ts +15 -0
- package/dist/measure/faces.d.ts.map +1 -0
- package/dist/measure/faces.js +70 -0
- package/dist/measure/faces.js.map +1 -0
- package/dist/measure/index.d.ts +16 -0
- package/dist/measure/index.d.ts.map +1 -0
- package/dist/measure/index.js +0 -0
- package/dist/measure/index.js.map +1 -0
- package/dist/measure/runs.d.ts +17 -0
- package/dist/measure/runs.d.ts.map +1 -0
- package/dist/measure/runs.js +39 -0
- package/dist/measure/runs.js.map +1 -0
- package/dist/measure/select.d.ts +13 -0
- package/dist/measure/select.d.ts.map +1 -0
- package/dist/measure/select.js +47 -0
- package/dist/measure/select.js.map +1 -0
- package/dist/meta/tags.d.ts +6 -6
- package/dist/meta/tags.js +6 -6
- package/dist/meta/url.d.ts +4 -4
- package/dist/meta/url.js +4 -4
- package/dist/placement/check.d.ts +1 -1
- package/dist/placement/check.js +1 -1
- package/dist/placement/index.js +1 -1
- package/dist/placement/relative.d.ts +3 -3
- package/dist/placement/relative.js +3 -3
- package/dist/pool.d.ts +2 -2
- package/dist/pool.js +3 -3
- package/dist/pool.js.map +1 -1
- package/dist/props.d.ts +7 -0
- package/dist/props.d.ts.map +1 -0
- package/dist/props.js +17 -0
- package/dist/props.js.map +1 -0
- package/dist/render/svg.d.ts +4 -2
- package/dist/render/svg.d.ts.map +1 -1
- package/dist/render/svg.js +19 -4
- package/dist/render/svg.js.map +1 -1
- package/dist/stamp/config-digest.d.ts.map +1 -1
- package/dist/stamp/config-digest.js +20 -1
- package/dist/stamp/config-digest.js.map +1 -1
- package/dist/stamp/index.js +2 -2
- package/dist/stamp/index.js.map +1 -1
- package/dist/stamp/read.d.ts +1 -1
- package/dist/stamp/read.js +4 -4
- package/dist/templates/attribution.d.ts +17 -0
- package/dist/templates/attribution.d.ts.map +1 -0
- package/dist/templates/attribution.js +39 -0
- package/dist/templates/attribution.js.map +1 -0
- package/dist/templates/banner/badge.d.ts.map +1 -1
- package/dist/templates/banner/badge.js +3 -6
- package/dist/templates/banner/badge.js.map +1 -1
- package/dist/templates/banner/index.d.ts +3 -0
- package/dist/templates/banner/index.d.ts.map +1 -1
- package/dist/templates/banner/index.js +37 -35
- package/dist/templates/banner/index.js.map +1 -1
- package/dist/templates/banner/lines.d.ts +7 -12
- package/dist/templates/banner/lines.d.ts.map +1 -1
- package/dist/templates/banner/lines.js +23 -34
- package/dist/templates/banner/lines.js.map +1 -1
- package/dist/templates/banner/version.d.ts +9 -0
- package/dist/templates/banner/version.d.ts.map +1 -0
- package/dist/templates/banner/version.js +21 -0
- package/dist/templates/banner/version.js.map +1 -0
- package/dist/templates/card/index.d.ts +4 -1
- package/dist/templates/card/index.d.ts.map +1 -1
- package/dist/templates/card/index.js +37 -25
- package/dist/templates/card/index.js.map +1 -1
- package/dist/templates/card/lines.d.ts +17 -13
- package/dist/templates/card/lines.d.ts.map +1 -1
- package/dist/templates/card/lines.js +24 -20
- package/dist/templates/card/lines.js.map +1 -1
- package/dist/templates/code/chrome.d.ts +7 -3
- package/dist/templates/code/chrome.d.ts.map +1 -1
- package/dist/templates/code/chrome.js +12 -11
- package/dist/templates/code/chrome.js.map +1 -1
- package/dist/templates/code/clip.d.ts +1 -1
- package/dist/templates/code/clip.js +1 -1
- package/dist/templates/code/fit.d.ts +2 -2
- package/dist/templates/code/fit.d.ts.map +1 -1
- package/dist/templates/code/fit.js +4 -4
- package/dist/templates/code/fit.js.map +1 -1
- package/dist/templates/code/index.d.ts.map +1 -1
- package/dist/templates/code/index.js +7 -6
- package/dist/templates/code/index.js.map +1 -1
- package/dist/templates/code/layout.d.ts +1 -1
- package/dist/templates/code/layout.d.ts.map +1 -1
- package/dist/templates/code/layout.js +6 -6
- package/dist/templates/code/layout.js.map +1 -1
- package/dist/templates/code/panel.d.ts +13 -0
- package/dist/templates/code/panel.d.ts.map +1 -1
- package/dist/templates/code/panel.js +34 -2
- package/dist/templates/code/panel.js.map +1 -1
- package/dist/templates/code/plate.d.ts +3 -1
- package/dist/templates/code/plate.d.ts.map +1 -1
- package/dist/templates/code/plate.js +11 -9
- package/dist/templates/code/plate.js.map +1 -1
- package/dist/templates/code/spans.js +1 -1
- package/dist/templates/code/spans.js.map +1 -1
- package/dist/templates/code/width.d.ts +10 -0
- package/dist/templates/code/width.d.ts.map +1 -0
- package/dist/templates/code/width.js +26 -0
- package/dist/templates/code/width.js.map +1 -0
- package/dist/templates/footer.d.ts +8 -0
- package/dist/templates/footer.d.ts.map +1 -1
- package/dist/templates/footer.js +11 -1
- package/dist/templates/footer.js.map +1 -1
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +1 -1
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/logo.d.ts +15 -0
- package/dist/templates/logo.d.ts.map +1 -0
- package/dist/templates/logo.js +30 -0
- package/dist/templates/logo.js.map +1 -0
- package/dist/templates/measure.d.ts +11 -0
- package/dist/templates/measure.d.ts.map +1 -0
- package/dist/templates/measure.js +11 -0
- package/dist/templates/measure.js.map +1 -0
- package/dist/templates/props.d.ts +2 -2
- package/dist/templates/props.js +2 -2
- package/dist/templates/text.d.ts +37 -0
- package/dist/templates/text.d.ts.map +1 -0
- package/dist/templates/text.js +26 -0
- package/dist/templates/text.js.map +1 -0
- package/dist/text/break.d.ts +11 -0
- package/dist/text/break.d.ts.map +1 -0
- package/dist/text/break.js +30 -0
- package/dist/text/break.js.map +1 -0
- package/dist/text/fit.d.ts +30 -0
- package/dist/text/fit.d.ts.map +1 -0
- package/dist/text/fit.js +29 -0
- package/dist/text/fit.js.map +1 -0
- package/dist/text/index.d.ts +5 -3
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.js +3 -2
- package/dist/text/index.js.map +1 -1
- package/dist/text/wrap.d.ts +17 -7
- package/dist/text/wrap.d.ts.map +1 -1
- package/dist/text/wrap.js +25 -17
- package/dist/text/wrap.js.map +1 -1
- package/dist/types.d.ts +161 -45
- package/dist/types.d.ts.map +1 -1
- package/dist/validate/index.d.ts +1 -1
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +3 -2
- package/dist/validate/index.js.map +1 -1
- package/dist/validate/keys.d.ts +19 -2
- package/dist/validate/keys.d.ts.map +1 -1
- package/dist/validate/keys.js +40 -3
- package/dist/validate/keys.js.map +1 -1
- package/dist/validate/suggest.d.ts.map +1 -1
- package/dist/validate/suggest.js +21 -3
- package/dist/validate/suggest.js.map +1 -1
- package/dist/validate/values.d.ts +2 -2
- package/dist/validate/values.d.ts.map +1 -1
- package/dist/validate/values.js +17 -3
- package/dist/validate/values.js.map +1 -1
- package/package.json +7 -1
package/dist/stamp/read.js
CHANGED
|
@@ -2,14 +2,14 @@ import { open } from "node:fs/promises";
|
|
|
2
2
|
import { pngSignature, stampKeyword } from "./chunk.js";
|
|
3
3
|
/**
|
|
4
4
|
* How much of a PNG to read when looking for a stamp. The stamp goes in
|
|
5
|
-
* immediately after `IHDR`, so this only has to cover the header
|
|
5
|
+
* immediately after `IHDR`, so this only has to cover the header. Reading
|
|
6
6
|
* whole images just to compare a hash would defeat the point of skipping them.
|
|
7
7
|
*/
|
|
8
8
|
const headBytes = 4096;
|
|
9
9
|
/**
|
|
10
10
|
* Find the stamp in the leading bytes of a PNG, or `undefined` if there is
|
|
11
|
-
* none
|
|
12
|
-
* not stamp yet.
|
|
11
|
+
* none, meaning the image was written by something else, or by a Colophon
|
|
12
|
+
* that did not stamp yet.
|
|
13
13
|
*/
|
|
14
14
|
function findStamp(head) {
|
|
15
15
|
if (!head.subarray(0, pngSignature.length).equals(pngSignature)) {
|
|
@@ -39,7 +39,7 @@ function findStamp(head) {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Read the stamp out of a PNG file. Returns `undefined` when the file is
|
|
42
|
-
* missing, unreadable, not a PNG, or carries no stamp
|
|
42
|
+
* missing, unreadable, not a PNG, or carries no stamp, all of which mean the
|
|
43
43
|
* image cannot be shown to be up to date, so it should be rendered again.
|
|
44
44
|
*/
|
|
45
45
|
export async function readPngStamp(file) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ImageAsset, MeasureText, ResolvedConfig } from "../types.js";
|
|
2
|
+
import type { FooterPlacement } from "./footer.js";
|
|
3
|
+
/** Where the attribution line goes: a footer placement, plus room to lay it out. */
|
|
4
|
+
export interface AttributionPlacement extends FooterPlacement {
|
|
5
|
+
/** Left edge and width of the content area the line is set within. */
|
|
6
|
+
readonly left: number;
|
|
7
|
+
readonly width: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The footer line, with the post's avatar before it.
|
|
11
|
+
*
|
|
12
|
+
* Both belong to the same idea, which is who made this, so they are drawn as
|
|
13
|
+
* one line rather than tucked into separate corners. Without an avatar this is
|
|
14
|
+
* the footer exactly as it was, down to the byte.
|
|
15
|
+
*/
|
|
16
|
+
export declare function attribution(config: ResolvedConfig, placement: AttributionPlacement, avatar: ImageAsset | undefined, measure: MeasureText): string;
|
|
17
|
+
//# sourceMappingURL=attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/templates/attribution.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAYnD,oFAAoF;AACpF,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,oBAAoB,EAC/B,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,OAAO,EAAE,WAAW,GACnB,MAAM,CAqCR"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { image, measureIn, row } from "../layout/index.js";
|
|
2
|
+
import { footerElement, hasFooter } from "./footer.js";
|
|
3
|
+
/** The avatar's diameter, as a multiple of the footer's font size. */
|
|
4
|
+
const avatarScale = 1.9;
|
|
5
|
+
/** Where a circular avatar's centre sits above the footer's baseline. */
|
|
6
|
+
const avatarRise = 0.34;
|
|
7
|
+
/** Unique within one image, which is as many avatars as there are. */
|
|
8
|
+
const avatarId = "colophon-avatar";
|
|
9
|
+
/**
|
|
10
|
+
* The footer line, with the post's avatar before it.
|
|
11
|
+
*
|
|
12
|
+
* Both belong to the same idea, which is who made this, so they are drawn as
|
|
13
|
+
* one line rather than tucked into separate corners. Without an avatar this is
|
|
14
|
+
* the footer exactly as it was, down to the byte.
|
|
15
|
+
*/
|
|
16
|
+
export function attribution(config, placement, avatar, measure) {
|
|
17
|
+
if (avatar === undefined) {
|
|
18
|
+
return footerElement(config, placement);
|
|
19
|
+
}
|
|
20
|
+
const { fontSize } = placement;
|
|
21
|
+
const size = Math.round(fontSize * avatarScale);
|
|
22
|
+
const text = hasFooter(config) ? (config.footer ?? "") : "";
|
|
23
|
+
const gap = text === "" ? 0 : Math.round(fontSize * 0.5);
|
|
24
|
+
const textWidth = text === ""
|
|
25
|
+
? 0
|
|
26
|
+
: measureIn(measure, config.fontFamily, 500)(text, fontSize);
|
|
27
|
+
// Only the horizontal placement comes from the row. The baseline is the one
|
|
28
|
+
// the template asked for, so a footer with no avatar and a footer with one
|
|
29
|
+
// sit at the same height.
|
|
30
|
+
const [portrait, label] = row([{ size }, { size: Math.round(textWidth), gapBefore: gap }], { x: placement.left, y: placement.y, width: placement.width, height: size }, placement.anchor === "middle" ? "centre" : "start");
|
|
31
|
+
const top = Math.round(placement.y - fontSize * avatarRise - size / 2);
|
|
32
|
+
return (image({ x: portrait?.x ?? placement.left, y: top, width: size, height: size }, avatar.href, { fit: "cover", radius: Math.round(size / 2), id: avatarId }) +
|
|
33
|
+
footerElement(config, {
|
|
34
|
+
...placement,
|
|
35
|
+
x: label?.x ?? placement.left,
|
|
36
|
+
anchor: "start",
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=attribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.js","sourceRoot":"","sources":["../../src/templates/attribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvD,sEAAsE;AACtE,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,yEAAyE;AACzE,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,sEAAsE;AACtE,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AASnC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAAsB,EACtB,SAA+B,EAC/B,MAA8B,EAC9B,OAAoB;IAEpB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;IACzD,MAAM,SAAS,GACb,IAAI,KAAK,EAAE;QACT,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEjE,4EAA4E;IAC5E,2EAA2E;IAC3E,0BAA0B;IAC1B,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,GAAG,CAC3B,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAC3D,EAAE,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAC3E,SAAS,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CACnD,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;IAEvE,OAAO,CACL,KAAK,CACH,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EACvE,MAAM,CAAC,IAAI,EACX,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAC7D;QACD,aAAa,CAAC,MAAM,EAAE;YACpB,GAAG,SAAS;YACZ,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,SAAS,CAAC,IAAI;YAC7B,MAAM,EAAE,OAAO;SAChB,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/badge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/badge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAoBR"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { textElement } from "../../
|
|
1
|
+
import { box, textElement } from "../../layout/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* The corner badge: a rounded plate with the badge text on it, sized from the
|
|
4
4
|
* plate height so it scales with the image rather than the text length.
|
|
@@ -7,10 +7,7 @@ export function renderBadge(badge, fontFamily, brand, pad, height) {
|
|
|
7
7
|
const fontSize = Math.round(height * 0.6);
|
|
8
8
|
const padX = Math.round(height * 0.36);
|
|
9
9
|
const width = Math.round(badge.text.length * fontSize * 0.64 + padX * 2);
|
|
10
|
-
const
|
|
11
|
-
const rect = `<rect x="${String(pad)}" y="${String(pad)}"` +
|
|
12
|
-
` width="${String(width)}" height="${String(height)}"` +
|
|
13
|
-
` rx="${String(radius)}" fill="${badge.background ?? "#ffffff"}"/>`;
|
|
10
|
+
const plate = box({ x: pad, y: pad, width, height }, { radius: Math.round(height * 0.1), fill: badge.background ?? "#ffffff" });
|
|
14
11
|
const text = textElement(badge.text, {
|
|
15
12
|
x: pad + padX,
|
|
16
13
|
y: pad + Math.round(height * 0.72),
|
|
@@ -19,6 +16,6 @@ export function renderBadge(badge, fontFamily, brand, pad, height) {
|
|
|
19
16
|
fontWeight: 900,
|
|
20
17
|
fill: badge.color ?? brand,
|
|
21
18
|
});
|
|
22
|
-
return
|
|
19
|
+
return plate + text;
|
|
23
20
|
}
|
|
24
21
|
//# sourceMappingURL=badge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../src/templates/banner/badge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../src/templates/banner/badge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,KAAY,EACZ,UAAkB,EAClB,KAAa,EACb,GAAW,EACX,MAAc;IAEd,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;IAEzE,MAAM,KAAK,GAAG,GAAG,CACf,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EACjC,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,EAAE,CAC1E,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE;QACnC,CAAC,EAAE,GAAG,GAAG,IAAI;QACb,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QAClC,UAAU;QACV,QAAQ;QACR,UAAU,EAAE,GAAG;QACf,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK;KAC3B,CAAC,CAAC;IAEH,OAAO,KAAK,GAAG,IAAI,CAAC;AACtB,CAAC"}
|
|
@@ -4,6 +4,9 @@ import type { Template } from "../../types.js";
|
|
|
4
4
|
* version and wrapped subtitle, an optional corner badge, and an optional
|
|
5
5
|
* footer. This is the configurable descendant of the original `npm_package`
|
|
6
6
|
* layout.
|
|
7
|
+
*
|
|
8
|
+
* A logo goes in the opposite corner to the badge, which is the corner the
|
|
9
|
+
* left-aligned text leaves free, and the avatar sits with the footer.
|
|
7
10
|
*/
|
|
8
11
|
export declare const bannerTemplate: Template;
|
|
9
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAOhE;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,QAmF5B,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { drawLines, inset } from "../../layout/index.js";
|
|
2
|
+
import { optionalString } from "../../props.js";
|
|
3
|
+
import { attribution } from "../attribution.js";
|
|
4
|
+
import { footerBaseline, hasFooter } from "../footer.js";
|
|
5
|
+
import { logoElement, logoRect } from "../logo.js";
|
|
4
6
|
import { renderBadge } from "./badge.js";
|
|
5
7
|
import { bannerLines } from "./lines.js";
|
|
6
8
|
/**
|
|
@@ -8,59 +10,59 @@ import { bannerLines } from "./lines.js";
|
|
|
8
10
|
* version and wrapped subtitle, an optional corner badge, and an optional
|
|
9
11
|
* footer. This is the configurable descendant of the original `npm_package`
|
|
10
12
|
* layout.
|
|
13
|
+
*
|
|
14
|
+
* A logo goes in the opposite corner to the badge, which is the corner the
|
|
15
|
+
* left-aligned text leaves free, and the avatar sits with the footer.
|
|
11
16
|
*/
|
|
12
17
|
export const bannerTemplate = {
|
|
13
18
|
name: "banner",
|
|
14
|
-
render({ props, config, dimensions }) {
|
|
19
|
+
render({ props, config, dimensions, measure, logo, avatar, }) {
|
|
15
20
|
const { width, height } = dimensions;
|
|
16
21
|
const { fontFamily } = config;
|
|
17
22
|
const pad = Math.round(width * 0.075);
|
|
18
|
-
const contentWidth = width - pad * 2;
|
|
19
|
-
const subtitle = optionalString(props.subtitle);
|
|
20
|
-
const hasSubtitle = subtitle !== undefined && subtitle !== "";
|
|
21
|
-
const titleFs = Math.round(height * (hasSubtitle ? 0.078 : 0.092));
|
|
22
23
|
const footerFs = Math.round(height * 0.034);
|
|
23
24
|
const badgeHeight = Math.round(height * 0.072);
|
|
25
|
+
const mark = logoRect(logo, dimensions, pad, "start");
|
|
26
|
+
const subtitle = optionalString(props.subtitle);
|
|
27
|
+
const hasSubtitle = subtitle !== undefined && subtitle !== "";
|
|
28
|
+
// The text sits between whatever the marks along the top and the footer
|
|
29
|
+
// along the bottom leave behind.
|
|
30
|
+
const topMark = Math.max(config.badge === undefined ? 0 : badgeHeight, mark?.height ?? 0);
|
|
31
|
+
const area = inset({ x: 0, y: 0, width, height }, {
|
|
32
|
+
top: pad + (topMark === 0 ? 0 : topMark + Math.round(height * 0.03)),
|
|
33
|
+
right: pad,
|
|
34
|
+
left: pad,
|
|
35
|
+
bottom: pad +
|
|
36
|
+
(hasFooter(config) || avatar !== undefined
|
|
37
|
+
? footerFs + Math.round(height * 0.02)
|
|
38
|
+
: 0),
|
|
39
|
+
});
|
|
24
40
|
const lines = bannerLines(props, {
|
|
25
41
|
height,
|
|
26
|
-
contentWidth,
|
|
27
|
-
titleFs,
|
|
42
|
+
contentWidth: area.width,
|
|
43
|
+
titleFs: Math.round(height * (hasSubtitle ? 0.078 : 0.092)),
|
|
28
44
|
versionFs: Math.round(height * 0.04),
|
|
29
45
|
subFs: Math.round(height * 0.05),
|
|
46
|
+
measure,
|
|
47
|
+
fontFamily,
|
|
30
48
|
});
|
|
31
|
-
const
|
|
32
|
-
(config.badge === undefined
|
|
33
|
-
? 0
|
|
34
|
-
: badgeHeight + Math.round(height * 0.03));
|
|
35
|
-
const bottom = height -
|
|
36
|
-
pad -
|
|
37
|
-
(hasFooter(config) ? footerFs + Math.round(height * 0.02) : 0);
|
|
38
|
-
const placed = layoutStack(lines.map((line) => ({
|
|
39
|
-
fontSize: line.fontSize,
|
|
40
|
-
lineHeight: 1.15,
|
|
41
|
-
...(line.gapBefore !== undefined && { gapBefore: line.gapBefore }),
|
|
42
|
-
})), top, bottom);
|
|
43
|
-
const body = lines
|
|
44
|
-
.map((line, index) => textElement(line.text, {
|
|
45
|
-
x: pad,
|
|
46
|
-
y: placed[index]?.y ?? top,
|
|
49
|
+
const body = drawLines(lines, area, {
|
|
47
50
|
fontFamily,
|
|
48
|
-
fontSize: line.fontSize,
|
|
49
|
-
fontWeight: line.fontWeight,
|
|
50
51
|
fill: config.colors.foreground,
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
.join("");
|
|
52
|
+
lineHeight: 1.28,
|
|
53
|
+
});
|
|
54
54
|
const badge = config.badge === undefined
|
|
55
55
|
? ""
|
|
56
56
|
: renderBadge(config.badge, fontFamily, config.colors.brand, pad, badgeHeight);
|
|
57
|
-
const footer =
|
|
57
|
+
const footer = attribution(config, {
|
|
58
58
|
x: pad,
|
|
59
|
-
y: height
|
|
59
|
+
y: footerBaseline(height, pad, footerFs),
|
|
60
60
|
fontSize: footerFs,
|
|
61
61
|
opacity: 0.78,
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
left: pad,
|
|
63
|
+
width: width - pad * 2,
|
|
64
|
+
}, avatar, measure);
|
|
65
|
+
return badge + logoElement(logo, mark) + body + footer;
|
|
64
66
|
},
|
|
65
67
|
};
|
|
66
68
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/banner/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
import type { MetaImageProps } from "../../types.js";
|
|
1
|
+
import type { MeasureText, MetaImageProps } from "../../types.js";
|
|
2
|
+
import type { TextLine } from "../../layout/index.js";
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* The font sizes the banner's text is drawn at, all keyed to image height,
|
|
5
|
+
* along with the space it has and how to measure text into it.
|
|
5
6
|
*/
|
|
6
|
-
export interface BannerLine {
|
|
7
|
-
readonly text: string;
|
|
8
|
-
readonly fontSize: number;
|
|
9
|
-
readonly fontWeight: number;
|
|
10
|
-
readonly opacity: number;
|
|
11
|
-
readonly gapBefore?: number;
|
|
12
|
-
}
|
|
13
|
-
/** The font sizes the banner's text is drawn at, all keyed to image height. */
|
|
14
7
|
export interface BannerSizes {
|
|
15
8
|
readonly height: number;
|
|
16
9
|
readonly contentWidth: number;
|
|
17
10
|
readonly titleFs: number;
|
|
18
11
|
readonly versionFs: number;
|
|
19
12
|
readonly subFs: number;
|
|
13
|
+
readonly measure: MeasureText;
|
|
14
|
+
readonly fontFamily: string;
|
|
20
15
|
}
|
|
21
16
|
/**
|
|
22
17
|
* The banner's text block: the wrapped title, an optional version, and the
|
|
23
18
|
* wrapped subtitle. Extra breathing room goes before the version and subtitle
|
|
24
19
|
* groups so the three do not read as one squashed block.
|
|
25
20
|
*/
|
|
26
|
-
export declare function bannerLines(props: MetaImageProps, sizes: BannerSizes):
|
|
21
|
+
export declare function bannerLines(props: MetaImageProps, sizes: BannerSizes): TextLine[];
|
|
27
22
|
//# sourceMappingURL=lines.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAStD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,GACjB,QAAQ,EAAE,CAuBZ"}
|
|
@@ -1,46 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { blockLines } from "../../layout/index.js";
|
|
2
|
+
import { versionLines } from "./version.js";
|
|
3
3
|
const maxTitleLines = 3;
|
|
4
4
|
const maxSubtitleLines = 4;
|
|
5
|
+
const titleFloor = 0.62;
|
|
6
|
+
const subtitleFloor = 0.8;
|
|
5
7
|
/**
|
|
6
8
|
* The banner's text block: the wrapped title, an optional version, and the
|
|
7
9
|
* wrapped subtitle. Extra breathing room goes before the version and subtitle
|
|
8
10
|
* groups so the three do not read as one squashed block.
|
|
9
11
|
*/
|
|
10
12
|
export function bannerLines(props, sizes) {
|
|
11
|
-
const { height, contentWidth,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fontWeight: 700,
|
|
28
|
-
opacity: 0.85,
|
|
29
|
-
gapBefore: Math.round(height * 0.03),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
const subtitleLines = subtitle === undefined || subtitle === ""
|
|
33
|
-
? []
|
|
34
|
-
: wrapText(subtitle, estimateCharsPerLine(contentWidth, subFs, 0.55)).slice(0, maxSubtitleLines);
|
|
35
|
-
for (const [index, text] of subtitleLines.entries()) {
|
|
36
|
-
lines.push({
|
|
37
|
-
text,
|
|
38
|
-
fontSize: subFs,
|
|
13
|
+
const { height, contentWidth, measure, fontFamily } = sizes;
|
|
14
|
+
return [
|
|
15
|
+
...blockLines(props.title, measure, fontFamily, {
|
|
16
|
+
maxWidth: contentWidth,
|
|
17
|
+
maxLines: maxTitleLines,
|
|
18
|
+
fontSize: sizes.titleFs,
|
|
19
|
+
floor: titleFloor,
|
|
20
|
+
fontWeight: 800,
|
|
21
|
+
opacity: 0.98,
|
|
22
|
+
}),
|
|
23
|
+
...versionLines(props, sizes),
|
|
24
|
+
...blockLines(props.subtitle, measure, fontFamily, {
|
|
25
|
+
maxWidth: contentWidth,
|
|
26
|
+
maxLines: maxSubtitleLines,
|
|
27
|
+
fontSize: sizes.subFs,
|
|
28
|
+
floor: subtitleFloor,
|
|
39
29
|
fontWeight: 500,
|
|
40
30
|
opacity: 0.86,
|
|
41
|
-
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
return lines;
|
|
31
|
+
gapBefore: Math.round(height * 0.045),
|
|
32
|
+
}),
|
|
33
|
+
];
|
|
45
34
|
}
|
|
46
35
|
//# sourceMappingURL=lines.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../../../src/templates/banner/lines.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,aAAa,GAAG,GAAG,CAAC;AAgB1B;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,KAAqB,EACrB,KAAkB;IAElB,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAE5D,OAAO;QACL,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;YAC9C,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,KAAK,CAAC,OAAO;YACvB,KAAK,EAAE,UAAU;YACjB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;SACd,CAAC;QACF,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC;QAC7B,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE;YACjD,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,KAAK,CAAC,KAAK;YACrB,KAAK,EAAE,aAAa;YACpB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;SACtC,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MetaImageProps } from "../../types.js";
|
|
2
|
+
import type { TextLine } from "../../layout/index.js";
|
|
3
|
+
import type { BannerSizes } from "./lines.js";
|
|
4
|
+
/**
|
|
5
|
+
* The version line, or nothing where there is no version. It is never wrapped
|
|
6
|
+
* or shrunk: a version string that needed either would not be one.
|
|
7
|
+
*/
|
|
8
|
+
export declare function versionLines(props: MetaImageProps, sizes: BannerSizes): readonly TextLine[];
|
|
9
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/templates/banner/version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,GACjB,SAAS,QAAQ,EAAE,CAgBrB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { optionalString } from "../../props.js";
|
|
2
|
+
/**
|
|
3
|
+
* The version line, or nothing where there is no version. It is never wrapped
|
|
4
|
+
* or shrunk: a version string that needed either would not be one.
|
|
5
|
+
*/
|
|
6
|
+
export function versionLines(props, sizes) {
|
|
7
|
+
const version = optionalString(props.version);
|
|
8
|
+
if (version === undefined || version === "") {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
text: `v${version}`,
|
|
14
|
+
fontSize: sizes.versionFs,
|
|
15
|
+
fontWeight: 700,
|
|
16
|
+
opacity: 0.85,
|
|
17
|
+
gapBefore: Math.round(sizes.height * 0.03),
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/templates/banner/version.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIhD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAqB,EACrB,KAAkB;IAElB,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QAC5C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL;YACE,IAAI,EAAE,IAAI,OAAO,EAAE;YACnB,QAAQ,EAAE,KAAK,CAAC,SAAS;YACzB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;SAC3C;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Template } from "../../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Minimal "card" template: a centred title with an optional subtitle. No
|
|
4
|
-
* badge or version
|
|
4
|
+
* badge or version, so it is a quieter alternative to `banner`.
|
|
5
|
+
*
|
|
6
|
+
* A logo goes above the title, centred like everything else here, and the
|
|
7
|
+
* avatar sits with the footer along the bottom.
|
|
5
8
|
*/
|
|
6
9
|
export declare const cardTemplate: Template;
|
|
7
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,gBAAgB,CAAC;AAMhE;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,QA8D1B,CAAC"}
|
|
@@ -1,43 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { drawLines, inset } from "../../layout/index.js";
|
|
2
|
+
import { attribution } from "../attribution.js";
|
|
3
|
+
import { footerBaseline, hasFooter } from "../footer.js";
|
|
4
|
+
import { logoElement, logoRect } from "../logo.js";
|
|
3
5
|
import { cardLines } from "./lines.js";
|
|
4
6
|
/**
|
|
5
7
|
* Minimal "card" template: a centred title with an optional subtitle. No
|
|
6
|
-
* badge or version
|
|
8
|
+
* badge or version, so it is a quieter alternative to `banner`.
|
|
9
|
+
*
|
|
10
|
+
* A logo goes above the title, centred like everything else here, and the
|
|
11
|
+
* avatar sits with the footer along the bottom.
|
|
7
12
|
*/
|
|
8
13
|
export const cardTemplate = {
|
|
9
14
|
name: "card",
|
|
10
|
-
render({ props, config, dimensions }) {
|
|
15
|
+
render({ props, config, dimensions, measure, logo, avatar, }) {
|
|
11
16
|
const { width, height } = dimensions;
|
|
12
17
|
const pad = Math.round(width * 0.09);
|
|
13
|
-
const centreX = Math.round(width / 2);
|
|
14
|
-
const titleFs = Math.round(height * 0.1);
|
|
15
18
|
const footerFs = Math.round(height * 0.032);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
pad
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
const mark = logoRect(logo, dimensions, pad, "middle");
|
|
20
|
+
const area = inset({ x: 0, y: 0, width, height }, {
|
|
21
|
+
top: pad + (mark === undefined ? 0 : mark.height + pad / 2),
|
|
22
|
+
right: pad,
|
|
23
|
+
left: pad,
|
|
24
|
+
bottom: pad +
|
|
25
|
+
(hasFooter(config) || avatar !== undefined
|
|
26
|
+
? footerFs + Math.round(height * 0.02)
|
|
27
|
+
: 0),
|
|
28
|
+
});
|
|
29
|
+
const lines = cardLines(props, {
|
|
30
|
+
measure,
|
|
31
|
+
fontFamily: config.fontFamily,
|
|
32
|
+
contentWidth: area.width,
|
|
33
|
+
titleFs: Math.round(height * 0.1),
|
|
34
|
+
subFs: Math.round(height * 0.045),
|
|
35
|
+
height,
|
|
36
|
+
});
|
|
37
|
+
const body = drawLines(lines, area, {
|
|
25
38
|
fontFamily: config.fontFamily,
|
|
26
|
-
fontSize: line.fontSize,
|
|
27
|
-
fontWeight: line.fontWeight,
|
|
28
39
|
fill: config.colors.foreground,
|
|
29
|
-
|
|
40
|
+
lineHeight: 1.28,
|
|
30
41
|
anchor: "middle",
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
y: height - pad,
|
|
42
|
+
});
|
|
43
|
+
const footer = attribution(config, {
|
|
44
|
+
x: Math.round(width / 2),
|
|
45
|
+
y: footerBaseline(height, pad, footerFs),
|
|
36
46
|
fontSize: footerFs,
|
|
37
47
|
opacity: 0.75,
|
|
38
48
|
anchor: "middle",
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
left: pad,
|
|
50
|
+
width: width - pad * 2,
|
|
51
|
+
}, avatar, measure);
|
|
52
|
+
return logoElement(logo, mark) + body + footer;
|
|
41
53
|
},
|
|
42
54
|
};
|
|
43
55
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAa;IACpC,IAAI,EAAE,MAAM;IACZ,MAAM,CAAC,EACL,KAAK,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,MAAM,GACU;QAChB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,KAAK,CAChB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAC7B;YACE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;YAC3D,KAAK,EAAE,GAAG;YACV,IAAI,EAAE,GAAG;YACT,MAAM,EACJ,GAAG;gBACH,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,SAAS;oBACxC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;oBACtC,CAAC,CAAC,CAAC,CAAC;SACT,CACF,CAAC;QAEF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE;YAC7B,OAAO;YACP,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,IAAI,CAAC,KAAK;YACxB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;YACjC,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;YAClC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;YAC9B,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,WAAW,CACxB,MAAM,EACN;YACE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;YACxB,CAAC,EAAE,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,GAAG;YACT,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,CAAC;SACvB,EACD,MAAM,EACN,OAAO,CACR,CAAC;QAEF,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC;IACjD,CAAC;CACF,CAAC"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import type { MetaImageProps } from "../../types.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
1
|
+
import type { MeasureText, MetaImageProps } from "../../types.js";
|
|
2
|
+
import type { TextLine } from "../../layout/index.js";
|
|
3
|
+
/** The space the card's text has, and how to measure text into it. */
|
|
4
|
+
export interface CardText {
|
|
5
|
+
readonly measure: MeasureText;
|
|
6
|
+
readonly fontFamily: string;
|
|
7
|
+
readonly contentWidth: number;
|
|
8
|
+
readonly titleFs: number;
|
|
9
|
+
readonly subFs: number;
|
|
10
|
+
readonly height: number;
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
|
-
* The card's text block: the wrapped title, then the wrapped subtitle.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* The card's text block: the wrapped title, then the wrapped subtitle.
|
|
14
|
+
*
|
|
15
|
+
* The gap before the subtitle is smaller than the banner's, because the card
|
|
16
|
+
* has only the two groups and they belong together. It is not nothing, though:
|
|
17
|
+
* a title that wraps ends on a line the subtitle would otherwise sit straight
|
|
18
|
+
* underneath, and the change of size and weight alone does not separate them.
|
|
15
19
|
*/
|
|
16
|
-
export declare function cardLines(props: MetaImageProps,
|
|
20
|
+
export declare function cardLines(props: MetaImageProps, text: CardText): TextLine[];
|
|
17
21
|
//# sourceMappingURL=lines.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../../../src/templates/card/lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAQtD,sEAAsE;AACtE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAsB3E"}
|