-
-
Notifications
You must be signed in to change notification settings - Fork 439
feat(component-meta): extend component meta #5169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -266,8 +266,9 @@ | |
let _events: ReturnType<typeof getEvents> | undefined; | ||
let _slots: ReturnType<typeof getSlots> | undefined; | ||
let _exposed: ReturnType<typeof getExposed> | undefined; | ||
let _extended_meta: ReturnType<typeof getExtendedMeta> | undefined; | ||
|
||
return { | ||
const meta = { | ||
get type() { | ||
return _type ?? (_type = getType()); | ||
}, | ||
|
@@ -282,8 +283,16 @@ | |
}, | ||
get exposed() { | ||
return _exposed ?? (_exposed = getExposed()); | ||
}, | ||
}; | ||
} | ||
} | ||
|
||
return new Proxy(meta, { | ||
get(target, prop) { | ||
if (prop in target) return target[prop as keyof typeof target] | ||
const extendedMeta = _extended_meta ?? (_extended_meta = getExtendedMeta()) | ||
return extendedMeta?.[prop as string] | ||
} | ||
}) | ||
|
||
function getType() { | ||
|
||
|
@@ -297,6 +306,36 @@ | |
return 0; | ||
} | ||
|
||
|
||
function getExtendedMeta() { | ||
let meta: Record<string, any> = {}; | ||
const snapshot = language.scripts.get(componentPath)?.snapshot!; | ||
const fileText = snapshot.getText(0, snapshot.getLength()); | ||
const ast = ts.createSourceFile('/temp', fileText, ts.ScriptTarget.Latest, true); | ||
const identifier = 'defineComponentMeta' | ||
const printer = ts.createPrinter(checkerOptions.printer); | ||
|
||
if (!ast.identifiers.get(identifier)) return | ||
Check failure on line 318 in packages/component-meta/lib/base.ts
|
||
|
||
function traverse(node: ts.Node): void { | ||
if (ts.isIdentifier(node) && node.text === identifier) { | ||
const argument = node.parent.arguments[0]; | ||
Check failure on line 322 in packages/component-meta/lib/base.ts
|
||
if (ts.isObjectLiteralExpression(argument)) { | ||
argument.properties.forEach(property => { | ||
if (!ts.isPropertyAssignment(property)) return | ||
const key = property.name.getText(); | ||
const valueNode = resolveDefaultOptionExpression(property.initializer, ts); | ||
meta[key] = printer?.printNode(ts.EmitHint.Expression, valueNode, ast) ?? valueNode.getText(ast) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @KazariEX I'm wondering if it's a good idea to parse nested objects and arrays by traversing the rest of the AST here. I tried to match the parser for prop default values. On one side it would be nice for end users to receive plain objects / arrays, but might be a bit heavy on performances. |
||
}); | ||
} | ||
} | ||
return ts.forEachChild(node, traverse) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit aggressive since it'll walk the entire AST. I'll look into restraining it to the top level of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if we can parse There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll look into it! |
||
} | ||
|
||
traverse(ast); | ||
return meta; | ||
} | ||
|
||
function getProps() { | ||
|
||
const $props = symbolProperties.find(prop => prop.escapedName === 'props'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { h, defineComponent } from 'vue'; | ||
|
||
export default defineComponent(() => { | ||
defineComponentMeta({ foo: 'bar', nested: { foo: 'baz', arr: [1, 2] } }) | ||
return () => h('span'); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { defineComponent } from 'vue'; | ||
|
||
export default defineComponent(() => { | ||
defineComponentMeta({ foo: 'bar', nested: { foo: 'baz', arr: [1, 2] } }) | ||
return () => <span /> | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<script setup lang="ts"> | ||
defineComponentMeta({ foo: 'bar', nested: { foo: 'baz', arr: [1, 2] } }) | ||
</script> | ||
|
||
<template> | ||
<span /> | ||
</template> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See:
language-tools/packages/component-meta/lib/base.ts
Lines 334 to 344 in 317b0cc
We can read ast from
sourceFile.generated.root._sfc
if it's a.vue
file, or try sharing parsed ast if it's a.ts
file.