Skip to content

Commit 48f1260

Browse files
committed
chore: add compiler-vapor
1 parent 49fac6d commit 48f1260

19 files changed

+1898
-3
lines changed

.prettierrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true,
4+
"trailingComma": "all"
5+
}

.vscode/settings.json

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
11
{
2-
"eslint.experimental.useFlatConfig": true
2+
// Use the project's typescript version
3+
"typescript.tsdk": "node_modules/typescript/lib",
4+
5+
"cSpell.enabledLanguageIds": ["markdown", "plaintext", "text", "yml"],
6+
7+
// Use prettier to format typescript, javascript and JSON files
8+
"editor.formatOnSave": true,
9+
"[typescript]": {
10+
"editor.defaultFormatter": "esbenp.prettier-vscode"
11+
},
12+
"[javascript]": {
13+
"editor.defaultFormatter": "esbenp.prettier-vscode"
14+
},
15+
"[json]": {
16+
"editor.defaultFormatter": "esbenp.prettier-vscode"
17+
}
318
}

eslint.config.js

+134-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,135 @@
1-
import antfu from '@antfu/eslint-config'
1+
const { builtinModules } = require('node:module')
22

3-
export default antfu()
3+
const DOMGlobals = ['window', 'document']
4+
const NodeGlobals = ['module', 'require']
5+
6+
const banConstEnum = {
7+
selector: 'TSEnumDeclaration[const=true]',
8+
message:
9+
'Please use non-const enums. This project automatically inlines enums.',
10+
}
11+
12+
/**
13+
* @type {import('eslint-define-config').ESLintConfig}
14+
*/
15+
module.exports = {
16+
parser: '@typescript-eslint/parser',
17+
parserOptions: {
18+
sourceType: 'module',
19+
},
20+
plugins: ['jest', 'import', '@typescript-eslint'],
21+
rules: {
22+
'no-debugger': 'error',
23+
'no-console': ['error', { allow: ['warn', 'error', 'info'] }],
24+
// most of the codebase are expected to be env agnostic
25+
'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],
26+
27+
'no-restricted-syntax': [
28+
'error',
29+
banConstEnum,
30+
// since we target ES2015 for baseline support, we need to forbid object
31+
// rest spread usage in destructure as it compiles into a verbose helper.
32+
'ObjectPattern > RestElement',
33+
// tsc compiles assignment spread into Object.assign() calls, but esbuild
34+
// still generates verbose helpers, so spread assignment is also prohiboted
35+
'ObjectExpression > SpreadElement',
36+
'AwaitExpression',
37+
],
38+
'sort-imports': ['error', { ignoreDeclarationSort: true }],
39+
40+
'import/no-nodejs-modules': [
41+
'error',
42+
{ allow: builtinModules.map(mod => `node:${mod}`) },
43+
],
44+
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
45+
// code to indicate intentional type errors, improving code clarity and maintainability.
46+
'@typescript-eslint/prefer-ts-expect-error': 'error',
47+
// Enforce the use of 'import type' for importing types
48+
'@typescript-eslint/consistent-type-imports': [
49+
'error',
50+
{
51+
fixStyle: 'inline-type-imports',
52+
disallowTypeAnnotations: false,
53+
},
54+
],
55+
// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers
56+
'@typescript-eslint/no-import-type-side-effects': 'error',
57+
},
58+
overrides: [
59+
// tests, no restrictions (runs in Node / jest with jsdom)
60+
{
61+
files: ['**/__tests__/**', 'packages/dts-test/**'],
62+
rules: {
63+
'no-console': 'off',
64+
'no-restricted-globals': 'off',
65+
'no-restricted-syntax': 'off',
66+
'jest/no-disabled-tests': 'error',
67+
'jest/no-focused-tests': 'error',
68+
},
69+
},
70+
// shared, may be used in any env
71+
{
72+
files: ['packages/shared/**', '.eslintrc.cjs'],
73+
rules: {
74+
'no-restricted-globals': 'off',
75+
},
76+
},
77+
// Packages targeting DOM
78+
{
79+
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
80+
rules: {
81+
'no-restricted-globals': ['error', ...NodeGlobals],
82+
},
83+
},
84+
// Packages targeting Node
85+
{
86+
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
87+
rules: {
88+
'no-restricted-globals': ['error', ...DOMGlobals],
89+
'no-restricted-syntax': ['error', banConstEnum],
90+
},
91+
},
92+
// Private package, browser only + no syntax restrictions
93+
{
94+
files: [
95+
'packages/template-explorer/**',
96+
'packages/sfc-playground/**',
97+
'playground/**',
98+
],
99+
rules: {
100+
'no-restricted-globals': ['error', ...NodeGlobals],
101+
'no-restricted-syntax': ['error', banConstEnum],
102+
'no-console': 'off',
103+
},
104+
},
105+
// JavaScript files
106+
{
107+
files: ['*.js', '*.cjs'],
108+
rules: {
109+
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
110+
'no-unused-vars': ['error', { vars: 'all', args: 'none' }],
111+
},
112+
},
113+
// Node scripts
114+
{
115+
files: [
116+
'scripts/**',
117+
'./*.{js,ts}',
118+
'packages/*/*.js',
119+
'packages/vue/*/*.js',
120+
],
121+
rules: {
122+
'no-restricted-globals': 'off',
123+
'no-restricted-syntax': ['error', banConstEnum],
124+
'no-console': 'off',
125+
},
126+
},
127+
// Import nodejs modules in compiler-sfc
128+
{
129+
files: ['packages/compiler-sfc/src/**'],
130+
rules: {
131+
'import/no-nodejs-modules': ['error', { allow: builtinModules }],
132+
},
133+
},
134+
],
135+
}

