wip: filters compat
This commit is contained in:
@@ -22,7 +22,7 @@ export const enum CompilerDeprecationTypes {
|
||||
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
|
||||
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
||||
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
||||
COMPILER_FILTER = 'COMPILER_FILTER'
|
||||
COMPILER_FILTERS = 'COMPILER_FILTER'
|
||||
}
|
||||
|
||||
type DeprecationData = {
|
||||
@@ -89,8 +89,11 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||
link: `https://v3.vuejs.org/guide/migration/inline-template-attribute.html`
|
||||
},
|
||||
|
||||
[CompilerDeprecationTypes.COMPILER_FILTER]: {
|
||||
message: `filters have been removed in Vue 3.`,
|
||||
[CompilerDeprecationTypes.COMPILER_FILTERS]: {
|
||||
message:
|
||||
`filters have been removed in Vue 3. ` +
|
||||
`The "|" symbol will be treated as native JavaScript bitwise OR operator. ` +
|
||||
`Use method calls or computed properties instead.`,
|
||||
link: `https://v3.vuejs.org/guide/migration/filters.html`
|
||||
}
|
||||
}
|
||||
|
||||
194
packages/compiler-core/src/compat/transformFilter.ts
Normal file
194
packages/compiler-core/src/compat/transformFilter.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
||||
import {
|
||||
AttributeNode,
|
||||
DirectiveNode,
|
||||
NodeTransform,
|
||||
NodeTypes,
|
||||
SimpleExpressionNode,
|
||||
toValidAssetId,
|
||||
TransformContext
|
||||
} from '@vue/compiler-core'
|
||||
import {
|
||||
CompilerDeprecationTypes,
|
||||
isCompatEnabled,
|
||||
warnDeprecation
|
||||
} from './compatConfig'
|
||||
import { ExpressionNode } from '../ast'
|
||||
|
||||
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||
|
||||
export const transformFilter: NodeTransform = (node, context) => {
|
||||
if (!isCompatEnabled(CompilerDeprecationTypes.COMPILER_FILTERS, context)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (node.type === NodeTypes.INTERPOLATION) {
|
||||
// filter rewrite is applied before expression transform so only
|
||||
// simple expressions are possible at this stage
|
||||
rewriteFilter(node.content, context)
|
||||
}
|
||||
|
||||
if (node.type === NodeTypes.ELEMENT) {
|
||||
node.props.forEach((prop: AttributeNode | DirectiveNode) => {
|
||||
if (
|
||||
prop.type === NodeTypes.DIRECTIVE &&
|
||||
prop.name !== 'for' &&
|
||||
prop.exp
|
||||
) {
|
||||
rewriteFilter(prop.exp, context)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteFilter(node: ExpressionNode, context: TransformContext) {
|
||||
if (node.type === NodeTypes.SIMPLE_EXPRESSION) {
|
||||
parseFilter(node, context)
|
||||
} else {
|
||||
for (let i = 0; i < node.children.length; i++) {
|
||||
const child = node.children[i]
|
||||
if (typeof child !== 'object') continue
|
||||
if (child.type === NodeTypes.SIMPLE_EXPRESSION) {
|
||||
parseFilter(child, context)
|
||||
} else if (child.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||
rewriteFilter(node, context)
|
||||
} else if (child.type === NodeTypes.INTERPOLATION) {
|
||||
rewriteFilter(child.content, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
||||
const exp = node.content
|
||||
let inSingle = false
|
||||
let inDouble = false
|
||||
let inTemplateString = false
|
||||
let inRegex = false
|
||||
let curly = 0
|
||||
let square = 0
|
||||
let paren = 0
|
||||
let lastFilterIndex = 0
|
||||
let c,
|
||||
prev,
|
||||
i: number,
|
||||
expression,
|
||||
filters: string[] = []
|
||||
|
||||
for (i = 0; i < exp.length; i++) {
|
||||
prev = c
|
||||
c = exp.charCodeAt(i)
|
||||
if (inSingle) {
|
||||
if (c === 0x27 && prev !== 0x5c) inSingle = false
|
||||
} else if (inDouble) {
|
||||
if (c === 0x22 && prev !== 0x5c) inDouble = false
|
||||
} else if (inTemplateString) {
|
||||
if (c === 0x60 && prev !== 0x5c) inTemplateString = false
|
||||
} else if (inRegex) {
|
||||
if (c === 0x2f && prev !== 0x5c) inRegex = false
|
||||
} else if (
|
||||
c === 0x7c && // pipe
|
||||
exp.charCodeAt(i + 1) !== 0x7c &&
|
||||
exp.charCodeAt(i - 1) !== 0x7c &&
|
||||
!curly &&
|
||||
!square &&
|
||||
!paren
|
||||
) {
|
||||
if (expression === undefined) {
|
||||
// first filter, end of expression
|
||||
lastFilterIndex = i + 1
|
||||
expression = exp.slice(0, i).trim()
|
||||
} else {
|
||||
pushFilter()
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case 0x22:
|
||||
inDouble = true
|
||||
break // "
|
||||
case 0x27:
|
||||
inSingle = true
|
||||
break // '
|
||||
case 0x60:
|
||||
inTemplateString = true
|
||||
break // `
|
||||
case 0x28:
|
||||
paren++
|
||||
break // (
|
||||
case 0x29:
|
||||
paren--
|
||||
break // )
|
||||
case 0x5b:
|
||||
square++
|
||||
break // [
|
||||
case 0x5d:
|
||||
square--
|
||||
break // ]
|
||||
case 0x7b:
|
||||
curly++
|
||||
break // {
|
||||
case 0x7d:
|
||||
curly--
|
||||
break // }
|
||||
}
|
||||
if (c === 0x2f) {
|
||||
// /
|
||||
let j = i - 1
|
||||
let p
|
||||
// find first non-whitespace prev char
|
||||
for (; j >= 0; j--) {
|
||||
p = exp.charAt(j)
|
||||
if (p !== ' ') break
|
||||
}
|
||||
if (!p || !validDivisionCharRE.test(p)) {
|
||||
inRegex = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (expression === undefined) {
|
||||
expression = exp.slice(0, i).trim()
|
||||
} else if (lastFilterIndex !== 0) {
|
||||
pushFilter()
|
||||
}
|
||||
|
||||
function pushFilter() {
|
||||
filters.push(exp.slice(lastFilterIndex, i).trim())
|
||||
lastFilterIndex = i + 1
|
||||
}
|
||||
|
||||
if (
|
||||
filters.length &&
|
||||
warnDeprecation(
|
||||
CompilerDeprecationTypes.COMPILER_FILTERS,
|
||||
context,
|
||||
node.loc
|
||||
)
|
||||
) {
|
||||
for (i = 0; i < filters.length; i++) {
|
||||
expression = wrapFilter(expression, filters[i], context)
|
||||
}
|
||||
node.content = expression
|
||||
}
|
||||
}
|
||||
|
||||
function wrapFilter(
|
||||
exp: string,
|
||||
filter: string,
|
||||
context: TransformContext
|
||||
): string {
|
||||
context.helper(RESOLVE_FILTER)
|
||||
const i = filter.indexOf('(')
|
||||
if (i < 0) {
|
||||
context.filters!.add(filter)
|
||||
return `${toValidAssetId(filter, 'filter')}(${exp})`
|
||||
} else {
|
||||
const name = filter.slice(0, i)
|
||||
const args = filter.slice(i + 1)
|
||||
context.filters!.add(name)
|
||||
return `${toValidAssetId(name, 'filter')}(${exp}${
|
||||
args !== ')' ? ',' + args : args
|
||||
}`
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user