source: trip-planner-front/node_modules/postcss/lib/stringifier.js@ ceaed42

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

initial commit

  • Property mode set to 100644
File size: 8.0 KB
Line 
1'use strict'
2
3const DEFAULT_RAW = {
4 colon: ': ',
5 indent: ' ',
6 beforeDecl: '\n',
7 beforeRule: '\n',
8 beforeOpen: ' ',
9 beforeClose: '\n',
10 beforeComment: '\n',
11 after: '\n',
12 emptyBody: '',
13 commentLeft: ' ',
14 commentRight: ' ',
15 semicolon: false
16}
17
18function capitalize(str) {
19 return str[0].toUpperCase() + str.slice(1)
20}
21
22class Stringifier {
23 constructor(builder) {
24 this.builder = builder
25 }
26
27 stringify(node, semicolon) {
28 /* istanbul ignore if */
29 if (!this[node.type]) {
30 throw new Error(
31 'Unknown AST node type ' +
32 node.type +
33 '. ' +
34 'Maybe you need to change PostCSS stringifier.'
35 )
36 }
37 this[node.type](node, semicolon)
38 }
39
40 document(node) {
41 this.body(node)
42 }
43
44 root(node) {
45 this.body(node)
46 if (node.raws.after) this.builder(node.raws.after)
47 }
48
49 comment(node) {
50 let left = this.raw(node, 'left', 'commentLeft')
51 let right = this.raw(node, 'right', 'commentRight')
52 this.builder('/*' + left + node.text + right + '*/', node)
53 }
54
55 decl(node, semicolon) {
56 let between = this.raw(node, 'between', 'colon')
57 let string = node.prop + between + this.rawValue(node, 'value')
58
59 if (node.important) {
60 string += node.raws.important || ' !important'
61 }
62
63 if (semicolon) string += ';'
64 this.builder(string, node)
65 }
66
67 rule(node) {
68 this.block(node, this.rawValue(node, 'selector'))
69 if (node.raws.ownSemicolon) {
70 this.builder(node.raws.ownSemicolon, node, 'end')
71 }
72 }
73
74 atrule(node, semicolon) {
75 let name = '@' + node.name
76 let params = node.params ? this.rawValue(node, 'params') : ''
77
78 if (typeof node.raws.afterName !== 'undefined') {
79 name += node.raws.afterName
80 } else if (params) {
81 name += ' '
82 }
83
84 if (node.nodes) {
85 this.block(node, name + params)
86 } else {
87 let end = (node.raws.between || '') + (semicolon ? ';' : '')
88 this.builder(name + params + end, node)
89 }
90 }
91
92 body(node) {
93 let last = node.nodes.length - 1
94 while (last > 0) {
95 if (node.nodes[last].type !== 'comment') break
96 last -= 1
97 }
98
99 let semicolon = this.raw(node, 'semicolon')
100 for (let i = 0; i < node.nodes.length; i++) {
101 let child = node.nodes[i]
102 let before = this.raw(child, 'before')
103 if (before) this.builder(before)
104 this.stringify(child, last !== i || semicolon)
105 }
106 }
107
108 block(node, start) {
109 let between = this.raw(node, 'between', 'beforeOpen')
110 this.builder(start + between + '{', node, 'start')
111
112 let after
113 if (node.nodes && node.nodes.length) {
114 this.body(node)
115 after = this.raw(node, 'after')
116 } else {
117 after = this.raw(node, 'after', 'emptyBody')
118 }
119
120 if (after) this.builder(after)
121 this.builder('}', node, 'end')
122 }
123
124 raw(node, own, detect) {
125 let value
126 if (!detect) detect = own
127
128 // Already had
129 if (own) {
130 value = node.raws[own]
131 if (typeof value !== 'undefined') return value
132 }
133
134 let parent = node.parent
135
136 if (detect === 'before') {
137 // Hack for first rule in CSS
138 if (!parent || (parent.type === 'root' && parent.first === node)) {
139 return ''
140 }
141
142 // `root` nodes in `document` should use only their own raws
143 if (parent && parent.type === 'document') {
144 return ''
145 }
146 }
147
148 // Floating child without parent
149 if (!parent) return DEFAULT_RAW[detect]
150
151 // Detect style by other nodes
152 let root = node.root()
153 if (!root.rawCache) root.rawCache = {}
154 if (typeof root.rawCache[detect] !== 'undefined') {
155 return root.rawCache[detect]
156 }
157
158 if (detect === 'before' || detect === 'after') {
159 return this.beforeAfter(node, detect)
160 } else {
161 let method = 'raw' + capitalize(detect)
162 if (this[method]) {
163 value = this[method](root, node)
164 } else {
165 root.walk(i => {
166 value = i.raws[own]
167 if (typeof value !== 'undefined') return false
168 })
169 }
170 }
171
172 if (typeof value === 'undefined') value = DEFAULT_RAW[detect]
173
174 root.rawCache[detect] = value
175 return value
176 }
177
178 rawSemicolon(root) {
179 let value
180 root.walk(i => {
181 if (i.nodes && i.nodes.length && i.last.type === 'decl') {
182 value = i.raws.semicolon
183 if (typeof value !== 'undefined') return false
184 }
185 })
186 return value
187 }
188
189 rawEmptyBody(root) {
190 let value
191 root.walk(i => {
192 if (i.nodes && i.nodes.length === 0) {
193 value = i.raws.after
194 if (typeof value !== 'undefined') return false
195 }
196 })
197 return value
198 }
199
200 rawIndent(root) {
201 if (root.raws.indent) return root.raws.indent
202 let value
203 root.walk(i => {
204 let p = i.parent
205 if (p && p !== root && p.parent && p.parent === root) {
206 if (typeof i.raws.before !== 'undefined') {
207 let parts = i.raws.before.split('\n')
208 value = parts[parts.length - 1]
209 value = value.replace(/\S/g, '')
210 return false
211 }
212 }
213 })
214 return value
215 }
216
217 rawBeforeComment(root, node) {
218 let value
219 root.walkComments(i => {
220 if (typeof i.raws.before !== 'undefined') {
221 value = i.raws.before
222 if (value.includes('\n')) {
223 value = value.replace(/[^\n]+$/, '')
224 }
225 return false
226 }
227 })
228 if (typeof value === 'undefined') {
229 value = this.raw(node, null, 'beforeDecl')
230 } else if (value) {
231 value = value.replace(/\S/g, '')
232 }
233 return value
234 }
235
236 rawBeforeDecl(root, node) {
237 let value
238 root.walkDecls(i => {
239 if (typeof i.raws.before !== 'undefined') {
240 value = i.raws.before
241 if (value.includes('\n')) {
242 value = value.replace(/[^\n]+$/, '')
243 }
244 return false
245 }
246 })
247 if (typeof value === 'undefined') {
248 value = this.raw(node, null, 'beforeRule')
249 } else if (value) {
250 value = value.replace(/\S/g, '')
251 }
252 return value
253 }
254
255 rawBeforeRule(root) {
256 let value
257 root.walk(i => {
258 if (i.nodes && (i.parent !== root || root.first !== i)) {
259 if (typeof i.raws.before !== 'undefined') {
260 value = i.raws.before
261 if (value.includes('\n')) {
262 value = value.replace(/[^\n]+$/, '')
263 }
264 return false
265 }
266 }
267 })
268 if (value) value = value.replace(/\S/g, '')
269 return value
270 }
271
272 rawBeforeClose(root) {
273 let value
274 root.walk(i => {
275 if (i.nodes && i.nodes.length > 0) {
276 if (typeof i.raws.after !== 'undefined') {
277 value = i.raws.after
278 if (value.includes('\n')) {
279 value = value.replace(/[^\n]+$/, '')
280 }
281 return false
282 }
283 }
284 })
285 if (value) value = value.replace(/\S/g, '')
286 return value
287 }
288
289 rawBeforeOpen(root) {
290 let value
291 root.walk(i => {
292 if (i.type !== 'decl') {
293 value = i.raws.between
294 if (typeof value !== 'undefined') return false
295 }
296 })
297 return value
298 }
299
300 rawColon(root) {
301 let value
302 root.walkDecls(i => {
303 if (typeof i.raws.between !== 'undefined') {
304 value = i.raws.between.replace(/[^\s:]/g, '')
305 return false
306 }
307 })
308 return value
309 }
310
311 beforeAfter(node, detect) {
312 let value
313 if (node.type === 'decl') {
314 value = this.raw(node, null, 'beforeDecl')
315 } else if (node.type === 'comment') {
316 value = this.raw(node, null, 'beforeComment')
317 } else if (detect === 'before') {
318 value = this.raw(node, null, 'beforeRule')
319 } else {
320 value = this.raw(node, null, 'beforeClose')
321 }
322
323 let buf = node.parent
324 let depth = 0
325 while (buf && buf.type !== 'root') {
326 depth += 1
327 buf = buf.parent
328 }
329
330 if (value.includes('\n')) {
331 let indent = this.raw(node, null, 'indent')
332 if (indent.length) {
333 for (let step = 0; step < depth; step++) value += indent
334 }
335 }
336
337 return value
338 }
339
340 rawValue(node, prop) {
341 let value = node[prop]
342 let raw = node.raws[prop]
343 if (raw && raw.value === value) {
344 return raw.raw
345 }
346
347 return value
348 }
349}
350
351module.exports = Stringifier
Note: See TracBrowser for help on using the repository browser.