@wix/origami-transforms 0.1.7 → 0.1.9
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-transforms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Babel and PostCSS checks and transforms for Wix origami page files.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
},
|
|
55
55
|
"type": "module",
|
|
56
56
|
"types": "./dist/index.d.ts",
|
|
57
|
-
"falconPackageHash": "
|
|
57
|
+
"falconPackageHash": "3225c4d857f7c4821fc78ea579b9a416bd05abd58f4bf0b0ac7906c0"
|
|
58
58
|
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
// Checks the CSS of a stack's direct children (rule S2-STACK-001). It changes nothing: every violation in the
|
|
2
2
|
// stylesheet is collected, and the build fails once with all of them.
|
|
3
3
|
//
|
|
4
|
-
// A stack is a parent
|
|
5
|
-
// `flex-direction` says which way
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
4
|
+
// A stack is a parent laid out with a non-wrapping flex, as DM derives it; an internal container writes its
|
|
5
|
+
// layout in its `@origami-target internal-container-content-wrapper` block. `flex-direction` says which way
|
|
6
|
+
// it stacks (column → vertical, row or none → horizontal). Any other value, such as `inherit` or `var(--d)`,
|
|
7
|
+
// fails DM's import, so its children aren't checked here.
|
|
8
|
+
//
|
|
9
|
+
// Parent and child are the JSX tree's, so the tree comes from the item's structure file (see
|
|
10
|
+
// structureFile.js). The stylesheet is the page's, with its carriers already inlined (see
|
|
11
|
+
// ../transform/css/postcssPlugin.js), so every rule is in view.
|
|
9
12
|
|
|
10
13
|
import { basename } from 'node:path'
|
|
11
14
|
import { LayoutError } from '../transform/layoutError.js'
|
|
12
15
|
import { literalIdOf, parseStructure, structureFileOf, walk } from './structureFile.js'
|
|
13
16
|
|
|
14
|
-
const
|
|
17
|
+
const CONTENT_WRAPPER = 'internal-container-content-wrapper'
|
|
15
18
|
const BASE = ''
|
|
16
19
|
|
|
17
20
|
// What a stack child may write, per direction. `0` is allowed wherever a length is.
|
|
@@ -79,39 +82,68 @@ const conditionOf = rule => {
|
|
|
79
82
|
return conditions.join(' / ')
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
const
|
|
85
|
+
// Exports give an element both `#id` and `.id`, and write its CSS on the class.
|
|
86
|
+
const OWN_SELECTOR = /^([#.])([\w-]+)$/
|
|
87
|
+
|
|
88
|
+
const isContentWrapper = node =>
|
|
89
|
+
node.type === 'atrule' && node.name === 'origami-target' && node.params.trim() === CONTENT_WRAPPER
|
|
90
|
+
|
|
91
|
+
/** Id → condition → `.`/`#` → declarations, in source order. With `content`, a content wrapper block counts. */
|
|
92
|
+
const declarationsById = (root, { content = false } = {}) => {
|
|
84
93
|
const byId = new Map()
|
|
85
94
|
root.walkRules(rule => {
|
|
86
|
-
const
|
|
87
|
-
if (!
|
|
95
|
+
const own = rule.selectors.map(selector => OWN_SELECTOR.exec(selector.trim())).filter(Boolean)
|
|
96
|
+
if (!own.length) return
|
|
88
97
|
const condition = conditionOf(rule)
|
|
89
|
-
for (const id of
|
|
98
|
+
for (const [, kind, id] of own) {
|
|
90
99
|
const byCondition = byId.get(id) ?? new Map()
|
|
91
100
|
byId.set(id, byCondition)
|
|
92
|
-
const
|
|
93
|
-
byCondition.set(condition,
|
|
101
|
+
const byKind = byCondition.get(condition) ?? { '.': [], '#': [] }
|
|
102
|
+
byCondition.set(condition, byKind)
|
|
94
103
|
rule.each(node => {
|
|
95
|
-
if (node.type === 'decl')
|
|
104
|
+
if (node.type === 'decl') byKind[kind].push(node)
|
|
105
|
+
else if (content && isContentWrapper(node)) {
|
|
106
|
+
node.each(inner => {
|
|
107
|
+
if (inner.type === 'decl') byKind[kind].push(inner)
|
|
108
|
+
})
|
|
109
|
+
}
|
|
96
110
|
})
|
|
97
111
|
}
|
|
98
112
|
})
|
|
99
113
|
return byId
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* The declarations in effect under `condition`: the base ones, then the condition's own; `#id` beats `.id`, and
|
|
118
|
+
* `!important` beats both.
|
|
119
|
+
*/
|
|
103
120
|
const effective = (byCondition, condition) => {
|
|
104
121
|
const result = new Map()
|
|
105
|
-
for (const
|
|
106
|
-
for (const
|
|
122
|
+
for (const important of [false, true]) {
|
|
123
|
+
for (const kind of ['.', '#']) {
|
|
124
|
+
for (const key of condition === BASE ? [BASE] : [BASE, condition]) {
|
|
125
|
+
for (const declaration of byCondition?.get(key)?.[kind] ?? []) {
|
|
126
|
+
if (Boolean(declaration.important) === important) result.set(declaration.prop, declaration)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
107
130
|
}
|
|
108
131
|
return result
|
|
109
132
|
}
|
|
110
133
|
|
|
134
|
+
const selectorOf = (declaration, id) =>
|
|
135
|
+
declaration.parent.selectors.some(selector => selector.trim() === `#${id}`) ? `#${id}` : `.${id}`
|
|
136
|
+
|
|
137
|
+
// The flex-direction values DM's import accepts, matched as written.
|
|
138
|
+
const DIRECTIONS = { row: 'horizontal', 'row-reverse': 'horizontal', column: 'vertical', 'column-reverse': 'vertical' }
|
|
139
|
+
|
|
111
140
|
/** 'vertical' or 'horizontal' when these declarations make a stack, else undefined. */
|
|
112
141
|
const directionOf = declarations => {
|
|
113
|
-
if (declarations.get('
|
|
114
|
-
|
|
142
|
+
if (declarations.get('display')?.value.trim() !== 'flex') return undefined
|
|
143
|
+
const wrap = declarations.get('flex-wrap')?.value.trim()
|
|
144
|
+
if (wrap !== undefined && wrap !== 'nowrap') return undefined
|
|
145
|
+
const direction = declarations.get('flex-direction')?.value.trim() ?? 'row'
|
|
146
|
+
return Object.hasOwn(DIRECTIONS, direction) ? DIRECTIONS[direction] : undefined
|
|
115
147
|
}
|
|
116
148
|
|
|
117
149
|
/** ` (layout.css:12)`: the carrier the declaration was written in, which the bundler doesn't name. */
|
|
@@ -135,12 +167,13 @@ export const stackChildrenPlugin = {
|
|
|
135
167
|
const parents = parentsIn(structurePath)
|
|
136
168
|
if (parents.size === 0) return
|
|
137
169
|
const byId = declarationsById(root)
|
|
170
|
+
const layoutById = declarationsById(root, { content: true })
|
|
138
171
|
|
|
139
172
|
const violations = new Set()
|
|
140
173
|
let first
|
|
141
174
|
for (const [child, parent] of parents) {
|
|
142
175
|
const childRules = byId.get(child)
|
|
143
|
-
const parentRules =
|
|
176
|
+
const parentRules = layoutById.get(parent)
|
|
144
177
|
if (childRules === undefined || parentRules === undefined) continue
|
|
145
178
|
for (const condition of new Set([BASE, ...parentRules.keys(), ...childRules.keys()])) {
|
|
146
179
|
const direction = directionOf(effective(parentRules, condition))
|
|
@@ -156,8 +189,8 @@ export const stackChildrenPlugin = {
|
|
|
156
189
|
if (!bad.length) continue
|
|
157
190
|
first ??= declaration.source
|
|
158
191
|
violations.add(
|
|
159
|
-
|
|
160
|
-
`${or(allowed.map(unit => LABELS[unit]))}; found ${bad.join(' ')}.`
|
|
192
|
+
`${selectorOf(declaration, child)}${where(declaration)}, a ${direction} stack child: ` +
|
|
193
|
+
`${declaration.prop} must be ${or(allowed.map(unit => LABELS[unit]))}; found ${bad.join(' ')}.`
|
|
161
194
|
)
|
|
162
195
|
}
|
|
163
196
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// The item's structure file, for CSS plugins that check a stylesheet against its JSX tree: `structure.tsx` (or
|
|
2
2
|
// `.jsx`) next to the stylesheet, or one folder up when the stylesheet is the generated one in `_generated/`.
|
|
3
|
-
// Elements and rules meet on a literal `id` and `#id`.
|
|
3
|
+
// Elements and rules meet on a literal `id` and `#id` (or `.id`).
|
|
4
4
|
|
|
5
5
|
import { existsSync, readFileSync } from 'node:fs'
|
|
6
6
|
import { basename, dirname, join } from 'node:path'
|