@@ -17,39 +17,99 @@ const SAXParser = require("parse5").SAXParser
1717// Helpers
1818//------------------------------------------------------------------------------
1919
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+
2066/**
2167 * Extracts the text of the 1st script element in the given text.
2268 *
2369 * @param {string } originalText - The whole text to extract.
2470 * @returns {{text: string, offset: number} } The information of the 1st script.
71+ * @private
2572 */
2673function extractFirstScript ( originalText ) {
2774 const parser = new SAXParser ( { locationInfo : true } )
28- let inScript = false
75+ let inTemplate = 0
76+ let startToken = null
77+ let endToken = null
2978 let text = ""
3079 let offset = 0
3180
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 )
3590 }
3691 } )
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 ( )
4099 }
41100 } )
42101 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 )
46106 text = `${ spaces } ${ lineTerminators } ${ scriptText } `
47107 offset = location . startOffset
48108 }
49109 } )
50110 parser . end ( originalText )
51111
52- return { text, offset}
112+ return { startToken , endToken , text, offset}
53113}
54114
55115//------------------------------------------------------------------------------
@@ -77,6 +137,12 @@ module.exports.parse = function parse(text, options) {
77137 const ast = espree . parse ( script . text , options )
78138
79139 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+ }
80146
81147 return ast
82148}
0 commit comments