@@ -550,11 +550,10 @@ export function parseScriptElement(
550
550
parserOptions : ParserOptions ,
551
551
) : ESLintExtendedProgram {
552
552
const text = node . children [ 0 ]
553
- const offset =
553
+ const { code , offset } =
554
554
text != null && text . type === "VText"
555
- ? text . range [ 0 ]
556
- : node . startTag . range [ 1 ]
557
- const code = text != null && text . type === "VText" ? text . value : ""
555
+ ? { code : text . value , offset : text . range [ 0 ] }
556
+ : { code : "" , offset : node . startTag . range [ 1 ] }
558
557
const locationCalculator = globalLocationCalculator . getSubCalculatorAfter (
559
558
offset ,
560
559
)
@@ -566,14 +565,12 @@ export function parseScriptElement(
566
565
const startTag = node . startTag
567
566
const endTag = node . endTag
568
567
569
- if ( startTag != null ) {
570
- result . ast . tokens . unshift ( {
571
- type : "Punctuator" ,
572
- range : startTag . range ,
573
- loc : startTag . loc ,
574
- value : "<script>" ,
575
- } )
576
- }
568
+ result . ast . tokens . unshift ( {
569
+ type : "Punctuator" ,
570
+ range : startTag . range ,
571
+ loc : startTag . loc ,
572
+ value : "<script>" ,
573
+ } )
577
574
if ( endTag != null ) {
578
575
result . ast . tokens . push ( {
579
576
type : "Punctuator" ,
@@ -587,6 +584,126 @@ export function parseScriptElement(
587
584
return result
588
585
}
589
586
587
+ /**
588
+ * Parse the source code of the given `<script>` elements.
589
+ * @param nodes The `<script>` elements to parse.
590
+ * @param code The source code of SFC.
591
+ * @param globalLocationCalculatorWithoutGapOffsets The location calculator for fixLocations.
592
+ * @param parserOptions The parser options.
593
+ * @returns The result of parsing.
594
+ */
595
+ export function parseScriptElements (
596
+ nodes : VElement [ ] ,
597
+ code : string ,
598
+ globalLocationCalculatorWithoutGapOffsets : LocationCalculator ,
599
+ parserOptions : ParserOptions ,
600
+ ) : ESLintExtendedProgram {
601
+ let scriptCode = ""
602
+ let startOffset = 0
603
+ const tagTokens : Token [ ] = [ ]
604
+
605
+ let firstScriptTextNode : Token | null = null
606
+ for ( const node of nodes ) {
607
+ const scriptTextNode = node . children [ 0 ]
608
+ if ( scriptTextNode . type === "VText" ) {
609
+ const scriptText = code . slice ( ...scriptTextNode . range )
610
+ if ( ! scriptCode ) {
611
+ firstScriptTextNode = scriptTextNode
612
+ scriptCode += scriptText
613
+ } else {
614
+ const spaces = code
615
+ . slice ( startOffset , scriptTextNode . range [ 0 ] )
616
+ // eslint-disable-next-line require-unicode-regexp -- ignore u flag
617
+ . replace ( / [ ^ \n \r \u2028 \u2029 ] / g, " " )
618
+ scriptCode += spaces + scriptText
619
+ }
620
+ startOffset = scriptTextNode . range [ 1 ]
621
+
622
+ const startTag = node . startTag
623
+ const endTag = node . endTag
624
+ tagTokens . push ( {
625
+ type : "Punctuator" ,
626
+ range : startTag . range ,
627
+ loc : startTag . loc ,
628
+ value : "<script>" ,
629
+ } )
630
+ if ( endTag != null ) {
631
+ tagTokens . push ( {
632
+ type : "Punctuator" ,
633
+ range : endTag . range ,
634
+ loc : endTag . loc ,
635
+ value : "</script>" ,
636
+ } )
637
+ }
638
+ }
639
+ }
640
+ const offset =
641
+ firstScriptTextNode != null
642
+ ? firstScriptTextNode . range [ 0 ]
643
+ : nodes [ 0 ] . startTag . range [ 1 ]
644
+
645
+ const locationCalculator = globalLocationCalculatorWithoutGapOffsets . getSubCalculatorAfter (
646
+ offset ,
647
+ )
648
+ const result = parseScriptFragment (
649
+ scriptCode ,
650
+ locationCalculator ,
651
+ parserOptions ,
652
+ )
653
+
654
+ if ( result . ast . comments != null ) {
655
+ for ( const comment of result . ast . comments ) {
656
+ for ( const tagToken of tagTokens ) {
657
+ checkIntersect ( tagToken , comment )
658
+ }
659
+ }
660
+ }
661
+ if ( result . ast . tokens != null ) {
662
+ const newTokens : Token [ ] = [ ]
663
+ let tagToken = tagTokens . shift ( )
664
+ for ( const token of result . ast . tokens ) {
665
+ while ( tagToken && tagToken . range [ 0 ] < token . range [ 0 ] ) {
666
+ newTokens . push ( tagToken )
667
+ tagToken = tagTokens . shift ( )
668
+ }
669
+ checkIntersect ( tagToken , token )
670
+ newTokens . push ( token )
671
+ }
672
+ if ( tagToken ) {
673
+ newTokens . push ( tagToken , ...tagTokens )
674
+ }
675
+ result . ast . tokens = newTokens
676
+ }
677
+
678
+ return result
679
+
680
+ /**
681
+ * Check if the tokens intersect.
682
+ */
683
+ function checkIntersect ( tagToken : Token | undefined , token : Token ) {
684
+ if ( tagToken ) {
685
+ if (
686
+ token . range [ 0 ] < tagToken . range [ 0 ] &&
687
+ tagToken . range [ 0 ] < token . range [ 1 ]
688
+ ) {
689
+ throw new ParseError (
690
+ token . type === "Template"
691
+ ? "Unterminated template literal"
692
+ : token . type === "Block"
693
+ ? "Unterminated comment"
694
+ : token . type === "String"
695
+ ? "Unterminated string constant"
696
+ : `Unterminated '${ token . type } '` ,
697
+ undefined ,
698
+ tagToken . range [ 0 ] ,
699
+ tagToken . loc . start . line ,
700
+ tagToken . loc . start . column ,
701
+ )
702
+ }
703
+ }
704
+ }
705
+ }
706
+
590
707
/**
591
708
* Parse the source code of inline scripts.
592
709
* @param code The source code of inline scripts.
0 commit comments