import {
+ type DirectiveNode,
+ type ElementNode,
ElementTypes,
type IfBranchNode,
NodeTypes,
type SimpleExpressionNode,
type SlotsExpression,
+ type SourceLocation,
type TemplateChildNode,
createConditionalExpression,
createSimpleExpression,
} from '../ast'
import {
type NodeTransform,
+ type TransformContext,
createStructuralDirectiveTransform,
} from '../transform'
import {
export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
'skip',
(node, dir, context) => {
- const loc = dir.exp ? dir.exp.loc : node.loc
- if (isTemplateNode(node) || isSlotOutlet(node)) {
- context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
- return
- }
-
- if (findDir(node, 'for')) {
- context.onWarn(createCompilerError(ErrorCodes.X_V_SKIP_WITH_V_FOR, loc))
- }
-
- if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
- context.onError(
- createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc),
- )
- dir.exp = createSimpleExpression(`true`, false, loc)
- }
-
- if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
- dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
- }
-
- if (__DEV__ && __BROWSER__ && dir.exp) {
- validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
- }
-
- return () => {
- let children: TemplateChildNode[] = []
- // for components, extract default slot without props
- // if not found, throw an error
- if (node.tagType === ElementTypes.COMPONENT) {
- const codegenNode = node.codegenNode!
- if (codegenNode.type === NodeTypes.VNODE_CALL) {
- const genChildren = codegenNode.children! as SlotsExpression
- if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
- const prop = genChildren.properties.find(
- p =>
- p.type === NodeTypes.JS_PROPERTY &&
- p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
- p.key.content === 'default' &&
- p.value.params === undefined,
- )
- if (prop) {
- children = prop.value.returns as TemplateChildNode[]
- } else {
- context.onError(
- createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
+ return processSkip(node, dir, context, loc => {
+ return () => {
+ let children: TemplateChildNode[] = []
+ // for components, extract default slot without props
+ // if not found, throw an error
+ if (node.tagType === ElementTypes.COMPONENT) {
+ const codegenNode = node.codegenNode!
+ if (codegenNode.type === NodeTypes.VNODE_CALL) {
+ const genChildren = codegenNode.children! as SlotsExpression
+ if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
+ const prop = genChildren.properties.find(
+ p =>
+ p.type === NodeTypes.JS_PROPERTY &&
+ p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
+ p.key.content === 'default' &&
+ p.value.params === undefined,
)
+ if (prop) {
+ children = prop.value.returns as TemplateChildNode[]
+ } else {
+ context.onError(
+ createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
+ )
+ }
}
}
}
- }
- // for plain elements, take all children
- else {
- children = node.children
- }
- const consequent: IfBranchNode = {
- type: NodeTypes.IF_BRANCH,
- loc: node.loc,
- condition: undefined,
- children,
- userKey: findProp(node, `key`),
- }
+ // for plain elements, take all children
+ else {
+ children = node.children
+ }
+ const consequent: IfBranchNode = {
+ type: NodeTypes.IF_BRANCH,
+ loc: node.loc,
+ condition: undefined,
+ children,
+ userKey: findProp(node, `key`),
+ }
- const alternate: IfBranchNode = {
- type: NodeTypes.IF_BRANCH,
- loc: node.loc,
- condition: undefined,
- children: [node],
- userKey: findProp(node, `key`),
- }
+ const alternate: IfBranchNode = {
+ type: NodeTypes.IF_BRANCH,
+ loc: node.loc,
+ condition: undefined,
+ children: [node],
+ userKey: findProp(node, `key`),
+ }
- node.codegenNode = createConditionalExpression(
- dir.exp!,
- createCodegenNodeForBranch(consequent, 0, context),
- createCodegenNodeForBranch(alternate, 1, context),
- )
- }
+ node.codegenNode = createConditionalExpression(
+ dir.exp!,
+ createCodegenNodeForBranch(consequent, 0, context),
+ createCodegenNodeForBranch(alternate, 1, context),
+ )
+ }
+ })
},
)
+
+export function processSkip(
+ node: ElementNode,
+ dir: DirectiveNode,
+ context: TransformContext,
+ processCodegen?: (loc: SourceLocation) => () => void,
+): (() => void) | undefined {
+ const loc = dir.exp ? dir.exp.loc : node.loc
+ if (isTemplateNode(node) || isSlotOutlet(node)) {
+ context.onError(createCompilerError(ErrorCodes.X_V_SKIP_ON_TEMPLATE, loc))
+ return
+ }
+
+ if (findDir(node, 'for')) {
+ context.onError(createCompilerError(ErrorCodes.X_V_SKIP_WITH_V_FOR, loc))
+ }
+
+ if (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim()) {
+ context.onError(createCompilerError(ErrorCodes.X_V_SKIP_NO_EXPRESSION, loc))
+ dir.exp = createSimpleExpression(`true`, false, loc)
+ }
+
+ if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
+ dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)
+ }
+
+ if (__DEV__ && __BROWSER__ && dir.exp) {
+ validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
+ }
+
+ if (processCodegen) return processCodegen(loc)
+}