source: trip-planner-front/node_modules/postcss/lib/node.js

Last change on this file was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.9 KB
Line 
1'use strict'
2
3let { isClean, my } = require('./symbols')
4let CssSyntaxError = require('./css-syntax-error')
5let Stringifier = require('./stringifier')
6let stringify = require('./stringify')
7
8function cloneNode(obj, parent) {
9 let cloned = new obj.constructor()
10
11 for (let i in obj) {
12 if (!Object.prototype.hasOwnProperty.call(obj, i)) {
13 // istanbul ignore next
14 continue
15 }
16 if (i === 'proxyCache') continue
17 let value = obj[i]
18 let type = typeof value
19
20 if (i === 'parent' && type === 'object') {
21 if (parent) cloned[i] = parent
22 } else if (i === 'source') {
23 cloned[i] = value
24 } else if (Array.isArray(value)) {
25 cloned[i] = value.map(j => cloneNode(j, cloned))
26 } else {
27 if (type === 'object' && value !== null) value = cloneNode(value)
28 cloned[i] = value
29 }
30 }
31
32 return cloned
33}
34
35class Node {
36 constructor(defaults = {}) {
37 this.raws = {}
38 this[isClean] = false
39 this[my] = true
40
41 for (let name in defaults) {
42 if (name === 'nodes') {
43 this.nodes = []
44 for (let node of defaults[name]) {
45 if (typeof node.clone === 'function') {
46 this.append(node.clone())
47 } else {
48 this.append(node)
49 }
50 }
51 } else {
52 this[name] = defaults[name]
53 }
54 }
55 }
56
57 error(message, opts = {}) {
58 if (this.source) {
59 let pos = this.positionBy(opts)
60 return this.source.input.error(message, pos.line, pos.column, opts)
61 }
62 return new CssSyntaxError(message)
63 }
64
65 warn(result, text, opts) {
66 let data = { node: this }
67 for (let i in opts) data[i] = opts[i]
68 return result.warn(text, data)
69 }
70
71 remove() {
72 if (this.parent) {
73 this.parent.removeChild(this)
74 }
75 this.parent = undefined
76 return this
77 }
78
79 toString(stringifier = stringify) {
80 if (stringifier.stringify) stringifier = stringifier.stringify
81 let result = ''
82 stringifier(this, i => {
83 result += i
84 })
85 return result
86 }
87
88 assign(overrides = {}) {
89 for (let name in overrides) {
90 this[name] = overrides[name]
91 }
92 return this
93 }
94
95 clone(overrides = {}) {
96 let cloned = cloneNode(this)
97 for (let name in overrides) {
98 cloned[name] = overrides[name]
99 }
100 return cloned
101 }
102
103 cloneBefore(overrides = {}) {
104 let cloned = this.clone(overrides)
105 this.parent.insertBefore(this, cloned)
106 return cloned
107 }
108
109 cloneAfter(overrides = {}) {
110 let cloned = this.clone(overrides)
111 this.parent.insertAfter(this, cloned)
112 return cloned
113 }
114
115 replaceWith(...nodes) {
116 if (this.parent) {
117 let bookmark = this
118 let foundSelf = false
119 for (let node of nodes) {
120 if (node === this) {
121 foundSelf = true
122 } else if (foundSelf) {
123 this.parent.insertAfter(bookmark, node)
124 bookmark = node
125 } else {
126 this.parent.insertBefore(bookmark, node)
127 }
128 }
129
130 if (!foundSelf) {
131 this.remove()
132 }
133 }
134
135 return this
136 }
137
138 next() {
139 if (!this.parent) return undefined
140 let index = this.parent.index(this)
141 return this.parent.nodes[index + 1]
142 }
143
144 prev() {
145 if (!this.parent) return undefined
146 let index = this.parent.index(this)
147 return this.parent.nodes[index - 1]
148 }
149
150 before(add) {
151 this.parent.insertBefore(this, add)
152 return this
153 }
154
155 after(add) {
156 this.parent.insertAfter(this, add)
157 return this
158 }
159
160 root() {
161 let result = this
162 while (result.parent && result.parent.type !== 'document') {
163 result = result.parent
164 }
165 return result
166 }
167
168 raw(prop, defaultType) {
169 let str = new Stringifier()
170 return str.raw(this, prop, defaultType)
171 }
172
173 cleanRaws(keepBetween) {
174 delete this.raws.before
175 delete this.raws.after
176 if (!keepBetween) delete this.raws.between
177 }
178
179 toJSON(_, inputs) {
180 let fixed = {}
181 let emitInputs = inputs == null
182 inputs = inputs || new Map()
183 let inputsNextIndex = 0
184
185 for (let name in this) {
186 if (!Object.prototype.hasOwnProperty.call(this, name)) {
187 // istanbul ignore next
188 continue
189 }
190 if (name === 'parent' || name === 'proxyCache') continue
191 let value = this[name]
192
193 if (Array.isArray(value)) {
194 fixed[name] = value.map(i => {
195 if (typeof i === 'object' && i.toJSON) {
196 return i.toJSON(null, inputs)
197 } else {
198 return i
199 }
200 })
201 } else if (typeof value === 'object' && value.toJSON) {
202 fixed[name] = value.toJSON(null, inputs)
203 } else if (name === 'source') {
204 let inputId = inputs.get(value.input)
205 if (inputId == null) {
206 inputId = inputsNextIndex
207 inputs.set(value.input, inputsNextIndex)
208 inputsNextIndex++
209 }
210 fixed[name] = {
211 inputId,
212 start: value.start,
213 end: value.end
214 }
215 } else {
216 fixed[name] = value
217 }
218 }
219
220 if (emitInputs) {
221 fixed.inputs = [...inputs.keys()].map(input => input.toJSON())
222 }
223
224 return fixed
225 }
226
227 positionInside(index) {
228 let string = this.toString()
229 let column = this.source.start.column
230 let line = this.source.start.line
231
232 for (let i = 0; i < index; i++) {
233 if (string[i] === '\n') {
234 column = 1
235 line += 1
236 } else {
237 column += 1
238 }
239 }
240
241 return { line, column }
242 }
243
244 positionBy(opts) {
245 let pos = this.source.start
246 if (opts.index) {
247 pos = this.positionInside(opts.index)
248 } else if (opts.word) {
249 let index = this.toString().indexOf(opts.word)
250 if (index !== -1) pos = this.positionInside(index)
251 }
252 return pos
253 }
254
255 getProxyProcessor() {
256 return {
257 set(node, prop, value) {
258 if (node[prop] === value) return true
259 node[prop] = value
260 if (
261 prop === 'prop' ||
262 prop === 'value' ||
263 prop === 'name' ||
264 prop === 'params' ||
265 prop === 'important' ||
266 prop === 'text'
267 ) {
268 node.markDirty()
269 }
270 return true
271 },
272
273 get(node, prop) {
274 if (prop === 'proxyOf') {
275 return node
276 } else if (prop === 'root') {
277 return () => node.root().toProxy()
278 } else {
279 return node[prop]
280 }
281 }
282 }
283 }
284
285 toProxy() {
286 if (!this.proxyCache) {
287 this.proxyCache = new Proxy(this, this.getProxyProcessor())
288 }
289 return this.proxyCache
290 }
291
292 addToError(error) {
293 error.postcssNode = this
294 if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) {
295 let s = this.source
296 error.stack = error.stack.replace(
297 /\n\s{4}at /,
298 `$&${s.input.from}:${s.start.line}:${s.start.column}$&`
299 )
300 }
301 return error
302 }
303
304 markDirty() {
305 if (this[isClean]) {
306 this[isClean] = false
307 let next = this
308 while ((next = next.parent)) {
309 next[isClean] = false
310 }
311 }
312 }
313
314 get proxyOf() {
315 return this
316 }
317}
318
319module.exports = Node
320Node.default = Node
Note: See TracBrowser for help on using the repository browser.