+144
-6
lines changedFilter options
+144
-6
lines changed Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
1
+
/* @flow */
2
+
3
+
const range = 2
4
+
5
+
export function generateCodeFrame (
6
+
source: string,
7
+
start: number = 0,
8
+
end: number = source.length
9
+
): string {
10
+
const lines = source.split(/\r?\n/)
11
+
let count = 0
12
+
const res = []
13
+
for (let i = 0; i < lines.length; i++) {
14
+
count += lines[i].length + 1
15
+
if (count >= start) {
16
+
for (let j = i - range; j <= i + range || end > count; j++) {
17
+
if (j < 0 || j >= lines.length) continue
18
+
res.push(`${j + 1}${repeat(` `, 3 - String(j + 1).length)}| ${lines[j]}`)
19
+
const lineLength = lines[j].length
20
+
if (j === i) {
21
+
// push underline
22
+
const pad = start - (count - lineLength) + 1
23
+
const length = end > count ? lineLength - pad : end - start
24
+
res.push(` | ` + repeat(` `, pad) + repeat(`^`, length))
25
+
} else if (j > i) {
26
+
if (end > count) {
27
+
const length = Math.min(end - count, lineLength)
28
+
res.push(` | ` + repeat(`^`, length))
29
+
}
30
+
count += lineLength + 1
31
+
}
32
+
}
33
+
break
34
+
}
35
+
}
36
+
return res.join('\n')
37
+
}
38
+
39
+
function repeat (str, n) {
40
+
let result = ''
41
+
while (true) { // eslint-disable-line
42
+
if (n & 1) result += str
43
+
n >>>= 1
44
+
if (n <= 0) break
45
+
str += str
46
+
}
47
+
return result
48
+
}
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
2
2
3
3
import { noop, extend } from 'shared/util'
4
4
import { warn as baseWarn, tip } from 'core/util/debug'
5
+
import { generateCodeFrame } from './codeframe'
5
6
6
7
type CompiledFunctionResult = {
7
8
render: Function;
@@ -61,14 +62,28 @@ export function createCompileToFunctionFn (compile: Function): Function {
61
62
// check compilation errors/tips
62
63
if (process.env.NODE_ENV !== 'production') {
63
64
if (compiled.errors && compiled.errors.length) {
64
-
warn(
65
-
`Error compiling template:\n\n${template}\n\n` +
66
-
compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
67
-
vm
68
-
)
65
+
if (options.outputSourceRange) {
66
+
compiled.errors.forEach(e => {
67
+
warn(
68
+
`Error compiling template:\n\n${e.msg}\n\n` +
69
+
generateCodeFrame(template, e.start, e.end),
70
+
vm
71
+
)
72
+
})
73
+
} else {
74
+
warn(
75
+
`Error compiling template:\n\n${template}\n\n` +
76
+
compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
77
+
vm
78
+
)
79
+
}
69
80
}
70
81
if (compiled.tips && compiled.tips.length) {
71
-
compiled.tips.forEach(msg => tip(msg, vm))
82
+
if (options.outputSourceRange) {
83
+
compiled.tips.forEach(e => tip(e.msg, vm))
84
+
} else {
85
+
compiled.tips.forEach(msg => tip(msg, vm))
86
+
}
72
87
}
73
88
}
74
89
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@ Vue.prototype.$mount = function (
63
63
}
64
64
65
65
const { render, staticRenderFns } = compileToFunctions(template, {
66
+
outputSourceRange: process.env.NODE_ENV !== 'production',
66
67
shouldDecodeNewlines,
67
68
shouldDecodeNewlinesForHref,
68
69
delimiters: options.delimiters,
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
1
+
import { generateCodeFrame } from 'compiler/codeframe'
2
+
3
+
describe('codeframe', () => {
4
+
const source = `
5
+
<div>
6
+
<template key="one"></template>
7
+
<ul>
8
+
<li v-for="foobar">hi</li>
9
+
</ul>
10
+
<template key="two"></template>
11
+
</div>
12
+
`.trim()
13
+
14
+
it('line near top', () => {
15
+
const keyStart = source.indexOf(`key="one"`)
16
+
const keyEnd = keyStart + `key="one"`.length
17
+
expect(generateCodeFrame(source, keyStart, keyEnd)).toBe(`
18
+
1 | <div>
19
+
2 | <template key="one"></template>
20
+
| ^^^^^^^^^
21
+
3 | <ul>
22
+
4 | <li v-for="foobar">hi</li>
23
+
`.trim())
24
+
})
25
+
26
+
it('line in middle', () => {
27
+
// should cover 5 lines
28
+
const forStart = source.indexOf(`v-for=`)
29
+
const forEnd = forStart + `v-for="foobar"`.length
30
+
expect(generateCodeFrame(source, forStart, forEnd)).toBe(`
31
+
2 | <template key="one"></template>
32
+
3 | <ul>
33
+
4 | <li v-for="foobar">hi</li>
34
+
| ^^^^^^^^^^^^^^
35
+
5 | </ul>
36
+
6 | <template key="two"></template>
37
+
`.trim())
38
+
})
39
+
40
+
it('line near bottom', () => {
41
+
const keyStart = source.indexOf(`key="two"`)
42
+
const keyEnd = keyStart + `key="two"`.length
43
+
expect(generateCodeFrame(source, keyStart, keyEnd)).toBe(`
44
+
4 | <li v-for="foobar">hi</li>
45
+
5 | </ul>
46
+
6 | <template key="two"></template>
47
+
| ^^^^^^^^^
48
+
7 | </div>
49
+
`.trim())
50
+
})
51
+
52
+
it('multi-line highlights', () => {
53
+
const source = `
54
+
<div attr="some
55
+
multiline
56
+
attr
57
+
">
58
+
</div>
59
+
`.trim()
60
+
61
+
const attrStart = source.indexOf(`attr=`)
62
+
const attrEnd = source.indexOf(`">`) + 1
63
+
expect(generateCodeFrame(source, attrStart, attrEnd)).toBe(`
64
+
1 | <div attr="some
65
+
| ^^^^^^^^^^
66
+
2 | multiline
67
+
| ^^^^^^^^^^^
68
+
3 | attr
69
+
| ^^^^
70
+
4 | ">
71
+
| ^
72
+
`.trim())
73
+
})
74
+
})
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4