Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 1 | 'use strict' |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 2 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 3 | let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') |
| 4 | let { existsSync, readFileSync } = require('fs') |
| 5 | let { dirname, join } = require('path') |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 6 | |
| 7 | function fromBase64(str) { |
| 8 | if (Buffer) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 9 | return Buffer.from(str, 'base64').toString() |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 10 | } else { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 11 | // istanbul ignore next |
| 12 | return window.atob(str) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 13 | } |
| 14 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 15 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 16 | class PreviousMap { |
| 17 | constructor(css, opts) { |
| 18 | if (opts.map === false) return |
| 19 | this.loadAnnotation(css) |
| 20 | this.inline = this.startWith(this.annotation, 'data:') |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 21 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 22 | let prev = opts.map ? opts.map.prev : undefined |
| 23 | let text = this.loadMap(opts.from, prev) |
| 24 | if (!this.mapFile && opts.from) { |
| 25 | this.mapFile = opts.from |
| 26 | } |
| 27 | if (this.mapFile) this.root = dirname(this.mapFile) |
| 28 | if (text) this.text = text |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 29 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 30 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 31 | consumer() { |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 32 | if (!this.consumerCache) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 33 | this.consumerCache = new SourceMapConsumer(this.text) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 34 | } |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 35 | return this.consumerCache |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 36 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 37 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 38 | withContent() { |
| 39 | return !!( |
| 40 | this.consumer().sourcesContent && |
| 41 | this.consumer().sourcesContent.length > 0 |
| 42 | ) |
| 43 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 44 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 45 | startWith(string, start) { |
| 46 | if (!string) return false |
| 47 | return string.substr(0, start.length) === start |
| 48 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 49 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 50 | getAnnotationURL(sourceMapString) { |
| 51 | return sourceMapString.replace(/^\/\*\s*# sourceMappingURL=/, '').trim() |
| 52 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 53 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 54 | loadAnnotation(css) { |
| 55 | let comments = css.match(/\/\*\s*# sourceMappingURL=/gm) |
| 56 | if (!comments) return |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 57 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 58 | // sourceMappingURLs from comments, strings, etc. |
| 59 | let start = css.lastIndexOf(comments.pop()) |
| 60 | let end = css.indexOf('*/', start) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 61 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 62 | if (start > -1 && end > -1) { |
| 63 | // Locate the last sourceMappingURL to avoid pickin |
| 64 | this.annotation = this.getAnnotationURL(css.substring(start, end)) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 65 | } |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 66 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 67 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 68 | decodeInline(text) { |
| 69 | let baseCharsetUri = /^data:application\/json;charset=utf-?8;base64,/ |
| 70 | let baseUri = /^data:application\/json;base64,/ |
| 71 | let charsetUri = /^data:application\/json;charset=utf-?8,/ |
| 72 | let uri = /^data:application\/json,/ |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 73 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 74 | if (charsetUri.test(text) || uri.test(text)) { |
| 75 | return decodeURIComponent(text.substr(RegExp.lastMatch.length)) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | if (baseCharsetUri.test(text) || baseUri.test(text)) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 79 | return fromBase64(text.substr(RegExp.lastMatch.length)) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 80 | } |
| 81 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 82 | let encoding = text.match(/data:application\/json;([^,]+),/)[1] |
| 83 | throw new Error('Unsupported source map encoding ' + encoding) |
| 84 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 85 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 86 | loadFile(path) { |
| 87 | this.root = dirname(path) |
| 88 | if (existsSync(path)) { |
| 89 | this.mapFile = path |
| 90 | return readFileSync(path, 'utf-8').toString().trim() |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | loadMap(file, prev) { |
| 95 | if (prev === false) return false |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 96 | |
| 97 | if (prev) { |
| 98 | if (typeof prev === 'string') { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 99 | return prev |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 100 | } else if (typeof prev === 'function') { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 101 | let prevPath = prev(file) |
| 102 | if (prevPath) { |
| 103 | let map = this.loadFile(prevPath) |
| 104 | if (!map) { |
| 105 | throw new Error( |
| 106 | 'Unable to load previous source map: ' + prevPath.toString() |
| 107 | ) |
| 108 | } |
| 109 | return map |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 110 | } |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 111 | } else if (prev instanceof SourceMapConsumer) { |
| 112 | return SourceMapGenerator.fromSourceMap(prev).toString() |
| 113 | } else if (prev instanceof SourceMapGenerator) { |
| 114 | return prev.toString() |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 115 | } else if (this.isMap(prev)) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 116 | return JSON.stringify(prev) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 117 | } else { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 118 | throw new Error( |
| 119 | 'Unsupported previous source map format: ' + prev.toString() |
| 120 | ) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 121 | } |
| 122 | } else if (this.inline) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 123 | return this.decodeInline(this.annotation) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 124 | } else if (this.annotation) { |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 125 | let map = this.annotation |
| 126 | if (file) map = join(dirname(file), map) |
| 127 | return this.loadFile(map) |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 128 | } |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 129 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 130 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 131 | isMap(map) { |
| 132 | if (typeof map !== 'object') return false |
| 133 | return ( |
| 134 | typeof map.mappings === 'string' || |
| 135 | typeof map._mappings === 'string' || |
| 136 | Array.isArray(map.sections) |
| 137 | ) |
| 138 | } |
| 139 | } |
Mathias Bynens | 79e2cf0 | 2020-05-29 16:46:17 +0200 | [diff] [blame] | 140 | |
Tim van der Lippe | 16b8228 | 2021-11-08 13:50:26 +0000 | [diff] [blame] | 141 | module.exports = PreviousMap |
| 142 | PreviousMap.default = PreviousMap |