src/core/compiler/compile.ts

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import {
2+
type CompilerOptions as BaseCompilerOptions,
3+
type CodegenResult,
4+
ErrorCodes,
5+
type RootNode,
6+
createCompilerError,
7+
defaultOnError,
8+
parse,
9+
} from '@vue/compiler-dom'
10+
import { extend, isString } from '@vue/shared'
11+
import {
12+
type DirectiveTransform,
13+
type NodeTransform,
14+
transform,
15+
} from './transform'
16+
import { generate } from './generate'
17+
import { transformOnce } from './transforms/vOnce'
18+
import { transformElement } from './transforms/transformElement'
19+
import { transformVHtml } from './transforms/vHtml'
20+
import { transformVText } from './transforms/vText'
21+
import { transformVBind } from './transforms/vBind'
22+
import { transformVOn } from './transforms/vOn'
23+
import { transformVShow } from './transforms/vShow'
24+
import { transformInterpolation } from './transforms/transformInterpolation'
25+
import type { HackOptions } from './ir'
26+
27+
export type CompilerOptions = HackOptions<BaseCompilerOptions>
28+
29+
// TODO: copied from @vue/compiler-core
30+
// code/AST -> IR -> JS codegen
31+
export function compile(
32+
source: string | RootNode,
33+
options: CompilerOptions = {},
34+
): CodegenResult {
35+
const onError = options.onError || defaultOnError
36+
const isModuleMode = options.mode === 'module'
37+
/* istanbul ignore if */
38+
if (__BROWSER__) {
39+
if (options.prefixIdentifiers === true) {
40+
onError(createCompilerError(ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED))
41+
} else if (isModuleMode) {
42+
onError(createCompilerError(ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED))
43+
}
44+
}
45+
46+
const prefixIdentifiers =
47+
!__BROWSER__ && (options.prefixIdentifiers === true || isModuleMode)
48+
49+
// TODO scope id
50+
// if (options.scopeId && !isModuleMode) {
51+
// onError(createCompilerError(ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED))
52+
// }
53+
54+
const resolvedOptions = extend({}, options, {
55+
prefixIdentifiers,
56+
})
57+
const ast = isString(source) ? parse(source, resolvedOptions) : source
58+
const [nodeTransforms, directiveTransforms] =
59+
getBaseTransformPreset(prefixIdentifiers)
60+
61+
if (!__BROWSER__ && options.isTS) {
62+
const { expressionPlugins } = options
63+
if (!expressionPlugins || !expressionPlugins.includes('typescript')) {
64+
options.expressionPlugins = [...(expressionPlugins || []), 'typescript']
65+
}
66+
}
67+
68+
const ir = transform(
69+
ast,
70+
extend({}, options, {
71+
nodeTransforms: [
72+
...nodeTransforms,
73+
...(options.nodeTransforms || []), // user transforms
74+
],
75+
directiveTransforms: extend(
76+
{},
77+
directiveTransforms,
78+
options.directiveTransforms || {}, // user transforms
79+
),
80+
}),
81+
)
82+
83+
return generate(ir, resolvedOptions)
84+
}
85+
86+
export type TransformPreset = [
87+
NodeTransform[],
88+
Record<string, DirectiveTransform>,
89+
]
90+
91+
export function getBaseTransformPreset(
92+
prefixIdentifiers?: boolean,
93+
): TransformPreset {
94+
return [
95+
[transformOnce, transformInterpolation, transformElement],
96+
{
97+
bind: transformVBind,
98+
on: transformVOn,
99+
html: transformVHtml,
100+
text: transformVText,
101+
show: transformVShow,
102+
},
103+
]
104+
}

src/core/compiler/errors.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {
2+
type CompilerError,
3+
type SourceLocation,
4+
createCompilerError,
5+
} from '@vue/compiler-dom'
6+
7+
export interface VaporCompilerError extends CompilerError {
8+
code: VaporErrorCodes
9+
}
10+
11+
export function createVaporCompilerError(
12+
code: VaporErrorCodes,
13+
loc?: SourceLocation,
14+
) {
15+
return createCompilerError(
16+
code,
17+
loc,
18+
__DEV__ || !__BROWSER__ ? VaporErrorMessages : undefined,
19+
) as VaporCompilerError
20+
}
21+
22+
export enum VaporErrorCodes {
23+
X_V_PLACEHOLDER = 100,
24+
__EXTEND_POINT__,
25+
}
26+
27+
export const VaporErrorMessages: Record<VaporErrorCodes, string> = {
28+
[VaporErrorCodes.X_V_PLACEHOLDER]: `[placeholder]`,
29+
30+
// just to fulfill types
31+
[VaporErrorCodes.__EXTEND_POINT__]: ``,
32+
}

0 commit comments

Comments
 (0)