Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5d9c13b
wip: support vapor compile
ShenQingchuan Jul 13, 2025
f5c290e
wip: support vapor highlight and add demo
ShenQingchuan Jul 14, 2025
03e0324
wip: language service changes for vapor
ShenQingchuan Jul 14, 2025
5da89b0
wip: add vapor interop e2e test case
ShenQingchuan Jul 14, 2025
813eb16
wip: add guide for how to enable vapor in docs
ShenQingchuan Jul 14, 2025
5bb5231
wip: fix some pitfalls
ShenQingchuan Jul 14, 2025
604a56d
wip: fix vue-vine main package peer dep
ShenQingchuan Jul 14, 2025
200ebe1
wip: fix empty value pitfalls
ShenQingchuan Jul 14, 2025
95a7018
wip: fix transform assets url in vuejs/core#13623
ShenQingchuan Jul 14, 2025
6bb2def
wip: improve lowlight vapor tag
ShenQingchuan Jul 15, 2025
482532c
wip: add test case for SHOULD_ADD_SUFFIX_REGEXP
ShenQingchuan Jul 15, 2025
262bcdc
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Jul 16, 2025
2f77366
feat: add transform srcset
ShenQingchuan Jul 17, 2025
1944a16
fix: implementation for srcset statically hoist
ShenQingchuan Jul 17, 2025
2780956
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Jul 17, 2025
e38b1de
Merge branches 'feat/vine-vapor' and 'main' of https://github.com/vue…
ShenQingchuan Jul 20, 2025
8d751a2
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Jul 21, 2025
a8eaf4b
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Jul 21, 2025
89ce517
feat: support use vapor directive
ShenQingchuan Jul 21, 2025
51543ce
chore(e2e): add image loaded test check
ShenQingchuan Jul 21, 2025
d3a8b16
test: add typecheck and lint output snapshot
ShenQingchuan Jul 22, 2025
ec19ff9
chore: add minor,major for local-ext-pack [ci skip]
ShenQingchuan Jul 22, 2025
fab73b0
test(e2e): add remote assets url test cases
ShenQingchuan Jul 22, 2025
a1f3eb7
chore: use explicit tsgo version number
ShenQingchuan Jul 22, 2025
67282d6
test(e2e): remove userland path prefix in snapshot
ShenQingchuan Jul 22, 2025
275aff6
fix: use common path functions for windows
ShenQingchuan Jul 22, 2025
30e5b3d
fix: use strict template in vue-vine-tsc
ShenQingchuan Jul 22, 2025
c2d15fd
fix: remove path posix import
ShenQingchuan Jul 22, 2025
564b2e6
fix: remove another path posix import
ShenQingchuan Jul 22, 2025
f2c68f8
fix: normalize reference path sepatators
ShenQingchuan Jul 22, 2025
2f3932f
fix: add gitattributes for eol as LF
ShenQingchuan Jul 22, 2025
979fe28
fix: join search text in path.sep
ShenQingchuan Jul 22, 2025
1794bf5
test(e2e): wait a few seconds for remote img loading
ShenQingchuan Jul 22, 2025
a0e806b
test(e2e): change image loaded check implementation
ShenQingchuan Jul 22, 2025
3fcf56f
fix(lang-service): avoid duplicate references in scoped class names
ShenQingchuan Jul 23, 2025
4a2d31b
test(e2e): add vineEmits test cases
ShenQingchuan Jul 23, 2025
1da0979
fix(lang-service): gurantee using pipeline for completions list
ShenQingchuan Jul 23, 2025
54c00aa
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Jul 23, 2025
eb9e497
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 2, 2025
9c10c3e
enhance(lang-service): performance improve for generate virtual code
ShenQingchuan Aug 8, 2025
5410ef5
Merge branch 'fix/improve-compiler-arch' of https://github.com/vue-vi…
ShenQingchuan Aug 8, 2025
6eaccf9
Merge branch 'main' of https://github.com/vue-vine/vue-vine into temp…
ShenQingchuan Aug 8, 2025
e3f74ef
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
24c22a3
fix: snapshot needs update
ShenQingchuan Aug 12, 2025
fd862d5
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
530e482
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
e9eccba
Merge branch 'main' into feat/vine-vapor
ShenQingchuan Aug 12, 2025
8e7fb61
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
f8bcf6c
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
28de59a
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 12, 2025
2d83980
chore(ci): do not use shell env syntax in windows
ShenQingchuan Aug 12, 2025
5274062
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 13, 2025
774b8a4
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 17, 2025
7295a69
Merge branch 'main' of https://github.com/vue-vine/vue-vine into feat…
ShenQingchuan Aug 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default antfu(
'dist',
'pnpm-lock.yaml',

'packages/docs/.vitepress/cache',
'packages/docs/**/*',
'packages/e2e-test/**/*.vine.ts',
'packages/create-vue-vine/template/**/*',
'packages/nuxt-module/playground/*',
Expand Down
2 changes: 2 additions & 0 deletions packages/compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
"dependencies": {
"@babel/parser": "catalog:compiler",
"@babel/types": "catalog:compiler",
"@vue/compiler-core": "catalog:vue-libs",
"@vue/compiler-dom": "catalog:vue-libs",
"@vue/compiler-ssr": "catalog:vue-libs",
"@vue/compiler-vapor": "catalog:vue-libs",
"@vue/shared": "catalog:vue-libs",
"get-tsconfig": "catalog:compiler",
"hash-sum": "catalog:utils",
Expand Down
33 changes: 33 additions & 0 deletions packages/compiler/src/analyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
ObjectPattern,
Statement,
StringLiteral,
TaggedTemplateExpression,
TSFunctionType,
TSPropertySignature,
TSTypeAnnotation,
Expand Down Expand Up @@ -92,6 +93,7 @@ import {
isVineSlots,
isVineStyle,
isVineValidators,
isVineVaporTaggedTemplateString,
tryInferExpressionTSType,
} from './babel-helpers/ast'
import { DEFAULT_MODEL_MODIFIERS_NAME, SUPPORTED_STYLE_FILE_EXTS, VineBindingTypes } from './constants'
Expand Down Expand Up @@ -1166,6 +1168,36 @@ function analyzeFileImportStmts(
vineFileCtx.importsLastLine = lastImportStmt.loc
}

/**
* Check if the function is a Vapor Vine component function
* @param fnItselfNode - The function AST node itself
* @param templateStringNode - The template string node
* @returns True if the function is a Vapor Vine component function, false otherwise
*/
function isVaporVineCompFn(
fnItselfNode: BabelFunctionNodeTypes | undefined,
templateStringNode: TaggedTemplateExpression | undefined,
): boolean {
// function MyComp() {
// 'use vapor'
// }
if (fnItselfNode && isBlockStatement(fnItselfNode.body)) {
const hasUseVaporDirective = fnItselfNode.body.directives?.some(
directive => directive.value.value === 'use vapor',
)
if (hasUseVaporDirective) {
return true
}
}

// return vine.vapor`...`
if (templateStringNode && isVineVaporTaggedTemplateString(templateStringNode)) {
return true
}

return false
}

function buildVineCompFnCtx(
vineCompilerHooks: VineCompilerHooks,
vineFileCtx: VineFileCtx,
Expand Down Expand Up @@ -1193,6 +1225,7 @@ function buildVineCompFnCtx(
isExportDefault: isExportDefaultDeclaration(fnDeclNode),
isAsync: fnItselfNode?.async ?? false,
isCustomElement: false,
isVapor: isVaporVineCompFn(fnItselfNode, templateStringNode),
fnName,
scopeId,
fnDeclNode,
Expand Down
26 changes: 22 additions & 4 deletions packages/compiler/src/babel-helpers/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,32 @@ export function isDescendant(node: Node, potentialDescendant: Node): boolean {
return false
}

export function isVineTaggedTemplateString(node: Node | null | undefined): node is TaggedTemplateExpression {
export function isVineVaporTaggedTemplateString(node: TaggedTemplateExpression): boolean {
return (
isTaggedTemplateExpression(node)
&& isIdentifier(node.tag)
&& node.tag.name === 'vine'
isMemberExpression(node.tag)
&& isIdentifier(node.tag.object)
&& node.tag.object.name === 'vine'
&& isIdentifier(node.tag.property)
&& node.tag.property.name === 'vapor'
)
}

export function isVineTaggedTemplateString(node: Node | null | undefined): node is TaggedTemplateExpression {
if (!node || !isTaggedTemplateExpression(node)) {
return false
}

// vine`...` or vine.vapor`...`
if (isIdentifier(node.tag) && node.tag.name === 'vine') {
return true
}
if (isVineVaporTaggedTemplateString(node)) {
return true
}

return false
}

export function isVineMacroCallExpression(node: Node): node is CallExpression {
if (isCallExpression(node)) {
const calleeName = getVineMacroCalleeName(node)
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { BindingTypes as VueBindingTypes } from '@vue/compiler-dom'

export const DEFINE_COMPONENT_HELPER = 'defineComponent'
export const DEFINE_VAPOR_COMPONENT_HELPER = 'defineVaporComponent'
export const DEFINE_CUSTOM_ELEMENT_HELPER = 'defineCustomElement'
export const USE_DEFAULTS_HELPER = 'useDefaults'
export const TO_REFS_HELPER = 'toRefs'
Expand Down
176 changes: 126 additions & 50 deletions packages/compiler/src/template/compose.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import type { SourceLocation as BabelSourceLocation, ExportNamedDeclaration, ImportDeclaration, Node } from '@babel/types'
import type { AttributeNode, BindingTypes, CodegenResult, CompilerOptions, NodeTransform, SourceLocation as VueSourceLocation } from '@vue/compiler-dom'
import type { VineCompFnCtx, VineCompilerHooks, VineCompilerOptions, VineFileCtx } from '../types'
import type { BaseCodegenResult, CompilerOptions, RootNode, SimpleExpressionNode } from '@vue/compiler-core'
import type { AttributeNode, BindingTypes, CodegenResult as VDOMCodegenResult, SourceLocation as VueSourceLocation } from '@vue/compiler-dom'
import type { VaporCodegenResult } from '@vue/compiler-vapor'
import type { VineCompFnCtx, VineCompilerHooks, VineFileCtx } from '../types'
import type { ImportItem } from './transform-asset-url'
import { isExportNamedDeclaration, isFunctionDeclaration, isIdentifier, isImportDeclaration, isImportDefaultSpecifier, isImportSpecifier } from '@babel/types'
import { compile, ElementTypes, NodeTypes, parse } from '@vue/compiler-dom'
import { compile as ssrCompile } from '@vue/compiler-ssr'
import { compile as compileVDOM, ElementTypes, NodeTypes, parse as vdomParse } from '@vue/compiler-dom'
import { compile as compileSSR } from '@vue/compiler-ssr'
import { compile as compileVapor, parse as vaporParse } from '@vue/compiler-vapor'
import lineColumn from 'line-column'
import { babelParse } from '../babel-helpers/parse'
import { VineBindingTypes } from '../constants'
import { vineErr, vineWarn } from '../diagnostics'
import { appendToMapArray } from '../utils'
import { transformAssetUrl } from './transform-asset-url'
import { transformBooleanProp } from './transform-negative-bool'
import { getTransformNegativeBoolPlugin } from './transform-negative-bool'
import { transformSrcset } from './transform-srcset'
import { walkVueTemplateAst } from './walk'

const SHOULD_ADD_SUFFIX_REGEXP = /(?<=<[^>/]+)$/
const SHOULD_ADD_SUFFIX_REGEXP = /(?<=<[a-z][^>/]*)$/i
const basicCompilerOptions = {
mode: 'module',
hoistStatic: true,
cacheHandlers: true,
prefixIdentifiers: true,
inline: true,
} as const

function toPascalCase(str: string) {
return str.replace(/(?:^|-)(\w)/g, (_, c) => c.toUpperCase())
}

export function postProcessForRenderCodegen(codegen: string): string {
return codegen
// https://github.com/vue-vine/vue-vine/issues/171
Expand All @@ -32,16 +45,36 @@ export function postProcessForRenderCodegen(codegen: string): string {
)
}

function getTransformNegativeBoolPlugin(
transformNegativeBool: Required<VineCompilerOptions>['vueCompilerOptions']['__transformNegativeBool'],
): NodeTransform[] {
if (typeof transformNegativeBool === 'object') {
return [transformBooleanProp({ constType: transformNegativeBool.constType })]
function getTemplateParsedAst(
vineCompFnCtx: VineCompFnCtx,
getParsedAst: boolean,
) {
if (!getParsedAst) {
return
}

return [transformBooleanProp()]
const _parse = vineCompFnCtx.isVapor
? vaporParse
: vdomParse

return {
templateParsedAst: _parse(vineCompFnCtx.templateSource, {
parseMode: 'base',
prefixIdentifiers: true,
expressionPlugins: ['typescript'],
}),
}
}

type TemplateCompileFn = (
src: string | RootNode,
options?: CompilerOptions
) => BaseCodegenResult
type VineCompileResult
= (VaporCodegenResult | VDOMCodegenResult)
& { templateParsedAst?: RootNode }
& { imports?: ImportItem[] }

export function compileVineTemplate(
vineCompFnCtx: VineCompFnCtx,
compilerHooks: VineCompilerHooks,
Expand All @@ -51,56 +84,80 @@ export function compileVineTemplate(
getParsedAst?: boolean
},
): (
CodegenResult
& { templateParsedAst?: ReturnType<typeof parse> }
BaseCodegenResult
& { templateParsedAst?: RootNode }
& { imports?: ImportItem[] }
) | null {
const _compile = ssr ? ssrCompile : compile
const { volar = false } = compilerHooks.getCompilerCtx()?.options ?? {}
const {
__enableTransformAssetsURL = true,
__transformNegativeBool,
__shouldAddTemplateSuffix,
} = compilerHooks.getCompilerCtx()
?.options
?.vueCompilerOptions ?? {}

try {
// vue/language-tools / #4583:
if (
__shouldAddTemplateSuffix
&& SHOULD_ADD_SUFFIX_REGEXP.test(vineCompFnCtx.templateSource)
) {
if (volar && SHOULD_ADD_SUFFIX_REGEXP.test(vineCompFnCtx.templateSource)) {
vineCompFnCtx.templateSource += '>'
}

return {
..._compile(vineCompFnCtx.templateSource, {
mode: 'module',
hoistStatic: true,
cacheHandlers: true,
prefixIdentifiers: true,
inline: true,
nodeTransforms: [
...(__enableTransformAssetsURL
? [transformAssetUrl]
: []
),
...getTransformNegativeBoolPlugin(
__transformNegativeBool,
),
],
...params,
}),
templateParsedAst: (
getParsedAst
? parse(vineCompFnCtx.templateSource, {
parseMode: 'base',
prefixIdentifiers: true,
expressionPlugins: [
'typescript',
],
})
: (void 0)
const nodeTransforms = [
...(__enableTransformAssetsURL
? [transformAssetUrl, transformSrcset]
: []
),
getTransformNegativeBoolPlugin(
__transformNegativeBool,
),
]

const compile = (
ssr
? (compileSSR as TemplateCompileFn)
: vineCompFnCtx.isVapor && !volar
? (compileVapor as TemplateCompileFn)
: compileVDOM
)

try {
const compileOptions = {
...basicCompilerOptions,
...params,
nodeTransforms: nodeTransforms.concat(
params.nodeTransforms ?? [],
),
}

const codegenResult = compile(
vineCompFnCtx.templateSource,
compileOptions,
)
const templateParsedAst = getTemplateParsedAst(
vineCompFnCtx,
getParsedAst,
)
const imports = vineCompFnCtx.isVapor
? ((codegenResult as VaporCodegenResult).ast).imports
: (codegenResult as VDOMCodegenResult).ast.imports

return {
...codegenResult,
imports,
...templateParsedAst,
}
}
catch (error) {
compilerHooks.onError(
vineErr(
{
vineCompFnCtx,
vineFileCtx: vineCompFnCtx.fileCtx,
},
{ msg: (error as Error).stack ?? String(error) },
),
)
return null
}
}
catch {
Expand Down Expand Up @@ -250,7 +307,16 @@ function setVineTemplateAst(
vineCompFnCtx: VineCompFnCtx,
compileResult: ReturnType<typeof compileVineTemplate>,
) {
const { ast, templateParsedAst } = compileResult!
const vineCompileResult = compileResult! as VineCompileResult
const { templateParsedAst } = vineCompileResult!
let ast = vineCompileResult!.ast

// Vapor mode's `ast` is `RootIRNode`
// but we need `RootNode`
if ('node' in ast) {
ast = ast.node
}

vineCompFnCtx.templateAst = ast
vineCompFnCtx.templateParsedAst = templateParsedAst

Expand Down Expand Up @@ -367,7 +433,17 @@ export function createSeparatedTemplateComposer(
return ''
}

const { code } = compileResult
const { code, imports } = compileResult

if (vineCompFnCtx.isVapor && imports) {
for (const assetImport of imports) {
mergedImportsMap.set(assetImport.path, {
type: 'defaultSpecifier',
localName: (assetImport.exp as SimpleExpressionNode).content,
})
}
}

const generatedCodeAst = babelParse(code)

// Find all import statements and store specifiers
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/template/import-usage-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function resolveTemplateUsedIdentifiers(

const ids = new Set<string>()

templateParsedAst!.children.forEach(walk)
templateParsedAst?.children.forEach(walk)

function walk(node: TemplateChildNode) {
switch (node.type) {
Expand Down
Loading
Loading