summaryrefslogtreecommitdiff
path: root/node_modules/postcss/lib/node.js
diff options
context:
space:
mode:
authorPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:54:57 +0100
committerPhilipp Tanlak <philipp.tanlak@gmail.com>2025-11-24 20:57:48 +0100
commitb1e2c8fd5cb5dfa46bc440a12eafaf56cd844b1c (patch)
tree49d360fd6cbc6a2754efe93524ac47ff0fbe0f7d /node_modules/postcss/lib/node.js
Docs
Diffstat (limited to 'node_modules/postcss/lib/node.js')
-rw-r--r--node_modules/postcss/lib/node.js381
1 files changed, 381 insertions, 0 deletions
diff --git a/node_modules/postcss/lib/node.js b/node_modules/postcss/lib/node.js
new file mode 100644
index 0000000..d79dd56
--- /dev/null
+++ b/node_modules/postcss/lib/node.js
@@ -0,0 +1,381 @@
+'use strict'
+
+let { isClean, my } = require('./symbols')
+let CssSyntaxError = require('./css-syntax-error')
+let Stringifier = require('./stringifier')
+let stringify = require('./stringify')
+
+function cloneNode(obj, parent) {
+ let cloned = new obj.constructor()
+
+ for (let i in obj) {
+ if (!Object.prototype.hasOwnProperty.call(obj, i)) {
+ /* c8 ignore next 2 */
+ continue
+ }
+ if (i === 'proxyCache') continue
+ let value = obj[i]
+ let type = typeof value
+
+ if (i === 'parent' && type === 'object') {
+ if (parent) cloned[i] = parent
+ } else if (i === 'source') {
+ cloned[i] = value
+ } else if (Array.isArray(value)) {
+ cloned[i] = value.map(j => cloneNode(j, cloned))
+ } else {
+ if (type === 'object' && value !== null) value = cloneNode(value)
+ cloned[i] = value
+ }
+ }
+
+ return cloned
+}
+
+class Node {
+ constructor(defaults = {}) {
+ this.raws = {}
+ this[isClean] = false
+ this[my] = true
+
+ for (let name in defaults) {
+ if (name === 'nodes') {
+ this.nodes = []
+ for (let node of defaults[name]) {
+ if (typeof node.clone === 'function') {
+ this.append(node.clone())
+ } else {
+ this.append(node)
+ }
+ }
+ } else {
+ this[name] = defaults[name]
+ }
+ }
+ }
+
+ addToError(error) {
+ error.postcssNode = this
+ if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) {
+ let s = this.source
+ error.stack = error.stack.replace(
+ /\n\s{4}at /,
+ `$&${s.input.from}:${s.start.line}:${s.start.column}$&`
+ )
+ }
+ return error
+ }
+
+ after(add) {
+ this.parent.insertAfter(this, add)
+ return this
+ }
+
+ assign(overrides = {}) {
+ for (let name in overrides) {
+ this[name] = overrides[name]
+ }
+ return this
+ }
+
+ before(add) {
+ this.parent.insertBefore(this, add)
+ return this
+ }
+
+ cleanRaws(keepBetween) {
+ delete this.raws.before
+ delete this.raws.after
+ if (!keepBetween) delete this.raws.between
+ }
+
+ clone(overrides = {}) {
+ let cloned = cloneNode(this)
+ for (let name in overrides) {
+ cloned[name] = overrides[name]
+ }
+ return cloned
+ }
+
+ cloneAfter(overrides = {}) {
+ let cloned = this.clone(overrides)
+ this.parent.insertAfter(this, cloned)
+ return cloned
+ }
+
+ cloneBefore(overrides = {}) {
+ let cloned = this.clone(overrides)
+ this.parent.insertBefore(this, cloned)
+ return cloned
+ }
+
+ error(message, opts = {}) {
+ if (this.source) {
+ let { end, start } = this.rangeBy(opts)
+ return this.source.input.error(
+ message,
+ { column: start.column, line: start.line },
+ { column: end.column, line: end.line },
+ opts
+ )
+ }
+ return new CssSyntaxError(message)
+ }
+
+ getProxyProcessor() {
+ return {
+ get(node, prop) {
+ if (prop === 'proxyOf') {
+ return node
+ } else if (prop === 'root') {
+ return () => node.root().toProxy()
+ } else {
+ return node[prop]
+ }
+ },
+
+ set(node, prop, value) {
+ if (node[prop] === value) return true
+ node[prop] = value
+ if (
+ prop === 'prop' ||
+ prop === 'value' ||
+ prop === 'name' ||
+ prop === 'params' ||
+ prop === 'important' ||
+ /* c8 ignore next */
+ prop === 'text'
+ ) {
+ node.markDirty()
+ }
+ return true
+ }
+ }
+ }
+
+ markDirty() {
+ if (this[isClean]) {
+ this[isClean] = false
+ let next = this
+ while ((next = next.parent)) {
+ next[isClean] = false
+ }
+ }
+ }
+
+ next() {
+ if (!this.parent) return undefined
+ let index = this.parent.index(this)
+ return this.parent.nodes[index + 1]
+ }
+
+ positionBy(opts, stringRepresentation) {
+ let pos = this.source.start
+ if (opts.index) {
+ pos = this.positionInside(opts.index, stringRepresentation)
+ } else if (opts.word) {
+ stringRepresentation = this.toString()
+ let index = stringRepresentation.indexOf(opts.word)
+ if (index !== -1) pos = this.positionInside(index, stringRepresentation)
+ }
+ return pos
+ }
+
+ positionInside(index, stringRepresentation) {
+ let string = stringRepresentation || this.toString()
+ let column = this.source.start.column
+ let line = this.source.start.line
+
+ for (let i = 0; i < index; i++) {
+ if (string[i] === '\n') {
+ column = 1
+ line += 1
+ } else {
+ column += 1
+ }
+ }
+
+ return { column, line }
+ }
+
+ prev() {
+ if (!this.parent) return undefined
+ let index = this.parent.index(this)
+ return this.parent.nodes[index - 1]
+ }
+
+ rangeBy(opts) {
+ let start = {
+ column: this.source.start.column,
+ line: this.source.start.line
+ }
+ let end = this.source.end
+ ? {
+ column: this.source.end.column + 1,
+ line: this.source.end.line
+ }
+ : {
+ column: start.column + 1,
+ line: start.line
+ }
+
+ if (opts.word) {
+ let stringRepresentation = this.toString()
+ let index = stringRepresentation.indexOf(opts.word)
+ if (index !== -1) {
+ start = this.positionInside(index, stringRepresentation)
+ end = this.positionInside(index + opts.word.length, stringRepresentation)
+ }
+ } else {
+ if (opts.start) {
+ start = {
+ column: opts.start.column,
+ line: opts.start.line
+ }
+ } else if (opts.index) {
+ start = this.positionInside(opts.index)
+ }
+
+ if (opts.end) {
+ end = {
+ column: opts.end.column,
+ line: opts.end.line
+ }
+ } else if (opts.endIndex) {
+ end = this.positionInside(opts.endIndex)
+ } else if (opts.index) {
+ end = this.positionInside(opts.index + 1)
+ }
+ }
+
+ if (
+ end.line < start.line ||
+ (end.line === start.line && end.column <= start.column)
+ ) {
+ end = { column: start.column + 1, line: start.line }
+ }
+
+ return { end, start }
+ }
+
+ raw(prop, defaultType) {
+ let str = new Stringifier()
+ return str.raw(this, prop, defaultType)
+ }
+
+ remove() {
+ if (this.parent) {
+ this.parent.removeChild(this)
+ }
+ this.parent = undefined
+ return this
+ }
+
+ replaceWith(...nodes) {
+ if (this.parent) {
+ let bookmark = this
+ let foundSelf = false
+ for (let node of nodes) {
+ if (node === this) {
+ foundSelf = true
+ } else if (foundSelf) {
+ this.parent.insertAfter(bookmark, node)
+ bookmark = node
+ } else {
+ this.parent.insertBefore(bookmark, node)
+ }
+ }
+
+ if (!foundSelf) {
+ this.remove()
+ }
+ }
+
+ return this
+ }
+
+ root() {
+ let result = this
+ while (result.parent && result.parent.type !== 'document') {
+ result = result.parent
+ }
+ return result
+ }
+
+ toJSON(_, inputs) {
+ let fixed = {}
+ let emitInputs = inputs == null
+ inputs = inputs || new Map()
+ let inputsNextIndex = 0
+
+ for (let name in this) {
+ if (!Object.prototype.hasOwnProperty.call(this, name)) {
+ /* c8 ignore next 2 */
+ continue
+ }
+ if (name === 'parent' || name === 'proxyCache') continue
+ let value = this[name]
+
+ if (Array.isArray(value)) {
+ fixed[name] = value.map(i => {
+ if (typeof i === 'object' && i.toJSON) {
+ return i.toJSON(null, inputs)
+ } else {
+ return i
+ }
+ })
+ } else if (typeof value === 'object' && value.toJSON) {
+ fixed[name] = value.toJSON(null, inputs)
+ } else if (name === 'source') {
+ let inputId = inputs.get(value.input)
+ if (inputId == null) {
+ inputId = inputsNextIndex
+ inputs.set(value.input, inputsNextIndex)
+ inputsNextIndex++
+ }
+ fixed[name] = {
+ end: value.end,
+ inputId,
+ start: value.start
+ }
+ } else {
+ fixed[name] = value
+ }
+ }
+
+ if (emitInputs) {
+ fixed.inputs = [...inputs.keys()].map(input => input.toJSON())
+ }
+
+ return fixed
+ }
+
+ toProxy() {
+ if (!this.proxyCache) {
+ this.proxyCache = new Proxy(this, this.getProxyProcessor())
+ }
+ return this.proxyCache
+ }
+
+ toString(stringifier = stringify) {
+ if (stringifier.stringify) stringifier = stringifier.stringify
+ let result = ''
+ stringifier(this, i => {
+ result += i
+ })
+ return result
+ }
+
+ warn(result, text, opts) {
+ let data = { node: this }
+ for (let i in opts) data[i] = opts[i]
+ return result.warn(text, data)
+ }
+
+ get proxyOf() {
+ return this
+ }
+}
+
+module.exports = Node
+Node.default = Node