@stats-forge/github-stats-forge-core 0.0.2 → 0.2.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 +0 -10
- package/build/api/api-result.d.ts +6 -7
- package/build/api/api-result.d.ts.map +1 -1
- package/build/api/api-result.js +4 -5
- package/build/api/contributed-to.d.ts +23 -0
- package/build/api/contributed-to.d.ts.map +1 -0
- package/build/api/contributed-to.js +43 -0
- package/build/api/gist.d.ts +8 -22
- package/build/api/gist.d.ts.map +1 -1
- package/build/api/gist.js +14 -36
- package/build/api/handler.d.ts +16 -0
- package/build/api/handler.d.ts.map +1 -0
- package/build/api/handler.js +29 -0
- package/build/api/index.d.ts +13 -12
- package/build/api/index.d.ts.map +1 -1
- package/build/api/index.js +1 -0
- package/build/api/params.d.ts +21 -12
- package/build/api/params.d.ts.map +1 -1
- package/build/api/params.js +41 -19
- package/build/api/pin.d.ts +11 -31
- package/build/api/pin.d.ts.map +1 -1
- package/build/api/pin.js +35 -63
- package/build/api/stats.d.ts +15 -16
- package/build/api/stats.d.ts.map +1 -1
- package/build/api/stats.js +60 -99
- package/build/api/top-langs.d.ts +13 -18
- package/build/api/top-langs.d.ts.map +1 -1
- package/build/api/top-langs.js +35 -72
- package/build/api/wakatime.d.ts +11 -17
- package/build/api/wakatime.d.ts.map +1 -1
- package/build/api/wakatime.js +27 -64
- package/build/calculateRank.d.ts +0 -9
- package/build/calculateRank.d.ts.map +1 -1
- package/build/calculateRank.js +12 -17
- package/build/cards/contributed-to.d.ts +19 -0
- package/build/cards/contributed-to.d.ts.map +1 -0
- package/build/cards/contributed-to.js +242 -0
- package/build/cards/gist.d.ts +3 -4
- package/build/cards/gist.d.ts.map +1 -1
- package/build/cards/gist.js +38 -43
- package/build/cards/options.d.ts +1 -1
- package/build/cards/repo.d.ts +14 -5
- package/build/cards/repo.d.ts.map +1 -1
- package/build/cards/repo.js +93 -103
- package/build/cards/stats.d.ts +18 -11
- package/build/cards/stats.d.ts.map +1 -1
- package/build/cards/stats.js +191 -222
- package/build/cards/top-languages.d.ts +18 -33
- package/build/cards/top-languages.d.ts.map +1 -1
- package/build/cards/top-languages.js +196 -387
- package/build/cards/wakatime.d.ts +17 -8
- package/build/cards/wakatime.d.ts.map +1 -1
- package/build/cards/wakatime.js +133 -187
- package/build/common/Card.d.ts +20 -59
- package/build/common/Card.d.ts.map +1 -1
- package/build/common/Card.js +131 -198
- package/build/common/I18n.d.ts +1 -7
- package/build/common/I18n.d.ts.map +1 -1
- package/build/common/I18n.js +7 -8
- package/build/common/brand.d.ts +76 -0
- package/build/common/brand.d.ts.map +1 -0
- package/build/common/brand.js +73 -0
- package/build/common/color.d.ts +4 -17
- package/build/common/color.d.ts.map +1 -1
- package/build/common/color.js +67 -49
- package/build/common/config.d.ts +4 -14
- package/build/common/config.d.ts.map +1 -1
- package/build/common/config.js +3 -16
- package/build/common/constants.d.ts +6 -2
- package/build/common/constants.d.ts.map +1 -1
- package/build/common/constants.js +5 -1
- package/build/common/date.d.ts +50 -5
- package/build/common/date.d.ts.map +1 -1
- package/build/common/date.js +104 -4
- package/build/common/emojiMap.d.ts +8 -0
- package/build/common/emojiMap.d.ts.map +1 -0
- package/build/common/emojiMap.js +10 -0
- package/build/common/emojiMap.json +1915 -0
- package/build/common/error.d.ts +1 -10
- package/build/common/error.d.ts.map +1 -1
- package/build/common/error.js +1 -10
- package/build/common/fmt.d.ts +3 -15
- package/build/common/fmt.d.ts.map +1 -1
- package/build/common/fmt.js +7 -35
- package/build/common/http.d.ts +2 -7
- package/build/common/http.d.ts.map +1 -1
- package/build/common/http.js +8 -17
- package/build/common/icons.d.ts +20 -20
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +108 -67
- package/build/common/languageColors.d.ts +0 -1
- package/build/common/languageColors.d.ts.map +1 -1
- package/build/common/languageColors.js +1 -4
- package/build/common/languageColors.json +18 -2
- package/build/common/ops.d.ts +11 -17
- package/build/common/ops.d.ts.map +1 -1
- package/build/common/ops.js +22 -39
- package/build/common/render.d.ts +34 -82
- package/build/common/render.d.ts.map +1 -1
- package/build/common/render.js +225 -259
- package/build/common/retryer.d.ts +2 -7
- package/build/common/retryer.d.ts.map +1 -1
- package/build/common/retryer.js +4 -11
- package/build/fetchers/contributed-to.d.ts +62 -0
- package/build/fetchers/contributed-to.d.ts.map +1 -0
- package/build/fetchers/contributed-to.js +184 -0
- package/build/fetchers/gist.d.ts +2 -5
- package/build/fetchers/gist.d.ts.map +1 -1
- package/build/fetchers/gist.js +1 -5
- package/build/fetchers/graphql-error.d.ts +13 -0
- package/build/fetchers/graphql-error.d.ts.map +1 -0
- package/build/fetchers/graphql-error.js +29 -0
- package/build/fetchers/index.d.ts +13 -12
- package/build/fetchers/index.d.ts.map +1 -1
- package/build/fetchers/index.js +1 -0
- package/build/fetchers/repo.d.ts +2 -11
- package/build/fetchers/repo.d.ts.map +1 -1
- package/build/fetchers/repo.js +20 -33
- package/build/fetchers/stats.d.ts +16 -40
- package/build/fetchers/stats.d.ts.map +1 -1
- package/build/fetchers/stats.js +89 -271
- package/build/fetchers/top-languages.d.ts +2 -9
- package/build/fetchers/top-languages.d.ts.map +1 -1
- package/build/fetchers/top-languages.js +16 -47
- package/build/fetchers/types.d.ts +25 -1
- package/build/fetchers/types.d.ts.map +1 -1
- package/build/fetchers/wakatime.d.ts +2 -6
- package/build/fetchers/wakatime.d.ts.map +1 -1
- package/build/fetchers/wakatime.js +1 -5
- package/build/graphql/contributionsCollection.d.ts +9 -0
- package/build/graphql/contributionsCollection.d.ts.map +1 -0
- package/build/graphql/contributionsCollection.js +12 -0
- package/build/graphql/contributionsDocument.d.ts +6 -6
- package/build/graphql/contributionsDocument.d.ts.map +1 -1
- package/build/graphql/contributionsDocument.js +8 -16
- package/build/graphql/generated/contributed-to.d.ts +22 -0
- package/build/graphql/generated/contributed-to.d.ts.map +1 -0
- package/build/graphql/generated/contributed-to.js +11 -0
- package/build/graphql/generated/gist.d.ts +1 -1
- package/build/graphql/generated/repo.d.ts +1 -1
- package/build/graphql/generated/stats.d.ts +16 -4
- package/build/graphql/generated/stats.d.ts.map +1 -1
- package/build/graphql/generated/stats.js +2 -2
- package/build/graphql/generated/top-languages.d.ts +2 -2
- package/build/graphql/graphqlDocument.d.ts +1 -2
- package/build/graphql/graphqlDocument.d.ts.map +1 -1
- package/build/graphql/graphqlDocument.js +0 -1
- package/build/graphql/reposContributedToDocument.d.ts +4 -5
- package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
- package/build/graphql/reposContributedToDocument.js +11 -7
- package/build/markup/css.d.ts +35 -0
- package/build/markup/css.d.ts.map +1 -0
- package/build/markup/css.js +64 -0
- package/build/markup/element.d.ts +41 -0
- package/build/markup/element.d.ts.map +1 -0
- package/build/markup/element.js +127 -0
- package/build/markup/html.d.ts +13 -0
- package/build/markup/html.d.ts.map +1 -0
- package/build/markup/html.js +27 -0
- package/build/markup/index.d.ts +9 -0
- package/build/markup/index.d.ts.map +1 -0
- package/build/markup/index.js +6 -0
- package/build/markup/serialize.d.ts +16 -0
- package/build/markup/serialize.d.ts.map +1 -0
- package/build/markup/serialize.js +17 -0
- package/build/themes/index.d.ts +332 -333
- package/build/themes/index.d.ts.map +1 -1
- package/build/themes/index.js +1 -1
- package/build/translations.d.ts +66 -7
- package/build/translations.d.ts.map +1 -1
- package/build/translations.js +686 -629
- package/package.json +17 -26
- package/src/api/api-result.ts +10 -9
- package/src/api/contributed-to.ts +84 -0
- package/src/api/gist.ts +22 -46
- package/src/api/handler.ts +42 -0
- package/src/api/index.ts +13 -12
- package/src/api/params.ts +74 -29
- package/src/api/pin.ts +38 -65
- package/src/api/stats.ts +81 -118
- package/src/api/top-langs.ts +38 -80
- package/src/api/wakatime.ts +35 -73
- package/src/calculateRank.ts +12 -23
- package/src/cards/contributed-to.ts +373 -0
- package/src/cards/gist.ts +55 -49
- package/src/cards/options.ts +1 -1
- package/src/cards/repo.ts +134 -120
- package/src/cards/stats.ts +262 -252
- package/src/cards/top-languages.ts +315 -422
- package/src/cards/wakatime.ts +207 -225
- package/src/common/Card.ts +207 -214
- package/src/common/I18n.ts +7 -8
- package/src/common/brand.ts +109 -0
- package/src/common/color.ts +80 -57
- package/src/common/config.ts +5 -18
- package/src/common/constants.ts +8 -2
- package/src/common/date.ts +135 -5
- package/src/common/emojiMap.json +1915 -0
- package/src/common/emojiMap.ts +13 -0
- package/src/common/error.ts +2 -11
- package/src/common/fmt.ts +7 -44
- package/src/common/http.ts +9 -15
- package/src/common/icons.ts +122 -42
- package/src/common/languageColors.json +18 -2
- package/src/common/languageColors.ts +1 -4
- package/src/common/ops.ts +31 -48
- package/src/common/render.ts +334 -284
- package/src/common/retryer.ts +8 -15
- package/src/fetchers/contributed-to.ts +271 -0
- package/src/fetchers/gist.ts +8 -12
- package/src/fetchers/graphql-error.ts +36 -0
- package/src/fetchers/index.ts +15 -12
- package/src/fetchers/repo.ts +27 -40
- package/src/fetchers/stats.ts +157 -366
- package/src/fetchers/top-languages.ts +27 -55
- package/src/fetchers/types.ts +27 -1
- package/src/fetchers/wakatime.ts +5 -9
- package/src/graphql/contributionsCollection.ts +18 -0
- package/src/graphql/contributionsDocument.ts +14 -19
- package/src/graphql/generated/contributed-to.ts +25 -0
- package/src/graphql/generated/gist.ts +1 -1
- package/src/graphql/generated/repo.ts +1 -1
- package/src/graphql/generated/stats.ts +21 -8
- package/src/graphql/generated/top-languages.ts +2 -2
- package/src/graphql/graphqlDocument.ts +1 -2
- package/src/graphql/queries/contributed-to.graphql +8 -0
- package/src/graphql/queries/stats.graphql +14 -2
- package/src/graphql/reposContributedToDocument.ts +16 -15
- package/src/markup/css.ts +118 -0
- package/src/markup/element.ts +246 -0
- package/src/markup/html.ts +34 -0
- package/src/markup/index.ts +9 -0
- package/src/markup/serialize.ts +27 -0
- package/src/themes/index.ts +1 -1
- package/src/translations.ts +699 -629
- package/build/cards/index.d.ts +0 -11
- package/build/cards/index.d.ts.map +0 -1
- package/build/cards/index.js +0 -7
- package/build/common/html.d.ts +0 -8
- package/build/common/html.d.ts.map +0 -1
- package/build/common/html.js +0 -14
- package/build/index.d.ts +0 -15
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -10
- package/src/_emoji-name-map.d.ts +0 -10
- package/src/_github-username-regex.d.ts +0 -4
- package/src/cards/index.ts +0 -21
- package/src/common/html.ts +0 -17
- package/src/index.ts +0 -18
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Sink } from './serialize.ts';
|
|
2
|
+
/** Every CSS property a card declares, closed so a typo is a compile error, not a dropped rule. */
|
|
3
|
+
type CssProperty = '-webkit-box-orient' | '-webkit-line-clamp' | 'animation' | 'animation-delay' | 'animation-duration' | 'color' | 'display' | 'fill' | 'font' | 'font-size' | 'font-variant-numeric' | 'font-weight' | 'line-clamp' | 'line-height' | 'margin' | 'opacity' | 'overflow' | 'overflow-wrap' | 'padding-bottom' | 'stroke' | 'stroke-dasharray' | 'stroke-dashoffset' | 'stroke-linecap' | 'stroke-width' | 'text-overflow' | 'transform' | 'transform-origin' | 'width' | 'word-break';
|
|
4
|
+
/** A declaration whose value is `undefined` is left out, so a caller can inline a condition. */
|
|
5
|
+
type Declarations = Partial<Record<CssProperty, string | number | undefined>>;
|
|
6
|
+
type CssNode = {
|
|
7
|
+
readonly kind: 'rule';
|
|
8
|
+
readonly selector: string;
|
|
9
|
+
readonly declarations: Declarations;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'at';
|
|
12
|
+
readonly prelude: string;
|
|
13
|
+
readonly children: Array<CssChild>;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: 'comment';
|
|
16
|
+
readonly text: string;
|
|
17
|
+
};
|
|
18
|
+
/** Anything accepted where CSS is expected; falsy entries drop out, arrays flatten. */
|
|
19
|
+
type CssChild = CssNode | false | null | undefined | Array<CssChild>;
|
|
20
|
+
/**
|
|
21
|
+
* Selectors stay free-form: they compose (`.badge rect`), and a keyframe stop is one too (`from`).
|
|
22
|
+
*/
|
|
23
|
+
declare const rule: (selector: string, declarations: Declarations) => CssNode;
|
|
24
|
+
declare const atRule: (prelude: string, ...children: Array<CssChild>) => CssNode;
|
|
25
|
+
declare const cssComment: (text: string) => CssNode;
|
|
26
|
+
/**
|
|
27
|
+
* Serializes a stylesheet, dropping every rule that would have come out empty.
|
|
28
|
+
*
|
|
29
|
+
* A block is written optimistically and rewound if its body turns out empty,
|
|
30
|
+
* so the tree is walked once however deeply the at-rules nest.
|
|
31
|
+
*/
|
|
32
|
+
declare const writeCss: (children: Array<CssChild>, depth: number, sink: Sink) => void;
|
|
33
|
+
export { atRule, cssComment, rule, writeCss };
|
|
34
|
+
export type { CssChild, Declarations };
|
|
35
|
+
//# sourceMappingURL=css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../../src/markup/css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAG3C,mGAAmG;AACnG,KAAK,WAAW,GACZ,oBAAoB,GACpB,oBAAoB,GACpB,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,OAAO,GACP,SAAS,GACT,MAAM,GACN,MAAM,GACN,WAAW,GACX,sBAAsB,GACtB,aAAa,GACb,YAAY,GACZ,aAAa,GACb,QAAQ,GACR,SAAS,GACT,UAAU,GACV,eAAe,GACf,gBAAgB,GAChB,QAAQ,GACR,kBAAkB,GAClB,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,eAAe,GACf,WAAW,GACX,kBAAkB,GAClB,OAAO,GACP,YAAY,CAAC;AAEjB,gGAAgG;AAChG,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE9E,KAAK,OAAO,GACR;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAA;CAAE,GACzF;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;CAAE,GACrF;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,uFAAuF;AACvF,KAAK,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;AAErE;;GAEG;AACH,QAAA,MAAM,IAAI,aAAc,MAAM,gBAAgB,YAAY,KAAG,OAI3D,CAAC;AAEH,QAAA,MAAM,MAAM,YAAa,MAAM,eAAe,KAAK,CAAC,QAAQ,CAAC,KAAG,OAI9D,CAAC;AAEH,QAAA,MAAM,UAAU,SAAU,MAAM,KAAG,OAAsC,CAAC;AAiB1E;;;;;GAKG;AACH,QAAA,MAAM,QAAQ,aAAc,KAAK,CAAC,QAAQ,CAAC,SAAS,MAAM,QAAQ,IAAI,KAAG,IA8BxE,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { INDENT, indentAt } from './serialize.js';
|
|
2
|
+
/**
|
|
3
|
+
* Selectors stay free-form: they compose (`.badge rect`), and a keyframe stop is one too (`from`).
|
|
4
|
+
*/
|
|
5
|
+
const rule = (selector, declarations) => ({
|
|
6
|
+
kind: 'rule',
|
|
7
|
+
selector,
|
|
8
|
+
declarations,
|
|
9
|
+
});
|
|
10
|
+
const atRule = (prelude, ...children) => ({
|
|
11
|
+
kind: 'at',
|
|
12
|
+
prelude,
|
|
13
|
+
children,
|
|
14
|
+
});
|
|
15
|
+
const cssComment = (text) => ({ kind: 'comment', text });
|
|
16
|
+
/** Drops the rules that carry nothing and flattens the arrays. */
|
|
17
|
+
const flatten = (children, into = []) => {
|
|
18
|
+
for (const child of children) {
|
|
19
|
+
if (!child) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(child)) {
|
|
23
|
+
flatten(child, into);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
into.push(child);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return into;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Serializes a stylesheet, dropping every rule that would have come out empty.
|
|
33
|
+
*
|
|
34
|
+
* A block is written optimistically and rewound if its body turns out empty,
|
|
35
|
+
* so the tree is walked once however deeply the at-rules nest.
|
|
36
|
+
*/
|
|
37
|
+
const writeCss = (children, depth, sink) => {
|
|
38
|
+
const indent = indentAt(depth);
|
|
39
|
+
for (const node of flatten(children)) {
|
|
40
|
+
if (node.kind === 'comment') {
|
|
41
|
+
sink.out += `${indent}/* ${node.text} */\n`;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const mark = sink.out.length;
|
|
45
|
+
if (node.kind === 'at') {
|
|
46
|
+
sink.out += `${indent}${node.prelude} {\n`;
|
|
47
|
+
const bodyStart = sink.out.length;
|
|
48
|
+
writeCss(node.children, depth + 1, sink);
|
|
49
|
+
sink.out =
|
|
50
|
+
sink.out.length === bodyStart ? sink.out.slice(0, mark) : `${sink.out}${indent}}\n`;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
sink.out += `${indent}${node.selector} {\n`;
|
|
54
|
+
const bodyStart = sink.out.length;
|
|
55
|
+
for (const property of Object.keys(node.declarations)) {
|
|
56
|
+
const value = node.declarations[property];
|
|
57
|
+
if (value !== undefined) {
|
|
58
|
+
sink.out += `${indent}${INDENT}${property}: ${String(value)};\n`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
sink.out = sink.out.length === bodyStart ? sink.out.slice(0, mark) : `${sink.out}${indent}}\n`;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export { atRule, cssComment, rule, writeCss };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CssChild } from './css.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Every element a card draws, closed so `el('circel', …)` is a compile error.
|
|
4
|
+
* `style` is absent on purpose: it comes from `style()`, which takes rules rather than children.
|
|
5
|
+
*/
|
|
6
|
+
type Tag = 'a' | 'circle' | 'defs' | 'desc' | 'div' | 'foreignObject' | 'g' | 'linearGradient' | 'mask' | 'path' | 'rect' | 'stop' | 'svg' | 'text' | 'title' | 'tspan';
|
|
7
|
+
/**
|
|
8
|
+
* Every attribute a card writes, closed like `Tag`:
|
|
9
|
+
* a misspelled `stroke-width` would otherwise be valid TypeScript and invisible in the output.
|
|
10
|
+
*/
|
|
11
|
+
type Attribute = 'alignment-baseline' | 'aria-hidden' | 'aria-labelledby' | 'class' | 'cx' | 'cy' | 'd' | 'data-testid' | 'data-view-component' | 'dominant-baseline' | 'dy' | 'fill' | 'fill-rule' | 'gradientTransform' | 'gradientUnits' | 'height' | 'href' | 'id' | 'mask' | 'offset' | 'r' | 'role' | 'rx' | 'ry' | 'size' | 'stop-color' | 'stroke' | 'stroke-dasharray' | 'stroke-dashoffset' | 'stroke-linecap' | 'stroke-opacity' | 'stroke-width' | 'style' | 'text-anchor' | 'transform' | 'version' | 'viewBox' | 'width' | 'x' | 'xmlns' | 'y';
|
|
12
|
+
/** An attribute whose value is `undefined` is not written, so a caller can inline a condition. */
|
|
13
|
+
type Attributes = Partial<Record<Attribute, string | number | undefined>>;
|
|
14
|
+
interface MarkupElement {
|
|
15
|
+
readonly tag: Tag;
|
|
16
|
+
readonly attributes: Attributes;
|
|
17
|
+
readonly children: Array<Child>;
|
|
18
|
+
}
|
|
19
|
+
interface StyleElement {
|
|
20
|
+
readonly tag: 'style';
|
|
21
|
+
readonly rules: Array<CssChild>;
|
|
22
|
+
}
|
|
23
|
+
/** Anything accepted as content; falsy entries drop out, arrays flatten, strings are escaped. */
|
|
24
|
+
type Child = MarkupElement | StyleElement | string | number | false | null | undefined | Array<Child>;
|
|
25
|
+
/**
|
|
26
|
+
* Builds one element. Attribute values and text children are encoded on the way out.
|
|
27
|
+
*/
|
|
28
|
+
declare const el: (tag: Tag, attributes?: Attributes, ...children: Array<Child>) => MarkupElement;
|
|
29
|
+
/**
|
|
30
|
+
* Builds the `<style>` element from a stylesheet rather than from text.
|
|
31
|
+
*/
|
|
32
|
+
declare const style: (...rules: Array<CssChild>) => StyleElement;
|
|
33
|
+
/**
|
|
34
|
+
* Serializes a finished card: one element per line, two spaces per nesting level.
|
|
35
|
+
*
|
|
36
|
+
* @returns The rendered SVG.
|
|
37
|
+
*/
|
|
38
|
+
declare const renderMarkup: (root: MarkupElement) => string;
|
|
39
|
+
export { el, renderMarkup, style };
|
|
40
|
+
export type { Child, MarkupElement };
|
|
41
|
+
//# sourceMappingURL=element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../src/markup/element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAMzC;;;GAGG;AACH,KAAK,GAAG,GACJ,GAAG,GACH,QAAQ,GACR,MAAM,GACN,MAAM,GACN,KAAK,GACL,eAAe,GACf,GAAG,GACH,gBAAgB,GAChB,MAAM,GACN,MAAM,GACN,MAAM,GACN,MAAM,GACN,KAAK,GACL,MAAM,GACN,OAAO,GACP,OAAO,CAAC;AAEZ;;;GAGG;AACH,KAAK,SAAS,GACV,oBAAoB,GACpB,aAAa,GACb,iBAAiB,GACjB,OAAO,GACP,IAAI,GACJ,IAAI,GACJ,GAAG,GACH,aAAa,GACb,qBAAqB,GACrB,mBAAmB,GACnB,IAAI,GACJ,MAAM,GACN,WAAW,GACX,mBAAmB,GACnB,eAAe,GACf,QAAQ,GACR,MAAM,GACN,IAAI,GACJ,MAAM,GACN,QAAQ,GACR,GAAG,GACH,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,kBAAkB,GAClB,mBAAmB,GACnB,gBAAgB,GAChB,gBAAgB,GAChB,cAAc,GACd,OAAO,GACP,aAAa,GACb,WAAW,GACX,SAAS,GACT,SAAS,GACT,OAAO,GACP,GAAG,GACH,OAAO,GACP,GAAG,CAAC;AAER,kGAAkG;AAClG,KAAK,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAK1E,UAAU,aAAa;IACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CACjC;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;CACjC;AAED,iGAAiG;AACjG,KAAK,KAAK,GACN,aAAa,GACb,YAAY,GACZ,MAAM,GACN,MAAM,GACN,KAAK,GACL,IAAI,GACJ,SAAS,GACT,KAAK,CAAC,KAAK,CAAC,CAAC;AAKjB;;GAEG;AACH,QAAA,MAAM,EAAE,QAAS,GAAG,eAAc,UAAU,eAAoB,KAAK,CAAC,KAAK,CAAC,KAAG,aAI7E,CAAC;AAEH;;GAEG;AACH,QAAA,MAAM,KAAK,aAAc,KAAK,CAAC,QAAQ,CAAC,KAAG,YAAyC,CAAC;AAmHrF;;;;GAIG;AACH,QAAA,MAAM,YAAY,SAAU,aAAa,KAAG,MAI3C,CAAC;AAEF,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AACnC,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { writeCss } from './css.js';
|
|
2
|
+
import { encodeHTML } from './html.js';
|
|
3
|
+
import { indentAt } from './serialize.js';
|
|
4
|
+
/** Elements whose character data is part of the rendering, so they stay on one line. */
|
|
5
|
+
const INLINE_ELEMENTS = new Set(['text', 'tspan', 'title', 'desc', 'div']);
|
|
6
|
+
/**
|
|
7
|
+
* Builds one element. Attribute values and text children are encoded on the way out.
|
|
8
|
+
*/
|
|
9
|
+
const el = (tag, attributes = {}, ...children) => ({
|
|
10
|
+
tag,
|
|
11
|
+
attributes,
|
|
12
|
+
children,
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Builds the `<style>` element from a stylesheet rather than from text.
|
|
16
|
+
*/
|
|
17
|
+
const style = (...rules) => ({ tag: 'style', rules });
|
|
18
|
+
const isStyle = (child) => 'rules' in child;
|
|
19
|
+
/** Drops the children that carry nothing and flattens the arrays. */
|
|
20
|
+
const flatten = (children, into = []) => {
|
|
21
|
+
for (const child of children) {
|
|
22
|
+
if (child === false || child === null || child === undefined || child === '') {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(child)) {
|
|
26
|
+
flatten(child, into);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
into.push(child);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return into;
|
|
33
|
+
};
|
|
34
|
+
const openTag = (node, selfClosing) => {
|
|
35
|
+
let tag = `<${node.tag}`;
|
|
36
|
+
const { attributes } = node;
|
|
37
|
+
// `Object.keys` widens to `string`, so the cast restores what the type already says.
|
|
38
|
+
for (const name of Object.keys(attributes)) {
|
|
39
|
+
const value = attributes[name];
|
|
40
|
+
if (value !== undefined) {
|
|
41
|
+
// A number can hold nothing that needs escaping, so it skips the scan.
|
|
42
|
+
tag += typeof value === 'number' ? ` ${name}="${value}"` : ` ${name}="${encodeHTML(value)}"`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return `${tag}${selfClosing ? ' />' : '>'}`;
|
|
46
|
+
};
|
|
47
|
+
/** Serializes an element and its descendants onto one line, whitespace and all. */
|
|
48
|
+
const writeInline = (node) => {
|
|
49
|
+
if (typeof node === 'string') {
|
|
50
|
+
return encodeHTML(node);
|
|
51
|
+
}
|
|
52
|
+
if (typeof node === 'number') {
|
|
53
|
+
return String(node);
|
|
54
|
+
}
|
|
55
|
+
if (isStyle(node)) {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
const children = flatten(node.children);
|
|
59
|
+
if (children.length === 0) {
|
|
60
|
+
return openTag(node, true);
|
|
61
|
+
}
|
|
62
|
+
let inner = '';
|
|
63
|
+
for (const child of children) {
|
|
64
|
+
inner += writeInline(child);
|
|
65
|
+
}
|
|
66
|
+
return `${openTag(node, false)}${inner}</${node.tag}>`;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* A container is written optimistically and rewound if its content turns out empty,
|
|
70
|
+
* so an element that draws nothing costs one walk rather than two.
|
|
71
|
+
*/
|
|
72
|
+
const write = (node, depth, sink) => {
|
|
73
|
+
const indent = indentAt(depth);
|
|
74
|
+
if (typeof node === 'string') {
|
|
75
|
+
sink.out += `${indent}${encodeHTML(node)}\n`;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (typeof node === 'number') {
|
|
79
|
+
sink.out += `${indent}${node}\n`;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const mark = sink.out.length;
|
|
83
|
+
if (isStyle(node)) {
|
|
84
|
+
sink.out += `${indent}<style>\n`;
|
|
85
|
+
const bodyStart = sink.out.length;
|
|
86
|
+
writeCss(node.rules, depth + 1, sink);
|
|
87
|
+
sink.out =
|
|
88
|
+
sink.out.length === bodyStart ? sink.out.slice(0, mark) : `${sink.out}${indent}</style>\n`;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const children = flatten(node.children);
|
|
92
|
+
if (children.length === 0) {
|
|
93
|
+
sink.out += `${indent}${openTag(node, true)}\n`;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (INLINE_ELEMENTS.has(node.tag)) {
|
|
97
|
+
let inner = '';
|
|
98
|
+
for (const child of children) {
|
|
99
|
+
inner += writeInline(child);
|
|
100
|
+
}
|
|
101
|
+
sink.out +=
|
|
102
|
+
inner === ''
|
|
103
|
+
? `${indent}${openTag(node, true)}\n`
|
|
104
|
+
: `${indent}${openTag(node, false)}${inner}</${node.tag}>\n`;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
sink.out += `${indent}${openTag(node, false)}\n`;
|
|
108
|
+
const bodyStart = sink.out.length;
|
|
109
|
+
for (const child of children) {
|
|
110
|
+
write(child, depth + 1, sink);
|
|
111
|
+
}
|
|
112
|
+
sink.out =
|
|
113
|
+
sink.out.length === bodyStart
|
|
114
|
+
? `${sink.out.slice(0, mark)}${indent}${openTag(node, true)}\n`
|
|
115
|
+
: `${sink.out}${indent}</${node.tag}>\n`;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Serializes a finished card: one element per line, two spaces per nesting level.
|
|
119
|
+
*
|
|
120
|
+
* @returns The rendered SVG.
|
|
121
|
+
*/
|
|
122
|
+
const renderMarkup = (root) => {
|
|
123
|
+
const sink = { out: '' };
|
|
124
|
+
write(root, 0, sink);
|
|
125
|
+
return sink.out;
|
|
126
|
+
};
|
|
127
|
+
export { el, renderMarkup, style };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encodes a string for use as markup, one numeric character reference each.
|
|
3
|
+
*
|
|
4
|
+
* The serializer is now the only place text becomes markup, so nothing arrives pre-escaped:
|
|
5
|
+
* a literal `&` is encoded like any other `&` rather than passed through as a reference.
|
|
6
|
+
*
|
|
7
|
+
* @see https://stackoverflow.com/a/48073476/10629172
|
|
8
|
+
*
|
|
9
|
+
* @returns The text, safe to place in an attribute or as character data.
|
|
10
|
+
*/
|
|
11
|
+
declare const encodeHTML: (str: string) => string;
|
|
12
|
+
export { encodeHTML };
|
|
13
|
+
//# sourceMappingURL=html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/markup/html.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,QAAA,MAAM,UAAU,QAAS,MAAM,KAAG,MASjC,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What has to be encoded: the markup characters, everything above plain ASCII, and a backspace.
|
|
3
|
+
* One source for both regexes, so the check and the replacement cannot disagree.
|
|
4
|
+
*/
|
|
5
|
+
const ENCODED = String.raw `[<>&"'\u00A0-\u9999\u0008]`;
|
|
6
|
+
/** Non-global, so `.test` stays stateless: a global regex would carry `lastIndex`. */
|
|
7
|
+
const NEEDS_ENCODING = new RegExp(ENCODED);
|
|
8
|
+
const TO_ENCODE = new RegExp(ENCODED, 'g');
|
|
9
|
+
const BACKSPACE = '\u0008';
|
|
10
|
+
/**
|
|
11
|
+
* Encodes a string for use as markup, one numeric character reference each.
|
|
12
|
+
*
|
|
13
|
+
* The serializer is now the only place text becomes markup, so nothing arrives pre-escaped:
|
|
14
|
+
* a literal `&` is encoded like any other `&` rather than passed through as a reference.
|
|
15
|
+
*
|
|
16
|
+
* @see https://stackoverflow.com/a/48073476/10629172
|
|
17
|
+
*
|
|
18
|
+
* @returns The text, safe to place in an attribute or as character data.
|
|
19
|
+
*/
|
|
20
|
+
const encodeHTML = (str) => {
|
|
21
|
+
// Most strings a card writes are plain ASCII, so they leave without a rewrite.
|
|
22
|
+
if (!NEEDS_ENCODING.test(str)) {
|
|
23
|
+
return str;
|
|
24
|
+
}
|
|
25
|
+
return str.replace(TO_ENCODE, (char) => char === BACKSPACE ? '' : `&#${char.codePointAt(0) ?? 0};`);
|
|
26
|
+
};
|
|
27
|
+
export { encodeHTML };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The markup layer: a card is built as a tree of elements and rules, then serialized once.
|
|
3
|
+
* It depends on nothing else in the package, so it sits below `cards/`, not inside `common/`.
|
|
4
|
+
*/
|
|
5
|
+
export { atRule, cssComment, rule } from './css.ts';
|
|
6
|
+
export type { CssChild, Declarations } from './css.ts';
|
|
7
|
+
export { el, renderMarkup, style } from './element.ts';
|
|
8
|
+
export type { Child, MarkupElement } from './element.ts';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markup/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACpD,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The markup layer: a card is built as a tree of elements and rules, then serialized once.
|
|
3
|
+
* It depends on nothing else in the package, so it sits below `cards/`, not inside `common/`.
|
|
4
|
+
*/
|
|
5
|
+
export { atRule, cssComment, rule } from './css.js';
|
|
6
|
+
export { el, renderMarkup, style } from './element.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the markup and stylesheet serializers share: where output goes, and how deep a line sits.
|
|
3
|
+
* Both write into one growing string rather than a list of chunks, so nothing needs joining.
|
|
4
|
+
*/
|
|
5
|
+
declare const INDENT = " ";
|
|
6
|
+
/** Collects serializer output. A plain holder so appends stay a property write. */
|
|
7
|
+
interface Sink {
|
|
8
|
+
out: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @returns Two spaces per level.
|
|
12
|
+
*/
|
|
13
|
+
declare const indentAt: (depth: number) => string;
|
|
14
|
+
export { INDENT, indentAt };
|
|
15
|
+
export type { Sink };
|
|
16
|
+
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/markup/serialize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAA,MAAM,MAAM,OAAO,CAAC;AAEpB,mFAAmF;AACnF,UAAU,IAAI;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAKD;;GAEG;AACH,QAAA,MAAM,QAAQ,UAAW,MAAM,KAAG,MAKjC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC5B,YAAY,EAAE,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the markup and stylesheet serializers share: where output goes, and how deep a line sits.
|
|
3
|
+
* Both write into one growing string rather than a list of chunks, so nothing needs joining.
|
|
4
|
+
*/
|
|
5
|
+
const INDENT = ' ';
|
|
6
|
+
/** Indentation by depth, grown as the tree is walked rather than rebuilt per line. */
|
|
7
|
+
const indents = ['', INDENT];
|
|
8
|
+
/**
|
|
9
|
+
* @returns Two spaces per level.
|
|
10
|
+
*/
|
|
11
|
+
const indentAt = (depth) => {
|
|
12
|
+
for (let i = indents.length; i <= depth; i += 1) {
|
|
13
|
+
indents.push(`${indents[i - 1] ?? ''}${INDENT}`);
|
|
14
|
+
}
|
|
15
|
+
return indents[depth] ?? '';
|
|
16
|
+
};
|
|
17
|
+
export { INDENT, indentAt };
|