@plotdb/lotion 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +79 -1
- package/cli.js +137 -46
- package/index.css +12 -1
- package/index.js +185 -4
- package/index.min.css +1 -1
- package/index.min.js +1 -1
- package/package.json +1 -1
- package/vector.js +817 -0
- package/vector.min.js +1 -0
package/vector.js
ADDED
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
(function(){
|
|
2
|
+
(function(){
|
|
3
|
+
var lotion, ref$, props, skip, i$, len$, s, c, textProps, unsupported, b64Bytes, b64, svgUri, fixUri, box, svgProps, svgSrc, bakeTransform, convert, fontCache, unquote, parseRange, parseSrc, faceOf, facesInText, facesInSheet, allFaces, getFaces, loadFont, hb, getHb, WGHT, subset, clamp, weightRank, fontsFor, render, vector;
|
|
4
|
+
lotion = window.lotion;
|
|
5
|
+
ref$ = lotion.libs;
|
|
6
|
+
ref$.satori = 'https://cdn.jsdelivr.net/npm/satori@0.36.0/+esm';
|
|
7
|
+
ref$.woff2 = 'https://cdn.jsdelivr.net/npm/woff2-encoder@2.0.0/dist/decompress.js';
|
|
8
|
+
ref$.hbsubset = 'https://cdn.jsdelivr.net/npm/harfbuzzjs@1.6.3/dist/harfbuzz-subset.wasm';
|
|
9
|
+
props = ['color', 'fontFamily', 'fontSize', 'fontWeight', 'fontStyle', 'lineHeight', 'letterSpacing', 'textAlign', 'whiteSpace', 'wordBreak', 'textTransform', 'textShadow', 'textIndent', 'backgroundColor', 'backgroundImage', 'backgroundPosition', 'backgroundSize', 'backgroundRepeat', 'backgroundClip', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'borderTopStyle', 'borderRightStyle', 'borderBottomStyle', 'borderLeftStyle', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'boxShadow', 'opacity', 'filter', 'clipPath', 'overflow', 'zIndex', 'transform', 'transformOrigin', 'maskImage', 'maskPosition', 'maskSize', 'maskRepeat'];
|
|
10
|
+
skip = {
|
|
11
|
+
textShadow: 'none',
|
|
12
|
+
textIndent: '0px',
|
|
13
|
+
textTransform: 'none',
|
|
14
|
+
backgroundColor: 'rgba(0, 0, 0, 0)',
|
|
15
|
+
backgroundImage: 'none',
|
|
16
|
+
backgroundPosition: '0% 0%',
|
|
17
|
+
backgroundSize: 'auto',
|
|
18
|
+
backgroundRepeat: 'repeat',
|
|
19
|
+
backgroundClip: 'border-box',
|
|
20
|
+
boxShadow: 'none',
|
|
21
|
+
opacity: '1',
|
|
22
|
+
filter: 'none',
|
|
23
|
+
clipPath: 'none',
|
|
24
|
+
overflow: 'visible',
|
|
25
|
+
zIndex: 'auto',
|
|
26
|
+
transform: 'none',
|
|
27
|
+
maskImage: 'none',
|
|
28
|
+
maskPosition: '0% 0%',
|
|
29
|
+
maskSize: 'auto',
|
|
30
|
+
maskRepeat: 'repeat',
|
|
31
|
+
lineHeight: 'normal',
|
|
32
|
+
letterSpacing: 'normal'
|
|
33
|
+
};
|
|
34
|
+
for (i$ = 0, len$ = (ref$ = ['Top', 'Right', 'Bottom', 'Left']).length; i$ < len$; ++i$) {
|
|
35
|
+
s = ref$[i$];
|
|
36
|
+
skip["border" + s + "Width"] = '0px';
|
|
37
|
+
skip["border" + s + "Style"] = 'none';
|
|
38
|
+
skip["padding" + s] = '0px';
|
|
39
|
+
}
|
|
40
|
+
for (i$ = 0, len$ = (ref$ = ['TopLeft', 'TopRight', 'BottomRight', 'BottomLeft']).length; i$ < len$; ++i$) {
|
|
41
|
+
c = ref$[i$];
|
|
42
|
+
skip["border" + c + "Radius"] = '0px';
|
|
43
|
+
}
|
|
44
|
+
textProps = ['color', 'fontFamily', 'fontSize', 'fontWeight', 'fontStyle', 'lineHeight', 'letterSpacing', 'textAlign', 'whiteSpace', 'wordBreak', 'textTransform', 'textShadow', 'textIndent'];
|
|
45
|
+
unsupported = {
|
|
46
|
+
backdropFilter: 'none',
|
|
47
|
+
textDecorationLine: 'none'
|
|
48
|
+
};
|
|
49
|
+
b64Bytes = function(buf){
|
|
50
|
+
var bytes, bin, i$, to$, i;
|
|
51
|
+
bytes = new Uint8Array(buf);
|
|
52
|
+
bin = '';
|
|
53
|
+
for (i$ = 0, to$ = bytes.length; i$ < to$; i$ += 0x8000) {
|
|
54
|
+
i = i$;
|
|
55
|
+
bin += String.fromCharCode.apply(null, bytes.subarray(i, i + 0x8000));
|
|
56
|
+
}
|
|
57
|
+
return btoa(bin);
|
|
58
|
+
};
|
|
59
|
+
b64 = function(str){
|
|
60
|
+
return b64Bytes(new TextEncoder().encode(str));
|
|
61
|
+
};
|
|
62
|
+
svgUri = function(xml){
|
|
63
|
+
return "data:image/svg+xml;base64," + b64(xml);
|
|
64
|
+
};
|
|
65
|
+
fixUri = function(v){
|
|
66
|
+
return v.replace(/url\("data:image\/svg\+xml(?:;charset=[^,;]+)?(?:;utf8)?,([^"]*)"\)/g, function(m, d){
|
|
67
|
+
var e;
|
|
68
|
+
return "url(\"" + svgUri((function(){
|
|
69
|
+
try {
|
|
70
|
+
return decodeURIComponent(d);
|
|
71
|
+
} catch (e$) {
|
|
72
|
+
e = e$;
|
|
73
|
+
return d;
|
|
74
|
+
}
|
|
75
|
+
}())) + "\")";
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
box = function(el, parent, cs, ctx){
|
|
79
|
+
var x, y, ref$, w, h;
|
|
80
|
+
if (el.offsetWidth != null) {
|
|
81
|
+
x = el.offsetLeft;
|
|
82
|
+
y = el.offsetTop;
|
|
83
|
+
if (el.offsetParent !== parent && parent.offsetParent === el.offsetParent) {
|
|
84
|
+
x -= parent.offsetLeft + parent.clientLeft;
|
|
85
|
+
y -= parent.offsetTop + parent.clientTop;
|
|
86
|
+
}
|
|
87
|
+
return [x, y, el.offsetWidth, el.offsetHeight];
|
|
88
|
+
}
|
|
89
|
+
ref$ = [parseFloat(cs.width) || 0, parseFloat(cs.height) || 0], w = ref$[0], h = ref$[1];
|
|
90
|
+
if ((ref$ = cs.position) === 'absolute' || ref$ === 'fixed') {
|
|
91
|
+
return [parseFloat(cs.left) || 0, parseFloat(cs.top) || 0, w, h];
|
|
92
|
+
}
|
|
93
|
+
ctx.warn("<" + el.tagName.toLowerCase() + "> not absolutely positioned: placed at its parent's origin");
|
|
94
|
+
return [0, 0, w, h];
|
|
95
|
+
};
|
|
96
|
+
svgProps = ['font-family', 'font-size', 'font-weight', 'font-style', 'letter-spacing', 'text-anchor', 'dominant-baseline', 'fill', 'fill-opacity', 'fill-rule', 'stroke', 'stroke-width', 'stroke-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'paint-order', 'opacity', 'visibility', 'display', 'filter', 'mask', 'clip-path', 'color'];
|
|
97
|
+
svgSrc = function(el, w, h, ctx, node){
|
|
98
|
+
var c, srcs, dsts, texts, ids, i$, len$, d, j$, ref$, len1$, a, re, m, defs;
|
|
99
|
+
c = el.cloneNode(true);
|
|
100
|
+
c.setAttribute('width', w);
|
|
101
|
+
c.setAttribute('height', h);
|
|
102
|
+
if (!c.getAttribute('viewBox')) {
|
|
103
|
+
c.setAttribute('viewBox', "0 0 " + w + " " + h);
|
|
104
|
+
}
|
|
105
|
+
c.removeAttribute('style');
|
|
106
|
+
srcs = [el].concat(Array.from(el.querySelectorAll('*')));
|
|
107
|
+
dsts = [c].concat(Array.from(c.querySelectorAll('*')));
|
|
108
|
+
texts = [];
|
|
109
|
+
srcs.map(function(e, i){
|
|
110
|
+
var d, cs, pcs, decl, i$, ref$, len$, k, v, f;
|
|
111
|
+
d = dsts[i];
|
|
112
|
+
cs = getComputedStyle(e);
|
|
113
|
+
pcs = i === 0
|
|
114
|
+
? null
|
|
115
|
+
: getComputedStyle(e.parentNode);
|
|
116
|
+
decl = [];
|
|
117
|
+
for (i$ = 0, len$ = (ref$ = svgProps).length; i$ < len$; ++i$) {
|
|
118
|
+
k = ref$[i$];
|
|
119
|
+
v = cs.getPropertyValue(k);
|
|
120
|
+
if (pcs && pcs.getPropertyValue(k) === v) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (i === 0 && (k === 'opacity' || k === 'visibility' || k === 'display' || k === 'filter' || k === 'mask' || k === 'clip-path')) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
decl.push(k + ":" + v);
|
|
127
|
+
}
|
|
128
|
+
if (decl.length) {
|
|
129
|
+
d.setAttribute('style', decl.join(';'));
|
|
130
|
+
}
|
|
131
|
+
if (((ref$ = e.tagName.toLowerCase()) === 'text' || ref$ === 'tspan' || ref$ === 'textpath') && !e.querySelector('tspan, textPath')) {
|
|
132
|
+
f = {};
|
|
133
|
+
ctx.text(cs, e.textContent, f);
|
|
134
|
+
return texts.push([d, f]);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
ids = new Set;
|
|
138
|
+
for (i$ = 0, len$ = dsts.length; i$ < len$; ++i$) {
|
|
139
|
+
d = dsts[i$];
|
|
140
|
+
for (j$ = 0, len1$ = (ref$ = Array.from(d.attributes)).length; j$ < len1$; ++j$) {
|
|
141
|
+
a = ref$[j$];
|
|
142
|
+
re = /url\(\s*['"]?#([^'")\s]+)['"]?\s*\)|^#(.+)$/g;
|
|
143
|
+
while (m = re.exec(a.value)) {
|
|
144
|
+
ids.add(m[1] || m[2]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
defs = null;
|
|
149
|
+
ids.forEach(function(id){
|
|
150
|
+
var src;
|
|
151
|
+
if (c.querySelector("[id=\"" + CSS.escape(id) + "\"]")) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (!(src = document.getElementById(id))) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!defs) {
|
|
158
|
+
defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
|
|
159
|
+
c.insertBefore(defs, c.firstChild);
|
|
160
|
+
}
|
|
161
|
+
return defs.appendChild(src.cloneNode(true));
|
|
162
|
+
});
|
|
163
|
+
ctx.later(function(fonts){
|
|
164
|
+
var names, i$, ref$, len$, ref1$, d, f, st, j$, len1$, n, faces;
|
|
165
|
+
names = new Set;
|
|
166
|
+
for (i$ = 0, len$ = (ref$ = texts).length; i$ < len$; ++i$) {
|
|
167
|
+
ref1$ = ref$[i$], d = ref1$[0], f = ref1$[1];
|
|
168
|
+
if (!f.fontFamily) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
st = d.getAttribute('style') || '';
|
|
172
|
+
d.setAttribute('style', st + ";font-family:" + f.fontFamily);
|
|
173
|
+
for (j$ = 0, len1$ = (ref1$ = f.fontFamily.split(',')).length; j$ < len1$; ++j$) {
|
|
174
|
+
n = ref1$[j$];
|
|
175
|
+
names.add(n.trim().replace(/'/g, ''));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
faces = fonts.filter(function(it){
|
|
179
|
+
return names.has(it.name);
|
|
180
|
+
}).map(function(f){
|
|
181
|
+
return ("@font-face{font-family:'" + f.name + "';font-weight:" + f.weight + ";font-style:" + f.style + ";") + ("src:url(data:font/ttf;base64," + b64Bytes(f.data) + ") format('truetype')}");
|
|
182
|
+
});
|
|
183
|
+
if (faces.length) {
|
|
184
|
+
st = document.createElementNS('http://www.w3.org/2000/svg', 'style');
|
|
185
|
+
st.textContent = faces.join('');
|
|
186
|
+
c.insertBefore(st, c.firstChild);
|
|
187
|
+
}
|
|
188
|
+
return node.props.src = svgUri(new XMLSerializer().serializeToString(c));
|
|
189
|
+
});
|
|
190
|
+
return '';
|
|
191
|
+
};
|
|
192
|
+
bakeTransform = function(node, ctx){
|
|
193
|
+
var st, m, v;
|
|
194
|
+
st = node.props.style;
|
|
195
|
+
if (!(st.maskImage || st.clipPath)) {
|
|
196
|
+
return node;
|
|
197
|
+
}
|
|
198
|
+
if (!st.transform) {
|
|
199
|
+
return node;
|
|
200
|
+
}
|
|
201
|
+
m = /^matrix\(([^)]+)\)$/.exec(st.transform);
|
|
202
|
+
v = m ? m[1].split(',').map(function(it){
|
|
203
|
+
return +it;
|
|
204
|
+
}) : null;
|
|
205
|
+
if (v && v[0] === 1 && v[1] === 0 && v[2] === 0 && v[3] === 1) {
|
|
206
|
+
st.left += v[4];
|
|
207
|
+
st.top += v[5];
|
|
208
|
+
delete st.transform;
|
|
209
|
+
delete st.transformOrigin;
|
|
210
|
+
} else {
|
|
211
|
+
ctx.warn("mask / clip-path with a non-translation transform: misplaced");
|
|
212
|
+
}
|
|
213
|
+
return node;
|
|
214
|
+
};
|
|
215
|
+
convert = function(el, ctx, depth){
|
|
216
|
+
var root, cs, tag, ref$, x, y, w, h, hidden, k, v, blend, kids, texts, elems, style, i$, len$, s, node, children, text, jc, c, that;
|
|
217
|
+
depth == null && (depth = 0);
|
|
218
|
+
root = depth === 0;
|
|
219
|
+
cs = getComputedStyle(el);
|
|
220
|
+
if (cs.display === 'none' || +cs.opacity === 0) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
tag = el.tagName.toLowerCase();
|
|
224
|
+
ref$ = box(el, el.parentNode, cs, ctx), x = ref$[0], y = ref$[1], w = ref$[2], h = ref$[3];
|
|
225
|
+
hidden = cs.visibility !== 'visible';
|
|
226
|
+
for (k in ref$ = unsupported) {
|
|
227
|
+
v = ref$[k];
|
|
228
|
+
if (cs[k] && cs[k] !== v) {
|
|
229
|
+
ctx.warn(k + ": " + cs[k]);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
blend = cs.mixBlendMode !== 'normal' ? cs.mixBlendMode : null;
|
|
233
|
+
if (blend && depth !== 1) {
|
|
234
|
+
ctx.warn("mixBlendMode on a nested element: " + blend + " ignored");
|
|
235
|
+
}
|
|
236
|
+
kids = Array.from(el.childNodes);
|
|
237
|
+
texts = kids.filter(function(n){
|
|
238
|
+
return n.nodeType === 3 && n.textContent.trim();
|
|
239
|
+
});
|
|
240
|
+
elems = kids.filter(function(n){
|
|
241
|
+
return n.nodeType === 1;
|
|
242
|
+
});
|
|
243
|
+
if (texts.length && elems.length) {
|
|
244
|
+
ctx.warn("mixed text and elements in <" + tag + ">");
|
|
245
|
+
}
|
|
246
|
+
style = {
|
|
247
|
+
display: 'flex',
|
|
248
|
+
boxSizing: 'border-box',
|
|
249
|
+
width: w,
|
|
250
|
+
height: h
|
|
251
|
+
};
|
|
252
|
+
if (!root) {
|
|
253
|
+
style.position = 'absolute';
|
|
254
|
+
style.left = x;
|
|
255
|
+
style.top = y;
|
|
256
|
+
}
|
|
257
|
+
for (i$ = 0, len$ = (ref$ = props).length; i$ < len$; ++i$) {
|
|
258
|
+
k = ref$[i$];
|
|
259
|
+
if (!texts.length && in$(k, textProps)) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
v = cs[k];
|
|
263
|
+
if (!v || skip[k] === v) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
style[k] = /data:image\/svg/.test(v) ? fixUri(v) : v;
|
|
267
|
+
}
|
|
268
|
+
for (i$ = 0, len$ = (ref$ = ['Top', 'Right', 'Bottom', 'Left']).length; i$ < len$; ++i$) {
|
|
269
|
+
s = ref$[i$];
|
|
270
|
+
if (!style["border" + s + "Width"]) {
|
|
271
|
+
delete style["border" + s + "Color"];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (style.overflow) {
|
|
275
|
+
style.overflow = 'hidden';
|
|
276
|
+
}
|
|
277
|
+
if (style.transform) {
|
|
278
|
+
style.transformOrigin = cs.transformOrigin;
|
|
279
|
+
} else {
|
|
280
|
+
delete style.transformOrigin;
|
|
281
|
+
}
|
|
282
|
+
if (hidden) {
|
|
283
|
+
for (i$ = 0, len$ = (ref$ = ['backgroundColor', 'backgroundImage', 'boxShadow', 'color', 'textShadow']).length; i$ < len$; ++i$) {
|
|
284
|
+
k = ref$[i$];
|
|
285
|
+
delete style[k];
|
|
286
|
+
}
|
|
287
|
+
for (i$ = 0, len$ = (ref$ = ['Top', 'Right', 'Bottom', 'Left']).length; i$ < len$; ++i$) {
|
|
288
|
+
s = ref$[i$];
|
|
289
|
+
delete style["border" + s + "Width"];
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (tag === 'img' || tag === 'canvas' || tag === 'svg') {
|
|
293
|
+
if (hidden) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
node = {
|
|
297
|
+
blend: depth === 1 ? blend : null,
|
|
298
|
+
type: 'img',
|
|
299
|
+
props: {
|
|
300
|
+
width: w,
|
|
301
|
+
height: h,
|
|
302
|
+
style: style
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
node.props.src = (function(){
|
|
306
|
+
switch (tag) {
|
|
307
|
+
case 'img':
|
|
308
|
+
return el.currentSrc || el.src;
|
|
309
|
+
case 'canvas':
|
|
310
|
+
return el.toDataURL();
|
|
311
|
+
case 'svg':
|
|
312
|
+
return svgSrc(el, w, h, ctx, node);
|
|
313
|
+
}
|
|
314
|
+
}());
|
|
315
|
+
return bakeTransform(node, ctx);
|
|
316
|
+
}
|
|
317
|
+
children = [];
|
|
318
|
+
if (texts.length && !hidden) {
|
|
319
|
+
text = texts.map(function(it){
|
|
320
|
+
return it.textContent;
|
|
321
|
+
}).join('');
|
|
322
|
+
ctx.text(cs, text, style);
|
|
323
|
+
children.push(text);
|
|
324
|
+
jc = {
|
|
325
|
+
center: 'center',
|
|
326
|
+
right: 'flex-end',
|
|
327
|
+
end: 'flex-end'
|
|
328
|
+
}[cs.textAlign];
|
|
329
|
+
if (jc && !elems.length) {
|
|
330
|
+
style.justifyContent = jc;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
for (i$ = 0, len$ = elems.length; i$ < len$; ++i$) {
|
|
334
|
+
c = elems[i$];
|
|
335
|
+
if (that = convert(c, ctx, depth + 1)) {
|
|
336
|
+
children.push(that);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
node = {
|
|
340
|
+
type: 'div',
|
|
341
|
+
props: {
|
|
342
|
+
style: style,
|
|
343
|
+
children: children
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
if (blend && depth === 1) {
|
|
347
|
+
node.blend = blend;
|
|
348
|
+
}
|
|
349
|
+
return bakeTransform(node, ctx);
|
|
350
|
+
};
|
|
351
|
+
fontCache = {};
|
|
352
|
+
unquote = function(s){
|
|
353
|
+
return s.trim().replace(/^["']|["']$/g, '');
|
|
354
|
+
};
|
|
355
|
+
parseRange = function(s){
|
|
356
|
+
if (!s) {
|
|
357
|
+
return [[0, 0x10FFFF]];
|
|
358
|
+
}
|
|
359
|
+
return s.split(',').map(function(r){
|
|
360
|
+
var ref$, a, b;
|
|
361
|
+
r = r.trim().replace(/^u\+/i, '');
|
|
362
|
+
if (/\?/.test(r)) {
|
|
363
|
+
return [parseInt(r.replace(/\?/g, '0'), 16), parseInt(r.replace(/\?/g, 'F'), 16)];
|
|
364
|
+
}
|
|
365
|
+
ref$ = r.split('-'), a = ref$[0], b = ref$[1];
|
|
366
|
+
return [parseInt(a, 16), parseInt(b || a, 16)];
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
parseSrc = function(s, base){
|
|
370
|
+
var ret, re, m;
|
|
371
|
+
ret = [];
|
|
372
|
+
re = /url\(\s*(['"]?)([^'")]+)\1\s*\)\s*(?:format\(\s*['"]?([^'")]+)['"]?\s*\))?/g;
|
|
373
|
+
while (m = re.exec(s)) {
|
|
374
|
+
try {
|
|
375
|
+
ret.push({
|
|
376
|
+
url: new URL(m[2], base).href,
|
|
377
|
+
format: (m[3] || m[2].split('.').pop()).toLowerCase()
|
|
378
|
+
});
|
|
379
|
+
} catch (e$) {}
|
|
380
|
+
}
|
|
381
|
+
return ret;
|
|
382
|
+
};
|
|
383
|
+
faceOf = function(get, base){
|
|
384
|
+
return {
|
|
385
|
+
family: unquote(get('font-family')),
|
|
386
|
+
weight: (get('font-weight') || '400').split(/\s+/).map(function(it){
|
|
387
|
+
if (it === 'normal') {
|
|
388
|
+
return 400;
|
|
389
|
+
} else if (it === 'bold') {
|
|
390
|
+
return 700;
|
|
391
|
+
} else {
|
|
392
|
+
return +it;
|
|
393
|
+
}
|
|
394
|
+
}),
|
|
395
|
+
style: get('font-style') || 'normal',
|
|
396
|
+
range: parseRange(get('unicode-range')),
|
|
397
|
+
src: parseSrc(get('src'), base)
|
|
398
|
+
};
|
|
399
|
+
};
|
|
400
|
+
facesInText = function(text, base){
|
|
401
|
+
return (text.match(/@font-face\s*\{[^}]*\}/g) || []).map(function(b){
|
|
402
|
+
return faceOf(function(k){
|
|
403
|
+
return (new RegExp("(?:^|[{;\\s])" + k + "\\s*:\\s*([^;}]+)").exec(b) || [])[1];
|
|
404
|
+
}, base);
|
|
405
|
+
});
|
|
406
|
+
};
|
|
407
|
+
facesInSheet = function(sheet){
|
|
408
|
+
var base, rules, e;
|
|
409
|
+
base = sheet.href || location.href;
|
|
410
|
+
try {
|
|
411
|
+
rules = sheet.cssRules;
|
|
412
|
+
} catch (e$) {
|
|
413
|
+
e = e$;
|
|
414
|
+
rules = null;
|
|
415
|
+
}
|
|
416
|
+
if (!rules) {
|
|
417
|
+
return sheet.href
|
|
418
|
+
? fetch(sheet.href).then(function(r){
|
|
419
|
+
return r.text();
|
|
420
|
+
}).then(function(t){
|
|
421
|
+
return facesInText(t, base);
|
|
422
|
+
})['catch'](function(){
|
|
423
|
+
return [];
|
|
424
|
+
})
|
|
425
|
+
: Promise.resolve([]);
|
|
426
|
+
}
|
|
427
|
+
return Promise.all(Array.from(rules).map(function(r){
|
|
428
|
+
if (r.styleSheet) {
|
|
429
|
+
return facesInSheet(r.styleSheet);
|
|
430
|
+
}
|
|
431
|
+
if (r.type === 5) {
|
|
432
|
+
return [faceOf(function(k){
|
|
433
|
+
return r.style.getPropertyValue(k);
|
|
434
|
+
}, base)];
|
|
435
|
+
}
|
|
436
|
+
return [];
|
|
437
|
+
})).then(function(l){
|
|
438
|
+
return l.flat();
|
|
439
|
+
});
|
|
440
|
+
};
|
|
441
|
+
allFaces = null;
|
|
442
|
+
getFaces = function(){
|
|
443
|
+
var allFaces;
|
|
444
|
+
return allFaces != null
|
|
445
|
+
? allFaces
|
|
446
|
+
: allFaces = Promise.all(Array.from(document.styleSheets).map(facesInSheet)).then(function(l){
|
|
447
|
+
return l.flat();
|
|
448
|
+
});
|
|
449
|
+
};
|
|
450
|
+
loadFont = function(src){
|
|
451
|
+
var pick, key$, ref$;
|
|
452
|
+
pick = src.find(function(it){
|
|
453
|
+
var ref$;
|
|
454
|
+
return (ref$ = it.format) === 'truetype' || ref$ === 'opentype' || ref$ === 'woff' || ref$ === 'ttf' || ref$ === 'otf';
|
|
455
|
+
}) || src.find(function(it){
|
|
456
|
+
return it.format === 'woff2';
|
|
457
|
+
});
|
|
458
|
+
if (!pick) {
|
|
459
|
+
return Promise.resolve(null);
|
|
460
|
+
}
|
|
461
|
+
return (ref$ = fontCache[key$ = pick.url]) != null
|
|
462
|
+
? ref$
|
|
463
|
+
: fontCache[key$] = fetch(pick.url).then(function(r){
|
|
464
|
+
return r.arrayBuffer();
|
|
465
|
+
}).then(function(buf){
|
|
466
|
+
if (pick.format !== 'woff2') {
|
|
467
|
+
return buf;
|
|
468
|
+
}
|
|
469
|
+
return lotion.lib('woff2').then(function(m){
|
|
470
|
+
var decompress;
|
|
471
|
+
decompress = m.decompress || m['default'];
|
|
472
|
+
return decompress(buf);
|
|
473
|
+
}).then(function(u8){
|
|
474
|
+
return u8.buffer.slice(u8.byteOffset, u8.byteOffset + u8.byteLength);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
};
|
|
478
|
+
hb = null;
|
|
479
|
+
getHb = function(){
|
|
480
|
+
var hb;
|
|
481
|
+
return hb != null
|
|
482
|
+
? hb
|
|
483
|
+
: hb = fetch(lotion.libs.hbsubset).then(function(r){
|
|
484
|
+
return r.arrayBuffer();
|
|
485
|
+
}).then(function(b){
|
|
486
|
+
return WebAssembly.instantiate(b, {});
|
|
487
|
+
}).then(function(arg$){
|
|
488
|
+
var instance, e;
|
|
489
|
+
instance = arg$.instance;
|
|
490
|
+
e = instance.exports;
|
|
491
|
+
if (e._initialize) {
|
|
492
|
+
e._initialize();
|
|
493
|
+
}
|
|
494
|
+
return e;
|
|
495
|
+
});
|
|
496
|
+
};
|
|
497
|
+
WGHT = 0x77676874;
|
|
498
|
+
subset = function(buf, weight, cps){
|
|
499
|
+
return getHb().then(function(e){
|
|
500
|
+
var n, p, blob, face, input, us, i$, ref$, len$, c, sub, ret, rb, d;
|
|
501
|
+
n = buf.byteLength;
|
|
502
|
+
p = e.malloc(n);
|
|
503
|
+
new Uint8Array(e.memory.buffer).set(new Uint8Array(buf), p);
|
|
504
|
+
blob = e.hb_blob_create(p, n, 1, 0, 0);
|
|
505
|
+
face = e.hb_face_create(blob, 0);
|
|
506
|
+
e.hb_blob_destroy(blob);
|
|
507
|
+
input = e.hb_subset_input_create_or_fail();
|
|
508
|
+
us = e.hb_subset_input_unicode_set(input);
|
|
509
|
+
for (i$ = 0, len$ = (ref$ = cps).length; i$ < len$; ++i$) {
|
|
510
|
+
c = ref$[i$];
|
|
511
|
+
e.hb_set_add(us, c);
|
|
512
|
+
}
|
|
513
|
+
e.hb_subset_input_pin_axis_location(input, face, WGHT, weight);
|
|
514
|
+
sub = e.hb_subset_or_fail(face, input);
|
|
515
|
+
e.hb_subset_input_destroy(input);
|
|
516
|
+
ret = null;
|
|
517
|
+
if (sub) {
|
|
518
|
+
rb = e.hb_face_reference_blob(sub);
|
|
519
|
+
d = e.hb_blob_get_data(rb, 0);
|
|
520
|
+
ret = new Uint8Array(e.memory.buffer).slice(d, d + e.hb_blob_get_length(rb)).buffer;
|
|
521
|
+
e.hb_blob_destroy(rb);
|
|
522
|
+
e.hb_face_destroy(sub);
|
|
523
|
+
}
|
|
524
|
+
e.hb_face_destroy(face);
|
|
525
|
+
e.free(p);
|
|
526
|
+
return ret;
|
|
527
|
+
});
|
|
528
|
+
};
|
|
529
|
+
clamp = function(v, a, b){
|
|
530
|
+
return Math.min(b, Math.max(a, v));
|
|
531
|
+
};
|
|
532
|
+
weightRank = function(f, w){
|
|
533
|
+
var ref$, a, b;
|
|
534
|
+
ref$ = [f.weight[0], f.weight[1] || f.weight[0]], a = ref$[0], b = ref$[1];
|
|
535
|
+
if (w >= a && w <= b) {
|
|
536
|
+
return 0;
|
|
537
|
+
}
|
|
538
|
+
if (w > 500) {
|
|
539
|
+
return a > w
|
|
540
|
+
? a - w
|
|
541
|
+
: 1000 + w - b;
|
|
542
|
+
}
|
|
543
|
+
if (w < 400) {
|
|
544
|
+
return b < w
|
|
545
|
+
? w - b
|
|
546
|
+
: 1000 + a - w;
|
|
547
|
+
}
|
|
548
|
+
if (a > w && a <= 500) {
|
|
549
|
+
return a - w;
|
|
550
|
+
} else if (b < w) {
|
|
551
|
+
return 1000 + w - b;
|
|
552
|
+
} else {
|
|
553
|
+
return 2000 + a - w;
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
fontsFor = function(used, ctx){
|
|
557
|
+
return getFaces().then(function(faces){
|
|
558
|
+
var groups, missing, nGroup, key, ref$, u, i$, ref1$, len$, c, cp, f, j$, ref2$, len1$, fam, cand, same, pin, gk, g, k, v;
|
|
559
|
+
groups = {};
|
|
560
|
+
missing = 0;
|
|
561
|
+
nGroup = 0;
|
|
562
|
+
for (key in ref$ = used) {
|
|
563
|
+
u = ref$[key];
|
|
564
|
+
u.names = [];
|
|
565
|
+
for (i$ = 0, len$ = (ref1$ = Array.from(u.chars)).length; i$ < len$; ++i$) {
|
|
566
|
+
c = ref1$[i$];
|
|
567
|
+
cp = c.codePointAt(0);
|
|
568
|
+
if (cp < 33) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
f = null;
|
|
572
|
+
for (j$ = 0, len1$ = (ref2$ = u.families).length; j$ < len1$; ++j$) {
|
|
573
|
+
fam = ref2$[j$];
|
|
574
|
+
cand = faces.filter(fn$);
|
|
575
|
+
if (!cand.length) {
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
same = cand.filter(fn1$);
|
|
579
|
+
if (same.length) {
|
|
580
|
+
cand = same;
|
|
581
|
+
}
|
|
582
|
+
f = cand.reduce(fn2$);
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
if (!f) {
|
|
586
|
+
missing++;
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
pin = clamp(u.weight, f.weight[0], f.weight[1] || f.weight[0]);
|
|
590
|
+
gk = f.src[0].url + "|" + u.weight + "|" + u.style;
|
|
591
|
+
g = (ref2$ = groups[gk]) != null
|
|
592
|
+
? ref2$
|
|
593
|
+
: groups[gk] = {
|
|
594
|
+
name: "lotion-font-" + (nGroup++),
|
|
595
|
+
face: f,
|
|
596
|
+
weight: u.weight,
|
|
597
|
+
pin: pin,
|
|
598
|
+
style: u.style,
|
|
599
|
+
cps: new Set([32])
|
|
600
|
+
};
|
|
601
|
+
g.cps.add(cp);
|
|
602
|
+
if (!in$(g.name, u.names)) {
|
|
603
|
+
u.names.push(g.name);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
if (missing) {
|
|
608
|
+
ctx.warn(missing + " characters have no web font ( system fonts are not available to satori )");
|
|
609
|
+
}
|
|
610
|
+
return Promise.all((function(){
|
|
611
|
+
var ref$, results$ = [];
|
|
612
|
+
for (k in ref$ = groups) {
|
|
613
|
+
v = ref$[k];
|
|
614
|
+
results$.push(v);
|
|
615
|
+
}
|
|
616
|
+
return results$;
|
|
617
|
+
}()).map(function(g){
|
|
618
|
+
return loadFont(g.face.src).then(function(buf){
|
|
619
|
+
if (!buf) {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
return subset(buf, g.pin, Array.from(g.cps)).then(function(data){
|
|
623
|
+
if (!data) {
|
|
624
|
+
ctx.warn("font " + g.face.family + ": subset failed");
|
|
625
|
+
return null;
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
name: g.name,
|
|
629
|
+
data: data,
|
|
630
|
+
weight: g.weight,
|
|
631
|
+
style: g.style
|
|
632
|
+
};
|
|
633
|
+
});
|
|
634
|
+
});
|
|
635
|
+
})).then(function(l){
|
|
636
|
+
return l.filter(function(it){
|
|
637
|
+
return it;
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
function fn$(f){
|
|
641
|
+
return f.family === fam && f.src.length && f.range.some(function(r){
|
|
642
|
+
return cp >= r[0] && cp <= r[1];
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
function fn1$(f){
|
|
646
|
+
return f.style === u.style;
|
|
647
|
+
}
|
|
648
|
+
function fn2$(a, b){
|
|
649
|
+
if (weightRank(b, u.weight) < weightRank(a, u.weight)) {
|
|
650
|
+
return b;
|
|
651
|
+
} else {
|
|
652
|
+
return a;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
};
|
|
657
|
+
render = function(satori, tree, o){
|
|
658
|
+
var kids, segs, i$, len$, k, bare;
|
|
659
|
+
kids = tree.props.children;
|
|
660
|
+
if (!kids.some(function(it){
|
|
661
|
+
return it.blend;
|
|
662
|
+
})) {
|
|
663
|
+
return satori(tree, o);
|
|
664
|
+
}
|
|
665
|
+
segs = [{
|
|
666
|
+
kids: []
|
|
667
|
+
}];
|
|
668
|
+
for (i$ = 0, len$ = kids.length; i$ < len$; ++i$) {
|
|
669
|
+
k = kids[i$];
|
|
670
|
+
if (k.blend) {
|
|
671
|
+
segs.push({
|
|
672
|
+
blend: k.blend,
|
|
673
|
+
kids: [k]
|
|
674
|
+
});
|
|
675
|
+
} else if (segs[segs.length - 1].blend) {
|
|
676
|
+
segs.push({
|
|
677
|
+
kids: [k]
|
|
678
|
+
});
|
|
679
|
+
} else {
|
|
680
|
+
segs[segs.length - 1].kids.push(k);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
bare = {
|
|
684
|
+
display: 'flex',
|
|
685
|
+
width: o.width,
|
|
686
|
+
height: o.height,
|
|
687
|
+
overflow: 'hidden'
|
|
688
|
+
};
|
|
689
|
+
return Promise.all(segs.map(function(g, i){
|
|
690
|
+
return satori({
|
|
691
|
+
type: 'div',
|
|
692
|
+
props: {
|
|
693
|
+
style: i === 0 ? tree.props.style : bare,
|
|
694
|
+
children: g.kids
|
|
695
|
+
}
|
|
696
|
+
}, o).then(function(svg){
|
|
697
|
+
var inner;
|
|
698
|
+
inner = svg.replace(/^<svg[^>]*>/, '').replace(/<\/svg>\s*$/, '').replace(/satori_/g, "satori_" + i + "_");
|
|
699
|
+
if (g.blend) {
|
|
700
|
+
return "<g style=\"mix-blend-mode:" + g.blend + "\">" + inner + "</g>";
|
|
701
|
+
} else {
|
|
702
|
+
return "<g>" + inner + "</g>";
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
})).then(function(layers){
|
|
706
|
+
return "<svg width=\"" + o.width + "\" height=\"" + o.height + "\" viewBox=\"0 0 " + o.width + " " + o.height + "\" xmlns=\"http://www.w3.org/2000/svg\">" + layers.join('') + "</svg>";
|
|
707
|
+
});
|
|
708
|
+
};
|
|
709
|
+
vector = function(el, opt){
|
|
710
|
+
var warns, used, laters, ctx, tree, w, h, ref$, that;
|
|
711
|
+
opt == null && (opt = {});
|
|
712
|
+
warns = {};
|
|
713
|
+
used = {};
|
|
714
|
+
laters = [];
|
|
715
|
+
ctx = {
|
|
716
|
+
warn: function(m){
|
|
717
|
+
return warns[m] = (warns[m] || 0) + 1;
|
|
718
|
+
},
|
|
719
|
+
later: function(f){
|
|
720
|
+
return laters.push(f);
|
|
721
|
+
},
|
|
722
|
+
text: function(cs, text, style){
|
|
723
|
+
var weight, key, u, ref$, i$, len$, c;
|
|
724
|
+
weight = +cs.fontWeight || 400;
|
|
725
|
+
key = cs.fontFamily + "|" + weight + "|" + cs.fontStyle;
|
|
726
|
+
u = (ref$ = used[key]) != null
|
|
727
|
+
? ref$
|
|
728
|
+
: used[key] = {
|
|
729
|
+
families: cs.fontFamily.split(',').map(unquote),
|
|
730
|
+
weight: weight,
|
|
731
|
+
style: cs.fontStyle,
|
|
732
|
+
chars: new Set,
|
|
733
|
+
styles: []
|
|
734
|
+
};
|
|
735
|
+
for (i$ = 0, len$ = (ref$ = Array.from(text)).length; i$ < len$; ++i$) {
|
|
736
|
+
c = ref$[i$];
|
|
737
|
+
u.chars.add(c);
|
|
738
|
+
}
|
|
739
|
+
return u.styles.push(style);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
tree = convert(el, ctx);
|
|
743
|
+
w = opt.width || el.offsetWidth;
|
|
744
|
+
h = opt.height || el.offsetHeight;
|
|
745
|
+
ref$ = tree.props.style;
|
|
746
|
+
ref$.width = w;
|
|
747
|
+
ref$.height = h;
|
|
748
|
+
ref$.overflow = 'hidden';
|
|
749
|
+
delete tree.props.style.transform;
|
|
750
|
+
delete tree.props.style.transformOrigin;
|
|
751
|
+
return Promise.all([
|
|
752
|
+
(that = opt.satori)
|
|
753
|
+
? Promise.resolve(that)
|
|
754
|
+
: lotion.lib('satori'), (that = opt.fonts)
|
|
755
|
+
? Promise.resolve(that)
|
|
756
|
+
: fontsFor(used, ctx)
|
|
757
|
+
]).then(function(arg$){
|
|
758
|
+
var m, fonts, k, ref$, u, i$, ref1$, len$, s, f, satori;
|
|
759
|
+
m = arg$[0], fonts = arg$[1];
|
|
760
|
+
if (!opt.fonts) {
|
|
761
|
+
for (k in ref$ = used) {
|
|
762
|
+
u = ref$[k];
|
|
763
|
+
for (i$ = 0, len$ = (ref1$ = u.styles).length; i$ < len$; ++i$) {
|
|
764
|
+
s = ref1$[i$];
|
|
765
|
+
s.fontFamily = u.names.map(fn$).join(', ');
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
for (i$ = 0, len$ = (ref$ = laters).length; i$ < len$; ++i$) {
|
|
770
|
+
f = ref$[i$];
|
|
771
|
+
f(fonts);
|
|
772
|
+
}
|
|
773
|
+
satori = m['default'] || m.satori || m;
|
|
774
|
+
return render(satori, tree, {
|
|
775
|
+
width: w,
|
|
776
|
+
height: h,
|
|
777
|
+
fonts: fonts
|
|
778
|
+
});
|
|
779
|
+
function fn$(it){
|
|
780
|
+
return "'" + it + "'";
|
|
781
|
+
}
|
|
782
|
+
}).then(function(svg){
|
|
783
|
+
var k, v;
|
|
784
|
+
return {
|
|
785
|
+
svg: svg,
|
|
786
|
+
warnings: (function(){
|
|
787
|
+
var ref$, results$ = [];
|
|
788
|
+
for (k in ref$ = warns) {
|
|
789
|
+
v = ref$[k];
|
|
790
|
+
results$.push(k + (v > 1 ? " ( x" + v + " )" : ''));
|
|
791
|
+
}
|
|
792
|
+
return results$;
|
|
793
|
+
}())
|
|
794
|
+
};
|
|
795
|
+
});
|
|
796
|
+
};
|
|
797
|
+
lotion.vector = vector;
|
|
798
|
+
return lotion.player.prototype.vector = function(t, opt){
|
|
799
|
+
var this$ = this;
|
|
800
|
+
opt == null && (opt = {});
|
|
801
|
+
if (t != null) {
|
|
802
|
+
this.opt.seek(t);
|
|
803
|
+
}
|
|
804
|
+
return vector(this.stage, opt).then(function(r){
|
|
805
|
+
if (t != null) {
|
|
806
|
+
this$.opt.seek(this$.t);
|
|
807
|
+
}
|
|
808
|
+
return r;
|
|
809
|
+
});
|
|
810
|
+
};
|
|
811
|
+
})();
|
|
812
|
+
function in$(x, xs){
|
|
813
|
+
var i = -1, l = xs.length >>> 0;
|
|
814
|
+
while (++i < l) if (x === xs[i]) return true;
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
}).call(this);
|