feat: support component-level compilerOptions
when using runtime compiler
- The `delimiters` component option is deprecated. Use `compilerOptions.delimiters` instead.
This commit is contained in:
parent
e486254431
commit
ce0bbe053a
@ -578,6 +578,13 @@ function setupStatefulComponent(
|
|||||||
validateDirectiveName(names[i])
|
validateDirectiveName(names[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Component.compilerOptions && isRuntimeOnly()) {
|
||||||
|
warn(
|
||||||
|
`"compilerOptions" is only supported when using a build of Vue that ` +
|
||||||
|
`includes the runtime compiler. Since you are using a runtime-only ` +
|
||||||
|
`build, the options should be passed via your build tool config instead.`
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 0. create render proxy property access cache
|
// 0. create render proxy property access cache
|
||||||
instance.accessCache = Object.create(null)
|
instance.accessCache = Object.create(null)
|
||||||
@ -728,12 +735,19 @@ export function finishComponentSetup(
|
|||||||
startMeasure(instance, `compile`)
|
startMeasure(instance, `compile`)
|
||||||
}
|
}
|
||||||
const { isCustomElement, compilerOptions } = instance.appContext.config
|
const { isCustomElement, compilerOptions } = instance.appContext.config
|
||||||
|
const {
|
||||||
|
delimiters,
|
||||||
|
compilerOptions: componentCompilerOptions
|
||||||
|
} = Component
|
||||||
const finalCompilerOptions: CompilerOptions = extend(
|
const finalCompilerOptions: CompilerOptions = extend(
|
||||||
|
extend(
|
||||||
{
|
{
|
||||||
isCustomElement: isCustomElement || NO,
|
isCustomElement,
|
||||||
delimiters: Component.delimiters
|
delimiters
|
||||||
},
|
},
|
||||||
compilerOptions
|
compilerOptions
|
||||||
|
),
|
||||||
|
componentCompilerOptions
|
||||||
)
|
)
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
// pass runtime compat config into the compiler
|
// pass runtime compat config into the compiler
|
||||||
|
@ -150,6 +150,9 @@ export interface ComponentOptionsBase<
|
|||||||
expose?: string[]
|
expose?: string[]
|
||||||
serverPrefetch?(): Promise<any>
|
serverPrefetch?(): Promise<any>
|
||||||
|
|
||||||
|
// Runtime compiler only -----------------------------------------------------
|
||||||
|
compilerOptions?: RuntimeCompilerOptions
|
||||||
|
|
||||||
// Internal ------------------------------------------------------------------
|
// Internal ------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,6 +206,16 @@ export interface ComponentOptionsBase<
|
|||||||
__defaults?: Defaults
|
__defaults?: Defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of compiler options that makes sense for the runtime.
|
||||||
|
*/
|
||||||
|
export interface RuntimeCompilerOptions {
|
||||||
|
isCustomElement?: (tag: string) => boolean
|
||||||
|
whitespace?: 'preserve' | 'condense'
|
||||||
|
comments?: boolean
|
||||||
|
delimiters?: [string, string]
|
||||||
|
}
|
||||||
|
|
||||||
export type ComponentOptionsWithoutProps<
|
export type ComponentOptionsWithoutProps<
|
||||||
Props = {},
|
Props = {},
|
||||||
RawBindings = {},
|
RawBindings = {},
|
||||||
@ -446,7 +459,10 @@ interface LegacyOptions<
|
|||||||
renderTriggered?: DebuggerHook
|
renderTriggered?: DebuggerHook
|
||||||
errorCaptured?: ErrorCapturedHook
|
errorCaptured?: ErrorCapturedHook
|
||||||
|
|
||||||
// runtime compile only
|
/**
|
||||||
|
* runtime compile only
|
||||||
|
* @deprecated use `compilerOptions.delimiters` instead.
|
||||||
|
*/
|
||||||
delimiters?: [string, string]
|
delimiters?: [string, string]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,7 +179,8 @@ export {
|
|||||||
ComponentOptionsBase,
|
ComponentOptionsBase,
|
||||||
RenderFunction,
|
RenderFunction,
|
||||||
MethodOptions,
|
MethodOptions,
|
||||||
ComputedOptions
|
ComputedOptions,
|
||||||
|
RuntimeCompilerOptions
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
export { EmitsOptions, ObjectEmitsOptions } from './componentEmits'
|
export { EmitsOptions, ObjectEmitsOptions } from './componentEmits'
|
||||||
export {
|
export {
|
||||||
|
104
packages/vue/__tests__/runtimeCompilerOptions.spec.ts
Normal file
104
packages/vue/__tests__/runtimeCompilerOptions.spec.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
|
||||||
|
describe('config.compilerOptions', () => {
|
||||||
|
test('isCustomElement', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<foo/>`
|
||||||
|
})
|
||||||
|
app.config.compilerOptions.isCustomElement = (tag: string) => tag === 'foo'
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.innerHTML).toBe('<foo></foo>')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('comments', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<div/><!--test--><div/>`
|
||||||
|
})
|
||||||
|
app.config.compilerOptions.comments = true
|
||||||
|
// the comments option is only relevant in production mode
|
||||||
|
__DEV__ = false
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.innerHTML).toBe('<div></div><!--test--><div></div>')
|
||||||
|
__DEV__ = true
|
||||||
|
})
|
||||||
|
|
||||||
|
test('whitespace', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<div><span/>\n <span/></div>`
|
||||||
|
})
|
||||||
|
app.config.compilerOptions.whitespace = 'preserve'
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.firstChild!.childNodes.length).toBe(3)
|
||||||
|
expect(root.firstChild!.childNodes[1].nodeType).toBe(Node.TEXT_NODE)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('delimiters', () => {
|
||||||
|
const app = createApp({
|
||||||
|
data: () => ({ foo: 'hi' }),
|
||||||
|
template: `[[ foo ]]`
|
||||||
|
})
|
||||||
|
app.config.compilerOptions.delimiters = [`[[`, `]]`]
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.textContent).toBe('hi')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('per-component compilerOptions', () => {
|
||||||
|
test('isCustomElement', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<foo/>`,
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag: string) => tag === 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.innerHTML).toBe('<foo></foo>')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('comments', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<div/><!--test--><div/>`,
|
||||||
|
compilerOptions: {
|
||||||
|
comments: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.config.compilerOptions.comments = false
|
||||||
|
// the comments option is only relevant in production mode
|
||||||
|
__DEV__ = false
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.innerHTML).toBe('<div></div><!--test--><div></div>')
|
||||||
|
__DEV__ = true
|
||||||
|
})
|
||||||
|
|
||||||
|
test('whitespace', () => {
|
||||||
|
const app = createApp({
|
||||||
|
template: `<div><span/>\n <span/></div>`,
|
||||||
|
compilerOptions: {
|
||||||
|
whitespace: 'preserve'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.firstChild!.childNodes.length).toBe(3)
|
||||||
|
expect(root.firstChild!.childNodes[1].nodeType).toBe(Node.TEXT_NODE)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('delimiters', () => {
|
||||||
|
const app = createApp({
|
||||||
|
data: () => ({ foo: 'hi' }),
|
||||||
|
template: `[[ foo ]]`,
|
||||||
|
compilerOptions: {
|
||||||
|
delimiters: [`[[`, `]]`]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const root = document.createElement('div')
|
||||||
|
app.mount(root)
|
||||||
|
expect(root.textContent).toBe('hi')
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user