Skip to content

Commit 1ade268

Browse files
committed
chore: temp commit
1 parent 28a3fbc commit 1ade268

File tree

6 files changed

+206
-2
lines changed

6 files changed

+206
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"@vitest/coverage-c8": "^0.31.1",
121121
"@vitest/ui": "^0.31.1",
122122
"@vue/compiler-sfc": "^3.3.4",
123+
"@vue/compiler-dom": "^3.3.4",
123124
"bumpp": "^9.1.0",
124125
"cross-env": "^7.0.3",
125126
"eslint": "^8.41.0",

packages/core/parser/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export * from './parser-variable'
22
export * from './parser-import'
33
export * from './parser-vbind-m'
44
export { parserCompiledSfc } from './parser-compiled-sfc'
5+
export { analyzeScriptBindings as parseScriptBindings } from './parser-script-bindings'
56
export type { IParseSFCRes } from './parser-compiled-sfc'
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import {
2+
ArrayExpression,
3+
Node,
4+
ObjectExpression,
5+
Statement
6+
} from '@babel/types'
7+
import { BindingMetadata } from '@vue/compiler-dom'
8+
import { CSSVarsBindingTypes } from "./utils";
9+
10+
/**
11+
* Analyze bindings in normal `<script>`
12+
* Note that `compileScriptSetup` already analyzes bindings as part of its
13+
* compilation process so this should only be used on single `<script>` SFCs.
14+
*/
15+
export function analyzeScriptBindings(ast: Statement[]): BindingMetadata {
16+
for (const node of ast) {
17+
if (
18+
node.type === 'ExportDefaultDeclaration' &&
19+
node.declaration.type === 'ObjectExpression'
20+
) {
21+
return analyzeBindingsFromOptions(node.declaration)
22+
}
23+
}
24+
return {}
25+
}
26+
27+
function analyzeBindingsFromOptions(node: ObjectExpression): BindingMetadata {
28+
const bindings: BindingMetadata = {}
29+
// #3270, #3275
30+
// mark non-script-setup so we don't resolve components/directives from these
31+
Object.defineProperty(bindings, '__isScriptSetup', {
32+
enumerable: false,
33+
value: false
34+
})
35+
for (const property of node.properties) {
36+
if (
37+
property.type === 'ObjectProperty' &&
38+
!property.computed &&
39+
property.key.type === 'Identifier'
40+
) {
41+
// props
42+
if (property.key.name === 'props') {
43+
// props: ['foo']
44+
// props: { foo: ... }
45+
for (const key of getObjectOrArrayExpressionKeys(property.value)) {
46+
bindings[key] = CSSVarsBindingTypes.PROPS
47+
}
48+
}
49+
50+
// inject
51+
else if (property.key.name === 'inject') {
52+
// inject: ['foo']
53+
// inject: { foo: {} }
54+
for (const key of getObjectOrArrayExpressionKeys(property.value)) {
55+
bindings[key] = CSSVarsBindingTypes.OPTIONS
56+
}
57+
}
58+
59+
// computed & methods
60+
else if (
61+
property.value.type === 'ObjectExpression' &&
62+
(property.key.name === 'computed' || property.key.name === 'methods')
63+
) {
64+
// methods: { foo() {} }
65+
// computed: { foo() {} }
66+
for (const key of getObjectExpressionKeys(property.value)) {
67+
bindings[key] = CSSVarsBindingTypes.OPTIONS
68+
}
69+
}
70+
}
71+
72+
// setup & data
73+
else if (
74+
property.type === 'ObjectMethod' &&
75+
property.key.type === 'Identifier' &&
76+
(property.key.name === 'setup' || property.key.name === 'data')
77+
) {
78+
for (const bodyItem of property.body.body) {
79+
// setup() {
80+
// return {
81+
// foo: null
82+
// }
83+
// }
84+
if (
85+
bodyItem.type === 'ReturnStatement' &&
86+
bodyItem.argument &&
87+
bodyItem.argument.type === 'ObjectExpression'
88+
) {
89+
for (const key of getObjectExpressionKeys(bodyItem.argument)) {
90+
bindings[key] =
91+
property.key.name === 'setup'
92+
? CSSVarsBindingTypes.SETUP_MAYBE_REF
93+
: CSSVarsBindingTypes.DATA
94+
}
95+
}
96+
}
97+
}
98+
}
99+
100+
return bindings
101+
}
102+
103+
function getObjectExpressionKeys(node: ObjectExpression): string[] {
104+
const keys = []
105+
for (const prop of node.properties) {
106+
if (prop.type === 'SpreadElement') continue
107+
const key = resolveObjectKey(prop.key, prop.computed)
108+
if (key) keys.push(String(key))
109+
}
110+
return keys
111+
}
112+
113+
function getArrayExpressionKeys(node: ArrayExpression): string[] {
114+
const keys = []
115+
for (const element of node.elements) {
116+
if (element && element.type === 'StringLiteral') {
117+
keys.push(element.value)
118+
}
119+
}
120+
return keys
121+
}
122+
123+
export function getObjectOrArrayExpressionKeys(value: Node): string[] {
124+
if (value.type === 'ArrayExpression') {
125+
return getArrayExpressionKeys(value)
126+
}
127+
if (value.type === 'ObjectExpression') {
128+
return getObjectExpressionKeys(value)
129+
}
130+
return []
131+
}
132+
133+
export function resolveObjectKey(node: Node, computed: boolean) {
134+
switch (node.type) {
135+
case 'StringLiteral':
136+
case 'NumericLiteral':
137+
return String(node.value)
138+
case 'Identifier':
139+
if (!computed) return node.name
140+
}
141+
return undefined
142+
}

