feat(compiler-core): add allowSideEffectTag option

By default, the compiler drops `<script>` and `<style>` tags from SFC files. There are good use cases for these tags (like generating stylesheets based on some refs or application state).

I see no documented reason to not allow a bypass if the user knows what's doing, so that's why I'm adding this new option

Signed-off-by: GitHub <noreply@github.com>
This commit is contained in:
Fernando Fernández 2024-06-20 19:23:39 +00:00 committed by GitHub
parent dadb3632a0
commit 42f4ccceda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 24 additions and 1 deletions

View File

@ -230,6 +230,12 @@ export interface TransformOptions
* @default null * @default null
*/ */
transformHoist?: HoistTransform | null transformHoist?: HoistTransform | null
/**
* Allow `<script>` and `<style>` tags inside the template of SFC files.
* Disabled by default to avoid unintentionally adding side effects into the application.
* @default false
*/
allowSideEffectTags?: boolean
/** /**
* If the pairing runtime provides additional built-in elements, use this to * If the pairing runtime provides additional built-in elements, use this to
* mark them as built-in so the compiler will generate component vnodes * mark them as built-in so the compiler will generate component vnodes

View File

@ -128,6 +128,7 @@ export function createTransformContext(
root: RootNode, root: RootNode,
{ {
filename = '', filename = '',
allowSideEffectTags = false,
prefixIdentifiers = false, prefixIdentifiers = false,
hoistStatic = false, hoistStatic = false,
hmr = false, hmr = false,
@ -156,6 +157,7 @@ export function createTransformContext(
// options // options
filename, filename,
selfName: nameMatch && capitalize(camelize(nameMatch[1])), selfName: nameMatch && capitalize(camelize(nameMatch[1])),
allowSideEffectTags,
prefixIdentifiers, prefixIdentifiers,
hoistStatic, hoistStatic,
hmr, hmr,

View File

@ -13,6 +13,13 @@ describe('compiler: ignore side effect tags', () => {
expect(err!.message).toMatch(`Tags with side effect`) expect(err!.message).toMatch(`Tags with side effect`)
}) })
it('should allow script when allowSideEffectTags is true', () => {
const { code } = compile(`<script>console.log(1)</script>`, {
allowSideEffectTags: true,
})
expect(code).toMatch('script')
})
it('should ignore style', () => { it('should ignore style', () => {
let err: CompilerError | undefined let err: CompilerError | undefined
const { code } = compile(`<style>h1 { color: red }</style>`, { const { code } = compile(`<style>h1 { color: red }</style>`, {
@ -24,4 +31,11 @@ describe('compiler: ignore side effect tags', () => {
expect(err).toBeDefined() expect(err).toBeDefined()
expect(err!.message).toMatch(`Tags with side effect`) expect(err!.message).toMatch(`Tags with side effect`)
}) })
it('should allow style when allowSideEffectTags is true', () => {
const { code } = compile(`<style>h1 { color: red }</style>`, {
allowSideEffectTags: true,
})
expect(code).toMatch('style')
})
}) })

View File

@ -5,7 +5,8 @@ export const ignoreSideEffectTags: NodeTransform = (node, context) => {
if ( if (
node.type === NodeTypes.ELEMENT && node.type === NodeTypes.ELEMENT &&
node.tagType === ElementTypes.ELEMENT && node.tagType === ElementTypes.ELEMENT &&
(node.tag === 'script' || node.tag === 'style') (node.tag === 'script' || node.tag === 'style') &&
!context.allowSideEffectTags
) { ) {
__DEV__ && __DEV__ &&
context.onError( context.onError(