@@ -17,39 +17,99 @@ const SAXParser = require("parse5").SAXParser
17
17
// Helpers
18
18
//------------------------------------------------------------------------------
19
19
20
+ const LINE_TERMINATORS = /\r\n|\r|\n|\u2028|\u2029/g
21
+
22
+ /**
23
+ * Calculates the end location.
24
+ *
25
+ * @param {string} raw - The text of the target token.
26
+ * @param {number} startLine - The start line of the target token.
27
+ * @param {number} startColumn - The start column of the target token.
28
+ * @returns {{line: number, column: number}} The end location.
29
+ * @private
30
+ */
31
+ function calcLocEnd(raw, startLine, startColumn) {
32
+ const lines = raw.split(LINE_TERMINATORS)
33
+ const line = startLine + lines.length - 1
34
+ const column = (lines.length === 1)
35
+ ? startColumn + raw.length
36
+ : lines[lines.length - 1].length
37
+
38
+ return {line, column}
39
+ }
40
+
41
+ /**
42
+ * Creates the token with the given parameters.
43
+ *
44
+ * @param {string} value - The token value to create.
45
+ * @param {string} text - The whole text.
46
+ * @param {object} location - The location object of `parse5` module.
47
+ * @returns {object} The created token object.
48
+ * @private
49
+ */
50
+ function createToken(value, text, location) {
51
+ const type = "Punctuator"
52
+ const start = location.startOffset
53
+ const end = location.endOffset
54
+ const line = location.line
55
+ const column = location.col - 1
56
+ const range = [start, end]
57
+ const raw = text.slice(start, end)
58
+ const loc = {
59
+ start: {line, column},
60
+ end: calcLocEnd(raw, line, column),
61
+ }
62
+
63
+ return {type, value, raw, start, end, range, loc}
64
+ }
65
+
20
66
/**
21
67
* Extracts the text of the 1st script element in the given text.
22
68
*
23
69
* @param {string} originalText - The whole text to extract.
24
70
* @returns {{text: string, offset: number}} The information of the 1st script.
71
+ * @private
25
72
*/
26
73
function extractFirstScript(originalText) {
27
74
const parser = new SAXParser({locationInfo: true})
28
- let inScript = false
75
+ let inTemplate = 0
76
+ let startToken = null
77
+ let endToken = null
29
78
let text = ""
30
79
let offset = 0
31
80
32
- parser.on("startTag", (name, attrs, selfClosing) => {
33
- if (name === "script" && !selfClosing) {
34
- inScript = true
81
+ parser.on("startTag", (name, attrs, selfClosing, location) => {
82
+ if (selfClosing) {
83
+ return
84
+ }
85
+ if (name === "template") {
86
+ inTemplate += 1
87
+ }
88
+ if (inTemplate === 0 && name === "script") {
89
+ startToken = createToken("<script>", originalText, location)
35
90
}
36
91
})
37
- parser.on("endTag", (name) => {
38
- if (name === "script") {
39
- inScript = false
92
+ parser.on("endTag", (name, location) => {
93
+ if (inTemplate > 0 && name === "template") {
94
+ inTemplate -= 1
95
+ }
96
+ if (startToken != null && name === "script") {
97
+ endToken = createToken("</script>", originalText, location)
98
+ parser.stop()
40
99
}
41
100
})
42
101
parser.on("text", (scriptText, location) => {
43
- if (inScript && text === "") {
44
- const lineTerminators = "\n".repeat(location.line - 1)
45
- const spaces = " ".repeat(location.startOffset - location.line + 1)
102
+ if (startToken != null) {
103
+ const countLines = location.line - 1
104
+ const lineTerminators = "\n".repeat(countLines)
105
+ const spaces = " ".repeat(location.startOffset - countLines)
46
106
text = `${spaces}${lineTerminators}${scriptText}`
47
107
offset = location.startOffset
48
108
}
49
109
})
50
110
parser.end(originalText)
51
111
52
- return {text, offset}
112
+ return {startToken, endToken, text, offset}
53
113
}
54
114
55
115
//------------------------------------------------------------------------------
@@ -77,6 +137,12 @@ module.exports.parse = function parse(text, options) {
77
137
const ast = espree.parse(script.text, options)
78
138
79
139
ast.start = script.offset
140
+ if (script.startToken) {
141
+ ast.tokens.unshift(script.startToken)
142
+ }
143
+ if (script.endToken) {
144
+ ast.tokens.push(script.endToken)
145
+ }
80
146
81
147
return ast
82
148
}
0 commit comments