BLOBBO/node_modules/postcss/lib/container.js
type-two 969f602dd4 Foundation: vite+ts+three+rapier scaffold, frozen contracts, lane docs A-E
Fixed-step world runtime, event bus wire protocol between lanes, integration
seam (game.ts) with placeholder ball. Lanes A/B/C own disjoint dirs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:55:43 +10:00

495 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict'
let Comment = require('./comment')
let Declaration = require('./declaration')
let Node = require('./node')
let { isClean, my } = require('./symbols')
let AtRule, parse, Root, Rule
function cleanSource(nodes) {
let stack = nodes.slice()
while (stack.length > 0) {
let node = stack.pop()
delete node.source
if (node.nodes) {
node.nodes = node.nodes.slice()
for (let i of node.nodes) stack.push(i)
}
}
return nodes.slice()
}
function markTreeDirty(node) {
let stack = [node]
while (stack.length > 0) {
let next = stack.pop()
next[isClean] = false
if (next.proxyOf.nodes) {
for (let i of next.proxyOf.nodes) stack.push(i)
}
}
}
class Container extends Node {
get first() {
if (!this.proxyOf.nodes) return undefined
return this.proxyOf.nodes[0]
}
get last() {
if (!this.proxyOf.nodes) return undefined
return this.proxyOf.nodes[this.proxyOf.nodes.length - 1]
}
append(...children) {
for (let child of children) {
let nodes = this.normalize(child, this.last)
for (let node of nodes) this.proxyOf.nodes.push(node)
}
this.markDirty()
return this
}
cleanRaws(keepBetween) {
let stack = [this]
while (stack.length > 0) {
let node = stack.pop()
if (node !== this && node.cleanRaws !== Container.prototype.cleanRaws) {
// Subclass with own logic; let it handle its subtree
node.cleanRaws(keepBetween)
continue
}
Node.prototype.cleanRaws.call(node, keepBetween)
if (node.nodes) {
for (let child of node.nodes) stack.push(child)
}
}
}
each(callback) {
if (!this.proxyOf.nodes) return undefined
let iterator = this.getIterator()
let index, result
while (this.indexes[iterator] < this.proxyOf.nodes.length) {
index = this.indexes[iterator]
result = callback(this.proxyOf.nodes[index], index)
if (result === false) break
this.indexes[iterator] += 1
}
delete this.indexes[iterator]
return result
}
every(condition) {
return this.nodes.every(condition)
}
getIterator() {
if (!this.lastEach) this.lastEach = 0
if (!this.indexes) this.indexes = {}
this.lastEach += 1
let iterator = this.lastEach
this.indexes[iterator] = 0
return iterator
}
getProxyProcessor() {
return {
get(node, prop) {
if (prop === 'proxyOf') {
return node
} else if (!node[prop]) {
return node[prop]
} else if (
prop === 'each' ||
(typeof prop === 'string' && prop.startsWith('walk'))
) {
return (...args) => {
return node[prop](
...args.map(i => {
if (typeof i === 'function') {
return (child, index) => i(child.toProxy(), index)
} else {
return i
}
})
)
}
} else if (prop === 'every' || prop === 'some') {
return cb => {
return node[prop]((child, ...other) =>
cb(child.toProxy(), ...other)
)
}
} else if (prop === 'root') {
return () => node.root().toProxy()
} else if (prop === 'nodes') {
return node.nodes.map(i => i.toProxy())
} else if (prop === 'first' || prop === 'last') {
return node[prop].toProxy()
} else {
return node[prop]
}
},
set(node, prop, value) {
if (node[prop] === value) return true
node[prop] = value
if (prop === 'name' || prop === 'params' || prop === 'selector') {
node.markDirty()
}
return true
}
}
}
index(child) {
if (typeof child === 'number') return child
if (child.proxyOf) child = child.proxyOf
return this.proxyOf.nodes.indexOf(child)
}
insertAfter(exist, add) {
let existIndex = this.index(exist)
let nodes = this.normalize(add, this.proxyOf.nodes[existIndex]).reverse()
existIndex = this.index(exist)
for (let node of nodes) this.proxyOf.nodes.splice(existIndex + 1, 0, node)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (existIndex < index) {
this.indexes[id] = index + nodes.length
}
}
this.markDirty()
return this
}
insertBefore(exist, add) {
let existIndex = this.index(exist)
let type = existIndex === 0 ? 'prepend' : false
let nodes = this.normalize(
add,
this.proxyOf.nodes[existIndex],
type
).reverse()
existIndex = this.index(exist)
for (let node of nodes) this.proxyOf.nodes.splice(existIndex, 0, node)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (existIndex <= index) {
this.indexes[id] = index + nodes.length
}
}
this.markDirty()
return this
}
normalize(nodes, sample) {
if (typeof nodes === 'string') {
nodes = cleanSource(parse(nodes).nodes)
} else if (typeof nodes === 'undefined') {
nodes = []
} else if (Array.isArray(nodes)) {
nodes = nodes.slice(0)
for (let i of nodes) {
if (i.parent) i.parent.removeChild(i, 'ignore')
}
} else if (nodes.type === 'root' && this.type !== 'document') {
nodes = nodes.nodes.slice(0)
for (let i of nodes) {
if (i.parent) i.parent.removeChild(i, 'ignore')
}
} else if (nodes.type) {
nodes = [nodes]
} else if (nodes.prop) {
if (typeof nodes.value === 'undefined') {
throw new Error('Value field is missed in node creation')
} else if (typeof nodes.value !== 'string') {
nodes.value = String(nodes.value)
}
nodes = [new Declaration(nodes)]
} else if (nodes.selector || nodes.selectors) {
nodes = [new Rule(nodes)]
} else if (nodes.name) {
nodes = [new AtRule(nodes)]
} else if (nodes.text) {
nodes = [new Comment(nodes)]
} else {
throw new Error('Unknown node type in node creation')
}
let processed = nodes.map(i => {
/* c8 ignore next */
if (!i[my]) Container.rebuild(i)
i = i.proxyOf
if (i.parent) i.parent.removeChild(i)
if (i[isClean]) markTreeDirty(i)
if (!i.raws) i.raws = {}
if (typeof i.raws.before === 'undefined') {
if (sample && typeof sample.raws.before !== 'undefined') {
i.raws.before = sample.raws.before.replace(/\S/g, '')
}
}
i.parent = this.proxyOf
return i
})
return processed
}
prepend(...children) {
children = children.reverse()
for (let child of children) {
let nodes = this.normalize(child, this.first, 'prepend').reverse()
for (let node of nodes) this.proxyOf.nodes.unshift(node)
for (let id in this.indexes) {
this.indexes[id] = this.indexes[id] + nodes.length
}
}
this.markDirty()
return this
}
push(child) {
child.parent = this
this.proxyOf.nodes.push(child)
return this
}
removeAll() {
for (let node of this.proxyOf.nodes) node.parent = undefined
this.proxyOf.nodes = []
this.markDirty()
return this
}
removeChild(child) {
child = this.index(child)
this.proxyOf.nodes[child].parent = undefined
this.proxyOf.nodes.splice(child, 1)
let index
for (let id in this.indexes) {
index = this.indexes[id]
if (index >= child) {
this.indexes[id] = index - 1
}
}
this.markDirty()
return this
}
replaceValues(pattern, opts, callback) {
if (!callback) {
callback = opts
opts = {}
}
this.walkDecls(decl => {
if (opts.props && !opts.props.includes(decl.prop)) return
if (opts.fast && !decl.value.includes(opts.fast)) return
decl.value = decl.value.replace(pattern, callback)
})
this.markDirty()
return this
}
some(condition) {
return this.nodes.some(condition)
}
walk(callback) {
if (!this.proxyOf.nodes) return undefined
// An explicit stack instead of recursive `each()` calls to survive
// deeply nested trees. Each frame keeps a live `indexes` slot, so
// insertion and removal during the walk behave like `each()`: the
// slot stays at the current child until its subtree is finished.
let stack = [{ iterator: this.getIterator(), node: this.proxyOf }]
while (stack.length > 0) {
let { iterator, node } = stack[stack.length - 1]
let index = node.indexes[iterator]
if (index >= node.proxyOf.nodes.length) {
delete node.indexes[iterator]
stack.pop()
let parent = stack[stack.length - 1]
// Finish the parents step for the child subtree we just left
if (parent) parent.node.indexes[parent.iterator] += 1
continue
}
let child = node.proxyOf.nodes[index]
let result
try {
result = callback(child, index)
} catch (e) {
throw child.addToError(e)
}
if (result === false) {
for (let opened of stack) {
delete opened.node.indexes[opened.iterator]
}
return false
}
if (child.walk && child.proxyOf.nodes) {
stack.push({ iterator: child.getIterator(), node: child })
} else {
node.indexes[iterator] += 1
}
}
return undefined
}
walkAtRules(name, callback) {
if (!callback) {
callback = name
return this.walk((child, i) => {
if (child.type === 'atrule') {
return callback(child, i)
}
})
}
if (name instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'atrule' && name.test(child.name)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'atrule' && child.name === name) {
return callback(child, i)
}
})
}
walkComments(callback) {
return this.walk((child, i) => {
if (child.type === 'comment') {
return callback(child, i)
}
})
}
walkDecls(prop, callback) {
if (!callback) {
callback = prop
return this.walk((child, i) => {
if (child.type === 'decl') {
return callback(child, i)
}
})
}
if (prop instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'decl' && prop.test(child.prop)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'decl' && child.prop === prop) {
return callback(child, i)
}
})
}
walkRules(selector, callback) {
if (!callback) {
callback = selector
return this.walk((child, i) => {
if (child.type === 'rule') {
return callback(child, i)
}
})
}
if (selector instanceof RegExp) {
return this.walk((child, i) => {
if (child.type === 'rule' && selector.test(child.selector)) {
return callback(child, i)
}
})
}
return this.walk((child, i) => {
if (child.type === 'rule' && child.selector === selector) {
return callback(child, i)
}
})
}
}
Container.registerParse = dependant => {
parse = dependant
}
Container.registerRule = dependant => {
Rule = dependant
}
Container.registerAtRule = dependant => {
AtRule = dependant
}
Container.registerRoot = dependant => {
Root = dependant
}
module.exports = Container
Container.default = Container
/* c8 ignore start */
Container.rebuild = node => {
let stack = [node]
while (stack.length > 0) {
let next = stack.pop()
if (next.type === 'atrule') {
Object.setPrototypeOf(next, AtRule.prototype)
} else if (next.type === 'rule') {
Object.setPrototypeOf(next, Rule.prototype)
} else if (next.type === 'decl') {
Object.setPrototypeOf(next, Declaration.prototype)
} else if (next.type === 'comment') {
Object.setPrototypeOf(next, Comment.prototype)
} else if (next.type === 'root') {
Object.setPrototypeOf(next, Root.prototype)
}
next[my] = true
if (next.nodes) {
for (let child of next.nodes) stack.push(child)
}
}
}
/* c8 ignore stop */