@@ -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