@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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { textElement } from "../text/index.js";
|
|
2
|
+
import { distribute } from "./distribute.js";
|
|
3
|
+
/** Vertical advance of a line, as a multiple of its font size. */
|
|
4
|
+
const defaultLineHeight = 1.2;
|
|
5
|
+
/**
|
|
6
|
+
* Where the baseline sits within a line's advance. A face puts its ascenders
|
|
7
|
+
* around here, and taking it as a fraction of the size rather than as a metric
|
|
8
|
+
* read from the font means a line lands in the same place whichever font the
|
|
9
|
+
* image is eventually drawn in.
|
|
10
|
+
*/
|
|
11
|
+
const baselineRatio = 0.8;
|
|
12
|
+
/**
|
|
13
|
+
* The baseline of one line of text sitting in a band of its own font size.
|
|
14
|
+
*
|
|
15
|
+
* A template that has set room aside for a single line, rather than stacking
|
|
16
|
+
* several, wants this rather than a fraction of the font size chosen by eye:
|
|
17
|
+
* the ink then lands inside the band that was written down, so the clear space
|
|
18
|
+
* either side of it is the space that was reserved. The descender takes the
|
|
19
|
+
* rest of the band, which is why the room below a line is not the same as the
|
|
20
|
+
* room above it.
|
|
21
|
+
*/
|
|
22
|
+
export function baselineFor(top, fontSize) {
|
|
23
|
+
return Math.round(top + fontSize * baselineRatio);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Place a block of lines within an area and return each baseline.
|
|
27
|
+
*
|
|
28
|
+
* The lines are placed as one block rather than each finding its own middle,
|
|
29
|
+
* which is what keeps a wrapped title reading as a paragraph. A block taller
|
|
30
|
+
* than its area starts at the top and runs over, since a template that has
|
|
31
|
+
* overflowed wants to see it.
|
|
32
|
+
*/
|
|
33
|
+
export function placeLines(lines, area, lineHeight = defaultLineHeight, align = "centre") {
|
|
34
|
+
const placed = distribute(lines.map((line) => ({
|
|
35
|
+
size: line.fontSize * lineHeight,
|
|
36
|
+
...(line.gapBefore !== undefined && { gapBefore: line.gapBefore }),
|
|
37
|
+
})), { start: area.y, end: area.y + area.height }, align);
|
|
38
|
+
return placed.map((placement, index) => ({
|
|
39
|
+
y: baselineFor(placement.start, lines[index]?.fontSize ?? 0),
|
|
40
|
+
index,
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
/** The x a line is drawn from, which the anchor decides. */
|
|
44
|
+
function anchorX(area, anchor) {
|
|
45
|
+
if (anchor === "middle") {
|
|
46
|
+
return Math.round(area.x + area.width / 2);
|
|
47
|
+
}
|
|
48
|
+
return anchor === "end" ? area.x + area.width : area.x;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Draw a block of lines within an area: place them, then write the `<text>`
|
|
52
|
+
* elements. Once a template has fitted its words, this is the whole of what it
|
|
53
|
+
* does with them.
|
|
54
|
+
*/
|
|
55
|
+
export function drawLines(lines, area, style) {
|
|
56
|
+
const placed = placeLines(lines, area, style.lineHeight ?? defaultLineHeight, style.align ?? "centre");
|
|
57
|
+
const x = anchorX(area, style.anchor);
|
|
58
|
+
return lines
|
|
59
|
+
.map((line, index) => textElement(line.text, {
|
|
60
|
+
x,
|
|
61
|
+
y: placed[index]?.y ?? area.y,
|
|
62
|
+
fontFamily: style.fontFamily,
|
|
63
|
+
fontSize: line.fontSize,
|
|
64
|
+
fontWeight: line.fontWeight,
|
|
65
|
+
fill: style.fill,
|
|
66
|
+
fillOpacity: line.opacity,
|
|
67
|
+
...(style.anchor !== undefined && { anchor: style.anchor }),
|
|
68
|
+
}))
|
|
69
|
+
.join("");
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=lines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../../src/layout/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,kEAAkE;AAClE,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAAgB;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,QAAQ,GAAG,aAAa,CAAC,CAAC;AACpD,CAAC;AAoBD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,KAA0B,EAC1B,IAAU,EACV,UAAU,GAAG,iBAAiB,EAC9B,KAAK,GAAU,QAAQ;IAEvB,MAAM,MAAM,GAAG,UAAU,CACvB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,UAAU;QAChC,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;KACnE,CAAC,CAAC,EACH,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAC5C,KAAK,CACN,CAAC;IAEF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC;QAC5D,KAAK;KACN,CAAC,CAAC,CAAC;AACN,CAAC;AAED,4DAA4D;AAC5D,SAAS,OAAO,CAAC,IAAU,EAAE,MAA4B;IACvD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,KAA0B,EAC1B,IAAU,EACV,KAAiB;IAEjB,MAAM,MAAM,GAAG,UAAU,CACvB,KAAK,EACL,IAAI,EACJ,KAAK,CAAC,UAAU,IAAI,iBAAiB,EACrC,KAAK,CAAC,KAAK,IAAI,QAAQ,CACxB,CAAC;IACF,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEtC,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACnB,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE;QACrB,CAAC;QACD,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;QAC7B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,IAAI,CAAC,OAAO;QACzB,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;KAC5D,CAAC,CACH;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MeasureAt } from "../text/index.js";
|
|
2
|
+
import type { MeasureText } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Bind a measurer to one family and weight, leaving only the size open.
|
|
5
|
+
*
|
|
6
|
+
* That is the shape fitting text wants, since choosing a size is the whole of
|
|
7
|
+
* what it varies, and it keeps a template from repeating the family and weight
|
|
8
|
+
* on every call.
|
|
9
|
+
*/
|
|
10
|
+
export declare function measureIn(measure: MeasureText, fontFamily: string, fontWeight: number): MeasureAt;
|
|
11
|
+
//# sourceMappingURL=measure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../../src/layout/measure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,SAAS,CAGX"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bind a measurer to one family and weight, leaving only the size open.
|
|
3
|
+
*
|
|
4
|
+
* That is the shape fitting text wants, since choosing a size is the whole of
|
|
5
|
+
* what it varies, and it keeps a template from repeating the family and weight
|
|
6
|
+
* on every call.
|
|
7
|
+
*/
|
|
8
|
+
export function measureIn(measure, fontFamily, fontWeight) {
|
|
9
|
+
return (text, fontSize) => measure(text, { fontFamily, fontSize, fontWeight });
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=measure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measure.js","sourceRoot":"","sources":["../../src/layout/measure.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,OAAoB,EACpB,UAAkB,EAClB,UAAkB;IAElB,OAAO,CAAC,IAAY,EAAE,QAAgB,EAAU,EAAE,CAChD,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BoxStyle, Rect } from "./types.js";
|
|
2
|
+
/** A panel is a box that casts a shadow. */
|
|
3
|
+
export interface PanelStyle extends BoxStyle {
|
|
4
|
+
/**
|
|
5
|
+
* How far the shadow falls below the panel. Omit for none, which is right
|
|
6
|
+
* for a panel that is a region of the image rather than a card on top of it.
|
|
7
|
+
*/
|
|
8
|
+
readonly shadow?: number;
|
|
9
|
+
readonly shadowColor?: string;
|
|
10
|
+
readonly shadowOpacity?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A raised plate: a soft shadow, then the surface on top of it.
|
|
14
|
+
*
|
|
15
|
+
* The shadow is a second rectangle rather than a blur filter. It costs a
|
|
16
|
+
* rasteriser nothing, it survives every backend, and at these sizes a hard
|
|
17
|
+
* offset reads as depth just as well as a blurred one.
|
|
18
|
+
*/
|
|
19
|
+
export declare function panel(rect: Rect, style?: PanelStyle): string;
|
|
20
|
+
//# sourceMappingURL=panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/layout/panel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEjD,4CAA4C;AAC5C,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAKD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,GAAE,UAAe,GAAG,MAAM,CAiBhE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { box } from "./box.js";
|
|
2
|
+
const defaultShadowColor = "#000000";
|
|
3
|
+
const defaultShadowOpacity = 0.22;
|
|
4
|
+
/**
|
|
5
|
+
* A raised plate: a soft shadow, then the surface on top of it.
|
|
6
|
+
*
|
|
7
|
+
* The shadow is a second rectangle rather than a blur filter. It costs a
|
|
8
|
+
* rasteriser nothing, it survives every backend, and at these sizes a hard
|
|
9
|
+
* offset reads as depth just as well as a blurred one.
|
|
10
|
+
*/
|
|
11
|
+
export function panel(rect, style = {}) {
|
|
12
|
+
const { shadow, shadowColor, shadowOpacity, ...surface } = style;
|
|
13
|
+
if (shadow === undefined) {
|
|
14
|
+
return box(rect, surface);
|
|
15
|
+
}
|
|
16
|
+
return (box({ ...rect, y: rect.y + shadow }, {
|
|
17
|
+
...(surface.radius !== undefined && { radius: surface.radius }),
|
|
18
|
+
fill: shadowColor ?? defaultShadowColor,
|
|
19
|
+
fillOpacity: shadowOpacity ?? defaultShadowOpacity,
|
|
20
|
+
}) + box(rect, surface));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../../src/layout/panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAc/B,MAAM,kBAAkB,GAAG,SAAS,CAAC;AACrC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,IAAU,EAAE,KAAK,GAAe,EAAE;IACtD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC;IAEjE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CACL,GAAG,CACD,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,EAAE,EAC/B;QACE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAC/D,IAAI,EAAE,WAAW,IAAI,kBAAkB;QACvC,WAAW,EAAE,aAAa,IAAI,oBAAoB;KACnD,CACF,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Align, Extent, Rect } from "./types.js";
|
|
2
|
+
/** A placed item's rectangle, and which item it belongs to. */
|
|
3
|
+
export interface RowRect extends Rect {
|
|
4
|
+
readonly index: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Set items across an area and give each one its rectangle: an avatar beside a
|
|
8
|
+
* name, a badge beside a title, a row of tags along the bottom.
|
|
9
|
+
*
|
|
10
|
+
* Each keeps the full height of the area, so an item shorter than the row
|
|
11
|
+
* centres itself within the rectangle it was given rather than being told
|
|
12
|
+
* where to sit.
|
|
13
|
+
*/
|
|
14
|
+
export declare function row(items: readonly Extent[], area: Rect, align?: Align): readonly RowRect[];
|
|
15
|
+
//# sourceMappingURL=row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.d.ts","sourceRoot":"","sources":["../../src/layout/row.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEtD,+DAA+D;AAC/D,MAAM,WAAW,OAAQ,SAAQ,IAAI;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CACjB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,GAAE,KAAgB,GACtB,SAAS,OAAO,EAAE,CAcpB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { distribute } from "./distribute.js";
|
|
2
|
+
/**
|
|
3
|
+
* Set items across an area and give each one its rectangle: an avatar beside a
|
|
4
|
+
* name, a badge beside a title, a row of tags along the bottom.
|
|
5
|
+
*
|
|
6
|
+
* Each keeps the full height of the area, so an item shorter than the row
|
|
7
|
+
* centres itself within the rectangle it was given rather than being told
|
|
8
|
+
* where to sit.
|
|
9
|
+
*/
|
|
10
|
+
export function row(items, area, align = "centre") {
|
|
11
|
+
const placed = distribute(items, { start: area.x, end: area.x + area.width }, align);
|
|
12
|
+
return placed.map((placement, index) => ({
|
|
13
|
+
x: placement.start,
|
|
14
|
+
y: area.y,
|
|
15
|
+
width: items[index]?.size ?? 0,
|
|
16
|
+
height: area.height,
|
|
17
|
+
index: placement.index,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row.js","sourceRoot":"","sources":["../../src/layout/row.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQ7C;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CACjB,KAAwB,EACxB,IAAU,EACV,KAAK,GAAU,QAAQ;IAEvB,MAAM,MAAM,GAAG,UAAU,CACvB,KAAK,EACL,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,EAC3C,KAAK,CACN,CAAC;IAEF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC,EAAE,SAAS,CAAC,KAAK;QAClB,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC;QAC9B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,SAAS,CAAC,KAAK;KACvB,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Rect } from "./types.js";
|
|
2
|
+
/** How heavily a scrim shades what is under it, and from which edge. */
|
|
3
|
+
export interface ScrimOptions {
|
|
4
|
+
readonly color?: string;
|
|
5
|
+
/** Opacity at the top edge. Defaults to none, so the image shows through. */
|
|
6
|
+
readonly from?: number;
|
|
7
|
+
/** Opacity at the bottom edge. */
|
|
8
|
+
readonly to?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A wash of colour over an image, so that text on top of it can be read.
|
|
12
|
+
*
|
|
13
|
+
* This is the difference between a designed image and text sitting on a photo.
|
|
14
|
+
* A photograph has light and dark in it wherever it likes, and white text over
|
|
15
|
+
* a bright sky is invisible; a gradient from clear at the top to dark at the
|
|
16
|
+
* bottom keeps a headline legible without hiding the picture.
|
|
17
|
+
*
|
|
18
|
+
* `id` names the gradient and has to be unique within the image. A flat wash
|
|
19
|
+
* needs no gradient, so it needs no `id` either: pass the same value for
|
|
20
|
+
* `from` and `to`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scrim(rect: Rect, id: string, options?: ScrimOptions): string;
|
|
23
|
+
//# sourceMappingURL=scrim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrim.d.ts","sourceRoot":"","sources":["../../src/layout/scrim.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CACnB,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,YAAiB,GACzB,MAAM,CA0BR"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { escapeXml } from "../text/index.js";
|
|
2
|
+
import { box } from "./box.js";
|
|
3
|
+
const defaultColor = "#000000";
|
|
4
|
+
/**
|
|
5
|
+
* A wash of colour over an image, so that text on top of it can be read.
|
|
6
|
+
*
|
|
7
|
+
* This is the difference between a designed image and text sitting on a photo.
|
|
8
|
+
* A photograph has light and dark in it wherever it likes, and white text over
|
|
9
|
+
* a bright sky is invisible; a gradient from clear at the top to dark at the
|
|
10
|
+
* bottom keeps a headline legible without hiding the picture.
|
|
11
|
+
*
|
|
12
|
+
* `id` names the gradient and has to be unique within the image. A flat wash
|
|
13
|
+
* needs no gradient, so it needs no `id` either: pass the same value for
|
|
14
|
+
* `from` and `to`.
|
|
15
|
+
*/
|
|
16
|
+
export function scrim(rect, id, options = {}) {
|
|
17
|
+
const from = options.from ?? 0;
|
|
18
|
+
const to = options.to ?? 0.55;
|
|
19
|
+
if (from === to) {
|
|
20
|
+
return box(rect, {
|
|
21
|
+
fill: options.color ?? defaultColor,
|
|
22
|
+
fillOpacity: from,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// Escaped here for the reason `box` escapes what it is given: both of these
|
|
26
|
+
// may have come from a post's frontmatter by way of a template. The fill
|
|
27
|
+
// below takes the id raw, since `box` does its own escaping and the two
|
|
28
|
+
// attributes have to agree once parsed rather than as written.
|
|
29
|
+
const color = escapeXml(options.color ?? defaultColor);
|
|
30
|
+
const gradient = `<defs>` +
|
|
31
|
+
`<linearGradient id="${escapeXml(id)}" x1="0" y1="0" x2="0" y2="1">` +
|
|
32
|
+
`<stop offset="0%" stop-color="${color}" stop-opacity="${String(from)}"/>` +
|
|
33
|
+
`<stop offset="100%" stop-color="${color}" stop-opacity="${String(to)}"/>` +
|
|
34
|
+
`</linearGradient>` +
|
|
35
|
+
`</defs>`;
|
|
36
|
+
return gradient + box(rect, { fill: `url(#${id})` });
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=scrim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrim.js","sourceRoot":"","sources":["../../src/layout/scrim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAY/B,MAAM,YAAY,GAAG,SAAS,CAAC;AAE/B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,KAAK,CACnB,IAAU,EACV,EAAU,EACV,OAAO,GAAiB,EAAE;IAE1B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC;IAE9B,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,OAAO,GAAG,CAAC,IAAI,EAAE;YACf,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,YAAY;YACnC,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,yEAAyE;IACzE,wEAAwE;IACxE,+DAA+D;IAC/D,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC;IAEvD,MAAM,QAAQ,GACZ,QAAQ;QACR,uBAAuB,SAAS,CAAC,EAAE,CAAC,gCAAgC;QACpE,iCAAiC,KAAK,mBAAmB,MAAM,CAAC,IAAI,CAAC,KAAK;QAC1E,mCAAmC,KAAK,mBAAmB,MAAM,CAAC,EAAE,CAAC,KAAK;QAC1E,mBAAmB;QACnB,SAAS,CAAC;IAEZ,OAAO,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Align, Extent, Rect } from "./types.js";
|
|
2
|
+
/** A stacked item's rectangle, and which item it belongs to. */
|
|
3
|
+
export interface StackedRect extends Rect {
|
|
4
|
+
readonly index: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Stack items down an area and give each one its rectangle.
|
|
8
|
+
*
|
|
9
|
+
* Each keeps the full width of the area, because the vertical placement is the
|
|
10
|
+
* only decision being made here. An item that wants less width draws itself
|
|
11
|
+
* narrower, or puts a `row` inside the rectangle it was given.
|
|
12
|
+
*/
|
|
13
|
+
export declare function stack(items: readonly Extent[], area: Rect, align?: Align): readonly StackedRect[];
|
|
14
|
+
//# sourceMappingURL=stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../src/layout/stack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEtD,gEAAgE;AAChE,MAAM,WAAW,WAAY,SAAQ,IAAI;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,GAAE,KAAgB,GACtB,SAAS,WAAW,EAAE,CAcxB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { distribute } from "./distribute.js";
|
|
2
|
+
/**
|
|
3
|
+
* Stack items down an area and give each one its rectangle.
|
|
4
|
+
*
|
|
5
|
+
* Each keeps the full width of the area, because the vertical placement is the
|
|
6
|
+
* only decision being made here. An item that wants less width draws itself
|
|
7
|
+
* narrower, or puts a `row` inside the rectangle it was given.
|
|
8
|
+
*/
|
|
9
|
+
export function stack(items, area, align = "centre") {
|
|
10
|
+
const placed = distribute(items, { start: area.y, end: area.y + area.height }, align);
|
|
11
|
+
return placed.map((placement, index) => ({
|
|
12
|
+
x: area.x,
|
|
13
|
+
y: placement.start,
|
|
14
|
+
width: area.width,
|
|
15
|
+
height: items[index]?.size ?? 0,
|
|
16
|
+
index: placement.index,
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../src/layout/stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQ7C;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CACnB,KAAwB,EACxB,IAAU,EACV,KAAK,GAAU,QAAQ;IAEvB,MAAM,MAAM,GAAG,UAAU,CACvB,KAAK,EACL,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAC5C,KAAK,CACN,CAAC;IAEF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,CAAC,EAAE,SAAS,CAAC,KAAK;QAClB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC;QAC/B,KAAK,EAAE,SAAS,CAAC,KAAK;KACvB,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rectangle in image coordinates, which is what every primitive here takes
|
|
3
|
+
* and returns. Templates are handed the image's `dimensions` and work down
|
|
4
|
+
* from there, so a rectangle is the one shape they all have in common.
|
|
5
|
+
*/
|
|
6
|
+
export interface Rect {
|
|
7
|
+
readonly x: number;
|
|
8
|
+
readonly y: number;
|
|
9
|
+
readonly width: number;
|
|
10
|
+
readonly height: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A stretch of one axis: top and bottom for a stack, left and right for a row.
|
|
14
|
+
* `start` is the smaller coordinate, so it is the top or the left edge.
|
|
15
|
+
*/
|
|
16
|
+
export interface Span {
|
|
17
|
+
readonly start: number;
|
|
18
|
+
readonly end: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Where a group of items sits within the space it was given. `centre` is the
|
|
22
|
+
* default everywhere, because a share image is looked at rather than read down,
|
|
23
|
+
* and the middle is where the eye goes.
|
|
24
|
+
*/
|
|
25
|
+
export type Align = "start" | "centre" | "end";
|
|
26
|
+
/**
|
|
27
|
+
* How much of an axis one item takes, and how much clear space goes before it.
|
|
28
|
+
* A gap on the first item is space at the head of the group.
|
|
29
|
+
*/
|
|
30
|
+
export interface Extent {
|
|
31
|
+
readonly size: number;
|
|
32
|
+
readonly gapBefore?: number;
|
|
33
|
+
}
|
|
34
|
+
/** Where an item ended up: its start coordinate along the axis. */
|
|
35
|
+
export interface Placed {
|
|
36
|
+
readonly start: number;
|
|
37
|
+
readonly index: number;
|
|
38
|
+
}
|
|
39
|
+
/** Fill, corners and stroke for a rectangle. Every field is optional. */
|
|
40
|
+
export interface BoxStyle {
|
|
41
|
+
readonly fill?: string;
|
|
42
|
+
readonly fillOpacity?: number;
|
|
43
|
+
/** Corner radius. Omit for square corners. */
|
|
44
|
+
readonly radius?: number;
|
|
45
|
+
readonly stroke?: string;
|
|
46
|
+
readonly strokeOpacity?: number;
|
|
47
|
+
readonly strokeWidth?: number;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/layout/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,mEAAmE;AACnE,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/layout/types.ts"],"names":[],"mappings":""}
|
package/dist/manifest/build.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Manifest } from "../types.js";
|
|
|
4
4
|
* Build the manifest for a planned build.
|
|
5
5
|
*
|
|
6
6
|
* It is built from the jobs rather than from what was written, so a rebuild
|
|
7
|
-
* that skips every image still describes the whole site
|
|
7
|
+
* that skips every image still describes the whole site. The manifest says
|
|
8
8
|
* what exists, not what happened this time.
|
|
9
9
|
*
|
|
10
10
|
* Pages are sorted by slug, and each page's images by size name, so a manifest
|
package/dist/manifest/build.js
CHANGED
|
@@ -27,7 +27,7 @@ function drafts(jobs) {
|
|
|
27
27
|
* Build the manifest for a planned build.
|
|
28
28
|
*
|
|
29
29
|
* It is built from the jobs rather than from what was written, so a rebuild
|
|
30
|
-
* that skips every image still describes the whole site
|
|
30
|
+
* that skips every image still describes the whole site. The manifest says
|
|
31
31
|
* what exists, not what happened this time.
|
|
32
32
|
*
|
|
33
33
|
* Pages are sorted by slug, and each page's images by size name, so a manifest
|
package/dist/manifest/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface PlannedManifest {
|
|
|
13
13
|
*
|
|
14
14
|
* Built while planning rather than from the results, so that a site with two
|
|
15
15
|
* pages sharing a slug hears about it before rendering the tree rather than
|
|
16
|
-
* after
|
|
16
|
+
* after. That is the same reason the output paths are checked up front.
|
|
17
17
|
*/
|
|
18
18
|
export declare function planManifest(manifestPath: string | undefined, jobs: readonly RenderJob[]): PlannedManifest | undefined;
|
|
19
19
|
/**
|
package/dist/manifest/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { buildManifest } from "./build.js";
|
|
|
7
7
|
*
|
|
8
8
|
* Built while planning rather than from the results, so that a site with two
|
|
9
9
|
* pages sharing a slug hears about it before rendering the tree rather than
|
|
10
|
-
* after
|
|
10
|
+
* after. That is the same reason the output paths are checked up front.
|
|
11
11
|
*/
|
|
12
12
|
export function planManifest(manifestPath, jobs) {
|
|
13
13
|
return manifestPath === undefined
|
package/dist/manifest/order.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The manifest is written into a site's repository and committed, so the order
|
|
6
6
|
* has to be the same on a laptop and on CI. `localeCompare` reads the default
|
|
7
|
-
* locale, and locales disagree about case and accented letters
|
|
7
|
+
* locale, and locales disagree about case and accented letters, so a slug of
|
|
8
8
|
* `Über` or `MyPost` could sort one way in development and another in the
|
|
9
9
|
* build, leaving a diff that says nothing happened.
|
|
10
10
|
*/
|
package/dist/manifest/order.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The manifest is written into a site's repository and committed, so the order
|
|
6
6
|
* has to be the same on a laptop and on CI. `localeCompare` reads the default
|
|
7
|
-
* locale, and locales disagree about case and accented letters
|
|
7
|
+
* locale, and locales disagree about case and accented letters, so a slug of
|
|
8
8
|
* `Über` or `MyPost` could sort one way in development and another in the
|
|
9
9
|
* build, leaving a diff that says nothing happened.
|
|
10
10
|
*/
|
package/dist/manifest/page.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import type { ManifestPage } from "../types.js";
|
|
|
5
5
|
* of them so far.
|
|
6
6
|
*
|
|
7
7
|
* A page is created from its first job rather than from an empty list, so
|
|
8
|
-
* there is never a page without images to explain away
|
|
9
|
-
* one of them.
|
|
8
|
+
* there is never a page without images to explain away, since `widest` has to
|
|
9
|
+
* name one of them.
|
|
10
10
|
*/
|
|
11
11
|
export interface PageDraft {
|
|
12
12
|
readonly jobs: RenderJob[];
|
package/dist/manifest/page.js
CHANGED
|
@@ -21,9 +21,9 @@ export function addToPage(page, job) {
|
|
|
21
21
|
* Reject two pages sharing a slug.
|
|
22
22
|
*
|
|
23
23
|
* The manifest is keyed by slug, so a site looking a page up would find
|
|
24
|
-
* whichever was written last
|
|
25
|
-
* which is worse than no manifest at all. Their images may well be
|
|
26
|
-
* disk, so nothing else in the build has any reason to complain.
|
|
24
|
+
* whichever was written last. That is an image quietly belonging to the wrong
|
|
25
|
+
* post, which is worse than no manifest at all. Their images may well be
|
|
26
|
+
* distinct on disk, so nothing else in the build has any reason to complain.
|
|
27
27
|
*/
|
|
28
28
|
function assertOnePage(slug, page) {
|
|
29
29
|
const paths = [...new Set(page.jobs.map((job) => job.contentPath))];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Width of `text` when there is no font to measure it in, either because none
|
|
3
|
+
* were configured or because the stack names one the build did not load.
|
|
4
|
+
*
|
|
5
|
+
* It is a guess, and a build that wants text laid out to the pixel supplies
|
|
6
|
+
* the font as a file. What it is not is a guess a template has to make: the
|
|
7
|
+
* one ratio lives here, where the reason for it can be written down once.
|
|
8
|
+
*/
|
|
9
|
+
export declare function estimateWidth(text: string, fontSize: number, weight: number, ratio?: number): number;
|
|
10
|
+
//# sourceMappingURL=estimate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate.d.ts","sourceRoot":"","sources":["../../src/measure/estimate.ts"],"names":[],"mappings":"AA8CA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,SAAe,GACnB,MAAM,CAQR"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advance width to assume for proportional text, as a fraction of the font
|
|
3
|
+
* size. It is the average over the sort of text a share image carries, mostly
|
|
4
|
+
* lower-case Latin with spaces, for the sans-serif faces a site is likely to
|
|
5
|
+
* use. Nothing here is exact, which is the point of measuring instead.
|
|
6
|
+
*/
|
|
7
|
+
const defaultRatio = 0.52;
|
|
8
|
+
/**
|
|
9
|
+
* Characters that occupy a full em rather than a fraction of one: the CJK
|
|
10
|
+
* ranges, Hangul, kana, the fullwidth forms and emoji.
|
|
11
|
+
*
|
|
12
|
+
* Estimating these at the Latin ratio is what makes a Japanese title overflow
|
|
13
|
+
* by nearly half its width, and no per-template fudge factor can be right for
|
|
14
|
+
* both scripts at once. Widths of the scripts in between, such as Devanagari,
|
|
15
|
+
* are still guesses; those want a font file, which is what measuring is for.
|
|
16
|
+
*/
|
|
17
|
+
const wideRanges = [
|
|
18
|
+
[0x11_00, 0x11_5f], // Hangul Jamo
|
|
19
|
+
[0x2e_80, 0x30_3e], // CJK radicals and punctuation
|
|
20
|
+
[0x30_41, 0x33_ff], // Kana through the CJK compatibility forms
|
|
21
|
+
[0x34_00, 0x4d_bf], // CJK extension A
|
|
22
|
+
[0x4e_00, 0x9f_ff], // CJK unified ideographs
|
|
23
|
+
[0xa0_00, 0xa4_cf], // Yi
|
|
24
|
+
[0xac_00, 0xd7_a3], // Hangul syllables
|
|
25
|
+
[0xf9_00, 0xfa_ff], // CJK compatibility ideographs
|
|
26
|
+
[0xfe_30, 0xfe_4f], // CJK compatibility forms
|
|
27
|
+
[0xff_00, 0xff_60], // Fullwidth forms, but not the halfwidth kana after them
|
|
28
|
+
[0xff_e0, 0xff_e6], // Fullwidth currency and bar symbols
|
|
29
|
+
[0x1_f3_00, 0x1_fa_ff], // Emoji
|
|
30
|
+
[0x2_00_00, 0x3_ff_fd], // CJK extensions B onwards
|
|
31
|
+
];
|
|
32
|
+
function isWide(character) {
|
|
33
|
+
const point = character.codePointAt(0) ?? 0;
|
|
34
|
+
return wideRanges.some(([from, to]) => point >= from && point <= to);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* How much wider a face gets as its weight rises. A bold cut of a family runs
|
|
38
|
+
* around a tenth wider than its regular; heavier than bold, little more.
|
|
39
|
+
*/
|
|
40
|
+
function weightFactor(weight) {
|
|
41
|
+
return 1 + Math.min(Math.max(weight - 400, 0) / 400, 1) * 0.1;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Width of `text` when there is no font to measure it in, either because none
|
|
45
|
+
* were configured or because the stack names one the build did not load.
|
|
46
|
+
*
|
|
47
|
+
* It is a guess, and a build that wants text laid out to the pixel supplies
|
|
48
|
+
* the font as a file. What it is not is a guess a template has to make: the
|
|
49
|
+
* one ratio lives here, where the reason for it can be written down once.
|
|
50
|
+
*/
|
|
51
|
+
export function estimateWidth(text, fontSize, weight, ratio = defaultRatio) {
|
|
52
|
+
let ems = 0;
|
|
53
|
+
for (const character of text) {
|
|
54
|
+
ems += isWide(character) ? 1 : ratio;
|
|
55
|
+
}
|
|
56
|
+
return ems * fontSize * weightFactor(weight);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=estimate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate.js","sourceRoot":"","sources":["../../src/measure/estimate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,UAAU,GAA2C;IACzD,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc;IAClC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,+BAA+B;IACnD,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,2CAA2C;IAC/D,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB;IACtC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAC7C,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,KAAK;IACzB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,mBAAmB;IACvC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,+BAA+B;IACnD,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,0BAA0B;IAC9C,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,yDAAyD;IAC7E,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,qCAAqC;IACzD,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,QAAQ;IAChC,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,2BAA2B;CACpD,CAAC;AAEF,SAAS,MAAM,CAAC,SAAiB;IAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,QAAgB,EAChB,MAAc,EACd,KAAK,GAAG,YAAY;IAEpB,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACvC,CAAC;IAED,OAAO,GAAG,GAAG,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Font } from "fontkit";
|
|
2
|
+
import type { FontSource, WarningHandler } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* One face loaded for measurement: the font itself, plus the family and weight
|
|
5
|
+
* it declares. Both are read from the file rather than from config, for the
|
|
6
|
+
* reason {@link FontSource} gives: the file is what the rasteriser matches on.
|
|
7
|
+
*/
|
|
8
|
+
export interface Face {
|
|
9
|
+
readonly family: string;
|
|
10
|
+
readonly weight: number;
|
|
11
|
+
readonly font: Font;
|
|
12
|
+
}
|
|
13
|
+
/** Every face the configured fonts hold, in the order they were configured. */
|
|
14
|
+
export declare function loadFaces(fonts: readonly FontSource[], onWarning: WarningHandler): Promise<readonly Face[]>;
|
|
15
|
+
//# sourceMappingURL=faces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"faces.d.ts","sourceRoot":"","sources":["../../src/measure/faces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAGpC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAuFD,+EAA+E;AAC/E,wBAAsB,SAAS,CAC7B,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAM1B"}
|