source: trip-planner-front/node_modules/postcss/lib/map-generator.js@ b738035

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

initial commit

  • Property mode set to 100644
File size: 7.5 KB
Line 
1'use strict'
2
3let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js')
4let { dirname, resolve, relative, sep } = require('path')
5let { pathToFileURL } = require('url')
6
7let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator)
8let pathAvailable = Boolean(dirname && resolve && relative && sep)
9
10class MapGenerator {
11 constructor(stringify, root, opts) {
12 this.stringify = stringify
13 this.mapOpts = opts.map || {}
14 this.root = root
15 this.opts = opts
16 }
17
18 isMap() {
19 if (typeof this.opts.map !== 'undefined') {
20 return !!this.opts.map
21 }
22 return this.previous().length > 0
23 }
24
25 previous() {
26 if (!this.previousMaps) {
27 this.previousMaps = []
28 this.root.walk(node => {
29 if (node.source && node.source.input.map) {
30 let map = node.source.input.map
31 if (!this.previousMaps.includes(map)) {
32 this.previousMaps.push(map)
33 }
34 }
35 })
36 }
37
38 return this.previousMaps
39 }
40
41 isInline() {
42 if (typeof this.mapOpts.inline !== 'undefined') {
43 return this.mapOpts.inline
44 }
45
46 let annotation = this.mapOpts.annotation
47 if (typeof annotation !== 'undefined' && annotation !== true) {
48 return false
49 }
50
51 if (this.previous().length) {
52 return this.previous().some(i => i.inline)
53 }
54 return true
55 }
56
57 isSourcesContent() {
58 if (typeof this.mapOpts.sourcesContent !== 'undefined') {
59 return this.mapOpts.sourcesContent
60 }
61 if (this.previous().length) {
62 return this.previous().some(i => i.withContent())
63 }
64 return true
65 }
66
67 clearAnnotation() {
68 if (this.mapOpts.annotation === false) return
69
70 let node
71 for (let i = this.root.nodes.length - 1; i >= 0; i--) {
72 node = this.root.nodes[i]
73 if (node.type !== 'comment') continue
74 if (node.text.indexOf('# sourceMappingURL=') === 0) {
75 this.root.removeChild(i)
76 }
77 }
78 }
79
80 setSourcesContent() {
81 let already = {}
82 this.root.walk(node => {
83 if (node.source) {
84 let from = node.source.input.from
85 if (from && !already[from]) {
86 already[from] = true
87 this.map.setSourceContent(
88 this.toUrl(this.path(from)),
89 node.source.input.css
90 )
91 }
92 }
93 })
94 }
95
96 applyPrevMaps() {
97 for (let prev of this.previous()) {
98 let from = this.toUrl(this.path(prev.file))
99 let root = prev.root || dirname(prev.file)
100 let map
101
102 if (this.mapOpts.sourcesContent === false) {
103 map = new SourceMapConsumer(prev.text)
104 if (map.sourcesContent) {
105 map.sourcesContent = map.sourcesContent.map(() => null)
106 }
107 } else {
108 map = prev.consumer()
109 }
110
111 this.map.applySourceMap(map, from, this.toUrl(this.path(root)))
112 }
113 }
114
115 isAnnotation() {
116 if (this.isInline()) {
117 return true
118 }
119 if (typeof this.mapOpts.annotation !== 'undefined') {
120 return this.mapOpts.annotation
121 }
122 if (this.previous().length) {
123 return this.previous().some(i => i.annotation)
124 }
125 return true
126 }
127
128 toBase64(str) {
129 if (Buffer) {
130 return Buffer.from(str).toString('base64')
131 } else {
132 // istanbul ignore next
133 return window.btoa(unescape(encodeURIComponent(str)))
134 }
135 }
136
137 addAnnotation() {
138 let content
139
140 if (this.isInline()) {
141 content =
142 'data:application/json;base64,' + this.toBase64(this.map.toString())
143 } else if (typeof this.mapOpts.annotation === 'string') {
144 content = this.mapOpts.annotation
145 } else if (typeof this.mapOpts.annotation === 'function') {
146 content = this.mapOpts.annotation(this.opts.to, this.root)
147 } else {
148 content = this.outputFile() + '.map'
149 }
150
151 let eol = '\n'
152 if (this.css.includes('\r\n')) eol = '\r\n'
153
154 this.css += eol + '/*# sourceMappingURL=' + content + ' */'
155 }
156
157 outputFile() {
158 if (this.opts.to) {
159 return this.path(this.opts.to)
160 }
161 if (this.opts.from) {
162 return this.path(this.opts.from)
163 }
164 return 'to.css'
165 }
166
167 generateMap() {
168 this.generateString()
169 if (this.isSourcesContent()) this.setSourcesContent()
170 if (this.previous().length > 0) this.applyPrevMaps()
171 if (this.isAnnotation()) this.addAnnotation()
172
173 if (this.isInline()) {
174 return [this.css]
175 }
176 return [this.css, this.map]
177 }
178
179 path(file) {
180 if (file.indexOf('<') === 0) return file
181 if (/^\w+:\/\//.test(file)) return file
182 if (this.mapOpts.absolute) return file
183
184 let from = this.opts.to ? dirname(this.opts.to) : '.'
185
186 if (typeof this.mapOpts.annotation === 'string') {
187 from = dirname(resolve(from, this.mapOpts.annotation))
188 }
189
190 file = relative(from, file)
191 return file
192 }
193
194 toUrl(path) {
195 if (sep === '\\') {
196 // istanbul ignore next
197 path = path.replace(/\\/g, '/')
198 }
199 return encodeURI(path).replace(/[#?]/g, encodeURIComponent)
200 }
201
202 sourcePath(node) {
203 if (this.mapOpts.from) {
204 return this.toUrl(this.mapOpts.from)
205 } else if (this.mapOpts.absolute) {
206 if (pathToFileURL) {
207 return pathToFileURL(node.source.input.from).toString()
208 } else {
209 // istanbul ignore next
210 throw new Error(
211 '`map.absolute` option is not available in this PostCSS build'
212 )
213 }
214 } else {
215 return this.toUrl(this.path(node.source.input.from))
216 }
217 }
218
219 generateString() {
220 this.css = ''
221 this.map = new SourceMapGenerator({ file: this.outputFile() })
222
223 let line = 1
224 let column = 1
225
226 let noSource = '<no source>'
227 let mapping = {
228 source: '',
229 generated: { line: 0, column: 0 },
230 original: { line: 0, column: 0 }
231 }
232
233 let lines, last
234 this.stringify(this.root, (str, node, type) => {
235 this.css += str
236
237 if (node && type !== 'end') {
238 mapping.generated.line = line
239 mapping.generated.column = column - 1
240 if (node.source && node.source.start) {
241 mapping.source = this.sourcePath(node)
242 mapping.original.line = node.source.start.line
243 mapping.original.column = node.source.start.column - 1
244 this.map.addMapping(mapping)
245 } else {
246 mapping.source = noSource
247 mapping.original.line = 1
248 mapping.original.column = 0
249 this.map.addMapping(mapping)
250 }
251 }
252
253 lines = str.match(/\n/g)
254 if (lines) {
255 line += lines.length
256 last = str.lastIndexOf('\n')
257 column = str.length - last
258 } else {
259 column += str.length
260 }
261
262 if (node && type !== 'start') {
263 let p = node.parent || { raws: {} }
264 if (node.type !== 'decl' || node !== p.last || p.raws.semicolon) {
265 if (node.source && node.source.end) {
266 mapping.source = this.sourcePath(node)
267 mapping.original.line = node.source.end.line
268 mapping.original.column = node.source.end.column - 1
269 mapping.generated.line = line
270 mapping.generated.column = column - 2
271 this.map.addMapping(mapping)
272 } else {
273 mapping.source = noSource
274 mapping.original.line = 1
275 mapping.original.column = 0
276 mapping.generated.line = line
277 mapping.generated.column = column - 1
278 this.map.addMapping(mapping)
279 }
280 }
281 }
282 })
283 }
284
285 generate() {
286 this.clearAnnotation()
287
288 if (pathAvailable && sourceMapAvailable && this.isMap()) {
289 return this.generateMap()
290 }
291
292 let result = ''
293 this.stringify(this.root, i => {
294 result += i
295 })
296 return [result]
297 }
298}
299
300module.exports = MapGenerator
Note: See TracBrowser for help on using the repository browser.