packages/core/parser/utils.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Enums:
2+
/** This is derived from `@vue/compiler-core` */
3+
import type { BindingTypes as VueBindingTypes } from '@vue/compiler-dom'
4+
export const CSSVarsBindingTypes = {
5+
/**
6+
* returned from data()
7+
*/
8+
DATA: 'data' as VueBindingTypes.DATA,
9+
/**
10+
* declared as a prop
11+
*/
12+
PROPS: 'props' as VueBindingTypes.PROPS,
13+
/**
14+
* a local alias of a `<script setup>` destructured prop.
15+
* the original is stored in __propsAliases of the bindingMetadata object.
16+
*/
17+
PROPS_ALIASED: 'props-aliased' as VueBindingTypes.PROPS_ALIASED,
18+
/**
19+
* a let binding (may or may not be a ref)
20+
*/
21+
SETUP_LET: 'setup-let' as VueBindingTypes.SETUP_LET,
22+
/**
23+
* a const binding that can never be a ref.
24+
* these bindings don't need `unref()` calls when processed in inlined
25+
* template expressions.
26+
*/
27+
SETUP_CONST: 'setup-const' as VueBindingTypes.SETUP_CONST,
28+
/**
29+
* a const binding that does not need `unref()`, but may be mutated.
30+
*/
31+
SETUP_REACTIVE_CONST: 'setup-reactive-const' as VueBindingTypes.SETUP_REACTIVE_CONST,
32+
/**
33+
* a const binding that may be a ref.
34+
*/
35+
SETUP_MAYBE_REF: 'setup-maybe-ref' as VueBindingTypes.SETUP_MAYBE_REF,
36+
/**
37+
* bindings that are guaranteed to be refs
38+
*/
39+
SETUP_REF: 'setup-ref' as VueBindingTypes.SETUP_REF,
40+
/**
41+
* declared by other options, e.g. computed, inject
42+
*/
43+
OPTIONS: 'options' as VueBindingTypes.OPTIONS,
44+
/**
45+
* a literal constant, e.g. 'foo', 1, true
46+
*/
47+
LITERAL_CONST: 'literal-const' as VueBindingTypes.LITERAL_CONST,
48+
} as const

packages/core/runtime/handle-variable.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { parse } from '@vue/compiler-sfc'
2-
import { getVariable, matchVariable } from '../parser'
1+
import { parse, compileScript } from '@vue/compiler-sfc'
2+
import { getVariable, matchVariable, parseScriptBindings } from '../parser'
33
import { getVBindVariableListByPath } from './process-css'
44
import type { IVueCSSVarsCtx } from '../types'
55

@@ -10,6 +10,15 @@ export function handleVBindVariable(
1010
) {
1111
debugger
1212
const { descriptor } = parse(code)
13+
const { scriptAst} = compileScript(descriptor,{
14+
id,
15+
inlineTemplate: true,
16+
})
17+
const bindings = parseScriptBindings(scriptAst!)
18+
console.log(bindings)
19+
20+
21+
1322
// let lang = 'js'
1423
// if (descriptor?.scriptSetup?.lang)
1524
// lang = descriptor.scriptSetup.lang

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)