@nuasite/cms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -0
- package/dist/src/build-processor.d.ts +20 -0
- package/dist/src/build-processor.d.ts.map +1 -0
- package/dist/src/collection-scanner.d.ts +6 -0
- package/dist/src/collection-scanner.d.ts.map +1 -0
- package/dist/src/component-registry.d.ts +63 -0
- package/dist/src/component-registry.d.ts.map +1 -0
- package/dist/src/config.d.ts +24 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/dev-middleware.d.ts +20 -0
- package/dist/src/dev-middleware.d.ts.map +1 -0
- package/dist/src/editor/ai.d.ts +60 -0
- package/dist/src/editor/ai.d.ts.map +1 -0
- package/dist/src/editor/api.d.ts +140 -0
- package/dist/src/editor/api.d.ts.map +1 -0
- package/dist/src/editor/color-utils.d.ts +106 -0
- package/dist/src/editor/color-utils.d.ts.map +1 -0
- package/dist/src/editor/components/ai-chat.d.ts +11 -0
- package/dist/src/editor/components/ai-chat.d.ts.map +1 -0
- package/dist/src/editor/components/ai-tooltip.d.ts +12 -0
- package/dist/src/editor/components/ai-tooltip.d.ts.map +1 -0
- package/dist/src/editor/components/attribute-editor.d.ts +5 -0
- package/dist/src/editor/components/attribute-editor.d.ts.map +1 -0
- package/dist/src/editor/components/block-editor.d.ts +12 -0
- package/dist/src/editor/components/block-editor.d.ts.map +1 -0
- package/dist/src/editor/components/collections-browser.d.ts +2 -0
- package/dist/src/editor/components/collections-browser.d.ts.map +1 -0
- package/dist/src/editor/components/color-toolbar.d.ts +12 -0
- package/dist/src/editor/components/color-toolbar.d.ts.map +1 -0
- package/dist/src/editor/components/confirm-dialog.d.ts +2 -0
- package/dist/src/editor/components/confirm-dialog.d.ts.map +1 -0
- package/dist/src/editor/components/create-page-modal.d.ts +2 -0
- package/dist/src/editor/components/create-page-modal.d.ts.map +1 -0
- package/dist/src/editor/components/editable-highlights.d.ts +9 -0
- package/dist/src/editor/components/editable-highlights.d.ts.map +1 -0
- package/dist/src/editor/components/error-boundary.d.ts +32 -0
- package/dist/src/editor/components/error-boundary.d.ts.map +1 -0
- package/dist/src/editor/components/fields.d.ts +75 -0
- package/dist/src/editor/components/fields.d.ts.map +1 -0
- package/dist/src/editor/components/frontmatter-fields.d.ts +29 -0
- package/dist/src/editor/components/frontmatter-fields.d.ts.map +1 -0
- package/dist/src/editor/components/highlight-overlay.d.ts +64 -0
- package/dist/src/editor/components/highlight-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/image-overlay.d.ts +12 -0
- package/dist/src/editor/components/image-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/markdown-editor-overlay.d.ts +6 -0
- package/dist/src/editor/components/markdown-editor-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/markdown-inline-editor.d.ts +10 -0
- package/dist/src/editor/components/markdown-inline-editor.d.ts.map +1 -0
- package/dist/src/editor/components/media-library.d.ts +2 -0
- package/dist/src/editor/components/media-library.d.ts.map +1 -0
- package/dist/src/editor/components/outline.d.ts +21 -0
- package/dist/src/editor/components/outline.d.ts.map +1 -0
- package/dist/src/editor/components/redirect-countdown.d.ts +2 -0
- package/dist/src/editor/components/redirect-countdown.d.ts.map +1 -0
- package/dist/src/editor/components/seo-editor.d.ts +2 -0
- package/dist/src/editor/components/seo-editor.d.ts.map +1 -0
- package/dist/src/editor/components/text-style-toolbar.d.ts +8 -0
- package/dist/src/editor/components/text-style-toolbar.d.ts.map +1 -0
- package/dist/src/editor/components/toast/toast-container.d.ts +7 -0
- package/dist/src/editor/components/toast/toast-container.d.ts.map +1 -0
- package/dist/src/editor/components/toast/toast.d.ts +7 -0
- package/dist/src/editor/components/toast/toast.d.ts.map +1 -0
- package/dist/src/editor/components/toast/types.d.ts +7 -0
- package/dist/src/editor/components/toast/types.d.ts.map +1 -0
- package/dist/src/editor/components/toolbar.d.ts +21 -0
- package/dist/src/editor/components/toolbar.d.ts.map +1 -0
- package/dist/src/editor/config.d.ts +4 -0
- package/dist/src/editor/config.d.ts.map +1 -0
- package/dist/src/editor/constants.d.ts +101 -0
- package/dist/src/editor/constants.d.ts.map +1 -0
- package/dist/src/editor/context.d.ts +14 -0
- package/dist/src/editor/context.d.ts.map +1 -0
- package/dist/src/editor/dom.d.ts +77 -0
- package/dist/src/editor/dom.d.ts.map +1 -0
- package/dist/src/editor/editor.d.ts +64 -0
- package/dist/src/editor/editor.d.ts.map +1 -0
- package/dist/src/editor/history.d.ts +20 -0
- package/dist/src/editor/history.d.ts.map +1 -0
- package/dist/src/editor/hooks/index.d.ts +14 -0
- package/dist/src/editor/hooks/index.d.ts.map +1 -0
- package/dist/src/editor/hooks/useAIHandlers.d.ts +22 -0
- package/dist/src/editor/hooks/useAIHandlers.d.ts.map +1 -0
- package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts +18 -0
- package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts.map +1 -0
- package/dist/src/editor/hooks/useElementDetection.d.ts +26 -0
- package/dist/src/editor/hooks/useElementDetection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useImageHoverDetection.d.ts +12 -0
- package/dist/src/editor/hooks/useImageHoverDetection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useTextSelection.d.ts +23 -0
- package/dist/src/editor/hooks/useTextSelection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useTooltipState.d.ts +19 -0
- package/dist/src/editor/hooks/useTooltipState.d.ts.map +1 -0
- package/dist/src/editor/hooks/utils.d.ts +32 -0
- package/dist/src/editor/hooks/utils.d.ts.map +1 -0
- package/dist/src/editor/index.d.ts +12 -0
- package/dist/src/editor/index.d.ts.map +1 -0
- package/dist/src/editor/lib/cn.d.ts +3 -0
- package/dist/src/editor/lib/cn.d.ts.map +1 -0
- package/dist/src/editor/manifest.d.ts +19 -0
- package/dist/src/editor/manifest.d.ts.map +1 -0
- package/dist/src/editor/markdown-api.d.ts +36 -0
- package/dist/src/editor/markdown-api.d.ts.map +1 -0
- package/dist/src/editor/signals.d.ts +242 -0
- package/dist/src/editor/signals.d.ts.map +1 -0
- package/dist/src/editor/storage.d.ts +27 -0
- package/dist/src/editor/storage.d.ts.map +1 -0
- package/dist/src/editor/text-styling.d.ts +350 -0
- package/dist/src/editor/text-styling.d.ts.map +1 -0
- package/dist/src/editor/themes.d.ts +38 -0
- package/dist/src/editor/themes.d.ts.map +1 -0
- package/dist/src/editor/types.d.ts +454 -0
- package/dist/src/editor/types.d.ts.map +1 -0
- package/dist/src/error-collector.d.ts +56 -0
- package/dist/src/error-collector.d.ts.map +1 -0
- package/dist/src/handlers/component-ops.d.ts +34 -0
- package/dist/src/handlers/component-ops.d.ts.map +1 -0
- package/dist/src/handlers/markdown-ops.d.ts +41 -0
- package/dist/src/handlers/markdown-ops.d.ts.map +1 -0
- package/dist/src/handlers/request-utils.d.ts +20 -0
- package/dist/src/handlers/request-utils.d.ts.map +1 -0
- package/dist/src/handlers/source-writer.d.ts +51 -0
- package/dist/src/handlers/source-writer.d.ts.map +1 -0
- package/dist/src/html-processor.d.ts +63 -0
- package/dist/src/html-processor.d.ts.map +1 -0
- package/dist/src/index.d.ts +41 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/manifest-writer.d.ts +111 -0
- package/dist/src/manifest-writer.d.ts.map +1 -0
- package/dist/src/media/contember.d.ts +15 -0
- package/dist/src/media/contember.d.ts.map +1 -0
- package/dist/src/media/local.d.ts +9 -0
- package/dist/src/media/local.d.ts.map +1 -0
- package/dist/src/media/s3.d.ts +12 -0
- package/dist/src/media/s3.d.ts.map +1 -0
- package/dist/src/media/types.d.ts +40 -0
- package/dist/src/media/types.d.ts.map +1 -0
- package/dist/src/preview-generator.d.ts +19 -0
- package/dist/src/preview-generator.d.ts.map +1 -0
- package/dist/src/seo-processor.d.ts +23 -0
- package/dist/src/seo-processor.d.ts.map +1 -0
- package/dist/src/source-finder/ast-extractors.d.ts +35 -0
- package/dist/src/source-finder/ast-extractors.d.ts.map +1 -0
- package/dist/src/source-finder/ast-parser.d.ts +16 -0
- package/dist/src/source-finder/ast-parser.d.ts.map +1 -0
- package/dist/src/source-finder/cache.d.ts +18 -0
- package/dist/src/source-finder/cache.d.ts.map +1 -0
- package/dist/src/source-finder/collection-finder.d.ts +29 -0
- package/dist/src/source-finder/collection-finder.d.ts.map +1 -0
- package/dist/src/source-finder/cross-file-tracker.d.ts +39 -0
- package/dist/src/source-finder/cross-file-tracker.d.ts.map +1 -0
- package/dist/src/source-finder/element-finder.d.ts +42 -0
- package/dist/src/source-finder/element-finder.d.ts.map +1 -0
- package/dist/src/source-finder/image-finder.d.ts +24 -0
- package/dist/src/source-finder/image-finder.d.ts.map +1 -0
- package/dist/src/source-finder/index.d.ts +9 -0
- package/dist/src/source-finder/index.d.ts.map +1 -0
- package/dist/src/source-finder/search-index.d.ts +27 -0
- package/dist/src/source-finder/search-index.d.ts.map +1 -0
- package/dist/src/source-finder/snippet-utils.d.ts +90 -0
- package/dist/src/source-finder/snippet-utils.d.ts.map +1 -0
- package/dist/src/source-finder/source-lookup.d.ts +16 -0
- package/dist/src/source-finder/source-lookup.d.ts.map +1 -0
- package/dist/src/source-finder/types.d.ts +167 -0
- package/dist/src/source-finder/types.d.ts.map +1 -0
- package/dist/src/source-finder/variable-extraction.d.ts +37 -0
- package/dist/src/source-finder/variable-extraction.d.ts.map +1 -0
- package/dist/src/tailwind-colors.d.ts +54 -0
- package/dist/src/tailwind-colors.d.ts.map +1 -0
- package/dist/src/tsconfig.tsbuildinfo +1 -0
- package/dist/src/types.d.ts +367 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +61 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/vite-plugin.d.ts +14 -0
- package/dist/src/vite-plugin.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +80 -0
- package/src/build-processor.ts +784 -0
- package/src/collection-scanner.ts +304 -0
- package/src/component-registry.ts +393 -0
- package/src/config.ts +74 -0
- package/src/dev-middleware.ts +525 -0
- package/src/dist/src/tsconfig.tsbuildinfo +1 -0
- package/src/editor/ai.ts +185 -0
- package/src/editor/api.ts +513 -0
- package/src/editor/color-utils.ts +556 -0
- package/src/editor/components/ai-chat.tsx +632 -0
- package/src/editor/components/ai-tooltip.tsx +179 -0
- package/src/editor/components/attribute-editor.tsx +596 -0
- package/src/editor/components/block-editor.tsx +546 -0
- package/src/editor/components/collections-browser.tsx +248 -0
- package/src/editor/components/color-toolbar.tsx +314 -0
- package/src/editor/components/confirm-dialog.tsx +69 -0
- package/src/editor/components/create-page-modal.tsx +163 -0
- package/src/editor/components/editable-highlights.tsx +260 -0
- package/src/editor/components/error-boundary.tsx +87 -0
- package/src/editor/components/fields.tsx +387 -0
- package/src/editor/components/frontmatter-fields.tsx +469 -0
- package/src/editor/components/highlight-overlay.ts +229 -0
- package/src/editor/components/image-overlay.tsx +230 -0
- package/src/editor/components/markdown-editor-overlay.tsx +505 -0
- package/src/editor/components/markdown-inline-editor.tsx +780 -0
- package/src/editor/components/media-library.tsx +297 -0
- package/src/editor/components/outline.tsx +402 -0
- package/src/editor/components/redirect-countdown.tsx +45 -0
- package/src/editor/components/seo-editor.tsx +498 -0
- package/src/editor/components/text-style-toolbar.tsx +362 -0
- package/src/editor/components/toast/toast-container.tsx +15 -0
- package/src/editor/components/toast/toast.tsx +49 -0
- package/src/editor/components/toast/types.ts +7 -0
- package/src/editor/components/toolbar.tsx +366 -0
- package/src/editor/config.ts +12 -0
- package/src/editor/constants.ts +106 -0
- package/src/editor/context.tsx +38 -0
- package/src/editor/dom.ts +357 -0
- package/src/editor/editor.ts +1510 -0
- package/src/editor/env.d.ts +4 -0
- package/src/editor/history.ts +355 -0
- package/src/editor/hooks/index.ts +19 -0
- package/src/editor/hooks/useAIHandlers.ts +345 -0
- package/src/editor/hooks/useBlockEditorHandlers.ts +206 -0
- package/src/editor/hooks/useElementDetection.ts +284 -0
- package/src/editor/hooks/useImageHoverDetection.ts +102 -0
- package/src/editor/hooks/useTextSelection.ts +187 -0
- package/src/editor/hooks/useTooltipState.ts +126 -0
- package/src/editor/hooks/utils.ts +101 -0
- package/src/editor/index.tsx +481 -0
- package/src/editor/lib/cn.ts +4 -0
- package/src/editor/manifest.ts +25 -0
- package/src/editor/markdown-api.ts +209 -0
- package/src/editor/signals.ts +1351 -0
- package/src/editor/storage.ts +266 -0
- package/src/editor/styles.css +465 -0
- package/src/editor/text-styling.ts +773 -0
- package/src/editor/themes.ts +210 -0
- package/src/editor/types.ts +591 -0
- package/src/error-collector.ts +106 -0
- package/src/handlers/component-ops.ts +463 -0
- package/src/handlers/markdown-ops.ts +202 -0
- package/src/handlers/request-utils.ts +151 -0
- package/src/handlers/source-writer.ts +649 -0
- package/src/html-processor.ts +1108 -0
- package/src/index.ts +284 -0
- package/src/manifest-writer.ts +371 -0
- package/src/media/contember.ts +84 -0
- package/src/media/local.ts +114 -0
- package/src/media/s3.ts +133 -0
- package/src/media/types.ts +33 -0
- package/src/preview-generator.ts +293 -0
- package/src/seo-processor.ts +567 -0
- package/src/source-finder/ast-extractors.ts +185 -0
- package/src/source-finder/ast-parser.ts +150 -0
- package/src/source-finder/cache.ts +76 -0
- package/src/source-finder/collection-finder.ts +335 -0
- package/src/source-finder/cross-file-tracker.ts +741 -0
- package/src/source-finder/element-finder.ts +387 -0
- package/src/source-finder/image-finder.ts +283 -0
- package/src/source-finder/index.ts +37 -0
- package/src/source-finder/search-index.ts +525 -0
- package/src/source-finder/snippet-utils.ts +668 -0
- package/src/source-finder/source-lookup.ts +200 -0
- package/src/source-finder/types.ts +210 -0
- package/src/source-finder/variable-extraction.ts +406 -0
- package/src/tailwind-colors.ts +874 -0
- package/src/tsconfig.json +25 -0
- package/src/types.ts +406 -0
- package/src/utils.ts +186 -0
- package/src/vite-plugin.ts +42 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { parse as parseBabel } from '@babel/parser'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { extractArrayElements, extractObjectProperties, getStringValue } from './ast-extractors'
|
|
6
|
+
import type { BabelFile, BabelNode, ImportInfo, VariableDefinition } from './types'
|
|
7
|
+
import { createFrontmatterLineTransformer, identityLine } from './types'
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Variable Definition Extraction
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extract variable definitions from Babel AST
|
|
15
|
+
* Finds const/let/var declarations with string literal values
|
|
16
|
+
*
|
|
17
|
+
* Note: Babel parses the frontmatter content (without --- delimiters) starting at line 1.
|
|
18
|
+
* frontmatterStartLine is the actual file line where the content begins (after first ---).
|
|
19
|
+
* So we convert: file_line = (babel_line - 1) + frontmatterStartLine
|
|
20
|
+
*/
|
|
21
|
+
export function extractVariableDefinitions(ast: BabelFile, frontmatterStartLine: number): VariableDefinition[] {
|
|
22
|
+
const definitions: VariableDefinition[] = []
|
|
23
|
+
const lineTransformer = createFrontmatterLineTransformer(frontmatterStartLine)
|
|
24
|
+
|
|
25
|
+
function visitNode(node: BabelNode) {
|
|
26
|
+
if (node.type === 'VariableDeclaration') {
|
|
27
|
+
const declarations = node.declarations as BabelNode[] | undefined
|
|
28
|
+
for (const decl of declarations ?? []) {
|
|
29
|
+
const id = decl.id as BabelNode | undefined
|
|
30
|
+
const init = decl.init as BabelNode | undefined
|
|
31
|
+
if (id?.type === 'Identifier' && init) {
|
|
32
|
+
const varName = id.name as string
|
|
33
|
+
const loc = decl.loc as { start: { line: number } } | undefined
|
|
34
|
+
const line = lineTransformer(loc?.start.line ?? 1)
|
|
35
|
+
|
|
36
|
+
// Simple string value
|
|
37
|
+
const stringValue = getStringValue(init)
|
|
38
|
+
if (stringValue !== null) {
|
|
39
|
+
definitions.push({ name: varName, value: stringValue, line })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Object expression - extract properties recursively
|
|
43
|
+
if (init.type === 'ObjectExpression') {
|
|
44
|
+
extractObjectProperties(init, varName, definitions, lineTransformer)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Array expression - extract elements
|
|
48
|
+
if (init.type === 'ArrayExpression') {
|
|
49
|
+
extractArrayElements(init, varName, definitions, lineTransformer, line)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Handle ObjectPattern (destructuring from Astro.props with default values)
|
|
54
|
+
// Pattern: const { title = ['a', 'b'] } = Astro.props
|
|
55
|
+
if (id?.type === 'ObjectPattern' && init?.type === 'MemberExpression') {
|
|
56
|
+
const object = init.object as BabelNode | undefined
|
|
57
|
+
const property = init.property as BabelNode | undefined
|
|
58
|
+
|
|
59
|
+
// Only process Astro.props destructuring
|
|
60
|
+
if (
|
|
61
|
+
object?.type === 'Identifier'
|
|
62
|
+
&& (object.name as string) === 'Astro'
|
|
63
|
+
&& property?.type === 'Identifier'
|
|
64
|
+
&& (property.name as string) === 'props'
|
|
65
|
+
) {
|
|
66
|
+
const properties = id.properties as BabelNode[] | undefined
|
|
67
|
+
for (const prop of properties ?? []) {
|
|
68
|
+
if (prop.type === 'ObjectProperty') {
|
|
69
|
+
const value = prop.value as BabelNode | undefined
|
|
70
|
+
|
|
71
|
+
// Handle default values: { title = [...] } or { heading: title = [...] }
|
|
72
|
+
if (value?.type === 'AssignmentPattern') {
|
|
73
|
+
const left = value.left as BabelNode | undefined
|
|
74
|
+
const right = value.right as BabelNode | undefined
|
|
75
|
+
|
|
76
|
+
// The local variable name is from `left` (e.g., 'title' in both cases)
|
|
77
|
+
if (left?.type === 'Identifier' && right) {
|
|
78
|
+
const localVarName = left.name as string
|
|
79
|
+
const loc = right.loc as { start: { line: number } } | undefined
|
|
80
|
+
const line = lineTransformer(loc?.start.line ?? 1)
|
|
81
|
+
|
|
82
|
+
// Extract the default value
|
|
83
|
+
const stringValue = getStringValue(right)
|
|
84
|
+
if (stringValue !== null) {
|
|
85
|
+
definitions.push({ name: localVarName, value: stringValue, line })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Object expression default value
|
|
89
|
+
if (right.type === 'ObjectExpression') {
|
|
90
|
+
extractObjectProperties(right, localVarName, definitions, lineTransformer)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Array expression default value
|
|
94
|
+
if (right.type === 'ArrayExpression') {
|
|
95
|
+
extractArrayElements(right, localVarName, definitions, lineTransformer, line)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Recursively visit child nodes
|
|
107
|
+
for (const key of Object.keys(node)) {
|
|
108
|
+
const value = node[key]
|
|
109
|
+
if (value && typeof value === 'object') {
|
|
110
|
+
if (Array.isArray(value)) {
|
|
111
|
+
for (const item of value) {
|
|
112
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
113
|
+
visitNode(item as BabelNode)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
} else if ('type' in value) {
|
|
117
|
+
visitNode(value as BabelNode)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
visitNode(ast.program)
|
|
124
|
+
return definitions
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Prop Alias Extraction
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Extract prop aliases from Astro.props destructuring patterns.
|
|
133
|
+
* Returns a Map of local variable name -> prop name.
|
|
134
|
+
* Examples:
|
|
135
|
+
* const { title } = Astro.props -> Map { 'title' => 'title' }
|
|
136
|
+
* const { items: navItems } = Astro.props -> Map { 'navItems' => 'items' }
|
|
137
|
+
*/
|
|
138
|
+
export function extractPropAliases(ast: BabelFile): Map<string, string> {
|
|
139
|
+
const propAliases = new Map<string, string>()
|
|
140
|
+
|
|
141
|
+
function visitNode(node: BabelNode) {
|
|
142
|
+
if (node.type === 'VariableDeclaration') {
|
|
143
|
+
const declarations = node.declarations as BabelNode[] | undefined
|
|
144
|
+
for (const decl of declarations ?? []) {
|
|
145
|
+
const id = decl.id as BabelNode | undefined
|
|
146
|
+
const init = decl.init as BabelNode | undefined
|
|
147
|
+
|
|
148
|
+
// Check for destructuring from Astro.props
|
|
149
|
+
// Pattern: const { x, y } = Astro.props;
|
|
150
|
+
if (id?.type === 'ObjectPattern' && init?.type === 'MemberExpression') {
|
|
151
|
+
const object = init.object as BabelNode | undefined
|
|
152
|
+
const property = init.property as BabelNode | undefined
|
|
153
|
+
|
|
154
|
+
if (
|
|
155
|
+
object?.type === 'Identifier'
|
|
156
|
+
&& (object.name as string) === 'Astro'
|
|
157
|
+
&& property?.type === 'Identifier'
|
|
158
|
+
&& (property.name as string) === 'props'
|
|
159
|
+
) {
|
|
160
|
+
// Extract property names from the destructuring pattern
|
|
161
|
+
const properties = id.properties as BabelNode[] | undefined
|
|
162
|
+
for (const prop of properties ?? []) {
|
|
163
|
+
if (prop.type === 'ObjectProperty') {
|
|
164
|
+
const key = prop.key as BabelNode | undefined
|
|
165
|
+
const value = prop.value as BabelNode | undefined
|
|
166
|
+
|
|
167
|
+
if (key?.type === 'Identifier') {
|
|
168
|
+
const propName = key.name as string
|
|
169
|
+
// Check for renaming: { items: navItems }
|
|
170
|
+
// key is the prop name (items), value is the local name (navItems)
|
|
171
|
+
if (value?.type === 'Identifier') {
|
|
172
|
+
const localName = value.name as string
|
|
173
|
+
propAliases.set(localName, propName)
|
|
174
|
+
} else if (value?.type === 'AssignmentPattern') {
|
|
175
|
+
// Handle default values: { items: navItems = [] } or { items = [] }
|
|
176
|
+
const left = value.left as BabelNode | undefined
|
|
177
|
+
if (left?.type === 'Identifier') {
|
|
178
|
+
propAliases.set(left.name as string, propName)
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Simple case: { items } - key and value are the same
|
|
182
|
+
propAliases.set(propName, propName)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} else if (prop.type === 'RestElement') {
|
|
186
|
+
// Handle rest pattern: const { x, ...rest } = Astro.props;
|
|
187
|
+
const argument = prop.argument as BabelNode | undefined
|
|
188
|
+
if (argument?.type === 'Identifier') {
|
|
189
|
+
// Rest element captures all remaining props
|
|
190
|
+
propAliases.set(argument.name as string, '...')
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Recursively visit child nodes
|
|
200
|
+
for (const key of Object.keys(node)) {
|
|
201
|
+
const value = node[key]
|
|
202
|
+
if (value && typeof value === 'object') {
|
|
203
|
+
if (Array.isArray(value)) {
|
|
204
|
+
for (const item of value) {
|
|
205
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
206
|
+
visitNode(item as BabelNode)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} else if ('type' in value) {
|
|
210
|
+
visitNode(value as BabelNode)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
visitNode(ast.program)
|
|
217
|
+
return propAliases
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ============================================================================
|
|
221
|
+
// Import Extraction
|
|
222
|
+
// ============================================================================
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Extract import information from Babel AST.
|
|
226
|
+
* Handles:
|
|
227
|
+
* import { foo } from './file' -> { localName: 'foo', importedName: 'foo', source: './file' }
|
|
228
|
+
* import { foo as bar } from './file' -> { localName: 'bar', importedName: 'foo', source: './file' }
|
|
229
|
+
* import foo from './file' -> { localName: 'foo', importedName: 'default', source: './file' }
|
|
230
|
+
* import * as foo from './file' -> { localName: 'foo', importedName: '*', source: './file' }
|
|
231
|
+
*/
|
|
232
|
+
export function extractImports(ast: BabelFile): ImportInfo[] {
|
|
233
|
+
const imports: ImportInfo[] = []
|
|
234
|
+
|
|
235
|
+
for (const node of ast.program.body) {
|
|
236
|
+
if (node.type === 'ImportDeclaration') {
|
|
237
|
+
const source = (node.source as BabelNode)?.value as string
|
|
238
|
+
if (!source) continue
|
|
239
|
+
|
|
240
|
+
const specifiers = node.specifiers as BabelNode[] | undefined
|
|
241
|
+
for (const spec of specifiers ?? []) {
|
|
242
|
+
if (spec.type === 'ImportSpecifier') {
|
|
243
|
+
// Named import: import { foo } from './file' or import { foo as bar } from './file'
|
|
244
|
+
const imported = spec.imported as BabelNode | undefined
|
|
245
|
+
const local = spec.local as BabelNode | undefined
|
|
246
|
+
if (imported?.type === 'Identifier' && local?.type === 'Identifier') {
|
|
247
|
+
imports.push({
|
|
248
|
+
localName: local.name as string,
|
|
249
|
+
importedName: imported.name as string,
|
|
250
|
+
source,
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
} else if (spec.type === 'ImportDefaultSpecifier') {
|
|
254
|
+
// Default import: import foo from './file'
|
|
255
|
+
const local = spec.local as BabelNode | undefined
|
|
256
|
+
if (local?.type === 'Identifier') {
|
|
257
|
+
imports.push({
|
|
258
|
+
localName: local.name as string,
|
|
259
|
+
importedName: 'default',
|
|
260
|
+
source,
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
} else if (spec.type === 'ImportNamespaceSpecifier') {
|
|
264
|
+
// Namespace import: import * as foo from './file'
|
|
265
|
+
const local = spec.local as BabelNode | undefined
|
|
266
|
+
if (local?.type === 'Identifier') {
|
|
267
|
+
imports.push({
|
|
268
|
+
localName: local.name as string,
|
|
269
|
+
importedName: '*',
|
|
270
|
+
source,
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return imports
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ============================================================================
|
|
282
|
+
// Import Resolution
|
|
283
|
+
// ============================================================================
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Resolve an import source path to an absolute file path.
|
|
287
|
+
* Handles relative paths and tries common extensions.
|
|
288
|
+
*/
|
|
289
|
+
export async function resolveImportPath(source: string, fromFile: string): Promise<string | null> {
|
|
290
|
+
// Only handle relative imports
|
|
291
|
+
if (!source.startsWith('.')) {
|
|
292
|
+
return null
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const fromDir = path.dirname(fromFile)
|
|
296
|
+
const basePath = path.resolve(fromDir, source)
|
|
297
|
+
|
|
298
|
+
// Try different extensions
|
|
299
|
+
const extensions = ['.ts', '.js', '.astro', '.tsx', '.jsx', '']
|
|
300
|
+
for (const ext of extensions) {
|
|
301
|
+
const fullPath = basePath + ext
|
|
302
|
+
try {
|
|
303
|
+
await fs.access(fullPath)
|
|
304
|
+
return fullPath
|
|
305
|
+
} catch {
|
|
306
|
+
// File doesn't exist with this extension
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Try index files
|
|
311
|
+
for (const ext of ['.ts', '.js', '.tsx', '.jsx']) {
|
|
312
|
+
const indexPath = path.join(basePath, `index${ext}`)
|
|
313
|
+
try {
|
|
314
|
+
await fs.access(indexPath)
|
|
315
|
+
return indexPath
|
|
316
|
+
} catch {
|
|
317
|
+
// File doesn't exist
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return null
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ============================================================================
|
|
325
|
+
// Export Extraction (for external files)
|
|
326
|
+
// ============================================================================
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Parse a TypeScript/JavaScript file and extract exported variable definitions.
|
|
330
|
+
*/
|
|
331
|
+
export async function getExportedDefinitions(filePath: string): Promise<VariableDefinition[]> {
|
|
332
|
+
try {
|
|
333
|
+
const content = await fs.readFile(filePath, 'utf-8')
|
|
334
|
+
const ast = parseBabel(content, {
|
|
335
|
+
sourceType: 'module',
|
|
336
|
+
plugins: ['typescript'],
|
|
337
|
+
errorRecovery: true,
|
|
338
|
+
}) as unknown as BabelFile
|
|
339
|
+
|
|
340
|
+
const definitions: VariableDefinition[] = []
|
|
341
|
+
|
|
342
|
+
for (const node of ast.program.body) {
|
|
343
|
+
// Handle: export const foo = 'value'
|
|
344
|
+
if (node.type === 'ExportNamedDeclaration') {
|
|
345
|
+
const declaration = node.declaration as BabelNode | undefined
|
|
346
|
+
if (declaration?.type === 'VariableDeclaration') {
|
|
347
|
+
const declarations = declaration.declarations as BabelNode[] | undefined
|
|
348
|
+
for (const decl of declarations ?? []) {
|
|
349
|
+
const id = decl.id as BabelNode | undefined
|
|
350
|
+
const init = decl.init as BabelNode | undefined
|
|
351
|
+
if (id?.type === 'Identifier' && init) {
|
|
352
|
+
const varName = id.name as string
|
|
353
|
+
const loc = decl.loc as { start: { line: number } } | undefined
|
|
354
|
+
const line = loc?.start.line ?? 1
|
|
355
|
+
|
|
356
|
+
const stringValue = getStringValue(init)
|
|
357
|
+
if (stringValue !== null) {
|
|
358
|
+
definitions.push({ name: varName, value: stringValue, line })
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (init.type === 'ObjectExpression') {
|
|
362
|
+
extractObjectProperties(init, varName, definitions, identityLine)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (init.type === 'ArrayExpression') {
|
|
366
|
+
extractArrayElements(init, varName, definitions, identityLine, line)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Handle: const foo = 'value'; export { foo }
|
|
374
|
+
// First collect all variable declarations
|
|
375
|
+
if (node.type === 'VariableDeclaration') {
|
|
376
|
+
const declarations = node.declarations as BabelNode[] | undefined
|
|
377
|
+
for (const decl of declarations ?? []) {
|
|
378
|
+
const id = decl.id as BabelNode | undefined
|
|
379
|
+
const init = decl.init as BabelNode | undefined
|
|
380
|
+
if (id?.type === 'Identifier' && init) {
|
|
381
|
+
const varName = id.name as string
|
|
382
|
+
const loc = decl.loc as { start: { line: number } } | undefined
|
|
383
|
+
const line = loc?.start.line ?? 1
|
|
384
|
+
|
|
385
|
+
const stringValue = getStringValue(init)
|
|
386
|
+
if (stringValue !== null) {
|
|
387
|
+
definitions.push({ name: varName, value: stringValue, line })
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (init.type === 'ObjectExpression') {
|
|
391
|
+
extractObjectProperties(init, varName, definitions, identityLine)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (init.type === 'ArrayExpression') {
|
|
395
|
+
extractArrayElements(init, varName, definitions, identityLine, line)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return definitions
|
|
403
|
+
} catch {
|
|
404
|
+
return []
|
|
405
|
+
}
|
|
406
|
+
}
|