@@ -58,6 +58,7 @@ import type {
5858 CustomTemplateTokenizer ,
5959 CustomTemplateTokenizerConstructor ,
6060} from "./custom-tokenizer"
61+ import { isScriptSetupElement , isTSLang } from "../common/ast-utils"
6162
6263const DIRECTIVE_NAME = / ^ (?: v - | [ . : @ # ] ) .* [ ^ . : @ # ] $ / u
6364const DT_DD = / ^ d [ d t ] $ / u
@@ -178,8 +179,10 @@ export class Parser {
178179 private document : VDocumentFragment
179180 private elementStack : VElement [ ]
180181 private vPreElement : VElement | null
181- private postProcessesForScript : ( ( parserOptions : ParserOptions ) => void ) [ ] =
182- [ ]
182+ private postProcessesForScript : ( (
183+ htmlParserOptions : ParserOptions ,
184+ scriptParserOptions : ParserOptions ,
185+ ) => void ) [ ] = [ ]
183186
184187 /**
185188 * The source code text.
@@ -290,7 +293,7 @@ export class Parser {
290293
291294 const doc = this . document
292295
293- const parserOptions = {
296+ const htmlParserOptions = {
294297 ...this . baseParserOptions ,
295298 parser : getScriptParser (
296299 this . baseParserOptions . parser ,
@@ -300,8 +303,14 @@ export class Parser {
300303 } ,
301304 ) ,
302305 }
306+ const scriptParserOptions = {
307+ ...this . baseParserOptions ,
308+ parser : getScriptParser ( this . baseParserOptions . parser , ( ) =>
309+ getParserLangFromSFC ( doc ) ,
310+ ) ,
311+ }
303312 for ( const proc of this . postProcessesForScript ) {
304- proc ( parserOptions )
313+ proc ( htmlParserOptions , scriptParserOptions )
305314 }
306315 this . postProcessesForScript = [ ]
307316
@@ -449,24 +458,18 @@ export class Parser {
449458 * @param namespace The current namespace.
450459 */
451460 private processAttribute ( node : VAttribute , namespace : Namespace ) : void {
452- const tagName = this . getTagName ( node . parent . parent )
453- const attrName = this . getTagName ( node . key )
454-
455- if (
456- ( this . expressionEnabled ||
457- ( attrName === "v-pre" && ! this . isInVPreElement ) ) &&
458- ( DIRECTIVE_NAME . test ( attrName ) ||
459- attrName === "slot-scope" ||
460- ( tagName === "template" && attrName === "scope" ) )
461- ) {
462- this . postProcessesForScript . push ( ( parserOptions ) => {
463- convertToDirective (
464- this . text ,
465- parserOptions ,
466- this . locationCalculator ,
467- node ,
468- )
469- } )
461+ if ( this . needConvertToDirective ( node ) ) {
462+ this . postProcessesForScript . push (
463+ ( parserOptions , scriptParserOptions ) => {
464+ convertToDirective (
465+ this . text ,
466+ parserOptions ,
467+ scriptParserOptions ,
468+ this . locationCalculator ,
469+ node ,
470+ )
471+ } ,
472+ )
470473 return
471474 }
472475
@@ -480,6 +483,35 @@ export class Parser {
480483 this . reportParseError ( node , "x-invalid-namespace" )
481484 }
482485 }
486+ /**
487+ * Checks whether the given attribute node is need convert to directive.
488+ * @param node The node to check
489+ */
490+ private needConvertToDirective ( node : VAttribute ) {
491+ const element = node . parent . parent
492+ const tagName = this . getTagName ( element )
493+ const attrName = this . getTagName ( node . key )
494+
495+ if (
496+ attrName === "generic" &&
497+ element . parent . type === "VDocumentFragment" &&
498+ isScriptSetupElement ( element ) &&
499+ isTSLang ( element )
500+ ) {
501+ return true
502+ }
503+ const expressionEnabled =
504+ this . expressionEnabled ||
505+ ( attrName === "v-pre" && ! this . isInVPreElement )
506+ if ( ! expressionEnabled ) {
507+ return false
508+ }
509+ return (
510+ DIRECTIVE_NAME . test ( attrName ) ||
511+ attrName === "slot-scope" ||
512+ ( tagName === "template" && attrName === "scope" )
513+ )
514+ }
483515
484516 /**
485517 * Process the given template text token with a configured template tokenizer, based on language.
0 commit comments