Spaces:
Sleeping
Sleeping
File size: 2,825 Bytes
4cadbaf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import { SourceMapGenerator } from 'source-map'
import {
RawSourceMap,
VueTemplateCompiler,
VueTemplateCompilerParseOptions
} from './types'
const hash = require('hash-sum')
const cache = new (require('lru-cache'))(100)
const splitRE = /\r?\n/g
const emptyRE = /^(?:\/\/)?\s*$/
export interface ParseOptions {
source: string
filename?: string
compiler: VueTemplateCompiler
compilerParseOptions?: VueTemplateCompilerParseOptions
sourceRoot?: string
needMap?: boolean
}
export interface SFCCustomBlock {
type: string
content: string
attrs: { [key: string]: string | true }
start: number
end: number
map?: RawSourceMap
}
export interface SFCBlock extends SFCCustomBlock {
lang?: string
src?: string
scoped?: boolean
module?: string | boolean
}
export interface SFCDescriptor {
template: SFCBlock | null
script: SFCBlock | null
styles: SFCBlock[]
customBlocks: SFCCustomBlock[]
}
export function parse(options: ParseOptions): SFCDescriptor {
const {
source,
filename = '',
compiler,
compilerParseOptions = { pad: 'line' } as VueTemplateCompilerParseOptions,
sourceRoot = '',
needMap = true
} = options
const cacheKey = hash(
filename + source + JSON.stringify(compilerParseOptions)
)
let output: SFCDescriptor = cache.get(cacheKey)
if (output) return output
output = compiler.parseComponent(source, compilerParseOptions)
if (needMap) {
if (output.script && !output.script.src) {
output.script.map = generateSourceMap(
filename,
source,
output.script.content,
sourceRoot,
compilerParseOptions.pad
)
}
if (output.styles) {
output.styles.forEach(style => {
if (!style.src) {
style.map = generateSourceMap(
filename,
source,
style.content,
sourceRoot,
compilerParseOptions.pad
)
}
})
}
}
cache.set(cacheKey, output)
return output
}
function generateSourceMap(
filename: string,
source: string,
generated: string,
sourceRoot: string,
pad?: 'line' | 'space'
): RawSourceMap {
const map = new SourceMapGenerator({
file: filename.replace(/\\/g, '/'),
sourceRoot: sourceRoot.replace(/\\/g, '/')
})
let offset = 0
if (!pad) {
offset =
source
.split(generated)
.shift()!
.split(splitRE).length - 1
}
map.setSourceContent(filename, source)
generated.split(splitRE).forEach((line, index) => {
if (!emptyRE.test(line)) {
map.addMapping({
source: filename,
original: {
line: index + 1 + offset,
column: 0
},
generated: {
line: index + 1,
column: 0
}
})
}
})
return JSON.parse(map.toString())
}
|