@react-x11/components 0.10.0 → 0.12.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/dist/code/index.d.ts.map +1 -1
- package/dist/code/index.js +25 -24
- package/dist/code/index.js.map +1 -1
- package/dist/code-language/index.d.ts +1 -1
- package/dist/code-language/index.d.ts.map +1 -1
- package/dist/code-language/index.js +1 -1
- package/dist/code-language/index.js.map +1 -1
- package/dist/code-language/runs.d.ts +31 -0
- package/dist/code-language/runs.d.ts.map +1 -1
- package/dist/code-language/runs.js +105 -0
- package/dist/code-language/runs.js.map +1 -1
- package/dist/codeblock/index.d.ts +13 -0
- package/dist/codeblock/index.d.ts.map +1 -1
- package/dist/codeblock/index.js +37 -1
- package/dist/codeblock/index.js.map +1 -1
- package/dist/flow/node.d.ts +14 -6
- package/dist/flow/node.d.ts.map +1 -1
- package/dist/flow/node.js +82 -64
- package/dist/flow/node.js.map +1 -1
- package/dist/html/controls.d.ts +26 -7
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +28 -3
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +32 -10
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +89 -31
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +19 -0
- package/dist/html/css/color.d.ts.map +1 -1
- package/dist/html/css/color.js +86 -0
- package/dist/html/css/color.js.map +1 -1
- package/dist/html/css/parse.d.ts +11 -0
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +114 -4
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +45 -5
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +363 -14
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.js +22 -5
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +10 -1
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +27 -2
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/css/vars.d.ts +5 -0
- package/dist/html/css/vars.d.ts.map +1 -1
- package/dist/html/css/vars.js +2 -2
- package/dist/html/css/vars.js.map +1 -1
- package/dist/html/dom.d.ts.map +1 -1
- package/dist/html/dom.js +35 -2
- package/dist/html/dom.js.map +1 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +38 -1
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/block.d.ts +11 -2
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +306 -25
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +61 -6
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +65 -16
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/cache.d.ts +2 -2
- package/dist/html/layout/cache.d.ts.map +1 -1
- package/dist/html/layout/cache.js +8 -3
- package/dist/html/layout/cache.js.map +1 -1
- package/dist/html/layout/floats.d.ts +4 -0
- package/dist/html/layout/floats.d.ts.map +1 -1
- package/dist/html/layout/floats.js +26 -0
- package/dist/html/layout/floats.js.map +1 -1
- package/dist/html/layout/inline.d.ts +29 -2
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +1454 -125
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/node.d.ts +33 -0
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +608 -86
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +53 -1
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +746 -214
- package/dist/html/paint.js.map +1 -1
- package/dist/html/surfaces.d.ts +7 -2
- package/dist/html/surfaces.d.ts.map +1 -1
- package/dist/html/surfaces.js +16 -0
- package/dist/html/surfaces.js.map +1 -1
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +27 -20
- package/dist/html/svg.js.map +1 -1
- package/dist/internal/codelines.d.ts +42 -0
- package/dist/internal/codelines.d.ts.map +1 -0
- package/dist/internal/codelines.js +170 -0
- package/dist/internal/codelines.js.map +1 -0
- package/dist/internal/window.d.ts +22 -0
- package/dist/internal/window.d.ts.map +1 -1
- package/dist/internal/window.js +35 -8
- package/dist/internal/window.js.map +1 -1
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +98 -26
- package/dist/markdown/index.js.map +1 -1
- package/dist/rich-text-editor/index.d.ts.map +1 -1
- package/dist/rich-text-editor/index.js +3 -8
- package/dist/rich-text-editor/index.js.map +1 -1
- package/dist/rich-text-editor/markdown.d.ts.map +1 -1
- package/dist/rich-text-editor/markdown.js +30 -1
- package/dist/rich-text-editor/markdown.js.map +1 -1
- package/dist/rich-text-editor/replace.d.ts +13 -0
- package/dist/rich-text-editor/replace.d.ts.map +1 -0
- package/dist/rich-text-editor/replace.js +64 -0
- package/dist/rich-text-editor/replace.js.map +1 -0
- package/dist/richtext/node.d.ts +7 -0
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js.map +1 -1
- package/dist/terminal-output/index.d.ts.map +1 -1
- package/dist/terminal-output/index.js +100 -25
- package/dist/terminal-output/index.js.map +1 -1
- package/dist/terminal-output/runs.d.ts +4 -1
- package/dist/terminal-output/runs.d.ts.map +1 -1
- package/dist/terminal-output/runs.js +5 -1
- package/dist/terminal-output/runs.js.map +1 -1
- package/package.json +5 -3
- package/src/code/index.ts +34 -32
- package/src/code-language/index.ts +1 -1
- package/src/code-language/runs.ts +111 -1
- package/src/codeblock/index.ts +48 -1
- package/src/flow/node.ts +80 -64
- package/src/html/controls.ts +50 -9
- package/src/html/css/cascade.ts +134 -43
- package/src/html/css/color.ts +87 -0
- package/src/html/css/parse.ts +107 -4
- package/src/html/css/style.ts +386 -23
- package/src/html/css/ua.ts +22 -5
- package/src/html/css/values.ts +31 -3
- package/src/html/css/vars.ts +2 -2
- package/src/html/dom.ts +38 -2
- package/src/html/index.ts +39 -1
- package/src/html/layout/block.ts +360 -22
- package/src/html/layout/boxes.ts +98 -23
- package/src/html/layout/cache.ts +8 -3
- package/src/html/layout/floats.ts +24 -0
- package/src/html/layout/inline.ts +1690 -119
- package/src/html/node.ts +648 -101
- package/src/html/paint.ts +883 -283
- package/src/html/surfaces.ts +21 -1
- package/src/html/svg.ts +30 -19
- package/src/internal/codelines.ts +200 -0
- package/src/internal/window.ts +36 -8
- package/src/markdown/index.ts +145 -26
- package/src/rich-text-editor/index.ts +3 -11
- package/src/rich-text-editor/markdown.ts +36 -1
- package/src/rich-text-editor/replace.ts +85 -0
- package/src/richtext/node.ts +7 -0
- package/src/terminal-output/index.ts +127 -34
- package/src/terminal-output/runs.ts +16 -2
package/dist/html/css/style.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { AUTO, alphaOf, fourSides, inkColor, isTransparent, keywordFontSize, parseAlpha, parseColor, isPct, parseLength, parseNumber, parseWeight, resolve, splitCommas, splitValue, } from './values.js';
|
|
16
16
|
import { parseUrl, readIdent, startsIdent } from './parse.js';
|
|
17
17
|
import { DEFAULT_QUOTES, parseContent, parseCounterList, parseListStyleType, parseQuotes, } from './content.js';
|
|
18
|
+
import { LIGHT_DARK, lightDark, usedColorScheme } from './color.js';
|
|
18
19
|
/** Whether a length is one `padding` takes: not `auto`, not negative. A
|
|
19
20
|
* `calc()` with a percentage in it has no sign until layout, which clamps
|
|
20
21
|
* it at zero (CSS Values 4 10.12). */
|
|
@@ -64,6 +65,7 @@ function parseClip(value, ctx) {
|
|
|
64
65
|
* same list. */
|
|
65
66
|
export const INHERITED = [
|
|
66
67
|
'color',
|
|
68
|
+
'colorScheme',
|
|
67
69
|
'textFillColor',
|
|
68
70
|
'fontFamily',
|
|
69
71
|
'fontSize',
|
|
@@ -116,6 +118,7 @@ export function initialStyle(look, scale = 1) {
|
|
|
116
118
|
// a copy of the literal, not the literal: see `copyStyle`
|
|
117
119
|
return copyStyle({
|
|
118
120
|
color: look.color,
|
|
121
|
+
colorScheme: look.colorScheme,
|
|
119
122
|
fontFamily: look.fontFamily,
|
|
120
123
|
fontSize: look.fontSize,
|
|
121
124
|
fontWeight: 400,
|
|
@@ -173,6 +176,7 @@ export function initialStyle(look, scale = 1) {
|
|
|
173
176
|
float: 'none',
|
|
174
177
|
clear: 'none',
|
|
175
178
|
boxSizing: 'content-box',
|
|
179
|
+
boxDecorationBreak: 'slice',
|
|
176
180
|
lineClamp: null,
|
|
177
181
|
maxLines: null,
|
|
178
182
|
clampContinue: 'auto',
|
|
@@ -267,6 +271,7 @@ export function initialStyle(look, scale = 1) {
|
|
|
267
271
|
backgroundClips: null,
|
|
268
272
|
backgroundOrigins: null,
|
|
269
273
|
borderImage: NO_BORDER_IMAGE,
|
|
274
|
+
mask: NO_MASK,
|
|
270
275
|
textFillColor: null,
|
|
271
276
|
textDecorationLine: 'none',
|
|
272
277
|
textDecorationColor: null,
|
|
@@ -350,6 +355,7 @@ export function inherit(parent, initial) {
|
|
|
350
355
|
// quarters of the cost of every element's style, a store through a
|
|
351
356
|
// computed name costing thirty times one through a written one
|
|
352
357
|
out.color = parent.color;
|
|
358
|
+
out.colorScheme = parent.colorScheme;
|
|
353
359
|
out.textFillColor = parent.textFillColor;
|
|
354
360
|
out.fontFamily = parent.fontFamily;
|
|
355
361
|
out.fontSize = parent.fontSize;
|
|
@@ -541,6 +547,16 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
541
547
|
if (/!\s*important$/i.test(value)) {
|
|
542
548
|
value = value.replace(/!\s*important$/i, '').trim();
|
|
543
549
|
}
|
|
550
|
+
// the branch of each `light-dark()` this element's scheme picks, before
|
|
551
|
+
// anything reads the value: it stands wherever a colour can, in a
|
|
552
|
+
// shorthand, a shadow, a gradient or a mix, and most often arrives
|
|
553
|
+
// through a `var()` from a theme on `:root`
|
|
554
|
+
if (LIGHT_DARK.test(value)) {
|
|
555
|
+
const picked = lightDark(value, style.colorScheme);
|
|
556
|
+
if (picked === null)
|
|
557
|
+
return;
|
|
558
|
+
value = picked;
|
|
559
|
+
}
|
|
544
560
|
const color = COLOR_PROPS[name];
|
|
545
561
|
if (color) {
|
|
546
562
|
const parsed = parseColor(value);
|
|
@@ -556,6 +572,12 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
556
572
|
return;
|
|
557
573
|
}
|
|
558
574
|
switch (name) {
|
|
575
|
+
case 'color-scheme': {
|
|
576
|
+
const scheme = usedColorScheme(value, ctx.initial?.colorScheme);
|
|
577
|
+
if (scheme)
|
|
578
|
+
style.colorScheme = scheme;
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
559
581
|
// --- box ----------------------------------------------------------------
|
|
560
582
|
case 'display': {
|
|
561
583
|
const v = value.toLowerCase();
|
|
@@ -775,6 +797,13 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
775
797
|
style.boxSizing = v;
|
|
776
798
|
return;
|
|
777
799
|
}
|
|
800
|
+
case 'box-decoration-break':
|
|
801
|
+
case '-webkit-box-decoration-break': {
|
|
802
|
+
const v = value.trim().toLowerCase();
|
|
803
|
+
if (v === 'slice' || v === 'clone')
|
|
804
|
+
style.boxDecorationBreak = v;
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
778
807
|
case 'aspect-ratio': {
|
|
779
808
|
const parsed = parseAspectRatio(value);
|
|
780
809
|
if (parsed !== undefined)
|
|
@@ -1253,15 +1282,29 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
1253
1282
|
}
|
|
1254
1283
|
case 'background-clip':
|
|
1255
1284
|
case '-webkit-background-clip': {
|
|
1256
|
-
// `text` the first layer's alone, which paints through the text
|
|
1285
|
+
// `text` the first layer's alone, which paints through the text —
|
|
1286
|
+
// and with `border-area` through its border as well, in either order
|
|
1287
|
+
// (CSS Backgrounds 4, 2.1)
|
|
1257
1288
|
const clips = layerValues(value, (part) => {
|
|
1258
1289
|
const v = part.toLowerCase();
|
|
1259
|
-
|
|
1290
|
+
if (v === 'text' || isBackgroundClip(v))
|
|
1291
|
+
return v;
|
|
1292
|
+
const [a, b, more] = splitValue(v);
|
|
1293
|
+
return !more &&
|
|
1294
|
+
((a === 'border-area' && b === 'text') ||
|
|
1295
|
+
(a === 'text' && b === 'border-area'))
|
|
1296
|
+
? 'border-area text'
|
|
1297
|
+
: null;
|
|
1260
1298
|
});
|
|
1261
1299
|
if (!clips)
|
|
1262
1300
|
return;
|
|
1263
|
-
style.backgroundClipText =
|
|
1264
|
-
|
|
1301
|
+
style.backgroundClipText =
|
|
1302
|
+
clips[0] === 'text' || clips[0] === 'border-area text';
|
|
1303
|
+
const boxes = clips.map((c) => c === 'text'
|
|
1304
|
+
? 'border-box'
|
|
1305
|
+
: c === 'border-area text'
|
|
1306
|
+
? 'border-area'
|
|
1307
|
+
: c);
|
|
1265
1308
|
style.backgroundClip = boxes[0];
|
|
1266
1309
|
style.backgroundClips = boxes.length > 1 ? boxes : null;
|
|
1267
1310
|
return;
|
|
@@ -1352,6 +1395,68 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
1352
1395
|
style.backgroundPositions = pairs.length > 1 ? pairs : null;
|
|
1353
1396
|
return;
|
|
1354
1397
|
}
|
|
1398
|
+
// --- masking --------------------------------------------------------------
|
|
1399
|
+
// Each `-webkit-` name is the same property's (Compatibility, 5): every
|
|
1400
|
+
// engine takes both, and a page writes both — Wikipedia's icons do.
|
|
1401
|
+
case 'mask':
|
|
1402
|
+
case '-webkit-mask': {
|
|
1403
|
+
const mask = readMask(value, ctx);
|
|
1404
|
+
if (mask)
|
|
1405
|
+
style.mask = mask;
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
case 'mask-image':
|
|
1409
|
+
case '-webkit-mask-image': {
|
|
1410
|
+
// `none` a layer as much as an image is; a bad url drops it all
|
|
1411
|
+
const images = [];
|
|
1412
|
+
for (const part of splitCommas(value)) {
|
|
1413
|
+
const image = maskImageOf(part, ctx);
|
|
1414
|
+
if (image === undefined)
|
|
1415
|
+
return;
|
|
1416
|
+
images.push(image);
|
|
1417
|
+
}
|
|
1418
|
+
if (images.length)
|
|
1419
|
+
style.mask = { ...style.mask, images };
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
case 'mask-repeat':
|
|
1423
|
+
case '-webkit-mask-repeat': {
|
|
1424
|
+
const repeats = layerValues(value, (part) => {
|
|
1425
|
+
const words = splitValue(part.toLowerCase());
|
|
1426
|
+
return words.length <= 2 ? readRepeat(words) : null;
|
|
1427
|
+
});
|
|
1428
|
+
if (repeats)
|
|
1429
|
+
style.mask = { ...style.mask, repeats };
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
case 'mask-size':
|
|
1433
|
+
case '-webkit-mask-size': {
|
|
1434
|
+
const sizes = layerValues(value, (part) => backgroundSizeOf(splitValue(part), ctx));
|
|
1435
|
+
if (sizes)
|
|
1436
|
+
style.mask = { ...style.mask, sizes };
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
case 'mask-position':
|
|
1440
|
+
case '-webkit-mask-position': {
|
|
1441
|
+
const positions = layerValues(value, (part) => positionPair(splitValue(part), ctx));
|
|
1442
|
+
if (positions)
|
|
1443
|
+
style.mask = { ...style.mask, positions };
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
case 'mask-origin':
|
|
1447
|
+
case '-webkit-mask-origin': {
|
|
1448
|
+
const origins = layerValues(value, (part) => maskBox(part));
|
|
1449
|
+
if (origins)
|
|
1450
|
+
style.mask = { ...style.mask, origins };
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
case 'mask-clip':
|
|
1454
|
+
case '-webkit-mask-clip': {
|
|
1455
|
+
const clips = layerValues(value, (part) => part.toLowerCase() === 'no-clip' ? 'border-box' : maskBox(part));
|
|
1456
|
+
if (clips)
|
|
1457
|
+
style.mask = { ...style.mask, clips };
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1355
1460
|
// --- generated content --------------------------------------------------
|
|
1356
1461
|
case 'content': {
|
|
1357
1462
|
const parsed = parseContent(value);
|
|
@@ -1469,7 +1574,13 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
1469
1574
|
style.lineHeightIsLength = true;
|
|
1470
1575
|
}
|
|
1471
1576
|
else if (len && typeof len === 'object') {
|
|
1472
|
-
|
|
1577
|
+
// a percentage of the element's own font size, the one it is
|
|
1578
|
+
// computed with (CSS 2.1 10.8.1), which `em` already is: not the
|
|
1579
|
+
// size in `style` as this declaration comes up, which a `font`
|
|
1580
|
+
// earlier in the same rule has just set to its own — `p { font:
|
|
1581
|
+
// 12px …; line-height: 100% }` under a `.lead { font-size: 16px }`
|
|
1582
|
+
// set sixteen-pixel text on twelve-pixel lines
|
|
1583
|
+
const px = resolve(len, ctx.em);
|
|
1473
1584
|
if (px < 0)
|
|
1474
1585
|
return;
|
|
1475
1586
|
style.lineHeight = px;
|
|
@@ -1950,7 +2061,11 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
1950
2061
|
return;
|
|
1951
2062
|
}
|
|
1952
2063
|
case 'align-content': {
|
|
1953
|
-
|
|
2064
|
+
// `normal` is `stretch` in a flex and a grid container, the only
|
|
2065
|
+
// boxes it moves anything in (CSS Box Alignment 3, 5.1)
|
|
2066
|
+
const v = value.trim().toLowerCase() === 'normal'
|
|
2067
|
+
? 'stretch'
|
|
2068
|
+
: alignKeyword(value);
|
|
1954
2069
|
if (v)
|
|
1955
2070
|
style.alignContent = v;
|
|
1956
2071
|
return;
|
|
@@ -2206,6 +2321,32 @@ export function applyDeclaration(style, parent, prop, rawValue, ctx) {
|
|
|
2206
2321
|
}
|
|
2207
2322
|
return;
|
|
2208
2323
|
}
|
|
2324
|
+
case 'place-content': {
|
|
2325
|
+
// `<'align-content'> <'justify-content'>?` (CSS Box Alignment 3,
|
|
2326
|
+
// 5.3), either half one keyword or two — `first baseline`, `safe
|
|
2327
|
+
// center` — and the second the first again where it is left out,
|
|
2328
|
+
// but for a baseline, which is no `justify-content`: `start`
|
|
2329
|
+
const words = value.trim().toLowerCase().split(/\s+/);
|
|
2330
|
+
const span = (at) => /^(?:safe|unsafe|first|last)$/.test(words[at] ?? '') ? 2 : 1;
|
|
2331
|
+
const cut = span(0);
|
|
2332
|
+
const align = words.slice(0, cut).join(' ');
|
|
2333
|
+
const rest = words.slice(cut);
|
|
2334
|
+
if (rest.length && rest.length !== span(cut))
|
|
2335
|
+
return;
|
|
2336
|
+
const justify = rest.length
|
|
2337
|
+
? rest.join(' ')
|
|
2338
|
+
: /baseline$/.test(align)
|
|
2339
|
+
? 'start'
|
|
2340
|
+
: align;
|
|
2341
|
+
// a shorthand is one declaration: either half unread drops both
|
|
2342
|
+
if (align !== 'normal' && !alignKeyword(align))
|
|
2343
|
+
return;
|
|
2344
|
+
if (!justifyKeyword(justify))
|
|
2345
|
+
return;
|
|
2346
|
+
applyDeclaration(style, parent, 'align-content', align, ctx);
|
|
2347
|
+
applyDeclaration(style, parent, 'justify-content', justify, ctx);
|
|
2348
|
+
return;
|
|
2349
|
+
}
|
|
2209
2350
|
case 'place-items':
|
|
2210
2351
|
case 'place-self': {
|
|
2211
2352
|
const parts = splitValue(value);
|
|
@@ -2401,6 +2542,15 @@ export function settleOverflow(style) {
|
|
|
2401
2542
|
function isVisualBox(v) {
|
|
2402
2543
|
return v === 'border-box' || v === 'padding-box' || v === 'content-box';
|
|
2403
2544
|
}
|
|
2545
|
+
function isBackgroundClip(v) {
|
|
2546
|
+
return v === 'border-area' || isVisualBox(v);
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* Whether a box is a scroll container: its `overflow` is neither `visible`
|
|
2550
|
+
* nor `clip`. `clip` cuts what overflows as `hidden` does, but makes no
|
|
2551
|
+
* formatting context and keeps a flex or grid item's automatic minimum
|
|
2552
|
+
* (CSS Overflow 3, 3.1) — so only this asks it apart from `hidden`.
|
|
2553
|
+
*/
|
|
2404
2554
|
export function scrolls(style) {
|
|
2405
2555
|
const x = style.overflowX;
|
|
2406
2556
|
const y = style.overflowY;
|
|
@@ -2598,6 +2748,154 @@ export const NO_BORDER_IMAGE = {
|
|
|
2598
2748
|
outset: [0, 0, 0, 0],
|
|
2599
2749
|
repeat: ['stretch', 'stretch'],
|
|
2600
2750
|
};
|
|
2751
|
+
/** Whether a style masks its element: a layer of its mask has an image. */
|
|
2752
|
+
export function masked(style) {
|
|
2753
|
+
const mask = style.mask;
|
|
2754
|
+
if (mask === NO_MASK)
|
|
2755
|
+
return false;
|
|
2756
|
+
for (const image of mask.images)
|
|
2757
|
+
if (image !== null)
|
|
2758
|
+
return true;
|
|
2759
|
+
return false;
|
|
2760
|
+
}
|
|
2761
|
+
/**
|
|
2762
|
+
* One layer's `mask-image`: a url, a gradient — or none, for an image
|
|
2763
|
+
* function this does not draw, or a `url(#id)`, which names an SVG
|
|
2764
|
+
* `<mask>` element in the document rather than an image to fetch (7.2):
|
|
2765
|
+
* drawn with no mask rather than as the transparent layer a mask that
|
|
2766
|
+
* cannot be had is, since this draws no `<mask>`. Undefined where it is no
|
|
2767
|
+
* image at all.
|
|
2768
|
+
*/
|
|
2769
|
+
function maskImageOf(text, ctx) {
|
|
2770
|
+
const image = backgroundImageOf(text, ctx);
|
|
2771
|
+
return typeof image === 'string' && image[0] === '#' ? null : image;
|
|
2772
|
+
}
|
|
2773
|
+
/** A `<geometry-box>` as an HTML element has it (CSS Masking 1, 7.5): the
|
|
2774
|
+
* SVG boxes are its content box and its border box. */
|
|
2775
|
+
function maskBox(text) {
|
|
2776
|
+
const v = text.trim().toLowerCase();
|
|
2777
|
+
if (isVisualBox(v))
|
|
2778
|
+
return v;
|
|
2779
|
+
if (v === 'fill-box')
|
|
2780
|
+
return 'content-box';
|
|
2781
|
+
if (v === 'stroke-box' || v === 'view-box')
|
|
2782
|
+
return 'border-box';
|
|
2783
|
+
return null;
|
|
2784
|
+
}
|
|
2785
|
+
/**
|
|
2786
|
+
* The `mask` shorthand (CSS Masking 1, 7.10): a layer a comma group, each
|
|
2787
|
+
* an image, a position with a size after a `/`, a repeat, one box for the
|
|
2788
|
+
* origin and the clip or two, `no-clip`, a compositing operator and a
|
|
2789
|
+
* mode, each at most once, in any order. The operator and the mode are
|
|
2790
|
+
* read and not honoured: layers are added, and an image masks by its
|
|
2791
|
+
* alpha, which is what `match-source` makes of one. Null where a layer is
|
|
2792
|
+
* not one, which drops the declaration.
|
|
2793
|
+
*/
|
|
2794
|
+
function readMask(value, ctx) {
|
|
2795
|
+
const out = {
|
|
2796
|
+
images: [],
|
|
2797
|
+
repeats: [],
|
|
2798
|
+
sizes: [],
|
|
2799
|
+
positions: [],
|
|
2800
|
+
origins: [],
|
|
2801
|
+
clips: [],
|
|
2802
|
+
};
|
|
2803
|
+
for (const text of splitCommas(value)) {
|
|
2804
|
+
const parts = splitValue(text).flatMap(splitSlash);
|
|
2805
|
+
let image = null;
|
|
2806
|
+
let repeat = NO_MASK.repeats[0];
|
|
2807
|
+
let size = 'auto';
|
|
2808
|
+
let position = [0, 0];
|
|
2809
|
+
const boxes = [];
|
|
2810
|
+
let seen = 0;
|
|
2811
|
+
const once = (bit) => {
|
|
2812
|
+
if (seen & bit)
|
|
2813
|
+
return false;
|
|
2814
|
+
seen |= bit;
|
|
2815
|
+
return true;
|
|
2816
|
+
};
|
|
2817
|
+
for (let i = 0; i < parts.length;) {
|
|
2818
|
+
const part = parts[i];
|
|
2819
|
+
const v = part.toLowerCase();
|
|
2820
|
+
if (v === 'none' || v.startsWith('url(') || IMAGE_FUNCTION.test(v)) {
|
|
2821
|
+
if (!once(1))
|
|
2822
|
+
return null;
|
|
2823
|
+
const read = maskImageOf(part, ctx);
|
|
2824
|
+
if (read === undefined)
|
|
2825
|
+
return null;
|
|
2826
|
+
image = read;
|
|
2827
|
+
i += 1;
|
|
2828
|
+
}
|
|
2829
|
+
else if (v === 'repeat-x' || v === 'repeat-y' || REPEATS.has(v)) {
|
|
2830
|
+
if (!once(2))
|
|
2831
|
+
return null;
|
|
2832
|
+
const pair = REPEATS.has(v) && REPEATS.has(parts[i + 1]?.toLowerCase());
|
|
2833
|
+
const read = readRepeat(pair ? [v, parts[i + 1].toLowerCase()] : [v]);
|
|
2834
|
+
if (!read)
|
|
2835
|
+
return null;
|
|
2836
|
+
repeat = read;
|
|
2837
|
+
i += pair ? 2 : 1;
|
|
2838
|
+
}
|
|
2839
|
+
else if (maskBox(v) || v === 'no-clip') {
|
|
2840
|
+
if (boxes.length === 2 || (v === 'no-clip' && !once(4)))
|
|
2841
|
+
return null;
|
|
2842
|
+
boxes.push(maskBox(v) ?? 'border-box');
|
|
2843
|
+
i += 1;
|
|
2844
|
+
}
|
|
2845
|
+
else if (/^(?:add|subtract|intersect|exclude)$/.test(v)) {
|
|
2846
|
+
if (!once(8))
|
|
2847
|
+
return null;
|
|
2848
|
+
i += 1;
|
|
2849
|
+
}
|
|
2850
|
+
else if (/^(?:alpha|luminance|match-source)$/.test(v)) {
|
|
2851
|
+
if (!once(16))
|
|
2852
|
+
return null;
|
|
2853
|
+
i += 1;
|
|
2854
|
+
}
|
|
2855
|
+
else if (isPositionPart(v, ctx)) {
|
|
2856
|
+
if (!once(32))
|
|
2857
|
+
return null;
|
|
2858
|
+
let end = i;
|
|
2859
|
+
while (end < parts.length &&
|
|
2860
|
+
isPositionPart(parts[end].toLowerCase(), ctx)) {
|
|
2861
|
+
end += 1;
|
|
2862
|
+
}
|
|
2863
|
+
const read = positionPair(parts.slice(i, end), ctx);
|
|
2864
|
+
if (!read)
|
|
2865
|
+
return null;
|
|
2866
|
+
position = read;
|
|
2867
|
+
i = end;
|
|
2868
|
+
if (parts[i] !== '/')
|
|
2869
|
+
continue;
|
|
2870
|
+
const first = parts[i + 1]?.toLowerCase();
|
|
2871
|
+
if (first === 'cover' || first === 'contain') {
|
|
2872
|
+
size = first;
|
|
2873
|
+
i += 2;
|
|
2874
|
+
}
|
|
2875
|
+
else if (first !== undefined && isSizePart(first, ctx)) {
|
|
2876
|
+
const two = i + 2 < parts.length && isSizePart(parts[i + 2].toLowerCase(), ctx);
|
|
2877
|
+
size =
|
|
2878
|
+
backgroundSizeOf(parts.slice(i + 1, i + (two ? 3 : 2)), ctx) ??
|
|
2879
|
+
'auto';
|
|
2880
|
+
i += two ? 3 : 2;
|
|
2881
|
+
}
|
|
2882
|
+
else {
|
|
2883
|
+
return null;
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
else {
|
|
2887
|
+
return null;
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
out.images.push(image);
|
|
2891
|
+
out.repeats.push(repeat);
|
|
2892
|
+
out.sizes.push(size);
|
|
2893
|
+
out.positions.push(position);
|
|
2894
|
+
out.origins.push(boxes[0] ?? 'border-box');
|
|
2895
|
+
out.clips.push(boxes[1] ?? boxes[0] ?? 'border-box');
|
|
2896
|
+
}
|
|
2897
|
+
return out.images.length ? out : null;
|
|
2898
|
+
}
|
|
2601
2899
|
/** One to four values, one a side as `margin` takes them; null where one
|
|
2602
2900
|
* is not a value. */
|
|
2603
2901
|
function sidesOf(parts, read) {
|
|
@@ -2784,6 +3082,14 @@ function repeatPair(x, y) {
|
|
|
2784
3082
|
return pair;
|
|
2785
3083
|
}
|
|
2786
3084
|
const REPEAT = repeatPair('repeat', 'repeat');
|
|
3085
|
+
export const NO_MASK = {
|
|
3086
|
+
images: [null],
|
|
3087
|
+
repeats: [REPEAT],
|
|
3088
|
+
sizes: ['auto'],
|
|
3089
|
+
positions: [[0, 0]],
|
|
3090
|
+
origins: ['border-box'],
|
|
3091
|
+
clips: ['border-box'],
|
|
3092
|
+
};
|
|
2787
3093
|
function applyBorderShorthand(style, name, value, ctx) {
|
|
2788
3094
|
const sides = name === 'border'
|
|
2789
3095
|
? ['Top', 'Right', 'Bottom', 'Left']
|
|
@@ -2998,11 +3304,19 @@ function readBackgroundLayer(text, ctx, last) {
|
|
|
2998
3304
|
i += 1;
|
|
2999
3305
|
}
|
|
3000
3306
|
else if (isVisualBox(v)) {
|
|
3001
|
-
// one box is both the origin and the clip, and a second the clip
|
|
3002
|
-
|
|
3307
|
+
// one box is both the origin and the clip, and a second the clip —
|
|
3308
|
+
// which `border-area` is instead of, and the one box the origin
|
|
3309
|
+
if ((boxes += 1) > (seen & 32 ? 1 : 2))
|
|
3003
3310
|
return null;
|
|
3004
3311
|
if (boxes === 1)
|
|
3005
3312
|
layer.origin = v;
|
|
3313
|
+
if (!(seen & 32))
|
|
3314
|
+
layer.clip = v;
|
|
3315
|
+
i += 1;
|
|
3316
|
+
}
|
|
3317
|
+
else if (v === 'border-area') {
|
|
3318
|
+
if (boxes > 1 || !once(32))
|
|
3319
|
+
return null;
|
|
3006
3320
|
layer.clip = v;
|
|
3007
3321
|
i += 1;
|
|
3008
3322
|
}
|
|
@@ -3447,12 +3761,11 @@ function applyFontShorthand(style, parent, value, ctx) {
|
|
|
3447
3761
|
style.lineHeight = 'normal';
|
|
3448
3762
|
style.lineHeightIsLength = false;
|
|
3449
3763
|
applyDeclaration(style, parent, 'font-size', sizeText, ctx);
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
}
|
|
3764
|
+
// against the element's own size, which `ctx.em` is once the cascade has
|
|
3765
|
+
// settled it: a later rule's `font-size` outranks this one's, and
|
|
3766
|
+
// `font: 12px/150%` under a `font-size: 16px` is on 24px lines
|
|
3767
|
+
if (lineText)
|
|
3768
|
+
applyDeclaration(style, parent, 'line-height', lineText, ctx);
|
|
3456
3769
|
applyDeclaration(style, parent, 'font-family', family, ctx);
|
|
3457
3770
|
}
|
|
3458
3771
|
/** Whether a line height is a number or a length below nought. */
|
|
@@ -4141,6 +4454,7 @@ function camel(name) {
|
|
|
4141
4454
|
}
|
|
4142
4455
|
const INHERITED_NAMES = new Set([
|
|
4143
4456
|
'color',
|
|
4457
|
+
'color-scheme',
|
|
4144
4458
|
'-webkit-text-fill-color',
|
|
4145
4459
|
'font',
|
|
4146
4460
|
'font-family',
|
|
@@ -4185,6 +4499,11 @@ export function isInherited(name) {
|
|
|
4185
4499
|
/** A property back to its initial value: what a declaration whose `var()`
|
|
4186
4500
|
* has no value comes to, where the property is not inherited. */
|
|
4187
4501
|
export function initialOne(style, initial, name) {
|
|
4502
|
+
const list = MASK_LISTS[name];
|
|
4503
|
+
if (list) {
|
|
4504
|
+
style.mask = { ...style.mask, [list]: initial.mask[list] };
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4188
4507
|
const keys = INHERIT_TARGETS[name];
|
|
4189
4508
|
if (!keys)
|
|
4190
4509
|
return;
|
|
@@ -4193,6 +4512,11 @@ export function initialOne(style, initial, name) {
|
|
|
4193
4512
|
}
|
|
4194
4513
|
}
|
|
4195
4514
|
function inheritOne(style, parent, name) {
|
|
4515
|
+
const list = MASK_LISTS[name];
|
|
4516
|
+
if (list) {
|
|
4517
|
+
style.mask = { ...style.mask, [list]: parent.mask[list] };
|
|
4518
|
+
return;
|
|
4519
|
+
}
|
|
4196
4520
|
const keys = INHERIT_TARGETS[name];
|
|
4197
4521
|
if (!keys)
|
|
4198
4522
|
return;
|
|
@@ -4205,8 +4529,29 @@ function inheritOne(style, parent, name) {
|
|
|
4205
4529
|
}
|
|
4206
4530
|
const SIDES = ['Top', 'Right', 'Bottom', 'Left'];
|
|
4207
4531
|
const sides = (make) => SIDES.map(make);
|
|
4532
|
+
/**
|
|
4533
|
+
* The list of the mask's layers each longhand is, which `initial`,
|
|
4534
|
+
* `inherit` and a `var()` that fails reset alone: one field holds them all,
|
|
4535
|
+
* and reset whole, a `mask-size: calc(var(--x) - 4px)` put back the
|
|
4536
|
+
* `mask-repeat: no-repeat` before it, and Wikipedia's chevron repeated.
|
|
4537
|
+
*/
|
|
4538
|
+
const MASK_LISTS = {
|
|
4539
|
+
'mask-image': 'images',
|
|
4540
|
+
'-webkit-mask-image': 'images',
|
|
4541
|
+
'mask-repeat': 'repeats',
|
|
4542
|
+
'-webkit-mask-repeat': 'repeats',
|
|
4543
|
+
'mask-size': 'sizes',
|
|
4544
|
+
'-webkit-mask-size': 'sizes',
|
|
4545
|
+
'mask-position': 'positions',
|
|
4546
|
+
'-webkit-mask-position': 'positions',
|
|
4547
|
+
'mask-origin': 'origins',
|
|
4548
|
+
'-webkit-mask-origin': 'origins',
|
|
4549
|
+
'mask-clip': 'clips',
|
|
4550
|
+
'-webkit-mask-clip': 'clips',
|
|
4551
|
+
};
|
|
4208
4552
|
const INHERIT_TARGETS = {
|
|
4209
4553
|
color: ['color'],
|
|
4554
|
+
'color-scheme': ['colorScheme'],
|
|
4210
4555
|
'-webkit-text-fill-color': ['textFillColor'],
|
|
4211
4556
|
'background-clip': [
|
|
4212
4557
|
'backgroundClipText',
|
|
@@ -4220,6 +4565,8 @@ const INHERIT_TARGETS = {
|
|
|
4220
4565
|
],
|
|
4221
4566
|
'background-origin': ['backgroundOrigin', 'backgroundOrigins'],
|
|
4222
4567
|
'border-image': ['borderImage'],
|
|
4568
|
+
mask: ['mask'],
|
|
4569
|
+
'-webkit-mask': ['mask'],
|
|
4223
4570
|
'border-image-source': ['borderImage'],
|
|
4224
4571
|
'border-image-slice': ['borderImage'],
|
|
4225
4572
|
'border-image-width': ['borderImage'],
|
|
@@ -4300,6 +4647,8 @@ const INHERIT_TARGETS = {
|
|
|
4300
4647
|
'min-height': ['minHeight', 'minHeightKeyword'],
|
|
4301
4648
|
'max-height': ['maxHeight', 'maxHeightKeyword'],
|
|
4302
4649
|
'box-sizing': ['boxSizing'],
|
|
4650
|
+
'box-decoration-break': ['boxDecorationBreak'],
|
|
4651
|
+
'-webkit-box-decoration-break': ['boxDecorationBreak'],
|
|
4303
4652
|
margin: sides((s) => `margin${s}`),
|
|
4304
4653
|
'margin-top': ['marginTop'],
|
|
4305
4654
|
'margin-right': ['marginRight'],
|