@tldraw/editor 3.12.0-canary.f3ad945f4591 → 3.12.0-internal.624e32507d98
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-cjs/index.js +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js +67 -24
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/cssRules.js +133 -0
- package/dist-cjs/lib/exports/cssRules.js.map +7 -0
- package/dist-cjs/lib/exports/exportToSvg.js +4 -1
- package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +0 -69
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs +69 -31
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/cssRules.mjs +113 -0
- package/dist-esm/lib/exports/cssRules.mjs.map +7 -0
- package/dist-esm/lib/exports/exportToSvg.mjs +4 -1
- package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +0 -69
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/lib/exports/StyleEmbedder.ts +93 -36
- package/src/lib/exports/cssRules.ts +132 -0
- package/src/lib/exports/exportToSvg.tsx +5 -1
- package/src/lib/exports/parseCss.ts +0 -79
- package/src/version.ts +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "A tiny little drawing app (editor).",
|
|
4
|
-
"version": "3.12.0-
|
|
4
|
+
"version": "3.12.0-internal.624e32507d98",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"@tiptap/core": "^2.9.1",
|
|
49
49
|
"@tiptap/pm": "^2.9.1",
|
|
50
50
|
"@tiptap/react": "^2.9.1",
|
|
51
|
-
"@tldraw/state": "3.12.0-
|
|
52
|
-
"@tldraw/state-react": "3.12.0-
|
|
53
|
-
"@tldraw/store": "3.12.0-
|
|
54
|
-
"@tldraw/tlschema": "3.12.0-
|
|
55
|
-
"@tldraw/utils": "3.12.0-
|
|
56
|
-
"@tldraw/validate": "3.12.0-
|
|
51
|
+
"@tldraw/state": "3.12.0-internal.624e32507d98",
|
|
52
|
+
"@tldraw/state-react": "3.12.0-internal.624e32507d98",
|
|
53
|
+
"@tldraw/store": "3.12.0-internal.624e32507d98",
|
|
54
|
+
"@tldraw/tlschema": "3.12.0-internal.624e32507d98",
|
|
55
|
+
"@tldraw/utils": "3.12.0-internal.624e32507d98",
|
|
56
|
+
"@tldraw/validate": "3.12.0-internal.624e32507d98",
|
|
57
57
|
"@types/core-js": "^2.5.8",
|
|
58
58
|
"@use-gesture/react": "^10.3.1",
|
|
59
59
|
"classnames": "^2.5.1",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assert, getOwnProperty, objectMapValues, uniqueId } from '@tldraw/utils'
|
|
2
2
|
import { FontEmbedder } from './FontEmbedder'
|
|
3
|
+
import { ReadonlyStyles, Styles, cssRules } from './cssRules'
|
|
3
4
|
import {
|
|
4
5
|
elementStyle,
|
|
5
6
|
getComputedStyle,
|
|
@@ -7,15 +8,8 @@ import {
|
|
|
7
8
|
getRenderedChildren,
|
|
8
9
|
} from './domUtils'
|
|
9
10
|
import { resourceToDataUrl } from './fetchCache'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
isPropertyInherited,
|
|
13
|
-
parseCssValueUrls,
|
|
14
|
-
shouldIncludeCssProperty,
|
|
15
|
-
} from './parseCss'
|
|
16
|
-
|
|
17
|
-
type Styles = { [K in string]?: string }
|
|
18
|
-
type ReadonlyStyles = { readonly [K in string]?: string }
|
|
11
|
+
import { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'
|
|
12
|
+
|
|
19
13
|
const NO_STYLES = {} as const
|
|
20
14
|
|
|
21
15
|
interface ElementStyleInfo {
|
|
@@ -29,6 +23,18 @@ export class StyleEmbedder {
|
|
|
29
23
|
private readonly styles = new Map<Element, ElementStyleInfo>()
|
|
30
24
|
readonly fonts = new FontEmbedder()
|
|
31
25
|
|
|
26
|
+
async collectDefaultStyles(elements: Element[]) {
|
|
27
|
+
const collected = new Set<string>()
|
|
28
|
+
const promises = []
|
|
29
|
+
for (const element of elements) {
|
|
30
|
+
const tagName = element.tagName.toLowerCase()
|
|
31
|
+
if (collected.has(tagName)) continue
|
|
32
|
+
collected.add(tagName)
|
|
33
|
+
promises.push(populateDefaultStylesForTagName(tagName))
|
|
34
|
+
}
|
|
35
|
+
await Promise.all(promises)
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
readRootElementStyles(rootElement: Element) {
|
|
33
39
|
// when reading a root, we always apply _all_ the styles, even if they match the defaults
|
|
34
40
|
this.readElementStyles(rootElement, {
|
|
@@ -239,15 +245,17 @@ function styleFromComputedStyleMap(
|
|
|
239
245
|
{ defaultStyles, parentStyles }: ReadStyleOpts
|
|
240
246
|
) {
|
|
241
247
|
const styles: Record<string, string> = {}
|
|
248
|
+
const currentColor = style.get('color')?.toString() || ''
|
|
249
|
+
const ruleOptions = { currentColor, parentStyles, defaultStyles, styles: style }
|
|
242
250
|
for (const property of style.keys()) {
|
|
243
251
|
if (!shouldIncludeCssProperty(property)) continue
|
|
244
252
|
|
|
245
253
|
const value = style.get(property)!.toString()
|
|
246
254
|
|
|
247
255
|
if (defaultStyles[property] === value) continue
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
256
|
+
|
|
257
|
+
const rule = getOwnProperty(cssRules, property)
|
|
258
|
+
if (rule && rule(value, property, ruleOptions)) continue
|
|
251
259
|
|
|
252
260
|
styles[property] = value
|
|
253
261
|
}
|
|
@@ -260,14 +268,18 @@ function styleFromComputedStyle(
|
|
|
260
268
|
{ defaultStyles, parentStyles }: ReadStyleOpts
|
|
261
269
|
) {
|
|
262
270
|
const styles: Record<string, string> = {}
|
|
271
|
+
const currentColor = style.color
|
|
272
|
+
const ruleOptions = { currentColor, parentStyles, defaultStyles, styles: style }
|
|
273
|
+
|
|
263
274
|
for (const property in style) {
|
|
264
275
|
if (!shouldIncludeCssProperty(property)) continue
|
|
265
276
|
|
|
266
277
|
const value = style.getPropertyValue(property)
|
|
267
278
|
|
|
268
279
|
if (defaultStyles[property] === value) continue
|
|
269
|
-
|
|
270
|
-
|
|
280
|
+
|
|
281
|
+
const rule = getOwnProperty(cssRules, property)
|
|
282
|
+
if (rule && rule(value, property, ruleOptions)) continue
|
|
271
283
|
|
|
272
284
|
styles[property] = value
|
|
273
285
|
}
|
|
@@ -285,43 +297,88 @@ function formatCss(style: ReadonlyStyles) {
|
|
|
285
297
|
// when we're figuring out the default values for a tag, we need read them from a separate document
|
|
286
298
|
// so they're not affected by the current document's styles
|
|
287
299
|
let defaultStyleFrame:
|
|
288
|
-
| {
|
|
300
|
+
| Promise<{
|
|
301
|
+
iframe: HTMLIFrameElement
|
|
302
|
+
foreignObject: SVGForeignObjectElement
|
|
303
|
+
document: Document
|
|
304
|
+
}>
|
|
289
305
|
| undefined
|
|
290
|
-
|
|
306
|
+
|
|
307
|
+
const defaultStylesByTagName: Record<
|
|
308
|
+
string,
|
|
309
|
+
| { type: 'resolved'; styles: ReadonlyStyles; promise: Promise<ReadonlyStyles> }
|
|
310
|
+
| { type: 'pending'; promise: Promise<ReadonlyStyles> }
|
|
311
|
+
> = {}
|
|
312
|
+
|
|
313
|
+
const emptyFrameBlob = new Blob(
|
|
314
|
+
['<svg xmlns="http://www.w3.org/2000/svg"><foreignObject/></svg>'],
|
|
315
|
+
{ type: 'image/svg+xml' }
|
|
316
|
+
)
|
|
317
|
+
const emptyFrameUrl = URL.createObjectURL(emptyFrameBlob)
|
|
318
|
+
|
|
291
319
|
function getDefaultStyleFrame() {
|
|
292
320
|
if (!defaultStyleFrame) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
321
|
+
defaultStyleFrame = new Promise((resolve) => {
|
|
322
|
+
const frame = document.createElement('iframe')
|
|
323
|
+
Object.assign(frame.style, {
|
|
324
|
+
position: 'absolute',
|
|
325
|
+
top: '-10000px',
|
|
326
|
+
left: '-10000px',
|
|
327
|
+
width: '1px',
|
|
328
|
+
height: '1px',
|
|
329
|
+
opacity: '0',
|
|
330
|
+
pointerEvents: 'none',
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
frame.onload = () => {
|
|
334
|
+
const contentDocument = frame.contentDocument!
|
|
335
|
+
const foreignObject = contentDocument.querySelector('foreignObject')!
|
|
336
|
+
resolve({ iframe: frame, foreignObject, document: contentDocument })
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
frame.src = emptyFrameUrl
|
|
340
|
+
document.body.appendChild(frame)
|
|
341
|
+
})
|
|
302
342
|
}
|
|
303
343
|
return defaultStyleFrame
|
|
304
344
|
}
|
|
305
345
|
|
|
306
346
|
function destroyDefaultStyleFrame() {
|
|
307
347
|
if (defaultStyleFrame) {
|
|
308
|
-
document.body.removeChild(
|
|
348
|
+
defaultStyleFrame.then(({ iframe }) => document.body.removeChild(iframe))
|
|
309
349
|
defaultStyleFrame = undefined
|
|
310
350
|
}
|
|
311
351
|
}
|
|
312
352
|
|
|
313
353
|
const defaultStyleReadOptions: ReadStyleOpts = { defaultStyles: NO_STYLES, parentStyles: NO_STYLES }
|
|
314
|
-
function
|
|
315
|
-
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
354
|
+
function populateDefaultStylesForTagName(tagName: string) {
|
|
355
|
+
const existing = defaultStylesByTagName[tagName]
|
|
356
|
+
if (existing && existing.type === 'resolved') {
|
|
357
|
+
return existing.promise
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (existing && existing.type === 'pending') {
|
|
361
|
+
return existing.promise
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const promise = getDefaultStyleFrame().then(({ foreignObject, document }) => {
|
|
365
|
+
const element = document.createElementNS('http://www.w3.org/1999/xhtml', tagName)
|
|
366
|
+
element.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
|
319
367
|
foreignObject.appendChild(element)
|
|
320
|
-
|
|
368
|
+
const styles = element.computedStyleMap
|
|
321
369
|
? styleFromComputedStyleMap(element.computedStyleMap(), defaultStyleReadOptions)
|
|
322
370
|
: styleFromComputedStyle(getComputedStyle(element), defaultStyleReadOptions)
|
|
323
371
|
foreignObject.removeChild(element)
|
|
324
|
-
defaultStylesByTagName[tagName] =
|
|
325
|
-
|
|
326
|
-
|
|
372
|
+
defaultStylesByTagName[tagName] = { type: 'resolved', styles, promise }
|
|
373
|
+
return styles
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
defaultStylesByTagName[tagName] = { type: 'pending', promise }
|
|
377
|
+
return promise
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function getDefaultStylesForTagName(tagName: string) {
|
|
381
|
+
const existing = defaultStylesByTagName[tagName]
|
|
382
|
+
assert(existing && existing.type === 'resolved', 'default styles must be populated & resolved')
|
|
383
|
+
return existing.styles
|
|
327
384
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export type Styles = { [K in string]?: string }
|
|
2
|
+
export type ReadonlyStyles = { readonly [K in string]?: string }
|
|
3
|
+
|
|
4
|
+
type CanSkipRule = (
|
|
5
|
+
value: string,
|
|
6
|
+
property: string,
|
|
7
|
+
options: {
|
|
8
|
+
styles: StylePropertyMapReadOnly | CSSStyleDeclaration
|
|
9
|
+
parentStyles: ReadonlyStyles
|
|
10
|
+
defaultStyles: ReadonlyStyles
|
|
11
|
+
currentColor: string
|
|
12
|
+
}
|
|
13
|
+
) => boolean
|
|
14
|
+
|
|
15
|
+
const getStyle = (styles: StylePropertyMapReadOnly | CSSStyleDeclaration, property: string) => {
|
|
16
|
+
if (styles instanceof CSSStyleDeclaration) {
|
|
17
|
+
return styles.getPropertyValue(property)
|
|
18
|
+
}
|
|
19
|
+
return styles.get(property)?.toString()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isCoveredByCurrentColor: CanSkipRule = (value, property, { currentColor }) => {
|
|
23
|
+
return value === 'currentColor' || value === currentColor
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isInherited: CanSkipRule = (value, property, { parentStyles }) => {
|
|
27
|
+
return parentStyles[property] === value
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const isExcludedBorder =
|
|
31
|
+
(borderDirection: string): CanSkipRule =>
|
|
32
|
+
(value, property, { styles }) => {
|
|
33
|
+
const borderWidth = getStyle(styles, `border-${borderDirection}-width`)
|
|
34
|
+
const borderStyle = getStyle(styles, `border-${borderDirection}-style`)
|
|
35
|
+
|
|
36
|
+
if (borderWidth === '0px') return true
|
|
37
|
+
if (borderStyle === 'none') return true
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const cssRules = {
|
|
42
|
+
// currentColor properties:
|
|
43
|
+
'border-block-end-color': isCoveredByCurrentColor,
|
|
44
|
+
'border-block-start-color': isCoveredByCurrentColor,
|
|
45
|
+
'border-bottom-color': isCoveredByCurrentColor,
|
|
46
|
+
'border-inline-end-color': isCoveredByCurrentColor,
|
|
47
|
+
'border-inline-start-color': isCoveredByCurrentColor,
|
|
48
|
+
'border-left-color': isCoveredByCurrentColor,
|
|
49
|
+
'border-right-color': isCoveredByCurrentColor,
|
|
50
|
+
'border-top-color': isCoveredByCurrentColor,
|
|
51
|
+
'caret-color': isCoveredByCurrentColor,
|
|
52
|
+
'column-rule-color': isCoveredByCurrentColor,
|
|
53
|
+
'outline-color': isCoveredByCurrentColor,
|
|
54
|
+
'text-decoration': (value, property, { currentColor }) => {
|
|
55
|
+
return value === 'none solid currentColor' || value === 'none solid ' + currentColor
|
|
56
|
+
},
|
|
57
|
+
'text-decoration-color': isCoveredByCurrentColor,
|
|
58
|
+
'text-emphasis-color': isCoveredByCurrentColor,
|
|
59
|
+
|
|
60
|
+
// inherited properties:
|
|
61
|
+
'border-collapse': isInherited,
|
|
62
|
+
'border-spacing': isInherited,
|
|
63
|
+
'caption-side': isInherited,
|
|
64
|
+
// N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
|
|
65
|
+
// 'color': isInherited,
|
|
66
|
+
cursor: isInherited,
|
|
67
|
+
direction: isInherited,
|
|
68
|
+
'empty-cells': isInherited,
|
|
69
|
+
'font-family': isInherited,
|
|
70
|
+
'font-size': isInherited,
|
|
71
|
+
'font-style': isInherited,
|
|
72
|
+
'font-variant': isInherited,
|
|
73
|
+
'font-weight': isInherited,
|
|
74
|
+
'font-size-adjust': isInherited,
|
|
75
|
+
'font-stretch': isInherited,
|
|
76
|
+
font: isInherited,
|
|
77
|
+
'letter-spacing': isInherited,
|
|
78
|
+
'line-height': isInherited,
|
|
79
|
+
'list-style-image': isInherited,
|
|
80
|
+
'list-style-position': isInherited,
|
|
81
|
+
'list-style-type': isInherited,
|
|
82
|
+
'list-style': isInherited,
|
|
83
|
+
orphans: isInherited,
|
|
84
|
+
'overflow-wrap': isInherited,
|
|
85
|
+
quotes: isInherited,
|
|
86
|
+
'stroke-linecap': isInherited,
|
|
87
|
+
'stroke-linejoin': isInherited,
|
|
88
|
+
'tab-size': isInherited,
|
|
89
|
+
'text-align': isInherited,
|
|
90
|
+
'text-align-last': isInherited,
|
|
91
|
+
'text-indent': isInherited,
|
|
92
|
+
'text-justify': isInherited,
|
|
93
|
+
'text-shadow': isInherited,
|
|
94
|
+
'text-transform': isInherited,
|
|
95
|
+
visibility: isInherited,
|
|
96
|
+
'white-space': isInherited,
|
|
97
|
+
'white-space-collapse': isInherited,
|
|
98
|
+
widows: isInherited,
|
|
99
|
+
'word-break': isInherited,
|
|
100
|
+
'word-spacing': isInherited,
|
|
101
|
+
'word-wrap': isInherited,
|
|
102
|
+
|
|
103
|
+
// special border cases - we have a weird case (tailwind seems to trigger this) where all
|
|
104
|
+
// border-styles sometimes get set to 'solid', but the border-width is 0 so they don't render.
|
|
105
|
+
// but in SVGs, **sometimes**, the border-width defaults (i think from a UA style-sheet? but
|
|
106
|
+
// honestly can't tell) to 1.5px so the border displays. we work around this by only including
|
|
107
|
+
// border styles at all if both the border-width and border-style are set to something that
|
|
108
|
+
// would show a border.
|
|
109
|
+
'border-top': isExcludedBorder('top'),
|
|
110
|
+
'border-right': isExcludedBorder('right'),
|
|
111
|
+
'border-bottom': isExcludedBorder('bottom'),
|
|
112
|
+
'border-left': isExcludedBorder('left'),
|
|
113
|
+
'border-block-end': isExcludedBorder('block-end'),
|
|
114
|
+
'border-block-start': isExcludedBorder('block-start'),
|
|
115
|
+
'border-inline-end': isExcludedBorder('inline-end'),
|
|
116
|
+
'border-inline-start': isExcludedBorder('inline-start'),
|
|
117
|
+
'border-top-style': isExcludedBorder('top'),
|
|
118
|
+
'border-right-style': isExcludedBorder('right'),
|
|
119
|
+
'border-bottom-style': isExcludedBorder('bottom'),
|
|
120
|
+
'border-left-style': isExcludedBorder('left'),
|
|
121
|
+
'border-block-end-style': isExcludedBorder('block-end'),
|
|
122
|
+
'border-block-start-style': isExcludedBorder('block-start'),
|
|
123
|
+
'border-inline-end-style': isExcludedBorder('inline-end'),
|
|
124
|
+
'border-inline-start-style': isExcludedBorder('inline-start'),
|
|
125
|
+
'border-top-width': isExcludedBorder('top'),
|
|
126
|
+
'border-right-width': isExcludedBorder('right'),
|
|
127
|
+
'border-bottom-width': isExcludedBorder('bottom'),
|
|
128
|
+
'border-left-width': isExcludedBorder('left'),
|
|
129
|
+
'border-block-end-width': isExcludedBorder('block-end'),
|
|
130
|
+
'border-block-start-width': isExcludedBorder('block-start'),
|
|
131
|
+
'border-inline-end-width': isExcludedBorder('inline-end'),
|
|
132
|
+
} satisfies Record<string, CanSkipRule>
|
|
@@ -101,11 +101,15 @@ async function applyChangesToForeignObjects(svg: SVGSVGElement) {
|
|
|
101
101
|
// urls, and things like videos will be converted to images.
|
|
102
102
|
await Promise.all(foreignObjectChildren.map((el) => embedMedia(el as HTMLElement)))
|
|
103
103
|
|
|
104
|
+
await styleEmbedder.collectDefaultStyles([
|
|
105
|
+
...svg.querySelectorAll('foreignObject.tl-export-embed-styles *'),
|
|
106
|
+
])
|
|
107
|
+
|
|
104
108
|
// read the computed styles of every element (+ it's children & pseudo-elements) in the
|
|
105
109
|
// document. we do this in a single pass before we start embedding any CSS stuff to avoid
|
|
106
110
|
// constantly forcing the browser to recompute styles & layout.
|
|
107
111
|
for (const el of foreignObjectChildren) {
|
|
108
|
-
styleEmbedder.readRootElementStyles(el as HTMLElement)
|
|
112
|
+
await styleEmbedder.readRootElementStyles(el as HTMLElement)
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
// fetch any resources that we need to embed in the CSS, like background images.
|
|
@@ -110,82 +110,3 @@ export function parseCssValueUrls(value: string) {
|
|
|
110
110
|
url: m[1] || m[2] || m[3],
|
|
111
111
|
}))
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
const currentColorProperties = new Set([
|
|
115
|
-
'border-block-end-color',
|
|
116
|
-
'border-block-start-color',
|
|
117
|
-
'border-bottom-color',
|
|
118
|
-
'border-inline-end-color',
|
|
119
|
-
'border-inline-start-color',
|
|
120
|
-
'border-left-color',
|
|
121
|
-
'border-right-color',
|
|
122
|
-
'border-top-color',
|
|
123
|
-
'caret-color',
|
|
124
|
-
'column-rule-color',
|
|
125
|
-
'outline-color',
|
|
126
|
-
'text-decoration',
|
|
127
|
-
'text-decoration-color',
|
|
128
|
-
'text-emphasis-color',
|
|
129
|
-
])
|
|
130
|
-
|
|
131
|
-
export function isPropertyCoveredByCurrentColor(
|
|
132
|
-
currentColor: string,
|
|
133
|
-
property: string,
|
|
134
|
-
value: string
|
|
135
|
-
) {
|
|
136
|
-
if (currentColorProperties.has(property)) {
|
|
137
|
-
return (
|
|
138
|
-
value === 'currentColor' ||
|
|
139
|
-
value === currentColor ||
|
|
140
|
-
(property === 'text-decoration' && value === `none solid ${currentColor}`)
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const inheritedProperties = new Set([
|
|
146
|
-
'border-collapse',
|
|
147
|
-
'border-spacing',
|
|
148
|
-
'caption-side',
|
|
149
|
-
// N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
|
|
150
|
-
// 'color',
|
|
151
|
-
'cursor',
|
|
152
|
-
'direction',
|
|
153
|
-
'empty-cells',
|
|
154
|
-
'font-family',
|
|
155
|
-
'font-size',
|
|
156
|
-
'font-style',
|
|
157
|
-
'font-variant',
|
|
158
|
-
'font-weight',
|
|
159
|
-
'font-size-adjust',
|
|
160
|
-
'font-stretch',
|
|
161
|
-
'font',
|
|
162
|
-
'letter-spacing',
|
|
163
|
-
'line-height',
|
|
164
|
-
'list-style-image',
|
|
165
|
-
'list-style-position',
|
|
166
|
-
'list-style-type',
|
|
167
|
-
'list-style',
|
|
168
|
-
'orphans',
|
|
169
|
-
'overflow-wrap',
|
|
170
|
-
'quotes',
|
|
171
|
-
'stroke-linecap',
|
|
172
|
-
'stroke-linejoin',
|
|
173
|
-
'tab-size',
|
|
174
|
-
'text-align',
|
|
175
|
-
'text-align-last',
|
|
176
|
-
'text-indent',
|
|
177
|
-
'text-justify',
|
|
178
|
-
'text-shadow',
|
|
179
|
-
'text-transform',
|
|
180
|
-
'visibility',
|
|
181
|
-
'white-space',
|
|
182
|
-
'white-space-collapse',
|
|
183
|
-
'widows',
|
|
184
|
-
'word-break',
|
|
185
|
-
'word-spacing',
|
|
186
|
-
'word-wrap',
|
|
187
|
-
])
|
|
188
|
-
|
|
189
|
-
export function isPropertyInherited(property: string) {
|
|
190
|
-
return inheritedProperties.has(property)
|
|
191
|
-
}
|
package/src/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '3.12.0-
|
|
4
|
+
export const version = '3.12.0-internal.624e32507d98'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-04-
|
|
8
|
-
patch: '2025-04-
|
|
7
|
+
minor: '2025-04-01T17:14:18.076Z',
|
|
8
|
+
patch: '2025-04-01T17:14:18.076Z',
|
|
9
9
|
}
|