@wix/origami-site-runtime 1.0.10 → 1.0.11
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/package.json +2 -2
- package/src/cssPlugins/index.js +4 -1
- package/src/cssPlugins/presets.js +67 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-site-runtime",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Vite development and build helpers for wix-import static sites",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"./default-error-404": "./src/default-error-404.jsx"
|
|
66
66
|
},
|
|
67
67
|
"type": "module",
|
|
68
|
-
"falconPackageHash": "
|
|
68
|
+
"falconPackageHash": "e22a7402b3249122540518d623a21731e722614ef9110bb8cce0eef7"
|
|
69
69
|
}
|
package/src/cssPlugins/index.js
CHANGED
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
// stage guarantees a plugin sees. The order matters once: mixin bodies are copied into their calling rules before
|
|
8
8
|
// layout routes declarations to wrappers and SPX converts calls using the browser's active settings. stack-children
|
|
9
9
|
// only checks, and runs between mixins and layout: it needs the mixins' declarations and the stack rules as authored,
|
|
10
|
-
// before layout compiles them away.
|
|
10
|
+
// before layout compiles them away. presets runs after mixins too, so a `--preset` a mixin body carries is moved
|
|
11
|
+
// like an authored one. fonts only checks the theme's font tokens, as authored.
|
|
11
12
|
//
|
|
12
13
|
// `@layer` needs no plugin: cascade layers have been in every browser since March 2022.
|
|
13
14
|
|
|
14
15
|
import { customMediaPlugin } from './customMedia.js'
|
|
15
16
|
import { fontsPlugin } from './fonts.js'
|
|
16
17
|
import { mixinsPlugin } from './mixins.js'
|
|
18
|
+
import { presetsPlugin } from './presets.js'
|
|
17
19
|
import { layoutPlugin } from './layout/index.js'
|
|
18
20
|
import { spxPlugin } from './spx/index.js'
|
|
19
21
|
import { stackChildrenPlugin } from './stackChildren.js'
|
|
@@ -24,6 +26,7 @@ export const cssPlugins = Object.freeze([
|
|
|
24
26
|
fontsPlugin,
|
|
25
27
|
mixinsPlugin,
|
|
26
28
|
stackChildrenPlugin,
|
|
29
|
+
presetsPlugin,
|
|
27
30
|
layoutPlugin,
|
|
28
31
|
spxPlugin,
|
|
29
32
|
])
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// A preset is set on the component's own rule (`#id` or `.id`): `--preset` for the component, `--preset-{key}` for
|
|
2
|
+
// its ref element `key` (as listed in the wrapper's `REF_ELEMENTS`). An element nested deeper is reached the same way,
|
|
3
|
+
// from the rule of the element it sits in: `.id .{parent} { --preset-{key}: … }`. The wrapper reads
|
|
4
|
+
// `--preset` off the presets-wrapper classes it renders (see the origami-component-usage skill), so each declaration
|
|
5
|
+
// moves there, as `--preset` in a rule of its own: `.{id}-presets-wrapper`, or `{selector} .{key}-presets-wrapper` so
|
|
6
|
+
// an inner element's preset reaches that instance only. A rule that does not start at a component is left as authored.
|
|
7
|
+
|
|
8
|
+
import postcss from 'postcss'
|
|
9
|
+
|
|
10
|
+
const PRESET = /^--preset(?:-([\w-]+))?$/
|
|
11
|
+
const COMPONENT = /^[#.]([\w-]+)$/
|
|
12
|
+
const WRAPPER = '-presets-wrapper'
|
|
13
|
+
|
|
14
|
+
/** Where a preset on `selector` goes: undefined when `selector` does not start at a component, null when it can't go. */
|
|
15
|
+
const target = (selector, key) => {
|
|
16
|
+
const [first] = selector.split(/\s+/, 1)
|
|
17
|
+
const id = COMPONENT.exec(first)?.[1]
|
|
18
|
+
if (id === undefined || id.endsWith(WRAPPER)) return undefined
|
|
19
|
+
if (key !== undefined) return `${selector} .${key}${WRAPPER}`
|
|
20
|
+
return selector === first ? `.${id}${WRAPPER}` : null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @type {import('../transform/types.js').CssTransformPlugin} */
|
|
24
|
+
export const presetsPlugin = {
|
|
25
|
+
name: 'presets',
|
|
26
|
+
order: 13,
|
|
27
|
+
transform(root) {
|
|
28
|
+
/** @type {import('postcss').Declaration[]} */
|
|
29
|
+
const declarations = []
|
|
30
|
+
root.walkDecls(PRESET, declaration => {
|
|
31
|
+
if (declaration.parent?.type === 'rule') declarations.push(declaration)
|
|
32
|
+
})
|
|
33
|
+
// Last first: each moved declaration lands right after its outermost rule, so source order is kept.
|
|
34
|
+
for (const declaration of declarations.reverse()) {
|
|
35
|
+
const rule = /** @type {import('postcss').Rule} */ (declaration.parent)
|
|
36
|
+
// The outermost rule, and the full selectors resolved as CSS Nesting does.
|
|
37
|
+
let outer = rule
|
|
38
|
+
let selectors = rule.selectors
|
|
39
|
+
while (outer.parent?.type === 'rule') {
|
|
40
|
+
outer = /** @type {import('postcss').Rule} */ (outer.parent)
|
|
41
|
+
const inner = selectors
|
|
42
|
+
selectors = outer.selectors.flatMap(parent =>
|
|
43
|
+
inner.map(selector => (selector.includes('&') ? selector.replaceAll('&', parent) : `${parent} ${selector}`))
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
const targets = selectors.map(selector => target(selector, PRESET.exec(declaration.prop)?.[1]))
|
|
47
|
+
if (targets.every(selector => selector === undefined)) continue
|
|
48
|
+
if (!targets.every(Boolean)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`${declaration.prop} on "${selectors.join(', ')}": set --preset on #id or .id alone, ` +
|
|
51
|
+
`and an inner element's as --preset-{key} on the rule of the element it sits in`
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
declaration.prop = '--preset'
|
|
55
|
+
const presetRule = postcss.rule({ selector: targets.join(', ') })
|
|
56
|
+
if (rule.source) presetRule.source = rule.source
|
|
57
|
+
outer.after(presetRule.append(declaration))
|
|
58
|
+
// Drop the rules the move left empty, from the declaration's own up to the outermost.
|
|
59
|
+
for (let node = rule; !node.nodes.length; ) {
|
|
60
|
+
const parent = node.parent
|
|
61
|
+
node.remove()
|
|
62
|
+
if (node === outer) break
|
|
63
|
+
node = /** @type {import('postcss').Rule} */ (parent)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
}
|