@react-x11/components 0.13.0 → 0.14.1
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/html/controls.d.ts +29 -2
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +70 -2
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +42 -1
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +336 -16
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +18 -0
- package/dist/html/css/color.d.ts.map +1 -1
- package/dist/html/css/color.js +27 -0
- package/dist/html/css/color.js.map +1 -1
- package/dist/html/css/parse.d.ts +18 -4
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +66 -28
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/shapes.d.ts +44 -0
- package/dist/html/css/shapes.d.ts.map +1 -0
- package/dist/html/css/shapes.js +194 -0
- package/dist/html/css/shapes.js.map +1 -0
- package/dist/html/css/style.d.ts +128 -15
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +547 -144
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/transform.d.ts +85 -0
- package/dist/html/css/transform.d.ts.map +1 -0
- package/dist/html/css/transform.js +425 -0
- package/dist/html/css/transform.js.map +1 -0
- package/dist/html/css/ua.d.ts.map +1 -1
- package/dist/html/css/ua.js +14 -2
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +4 -0
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/fonts.d.ts +55 -5
- package/dist/html/fonts.d.ts.map +1 -1
- package/dist/html/fonts.js +284 -23
- package/dist/html/fonts.js.map +1 -1
- package/dist/html/layout/axes.d.ts +14 -0
- package/dist/html/layout/axes.d.ts.map +1 -0
- package/dist/html/layout/axes.js +28 -0
- package/dist/html/layout/axes.js.map +1 -0
- package/dist/html/layout/block.d.ts +104 -12
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +410 -39
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +72 -1
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +40 -2
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/cache.d.ts +1 -1
- package/dist/html/layout/cache.d.ts.map +1 -1
- package/dist/html/layout/cache.js +6 -0
- package/dist/html/layout/cache.js.map +1 -1
- package/dist/html/layout/css-grid.d.ts.map +1 -1
- package/dist/html/layout/css-grid.js +144 -24
- package/dist/html/layout/css-grid.js.map +1 -1
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +585 -85
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/inline.d.ts +3 -0
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +144 -54
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/multicol.d.ts +42 -0
- package/dist/html/layout/multicol.d.ts.map +1 -0
- package/dist/html/layout/multicol.js +897 -0
- package/dist/html/layout/multicol.js.map +1 -0
- package/dist/html/layout/shaping.d.ts +7 -0
- package/dist/html/layout/shaping.d.ts.map +1 -1
- package/dist/html/layout/shaping.js +25 -20
- package/dist/html/layout/shaping.js.map +1 -1
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +97 -31
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/node.d.ts +4 -0
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +319 -47
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +83 -5
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +1474 -217
- package/dist/html/paint.js.map +1 -1
- package/dist/html/svg.d.ts +39 -9
- package/dist/html/svg.d.ts.map +1 -1
- package/dist/html/svg.js +482 -37
- package/dist/html/svg.js.map +1 -1
- package/dist/html/widgets.js +87 -7
- package/dist/html/widgets.js.map +1 -1
- package/dist/html/woff2.d.ts +14 -0
- package/dist/html/woff2.d.ts.map +1 -0
- package/dist/html/woff2.js +608 -0
- package/dist/html/woff2.js.map +1 -0
- package/dist/maps/controller.d.ts +17 -1
- package/dist/maps/controller.d.ts.map +1 -1
- package/dist/maps/controller.js +27 -7
- package/dist/maps/controller.js.map +1 -1
- package/dist/richtext/node.d.ts +8 -1
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +5 -1
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +25 -6
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +240 -24
- package/dist/richtext/runs.js.map +1 -1
- package/package.json +1 -1
- package/src/html/controls.ts +85 -2
- package/src/html/css/cascade.ts +366 -8
- package/src/html/css/color.ts +29 -0
- package/src/html/css/parse.ts +71 -31
- package/src/html/css/shapes.ts +239 -0
- package/src/html/css/style.ts +652 -147
- package/src/html/css/transform.ts +459 -0
- package/src/html/css/ua.ts +15 -2
- package/src/html/css/values.ts +4 -0
- package/src/html/fonts.ts +312 -29
- package/src/html/layout/axes.ts +62 -0
- package/src/html/layout/block.ts +466 -37
- package/src/html/layout/boxes.ts +95 -3
- package/src/html/layout/cache.ts +6 -0
- package/src/html/layout/css-grid.ts +169 -32
- package/src/html/layout/flex.ts +686 -79
- package/src/html/layout/inline.ts +149 -55
- package/src/html/layout/multicol.ts +977 -0
- package/src/html/layout/shaping.ts +27 -18
- package/src/html/layout/table.ts +105 -35
- package/src/html/node.ts +354 -48
- package/src/html/paint.ts +1804 -315
- package/src/html/svg.ts +573 -36
- package/src/html/widgets.ts +95 -9
- package/src/html/woff2.ts +612 -0
- package/src/maps/controller.ts +28 -7
- package/src/richtext/node.ts +13 -2
- package/src/richtext/runs.ts +313 -35
package/dist/html/css/cascade.js
CHANGED
|
@@ -19,14 +19,14 @@ import { compile } from 'css-select';
|
|
|
19
19
|
import * as DomUtils from 'domutils';
|
|
20
20
|
import { Element as DomElement, isTag } from 'domhandler';
|
|
21
21
|
import { attr, tagOf } from '../dom.js';
|
|
22
|
-
import { svgSizeHint } from '../svg.js';
|
|
23
22
|
import { asciiLower, escapeEnd, mediaMatches, readIdent, startsIdent, } from './parse.js';
|
|
24
|
-
import { applyDeclaration, blockify, settleContentVisibility, settleOverflow, settleClamp, copyStyle, decorate, inherit, initialOne, initialStyle, isInherited, } from './style.js';
|
|
23
|
+
import { applyDeclaration, blockify, settleButton, settleContentVisibility, settleOverflow, settleClamp, copyStyle, decorate, inherit, initialOne, initialStyle, isInherited, } from './style.js';
|
|
25
24
|
import { parseDeclarations } from './parse.js';
|
|
26
25
|
import { CounterStyles, counterStyleRule } from './counter-styles.js';
|
|
27
26
|
import { PALETTE_CHROME } from './ua.js';
|
|
28
27
|
import { viewportUnit } from './values.js';
|
|
29
28
|
import { customProperties, substituteIn } from './vars.js';
|
|
29
|
+
import { ROOT_BOX_PROPS, SHAPE_TAGS, isShapeProp, shapeValue, } from './shapes.js';
|
|
30
30
|
/** Where a declaration came from. Higher wins before specificity is asked. */
|
|
31
31
|
var Origin;
|
|
32
32
|
(function (Origin) {
|
|
@@ -104,6 +104,10 @@ class RuleIndex {
|
|
|
104
104
|
reaches(el) {
|
|
105
105
|
if (this.universal.length || this.byTag.has(tagOf(el)))
|
|
106
106
|
return true;
|
|
107
|
+
return this.names(el);
|
|
108
|
+
}
|
|
109
|
+
/** Whether a bucket here is for `el`'s id, or for a class of its. */
|
|
110
|
+
names(el) {
|
|
107
111
|
if (this.byId.size) {
|
|
108
112
|
const id = attr(el, 'id');
|
|
109
113
|
if (id && this.byId.has(id))
|
|
@@ -120,18 +124,19 @@ class RuleIndex {
|
|
|
120
124
|
}
|
|
121
125
|
return false;
|
|
122
126
|
}
|
|
123
|
-
add(rule) {
|
|
127
|
+
add(rule, key = rightmostKey(rule.selector)) {
|
|
124
128
|
this.size += 1;
|
|
125
129
|
const indexed = {
|
|
126
130
|
rule,
|
|
127
131
|
match: null,
|
|
128
132
|
compiled: false,
|
|
129
133
|
id: this._nextId++,
|
|
134
|
+
needs: null,
|
|
135
|
+
root: null,
|
|
130
136
|
};
|
|
131
137
|
if (rule.selector.includes(':hover') || rule.selector.includes(':active')) {
|
|
132
138
|
this.hoverSensitive = true;
|
|
133
139
|
}
|
|
134
|
-
const key = rightmostKey(rule.selector);
|
|
135
140
|
if (UNSHAREABLE.test(rule.selector)) {
|
|
136
141
|
if (key.kind === 'id')
|
|
137
142
|
this.ownStyleIds.add(key.name);
|
|
@@ -476,11 +481,11 @@ const POINTER_PSEUDO = /:(?:hover|active)(?![\w-])/i;
|
|
|
476
481
|
* `#box:has(a:hover) .m` answered what it did before the first move, for
|
|
477
482
|
* good.
|
|
478
483
|
*/
|
|
479
|
-
function compileSelector(selector, adapter) {
|
|
484
|
+
function compileSelector(selector, adapter, pseudos = PSEUDOS) {
|
|
480
485
|
return compile(noEmptyWords(selector), {
|
|
481
486
|
adapter,
|
|
482
487
|
xmlMode: false,
|
|
483
|
-
pseudos
|
|
488
|
+
pseudos,
|
|
484
489
|
cacheResults: !POINTER_PSEUDO.test(selector),
|
|
485
490
|
});
|
|
486
491
|
}
|
|
@@ -534,7 +539,10 @@ function rightmostKey(selector) {
|
|
|
534
539
|
start = i + 1;
|
|
535
540
|
}
|
|
536
541
|
}
|
|
537
|
-
|
|
542
|
+
return compoundKey(selector.slice(start));
|
|
543
|
+
}
|
|
544
|
+
/** A compound selector's most selective key (`rightmostKey`). */
|
|
545
|
+
function compoundKey(compound) {
|
|
538
546
|
let id = null;
|
|
539
547
|
let cls = null;
|
|
540
548
|
let tag = null;
|
|
@@ -577,6 +585,29 @@ function rightmostKey(selector) {
|
|
|
577
585
|
return { kind: 'tag', name: tag };
|
|
578
586
|
return { kind: 'any', name: '' };
|
|
579
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* The ids and classes a selector asks of its subject's ancestors: for each
|
|
590
|
+
* compound a descendant or a child combinator follows, its id, or else its
|
|
591
|
+
* first class, as `#name` or `.name`. Such a compound is an ancestor of
|
|
592
|
+
* the subject — one a sibling combinator follows is a sibling of one — so
|
|
593
|
+
* an element with no ancestor of some such name is not the rule's, which
|
|
594
|
+
* is known without matching it. A compound with neither asks nothing.
|
|
595
|
+
*/
|
|
596
|
+
function ancestorKeys(selector) {
|
|
597
|
+
const keys = [];
|
|
598
|
+
const compounds = compoundsOf(selector);
|
|
599
|
+
for (let i = 0; i < compounds.length - 1; i += 1) {
|
|
600
|
+
const { text, next } = compounds[i];
|
|
601
|
+
if (next !== ' ' && next !== '>')
|
|
602
|
+
continue;
|
|
603
|
+
const key = compoundKey(text);
|
|
604
|
+
if (key.kind === 'id')
|
|
605
|
+
keys.push(`#${key.name}`);
|
|
606
|
+
else if (key.kind === 'class')
|
|
607
|
+
keys.push(`.${key.name}`);
|
|
608
|
+
}
|
|
609
|
+
return keys;
|
|
610
|
+
}
|
|
580
611
|
function balancedEnd(text, from, open, close) {
|
|
581
612
|
let depth = 0;
|
|
582
613
|
for (let i = from; i < text.length; i += 1) {
|
|
@@ -618,6 +649,13 @@ export class Cascade {
|
|
|
618
649
|
marker: new RuleIndex(),
|
|
619
650
|
selection: new RuleIndex(),
|
|
620
651
|
};
|
|
652
|
+
/** The author's rules that could style a shape in a drawing: the ones
|
|
653
|
+
* that declare a property a shape has (`shapes.ts`) and whose subject
|
|
654
|
+
* is no element of HTML's alone. They are in `_index` too, for the
|
|
655
|
+
* elements that have boxes; these are asked of the ones in an inline
|
|
656
|
+
* `<svg>`, which have none (`shapeStyles`). */
|
|
657
|
+
_shapes = new RuleIndex();
|
|
658
|
+
_shapeNeeds = null;
|
|
621
659
|
_adapter;
|
|
622
660
|
/** The compounds of the selectors that test the pointer, each without
|
|
623
661
|
* its `:hover` or `:active` (`pointerCompounds`), and their matchers,
|
|
@@ -681,7 +719,15 @@ export class Cascade {
|
|
|
681
719
|
/** Whether any declaration has a length in `lh` or `rlh`: only then is
|
|
682
720
|
* the line height settled ahead of the declarations that read it. */
|
|
683
721
|
_lh = false;
|
|
684
|
-
|
|
722
|
+
/** The pseudo-classes css-select is handed, `:root` this cascade's. */
|
|
723
|
+
_pseudos;
|
|
724
|
+
constructor(sheets, look, viewportWidth, viewportHeight, scale = 1, xHeight = null, zeroWidth = null, normalLine = null, families = null,
|
|
725
|
+
/** The document's element where it is not an `<html>`: an SVG image's
|
|
726
|
+
* `<svg>`, which is `:root` there (Selectors 4, 14.1). */
|
|
727
|
+
documentElement = null) {
|
|
728
|
+
this._pseudos = documentElement
|
|
729
|
+
? { ...PSEUDOS, root: (el) => el === documentElement }
|
|
730
|
+
: PSEUDOS;
|
|
685
731
|
this._xHeightOf = xHeight;
|
|
686
732
|
this._zeroWidthOf = zeroWidth;
|
|
687
733
|
this._normalLineOf = normalLine;
|
|
@@ -712,8 +758,15 @@ export class Cascade {
|
|
|
712
758
|
const pseudo = splitPseudoElement(rule);
|
|
713
759
|
if (pseudo)
|
|
714
760
|
this._pseudo[pseudo.which].add(pseudo.rule);
|
|
715
|
-
else
|
|
716
|
-
|
|
761
|
+
else {
|
|
762
|
+
const key = rightmostKey(rule.selector);
|
|
763
|
+
this._index.add(rule, key);
|
|
764
|
+
if (rule.order >= 0 &&
|
|
765
|
+
(key.kind !== 'tag' || SHAPE_TAGS.has(key.name)) &&
|
|
766
|
+
declaresShape(rule.declarations)) {
|
|
767
|
+
this._shapes.add(rule, key);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
717
770
|
this._noteHover((pseudo?.rule ?? rule).selector);
|
|
718
771
|
}
|
|
719
772
|
for (const bp of sheet.breakpoints)
|
|
@@ -888,7 +941,7 @@ export class Cascade {
|
|
|
888
941
|
* it, as a rule it refuses drops out of the cascade. */
|
|
889
942
|
_compile(selector) {
|
|
890
943
|
try {
|
|
891
|
-
return compileSelector(selector, this._adapter);
|
|
944
|
+
return compileSelector(selector, this._adapter, this._pseudos);
|
|
892
945
|
}
|
|
893
946
|
catch {
|
|
894
947
|
return null;
|
|
@@ -1065,7 +1118,7 @@ export class Cascade {
|
|
|
1065
1118
|
let shared = this._sharedByMatch.get(key);
|
|
1066
1119
|
if (shared === undefined) {
|
|
1067
1120
|
shared = {
|
|
1068
|
-
style: this._computeStyle(el, parentStyle, inFlexContainer, candidates),
|
|
1121
|
+
style: this._computeStyle(el, parentStyle, inFlexContainer, candidates, true),
|
|
1069
1122
|
key: this._nextShareKey++,
|
|
1070
1123
|
};
|
|
1071
1124
|
this._sharedByMatch.set(key, shared);
|
|
@@ -1113,7 +1166,7 @@ export class Cascade {
|
|
|
1113
1166
|
* a style is computed only for the elements with none to share.
|
|
1114
1167
|
*/
|
|
1115
1168
|
styleFor(el, parentStyle, inFlexContainer) {
|
|
1116
|
-
return this._computeStyle(el, parentStyle, inFlexContainer, this._candidates(el));
|
|
1169
|
+
return this._computeStyle(el, parentStyle, inFlexContainer, this._candidates(el), true);
|
|
1117
1170
|
}
|
|
1118
1171
|
/**
|
|
1119
1172
|
* The style of an element's `::before` or `::after`, or null when it has
|
|
@@ -1305,7 +1358,10 @@ export class Cascade {
|
|
|
1305
1358
|
return line;
|
|
1306
1359
|
}
|
|
1307
1360
|
/** `styleFor`, from the rules and hints already gathered for `el`. */
|
|
1308
|
-
_computeStyle(el, parentStyle, inFlexContainer, candidates
|
|
1361
|
+
_computeStyle(el, parentStyle, inFlexContainer, candidates,
|
|
1362
|
+
/** Whether the style is the element's own, and not that of one of its
|
|
1363
|
+
* pseudo-elements. */
|
|
1364
|
+
own = false) {
|
|
1309
1365
|
const style = inherit(parentStyle, this.initial);
|
|
1310
1366
|
// custom properties first, in cascade order, so every `var()` in the
|
|
1311
1367
|
// declarations below finds the one that wins
|
|
@@ -1317,10 +1373,14 @@ export class Cascade {
|
|
|
1317
1373
|
// em-relative length in the same rule resolves against this element's.
|
|
1318
1374
|
const root = isRootElement(el);
|
|
1319
1375
|
const rootStyle = root ? this.initial : (this._root ?? this.initial);
|
|
1376
|
+
// whose declaration is being applied: the UA sheet's families are the
|
|
1377
|
+
// host's own faces, and its lists end where they end
|
|
1378
|
+
let authored = true;
|
|
1320
1379
|
const ctxParent = {
|
|
1321
1380
|
em: parentStyle.fontSize,
|
|
1322
1381
|
rem: rootStyle.fontSize,
|
|
1323
1382
|
initial: this.initial,
|
|
1383
|
+
fallbackFamily: () => (authored ? this.initial.fontFamily : null),
|
|
1324
1384
|
vw: this.viewportWidth,
|
|
1325
1385
|
vh: this.viewportHeight,
|
|
1326
1386
|
scale: this.scale,
|
|
@@ -1339,6 +1399,7 @@ export class Cascade {
|
|
|
1339
1399
|
let sized = false;
|
|
1340
1400
|
let keyword = false;
|
|
1341
1401
|
for (const c of candidates) {
|
|
1402
|
+
authored = c.origin !== Origin.UserAgent;
|
|
1342
1403
|
for (const d of pick(c)) {
|
|
1343
1404
|
if (d.prop === 'font-family' ||
|
|
1344
1405
|
d.prop === 'font-weight' ||
|
|
@@ -1401,6 +1462,7 @@ export class Cascade {
|
|
|
1401
1462
|
// them. A `font` sets the size as well, which the first pass settled.
|
|
1402
1463
|
if (this._lh) {
|
|
1403
1464
|
for (const c of candidates) {
|
|
1465
|
+
authored = c.origin !== Origin.UserAgent;
|
|
1404
1466
|
for (const d of pick(c)) {
|
|
1405
1467
|
if (d.prop === 'line-height' || d.prop === 'font') {
|
|
1406
1468
|
this._apply(style, parentStyle, d, ctx);
|
|
@@ -1416,6 +1478,7 @@ export class Cascade {
|
|
|
1416
1478
|
}
|
|
1417
1479
|
const settled = style.fontSize;
|
|
1418
1480
|
for (const c of candidates) {
|
|
1481
|
+
authored = c.origin !== Origin.UserAgent;
|
|
1419
1482
|
for (const d of pick(c)) {
|
|
1420
1483
|
if (d.prop === 'font-size' || d.custom)
|
|
1421
1484
|
continue;
|
|
@@ -1443,6 +1506,10 @@ export class Cascade {
|
|
|
1443
1506
|
settleOverflow(style);
|
|
1444
1507
|
settleContentVisibility(style);
|
|
1445
1508
|
blockify(style, inFlexContainer);
|
|
1509
|
+
// a button is laid out as one, whatever `display` it was given
|
|
1510
|
+
if (own && el.name.length === 6 && tagOf(el) === 'button') {
|
|
1511
|
+
settleButton(style);
|
|
1512
|
+
}
|
|
1446
1513
|
decorate(style);
|
|
1447
1514
|
// which faces of the document's own families this family, weight and
|
|
1448
1515
|
// slant ask for — known only now, with all three computed
|
|
@@ -1513,6 +1580,187 @@ export class Cascade {
|
|
|
1513
1580
|
// the root is still the initial containing block.
|
|
1514
1581
|
return { style: asRoot(this.styleFor(synthetic, parent, false)), html };
|
|
1515
1582
|
}
|
|
1583
|
+
/** Whether any rule could style a shape in a drawing: a document with
|
|
1584
|
+
* none asks nothing of its drawings (`shapeStyles`). */
|
|
1585
|
+
get stylesShapes() {
|
|
1586
|
+
return this._shapes.size > 0;
|
|
1587
|
+
}
|
|
1588
|
+
/** Whether a pointer move can change what a rule gives a shape in a
|
|
1589
|
+
* drawing. */
|
|
1590
|
+
get shapesFollowPointer() {
|
|
1591
|
+
return this._shapes.hoverSensitive;
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* What the rules give the elements of an inline drawing, `root` and what
|
|
1595
|
+
* is in it, or null where none reaches one: the narrow cascade of
|
|
1596
|
+
* `shapes.ts`. `style` is the root's computed style — its `color`, its
|
|
1597
|
+
* custom properties and its font size are what a value in the drawing is
|
|
1598
|
+
* read against, as though every element in it had inherited them, which
|
|
1599
|
+
* all but one a rule gives its own has.
|
|
1600
|
+
*
|
|
1601
|
+
* An element's rules and its `style` attribute are put in cascade order,
|
|
1602
|
+
* and each property is the last valid declaration's. The presentation
|
|
1603
|
+
* attributes are below them all (SVG 2, 6.2), and `SvgView` reads those
|
|
1604
|
+
* itself. The root's box has its paint, its opacity and whether it is
|
|
1605
|
+
* shown from its computed style, so those are left out for it.
|
|
1606
|
+
*
|
|
1607
|
+
* Asked as a drawing is first painted (`BoxTree.shapeStyler`), of the
|
|
1608
|
+
* rules in `_shapes` alone: a page of hundreds of icons pays for the ones
|
|
1609
|
+
* it shows, a look in the buckets for each of their elements where no
|
|
1610
|
+
* rule reaches them, and a document with no such rule nothing.
|
|
1611
|
+
*/
|
|
1612
|
+
shapeStyles(root, style) {
|
|
1613
|
+
const index = this._shapes;
|
|
1614
|
+
if (!index.size)
|
|
1615
|
+
return null;
|
|
1616
|
+
// The rules kept by a class or an id are asked of the elements with
|
|
1617
|
+
// that name. The rest — `.dark .logo path`, `.menu [aria-hidden]` — are
|
|
1618
|
+
// asked of every `<path>`, or of every element, and nearly all of them
|
|
1619
|
+
// are for some other part of the page: each says so by the class or the
|
|
1620
|
+
// id it asks of an ancestor, which is looked for once for the drawing,
|
|
1621
|
+
// around it and in it, where matching the rule would look for it from
|
|
1622
|
+
// each of its elements. On a page with none of them around a drawing,
|
|
1623
|
+
// nothing is matched at all.
|
|
1624
|
+
const needs = (this._shapeNeeds ??= this._needsOfShapes());
|
|
1625
|
+
const found = new Set();
|
|
1626
|
+
const asks = needs.classes.size > 0 || needs.ids.size > 0;
|
|
1627
|
+
const note = (el) => {
|
|
1628
|
+
if (needs.ids.size) {
|
|
1629
|
+
const id = attr(el, 'id');
|
|
1630
|
+
if (id && needs.ids.has(id))
|
|
1631
|
+
found.add(`#${id}`);
|
|
1632
|
+
}
|
|
1633
|
+
if (needs.classes.size) {
|
|
1634
|
+
const className = attr(el, 'class');
|
|
1635
|
+
if (className) {
|
|
1636
|
+
for (const name of className.split(/\s+/)) {
|
|
1637
|
+
if (needs.classes.has(name))
|
|
1638
|
+
found.add(`.${name}`);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
};
|
|
1643
|
+
if (asks) {
|
|
1644
|
+
let at = root.parent;
|
|
1645
|
+
while (at && at.type === 'tag') {
|
|
1646
|
+
note(at);
|
|
1647
|
+
at = at.parent;
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
const live = (indexed) => {
|
|
1651
|
+
const keys = indexed.needs;
|
|
1652
|
+
if (keys)
|
|
1653
|
+
for (const key of keys)
|
|
1654
|
+
if (!found.has(key))
|
|
1655
|
+
return false;
|
|
1656
|
+
return true;
|
|
1657
|
+
};
|
|
1658
|
+
// The root's box has its paint from its computed style, so most of the
|
|
1659
|
+
// rules that name a drawing by its class — an icon set's — have
|
|
1660
|
+
// nothing else to say of it.
|
|
1661
|
+
const liveForRoot = (indexed) => (indexed.root ??= declaresRootShape(indexed.rule.declarations)) &&
|
|
1662
|
+
live(indexed);
|
|
1663
|
+
let of = null;
|
|
1664
|
+
let key = '';
|
|
1665
|
+
let ctx = null;
|
|
1666
|
+
// in document order, the root first: an element's place in it is what
|
|
1667
|
+
// the key names it by, and its ancestors in the drawing are noted
|
|
1668
|
+
// before it is asked of
|
|
1669
|
+
const stack = [root];
|
|
1670
|
+
let place = -1;
|
|
1671
|
+
while (stack.length) {
|
|
1672
|
+
const el = stack.pop();
|
|
1673
|
+
place += 1;
|
|
1674
|
+
// what is in a `<foreignObject>` is not the drawing's to draw
|
|
1675
|
+
if (el.name !== 'foreignobject' && el.name !== 'foreignObject') {
|
|
1676
|
+
const children = el.children;
|
|
1677
|
+
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
1678
|
+
const child = children[i];
|
|
1679
|
+
if (child.type === 'tag')
|
|
1680
|
+
stack.push(child);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
if (asks)
|
|
1684
|
+
note(el);
|
|
1685
|
+
const tag = tagOf(el);
|
|
1686
|
+
const asked = found.size
|
|
1687
|
+
? index.universal.length > 0 || index.byTag.has(tag)
|
|
1688
|
+
: needs.universal || needs.tags.has(tag);
|
|
1689
|
+
if (!asked && !index.names(el))
|
|
1690
|
+
continue;
|
|
1691
|
+
const candidates = [];
|
|
1692
|
+
this._matchInto(index, el, candidates, undefined, el === root ? liveForRoot : live);
|
|
1693
|
+
if (!candidates.length)
|
|
1694
|
+
continue;
|
|
1695
|
+
const inline = attr(el, 'style');
|
|
1696
|
+
if (inline)
|
|
1697
|
+
pushInlineShapes(candidates, inline);
|
|
1698
|
+
candidates.sort(byCascade);
|
|
1699
|
+
ctx ??= {
|
|
1700
|
+
color: style.color,
|
|
1701
|
+
scheme: style.colorScheme,
|
|
1702
|
+
units: {
|
|
1703
|
+
em: style.fontSize,
|
|
1704
|
+
rem: (this._root ?? this.initial).fontSize,
|
|
1705
|
+
vw: this.viewportWidth,
|
|
1706
|
+
vh: this.viewportHeight,
|
|
1707
|
+
scale: this.scale,
|
|
1708
|
+
initial: this.initial,
|
|
1709
|
+
},
|
|
1710
|
+
};
|
|
1711
|
+
let own = null;
|
|
1712
|
+
for (const c of candidates) {
|
|
1713
|
+
for (const d of pick(c)) {
|
|
1714
|
+
if (!isShapeProp(d.prop))
|
|
1715
|
+
continue;
|
|
1716
|
+
if (el === root && ROOT_BOX_PROPS.has(d.prop))
|
|
1717
|
+
continue;
|
|
1718
|
+
// a `var()` with nothing to stand for it is invalid at
|
|
1719
|
+
// computed-value time, and the property as though `unset`
|
|
1720
|
+
const value = shapeValue(d.prop, d.vars ? (substituteIn(d.value, style.custom) ?? 'unset') : d.value, ctx);
|
|
1721
|
+
if (value !== null)
|
|
1722
|
+
(own ??= {})[d.prop] = value;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (!own)
|
|
1726
|
+
continue;
|
|
1727
|
+
(of ??= new Map()).set(el, own);
|
|
1728
|
+
key += `${place}{`;
|
|
1729
|
+
for (const prop in own)
|
|
1730
|
+
key += `${prop}:${own[prop]};`;
|
|
1731
|
+
key += '}';
|
|
1732
|
+
}
|
|
1733
|
+
return of ? { of, key } : null;
|
|
1734
|
+
}
|
|
1735
|
+
/** `ShapeNeeds`, and each such rule's own (`IndexedRule.needs`). */
|
|
1736
|
+
_needsOfShapes() {
|
|
1737
|
+
const index = this._shapes;
|
|
1738
|
+
const needs = {
|
|
1739
|
+
classes: new Set(),
|
|
1740
|
+
ids: new Set(),
|
|
1741
|
+
universal: false,
|
|
1742
|
+
tags: new Set(),
|
|
1743
|
+
};
|
|
1744
|
+
const read = (bucket) => {
|
|
1745
|
+
let free = false;
|
|
1746
|
+
for (const indexed of bucket) {
|
|
1747
|
+
const keys = ancestorKeys(indexed.rule.selector);
|
|
1748
|
+
indexed.needs = keys;
|
|
1749
|
+
if (!keys.length)
|
|
1750
|
+
free = true;
|
|
1751
|
+
for (const key of keys) {
|
|
1752
|
+
(key[0] === '#' ? needs.ids : needs.classes).add(key.slice(1));
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
return free;
|
|
1756
|
+
};
|
|
1757
|
+
needs.universal = read(index.universal);
|
|
1758
|
+
for (const [tag, bucket] of index.byTag) {
|
|
1759
|
+
if (read(bucket))
|
|
1760
|
+
needs.tags.add(tag);
|
|
1761
|
+
}
|
|
1762
|
+
return needs;
|
|
1763
|
+
}
|
|
1516
1764
|
/**
|
|
1517
1765
|
* Whether the pointer's move from `was` to where it is changed which
|
|
1518
1766
|
* rules match `el`, or its `::before`, `::after` or another of its
|
|
@@ -1550,7 +1798,9 @@ export class Cascade {
|
|
|
1550
1798
|
}
|
|
1551
1799
|
/** The rules of `index` that match `el`, pushed onto `out` as candidates,
|
|
1552
1800
|
* and their ids onto `matched` in the order they were tried. */
|
|
1553
|
-
_matchInto(index, el, out, matched
|
|
1801
|
+
_matchInto(index, el, out, matched,
|
|
1802
|
+
/** The rules to try, where some are known not to match without it. */
|
|
1803
|
+
live) {
|
|
1554
1804
|
// A media query's width is CSS pixels; the viewport is kept in device.
|
|
1555
1805
|
const width = this.viewportWidth / this.scale;
|
|
1556
1806
|
const height = this.viewportHeight / this.scale;
|
|
@@ -1558,6 +1808,8 @@ export class Cascade {
|
|
|
1558
1808
|
if (!bucket)
|
|
1559
1809
|
return;
|
|
1560
1810
|
for (const indexed of bucket) {
|
|
1811
|
+
if (live !== undefined && !live(indexed))
|
|
1812
|
+
continue;
|
|
1561
1813
|
const rule = indexed.rule;
|
|
1562
1814
|
if (!mediaMatches(rule.media, width, this.look.colorScheme, height, this.scale)) {
|
|
1563
1815
|
continue;
|
|
@@ -1565,7 +1817,7 @@ export class Cascade {
|
|
|
1565
1817
|
if (!indexed.compiled) {
|
|
1566
1818
|
indexed.compiled = true;
|
|
1567
1819
|
try {
|
|
1568
|
-
indexed.match = compileSelector(rule.selector, this._adapter);
|
|
1820
|
+
indexed.match = compileSelector(rule.selector, this._adapter, this._pseudos);
|
|
1569
1821
|
}
|
|
1570
1822
|
catch {
|
|
1571
1823
|
// A selector this matcher does not know (`::-moz-…`, a CSS4 form
|
|
@@ -1844,6 +2096,49 @@ function setsContent(c) {
|
|
|
1844
2096
|
}
|
|
1845
2097
|
/** Whether a rule's declarations set a custom property, by the array. */
|
|
1846
2098
|
const CUSTOM_IN = new WeakMap();
|
|
2099
|
+
/** Whether declarations set a property a shape in a drawing has. */
|
|
2100
|
+
function declaresShape(declarations) {
|
|
2101
|
+
for (const d of declarations)
|
|
2102
|
+
if (isShapeProp(d.prop))
|
|
2103
|
+
return true;
|
|
2104
|
+
return false;
|
|
2105
|
+
}
|
|
2106
|
+
/** Whether declarations set one a drawing's root does not have from its
|
|
2107
|
+
* box's style (`ROOT_BOX_PROPS`). */
|
|
2108
|
+
function declaresRootShape(declarations) {
|
|
2109
|
+
for (const d of declarations) {
|
|
2110
|
+
if (isShapeProp(d.prop) && !ROOT_BOX_PROPS.has(d.prop))
|
|
2111
|
+
return true;
|
|
2112
|
+
}
|
|
2113
|
+
return false;
|
|
2114
|
+
}
|
|
2115
|
+
/** A `style` attribute's declarations of a shape's properties, as
|
|
2116
|
+
* candidates: over every rule, and its `!important` ones over theirs. */
|
|
2117
|
+
function pushInlineShapes(out, inline) {
|
|
2118
|
+
const declarations = parseDeclarations(inline).filter((d) => isShapeProp(d.prop));
|
|
2119
|
+
const normal = declarations.filter((d) => !d.important);
|
|
2120
|
+
const important = declarations.filter((d) => d.important);
|
|
2121
|
+
if (normal.length) {
|
|
2122
|
+
out.push({
|
|
2123
|
+
origin: Origin.Inline,
|
|
2124
|
+
layer: null,
|
|
2125
|
+
specificity: 0,
|
|
2126
|
+
order: 0,
|
|
2127
|
+
declarations: normal,
|
|
2128
|
+
only: -1,
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
if (important.length) {
|
|
2132
|
+
out.push({
|
|
2133
|
+
origin: Origin.InlineImportant,
|
|
2134
|
+
layer: null,
|
|
2135
|
+
specificity: 0,
|
|
2136
|
+
order: 0,
|
|
2137
|
+
declarations: important,
|
|
2138
|
+
only: -1,
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
1847
2142
|
function pick(c) {
|
|
1848
2143
|
return c.only < 0 ? c.declarations : [c.declarations[c.only]];
|
|
1849
2144
|
}
|
|
@@ -2058,6 +2353,14 @@ function presentationHints(el) {
|
|
|
2058
2353
|
const h = height ? svgSizeHint(height) : null;
|
|
2059
2354
|
if (h)
|
|
2060
2355
|
push('height', h);
|
|
2356
|
+
// and its paint is its `fill` and `stroke` properties' (13.2), which a
|
|
2357
|
+
// rule of the document's then sets over the attribute
|
|
2358
|
+
const fill = attr(el, 'fill');
|
|
2359
|
+
if (fill)
|
|
2360
|
+
push('fill', fill);
|
|
2361
|
+
const stroke = attr(el, 'stroke');
|
|
2362
|
+
if (stroke)
|
|
2363
|
+
push('stroke', stroke);
|
|
2061
2364
|
}
|
|
2062
2365
|
if (tag === 'table') {
|
|
2063
2366
|
const border = attr(el, 'border');
|
|
@@ -2230,6 +2533,23 @@ function lengthAttr(value) {
|
|
|
2230
2533
|
const n = parseFloat(v);
|
|
2231
2534
|
return Number.isFinite(n) ? `${n}px` : v;
|
|
2232
2535
|
}
|
|
2536
|
+
/** A number and a unit, as an SVG's `width` and `height` are written. */
|
|
2537
|
+
const SVG_LENGTH = /^\s*([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)\s*([a-z]*)\s*$/i;
|
|
2538
|
+
/**
|
|
2539
|
+
* The `width`/`height` of an inline `<svg>` as CSS: they are presentation
|
|
2540
|
+
* attributes for the properties of the same names (SVG 2, 5.1.1), so
|
|
2541
|
+
* `height="50%"` is a percentage of the containing block like a style's.
|
|
2542
|
+
* A bare number is pixels; null for what CSS would not parse.
|
|
2543
|
+
*/
|
|
2544
|
+
function svgSizeHint(value) {
|
|
2545
|
+
const v = value.trim();
|
|
2546
|
+
if (/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?%$/i.test(v))
|
|
2547
|
+
return v;
|
|
2548
|
+
const m = SVG_LENGTH.exec(v);
|
|
2549
|
+
if (!m)
|
|
2550
|
+
return null;
|
|
2551
|
+
return m[2] ? v : `${parseFloat(m[1])}px`;
|
|
2552
|
+
}
|
|
2233
2553
|
function closestTable(el) {
|
|
2234
2554
|
let node = el.parent;
|
|
2235
2555
|
while (node) {
|