@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.
Files changed (269) hide show
  1. package/README.md +237 -0
  2. package/dist/src/build-processor.d.ts +20 -0
  3. package/dist/src/build-processor.d.ts.map +1 -0
  4. package/dist/src/collection-scanner.d.ts +6 -0
  5. package/dist/src/collection-scanner.d.ts.map +1 -0
  6. package/dist/src/component-registry.d.ts +63 -0
  7. package/dist/src/component-registry.d.ts.map +1 -0
  8. package/dist/src/config.d.ts +24 -0
  9. package/dist/src/config.d.ts.map +1 -0
  10. package/dist/src/dev-middleware.d.ts +20 -0
  11. package/dist/src/dev-middleware.d.ts.map +1 -0
  12. package/dist/src/editor/ai.d.ts +60 -0
  13. package/dist/src/editor/ai.d.ts.map +1 -0
  14. package/dist/src/editor/api.d.ts +140 -0
  15. package/dist/src/editor/api.d.ts.map +1 -0
  16. package/dist/src/editor/color-utils.d.ts +106 -0
  17. package/dist/src/editor/color-utils.d.ts.map +1 -0
  18. package/dist/src/editor/components/ai-chat.d.ts +11 -0
  19. package/dist/src/editor/components/ai-chat.d.ts.map +1 -0
  20. package/dist/src/editor/components/ai-tooltip.d.ts +12 -0
  21. package/dist/src/editor/components/ai-tooltip.d.ts.map +1 -0
  22. package/dist/src/editor/components/attribute-editor.d.ts +5 -0
  23. package/dist/src/editor/components/attribute-editor.d.ts.map +1 -0
  24. package/dist/src/editor/components/block-editor.d.ts +12 -0
  25. package/dist/src/editor/components/block-editor.d.ts.map +1 -0
  26. package/dist/src/editor/components/collections-browser.d.ts +2 -0
  27. package/dist/src/editor/components/collections-browser.d.ts.map +1 -0
  28. package/dist/src/editor/components/color-toolbar.d.ts +12 -0
  29. package/dist/src/editor/components/color-toolbar.d.ts.map +1 -0
  30. package/dist/src/editor/components/confirm-dialog.d.ts +2 -0
  31. package/dist/src/editor/components/confirm-dialog.d.ts.map +1 -0
  32. package/dist/src/editor/components/create-page-modal.d.ts +2 -0
  33. package/dist/src/editor/components/create-page-modal.d.ts.map +1 -0
  34. package/dist/src/editor/components/editable-highlights.d.ts +9 -0
  35. package/dist/src/editor/components/editable-highlights.d.ts.map +1 -0
  36. package/dist/src/editor/components/error-boundary.d.ts +32 -0
  37. package/dist/src/editor/components/error-boundary.d.ts.map +1 -0
  38. package/dist/src/editor/components/fields.d.ts +75 -0
  39. package/dist/src/editor/components/fields.d.ts.map +1 -0
  40. package/dist/src/editor/components/frontmatter-fields.d.ts +29 -0
  41. package/dist/src/editor/components/frontmatter-fields.d.ts.map +1 -0
  42. package/dist/src/editor/components/highlight-overlay.d.ts +64 -0
  43. package/dist/src/editor/components/highlight-overlay.d.ts.map +1 -0
  44. package/dist/src/editor/components/image-overlay.d.ts +12 -0
  45. package/dist/src/editor/components/image-overlay.d.ts.map +1 -0
  46. package/dist/src/editor/components/markdown-editor-overlay.d.ts +6 -0
  47. package/dist/src/editor/components/markdown-editor-overlay.d.ts.map +1 -0
  48. package/dist/src/editor/components/markdown-inline-editor.d.ts +10 -0
  49. package/dist/src/editor/components/markdown-inline-editor.d.ts.map +1 -0
  50. package/dist/src/editor/components/media-library.d.ts +2 -0
  51. package/dist/src/editor/components/media-library.d.ts.map +1 -0
  52. package/dist/src/editor/components/outline.d.ts +21 -0
  53. package/dist/src/editor/components/outline.d.ts.map +1 -0
  54. package/dist/src/editor/components/redirect-countdown.d.ts +2 -0
  55. package/dist/src/editor/components/redirect-countdown.d.ts.map +1 -0
  56. package/dist/src/editor/components/seo-editor.d.ts +2 -0
  57. package/dist/src/editor/components/seo-editor.d.ts.map +1 -0
  58. package/dist/src/editor/components/text-style-toolbar.d.ts +8 -0
  59. package/dist/src/editor/components/text-style-toolbar.d.ts.map +1 -0
  60. package/dist/src/editor/components/toast/toast-container.d.ts +7 -0
  61. package/dist/src/editor/components/toast/toast-container.d.ts.map +1 -0
  62. package/dist/src/editor/components/toast/toast.d.ts +7 -0
  63. package/dist/src/editor/components/toast/toast.d.ts.map +1 -0
  64. package/dist/src/editor/components/toast/types.d.ts +7 -0
  65. package/dist/src/editor/components/toast/types.d.ts.map +1 -0
  66. package/dist/src/editor/components/toolbar.d.ts +21 -0
  67. package/dist/src/editor/components/toolbar.d.ts.map +1 -0
  68. package/dist/src/editor/config.d.ts +4 -0
  69. package/dist/src/editor/config.d.ts.map +1 -0
  70. package/dist/src/editor/constants.d.ts +101 -0
  71. package/dist/src/editor/constants.d.ts.map +1 -0
  72. package/dist/src/editor/context.d.ts +14 -0
  73. package/dist/src/editor/context.d.ts.map +1 -0
  74. package/dist/src/editor/dom.d.ts +77 -0
  75. package/dist/src/editor/dom.d.ts.map +1 -0
  76. package/dist/src/editor/editor.d.ts +64 -0
  77. package/dist/src/editor/editor.d.ts.map +1 -0
  78. package/dist/src/editor/history.d.ts +20 -0
  79. package/dist/src/editor/history.d.ts.map +1 -0
  80. package/dist/src/editor/hooks/index.d.ts +14 -0
  81. package/dist/src/editor/hooks/index.d.ts.map +1 -0
  82. package/dist/src/editor/hooks/useAIHandlers.d.ts +22 -0
  83. package/dist/src/editor/hooks/useAIHandlers.d.ts.map +1 -0
  84. package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts +18 -0
  85. package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts.map +1 -0
  86. package/dist/src/editor/hooks/useElementDetection.d.ts +26 -0
  87. package/dist/src/editor/hooks/useElementDetection.d.ts.map +1 -0
  88. package/dist/src/editor/hooks/useImageHoverDetection.d.ts +12 -0
  89. package/dist/src/editor/hooks/useImageHoverDetection.d.ts.map +1 -0
  90. package/dist/src/editor/hooks/useTextSelection.d.ts +23 -0
  91. package/dist/src/editor/hooks/useTextSelection.d.ts.map +1 -0
  92. package/dist/src/editor/hooks/useTooltipState.d.ts +19 -0
  93. package/dist/src/editor/hooks/useTooltipState.d.ts.map +1 -0
  94. package/dist/src/editor/hooks/utils.d.ts +32 -0
  95. package/dist/src/editor/hooks/utils.d.ts.map +1 -0
  96. package/dist/src/editor/index.d.ts +12 -0
  97. package/dist/src/editor/index.d.ts.map +1 -0
  98. package/dist/src/editor/lib/cn.d.ts +3 -0
  99. package/dist/src/editor/lib/cn.d.ts.map +1 -0
  100. package/dist/src/editor/manifest.d.ts +19 -0
  101. package/dist/src/editor/manifest.d.ts.map +1 -0
  102. package/dist/src/editor/markdown-api.d.ts +36 -0
  103. package/dist/src/editor/markdown-api.d.ts.map +1 -0
  104. package/dist/src/editor/signals.d.ts +242 -0
  105. package/dist/src/editor/signals.d.ts.map +1 -0
  106. package/dist/src/editor/storage.d.ts +27 -0
  107. package/dist/src/editor/storage.d.ts.map +1 -0
  108. package/dist/src/editor/text-styling.d.ts +350 -0
  109. package/dist/src/editor/text-styling.d.ts.map +1 -0
  110. package/dist/src/editor/themes.d.ts +38 -0
  111. package/dist/src/editor/themes.d.ts.map +1 -0
  112. package/dist/src/editor/types.d.ts +454 -0
  113. package/dist/src/editor/types.d.ts.map +1 -0
  114. package/dist/src/error-collector.d.ts +56 -0
  115. package/dist/src/error-collector.d.ts.map +1 -0
  116. package/dist/src/handlers/component-ops.d.ts +34 -0
  117. package/dist/src/handlers/component-ops.d.ts.map +1 -0
  118. package/dist/src/handlers/markdown-ops.d.ts +41 -0
  119. package/dist/src/handlers/markdown-ops.d.ts.map +1 -0
  120. package/dist/src/handlers/request-utils.d.ts +20 -0
  121. package/dist/src/handlers/request-utils.d.ts.map +1 -0
  122. package/dist/src/handlers/source-writer.d.ts +51 -0
  123. package/dist/src/handlers/source-writer.d.ts.map +1 -0
  124. package/dist/src/html-processor.d.ts +63 -0
  125. package/dist/src/html-processor.d.ts.map +1 -0
  126. package/dist/src/index.d.ts +41 -0
  127. package/dist/src/index.d.ts.map +1 -0
  128. package/dist/src/manifest-writer.d.ts +111 -0
  129. package/dist/src/manifest-writer.d.ts.map +1 -0
  130. package/dist/src/media/contember.d.ts +15 -0
  131. package/dist/src/media/contember.d.ts.map +1 -0
  132. package/dist/src/media/local.d.ts +9 -0
  133. package/dist/src/media/local.d.ts.map +1 -0
  134. package/dist/src/media/s3.d.ts +12 -0
  135. package/dist/src/media/s3.d.ts.map +1 -0
  136. package/dist/src/media/types.d.ts +40 -0
  137. package/dist/src/media/types.d.ts.map +1 -0
  138. package/dist/src/preview-generator.d.ts +19 -0
  139. package/dist/src/preview-generator.d.ts.map +1 -0
  140. package/dist/src/seo-processor.d.ts +23 -0
  141. package/dist/src/seo-processor.d.ts.map +1 -0
  142. package/dist/src/source-finder/ast-extractors.d.ts +35 -0
  143. package/dist/src/source-finder/ast-extractors.d.ts.map +1 -0
  144. package/dist/src/source-finder/ast-parser.d.ts +16 -0
  145. package/dist/src/source-finder/ast-parser.d.ts.map +1 -0
  146. package/dist/src/source-finder/cache.d.ts +18 -0
  147. package/dist/src/source-finder/cache.d.ts.map +1 -0
  148. package/dist/src/source-finder/collection-finder.d.ts +29 -0
  149. package/dist/src/source-finder/collection-finder.d.ts.map +1 -0
  150. package/dist/src/source-finder/cross-file-tracker.d.ts +39 -0
  151. package/dist/src/source-finder/cross-file-tracker.d.ts.map +1 -0
  152. package/dist/src/source-finder/element-finder.d.ts +42 -0
  153. package/dist/src/source-finder/element-finder.d.ts.map +1 -0
  154. package/dist/src/source-finder/image-finder.d.ts +24 -0
  155. package/dist/src/source-finder/image-finder.d.ts.map +1 -0
  156. package/dist/src/source-finder/index.d.ts +9 -0
  157. package/dist/src/source-finder/index.d.ts.map +1 -0
  158. package/dist/src/source-finder/search-index.d.ts +27 -0
  159. package/dist/src/source-finder/search-index.d.ts.map +1 -0
  160. package/dist/src/source-finder/snippet-utils.d.ts +90 -0
  161. package/dist/src/source-finder/snippet-utils.d.ts.map +1 -0
  162. package/dist/src/source-finder/source-lookup.d.ts +16 -0
  163. package/dist/src/source-finder/source-lookup.d.ts.map +1 -0
  164. package/dist/src/source-finder/types.d.ts +167 -0
  165. package/dist/src/source-finder/types.d.ts.map +1 -0
  166. package/dist/src/source-finder/variable-extraction.d.ts +37 -0
  167. package/dist/src/source-finder/variable-extraction.d.ts.map +1 -0
  168. package/dist/src/tailwind-colors.d.ts +54 -0
  169. package/dist/src/tailwind-colors.d.ts.map +1 -0
  170. package/dist/src/tsconfig.tsbuildinfo +1 -0
  171. package/dist/src/types.d.ts +367 -0
  172. package/dist/src/types.d.ts.map +1 -0
  173. package/dist/src/utils.d.ts +61 -0
  174. package/dist/src/utils.d.ts.map +1 -0
  175. package/dist/src/vite-plugin.d.ts +14 -0
  176. package/dist/src/vite-plugin.d.ts.map +1 -0
  177. package/dist/types/tsconfig.tsbuildinfo +1 -0
  178. package/package.json +80 -0
  179. package/src/build-processor.ts +784 -0
  180. package/src/collection-scanner.ts +304 -0
  181. package/src/component-registry.ts +393 -0
  182. package/src/config.ts +74 -0
  183. package/src/dev-middleware.ts +525 -0
  184. package/src/dist/src/tsconfig.tsbuildinfo +1 -0
  185. package/src/editor/ai.ts +185 -0
  186. package/src/editor/api.ts +513 -0
  187. package/src/editor/color-utils.ts +556 -0
  188. package/src/editor/components/ai-chat.tsx +632 -0
  189. package/src/editor/components/ai-tooltip.tsx +179 -0
  190. package/src/editor/components/attribute-editor.tsx +596 -0
  191. package/src/editor/components/block-editor.tsx +546 -0
  192. package/src/editor/components/collections-browser.tsx +248 -0
  193. package/src/editor/components/color-toolbar.tsx +314 -0
  194. package/src/editor/components/confirm-dialog.tsx +69 -0
  195. package/src/editor/components/create-page-modal.tsx +163 -0
  196. package/src/editor/components/editable-highlights.tsx +260 -0
  197. package/src/editor/components/error-boundary.tsx +87 -0
  198. package/src/editor/components/fields.tsx +387 -0
  199. package/src/editor/components/frontmatter-fields.tsx +469 -0
  200. package/src/editor/components/highlight-overlay.ts +229 -0
  201. package/src/editor/components/image-overlay.tsx +230 -0
  202. package/src/editor/components/markdown-editor-overlay.tsx +505 -0
  203. package/src/editor/components/markdown-inline-editor.tsx +780 -0
  204. package/src/editor/components/media-library.tsx +297 -0
  205. package/src/editor/components/outline.tsx +402 -0
  206. package/src/editor/components/redirect-countdown.tsx +45 -0
  207. package/src/editor/components/seo-editor.tsx +498 -0
  208. package/src/editor/components/text-style-toolbar.tsx +362 -0
  209. package/src/editor/components/toast/toast-container.tsx +15 -0
  210. package/src/editor/components/toast/toast.tsx +49 -0
  211. package/src/editor/components/toast/types.ts +7 -0
  212. package/src/editor/components/toolbar.tsx +366 -0
  213. package/src/editor/config.ts +12 -0
  214. package/src/editor/constants.ts +106 -0
  215. package/src/editor/context.tsx +38 -0
  216. package/src/editor/dom.ts +357 -0
  217. package/src/editor/editor.ts +1510 -0
  218. package/src/editor/env.d.ts +4 -0
  219. package/src/editor/history.ts +355 -0
  220. package/src/editor/hooks/index.ts +19 -0
  221. package/src/editor/hooks/useAIHandlers.ts +345 -0
  222. package/src/editor/hooks/useBlockEditorHandlers.ts +206 -0
  223. package/src/editor/hooks/useElementDetection.ts +284 -0
  224. package/src/editor/hooks/useImageHoverDetection.ts +102 -0
  225. package/src/editor/hooks/useTextSelection.ts +187 -0
  226. package/src/editor/hooks/useTooltipState.ts +126 -0
  227. package/src/editor/hooks/utils.ts +101 -0
  228. package/src/editor/index.tsx +481 -0
  229. package/src/editor/lib/cn.ts +4 -0
  230. package/src/editor/manifest.ts +25 -0
  231. package/src/editor/markdown-api.ts +209 -0
  232. package/src/editor/signals.ts +1351 -0
  233. package/src/editor/storage.ts +266 -0
  234. package/src/editor/styles.css +465 -0
  235. package/src/editor/text-styling.ts +773 -0
  236. package/src/editor/themes.ts +210 -0
  237. package/src/editor/types.ts +591 -0
  238. package/src/error-collector.ts +106 -0
  239. package/src/handlers/component-ops.ts +463 -0
  240. package/src/handlers/markdown-ops.ts +202 -0
  241. package/src/handlers/request-utils.ts +151 -0
  242. package/src/handlers/source-writer.ts +649 -0
  243. package/src/html-processor.ts +1108 -0
  244. package/src/index.ts +284 -0
  245. package/src/manifest-writer.ts +371 -0
  246. package/src/media/contember.ts +84 -0
  247. package/src/media/local.ts +114 -0
  248. package/src/media/s3.ts +133 -0
  249. package/src/media/types.ts +33 -0
  250. package/src/preview-generator.ts +293 -0
  251. package/src/seo-processor.ts +567 -0
  252. package/src/source-finder/ast-extractors.ts +185 -0
  253. package/src/source-finder/ast-parser.ts +150 -0
  254. package/src/source-finder/cache.ts +76 -0
  255. package/src/source-finder/collection-finder.ts +335 -0
  256. package/src/source-finder/cross-file-tracker.ts +741 -0
  257. package/src/source-finder/element-finder.ts +387 -0
  258. package/src/source-finder/image-finder.ts +283 -0
  259. package/src/source-finder/index.ts +37 -0
  260. package/src/source-finder/search-index.ts +525 -0
  261. package/src/source-finder/snippet-utils.ts +668 -0
  262. package/src/source-finder/source-lookup.ts +200 -0
  263. package/src/source-finder/types.ts +210 -0
  264. package/src/source-finder/variable-extraction.ts +406 -0
  265. package/src/tailwind-colors.ts +874 -0
  266. package/src/tsconfig.json +25 -0
  267. package/src/types.ts +406 -0
  268. package/src/utils.ts +186 -0
  269. package/src/vite-plugin.ts +42 -0
@@ -0,0 +1,200 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'node:path'
3
+
4
+ import { getProjectRoot } from '../config'
5
+ import { getCachedParsedFile } from './ast-parser'
6
+ import { isSearchIndexInitialized } from './cache'
7
+ import { searchForExpressionProp, searchForImportedValue, searchForPropInParents } from './cross-file-tracker'
8
+ import { findElementWithText } from './element-finder'
9
+ import { findInTextIndex } from './search-index'
10
+ import { extractCompleteTagSnippet, extractInnerHtmlFromSnippet, extractOpeningTagSnippet } from './snippet-utils'
11
+ import type { SourceLocation } from './types'
12
+
13
+ // ============================================================================
14
+ // Main Source Location Finding
15
+ // ============================================================================
16
+
17
+ /**
18
+ * Find source file and line number for text content.
19
+ * Uses pre-built search index for fast lookups.
20
+ */
21
+ export async function findSourceLocation(
22
+ textContent: string,
23
+ tag: string,
24
+ ): Promise<SourceLocation | undefined> {
25
+ // Use index if available (much faster)
26
+ if (isSearchIndexInitialized()) {
27
+ return findInTextIndex(textContent, tag)
28
+ }
29
+
30
+ // Fallback to slow search if index not initialized
31
+ const srcDir = path.join(getProjectRoot(), 'src')
32
+
33
+ try {
34
+ const searchDirs = [
35
+ path.join(srcDir, 'components'),
36
+ path.join(srcDir, 'pages'),
37
+ path.join(srcDir, 'layouts'),
38
+ ]
39
+
40
+ for (const dir of searchDirs) {
41
+ try {
42
+ const result = await searchDirectory(dir, textContent, tag)
43
+ if (result) {
44
+ return result
45
+ }
46
+ } catch {
47
+ // Directory doesn't exist, continue
48
+ }
49
+ }
50
+
51
+ // If not found directly, try searching for prop values in parent components
52
+ for (const dir of searchDirs) {
53
+ try {
54
+ const result = await searchForPropInParents(dir, textContent)
55
+ if (result) {
56
+ return result
57
+ }
58
+ } catch {
59
+ // Directory doesn't exist, continue
60
+ }
61
+ }
62
+ } catch {
63
+ // Search failed
64
+ }
65
+
66
+ return undefined
67
+ }
68
+
69
+ // ============================================================================
70
+ // Directory Search
71
+ // ============================================================================
72
+
73
+ /**
74
+ * Recursively search directory for matching content
75
+ */
76
+ export async function searchDirectory(
77
+ dir: string,
78
+ textContent: string,
79
+ tag: string,
80
+ ): Promise<SourceLocation | undefined> {
81
+ try {
82
+ const entries = await fs.readdir(dir, { withFileTypes: true })
83
+
84
+ for (const entry of entries) {
85
+ const fullPath = path.join(dir, entry.name)
86
+
87
+ if (entry.isDirectory()) {
88
+ const result = await searchDirectory(fullPath, textContent, tag)
89
+ if (result) return result
90
+ } else if (entry.isFile() && entry.name.endsWith('.astro')) {
91
+ const result = await searchAstroFile(fullPath, textContent, tag)
92
+ if (result) return result
93
+ }
94
+ }
95
+ } catch {
96
+ // Error reading directory
97
+ }
98
+
99
+ return undefined
100
+ }
101
+
102
+ // ============================================================================
103
+ // Astro File Search
104
+ // ============================================================================
105
+
106
+ /**
107
+ * Search a single Astro file for matching content using AST parsing.
108
+ * Uses caching for better performance.
109
+ */
110
+ export async function searchAstroFile(
111
+ filePath: string,
112
+ textContent: string,
113
+ tag: string,
114
+ ): Promise<SourceLocation | undefined> {
115
+ try {
116
+ // Use cached parsed file
117
+ const cached = await getCachedParsedFile(filePath)
118
+ if (!cached) return undefined
119
+
120
+ const { lines, ast, variableDefinitions, propAliases, imports } = cached
121
+
122
+ // Find matching element in template AST
123
+ const { bestMatch, propCandidates, importCandidates } = findElementWithText(
124
+ ast,
125
+ tag,
126
+ textContent,
127
+ variableDefinitions,
128
+ propAliases,
129
+ imports,
130
+ )
131
+
132
+ // First, check if we have a direct match (local variable or static content)
133
+ if (bestMatch && !bestMatch.usesProp && !bestMatch.usesImport) {
134
+ // Determine the editable line (definition for variables, usage for static)
135
+ const editableLine = bestMatch.type === 'variable' && bestMatch.definitionLine
136
+ ? bestMatch.definitionLine
137
+ : bestMatch.line
138
+
139
+ // Get the source snippet - complete element for static content, definition line for variables
140
+ let snippet: string
141
+ let openingTagSnippet: string | undefined
142
+ if (bestMatch.type === 'static') {
143
+ // For static content, extract the complete element (including wrapper tags)
144
+ snippet = extractCompleteTagSnippet(lines, editableLine - 1, tag)
145
+ // Also extract just the opening tag for attribute updates
146
+ openingTagSnippet = extractOpeningTagSnippet(lines, editableLine - 1, tag)
147
+ } else {
148
+ // For variables/props, just the definition line with indentation
149
+ snippet = lines[editableLine - 1] || ''
150
+ }
151
+
152
+ return {
153
+ file: path.relative(getProjectRoot(), filePath),
154
+ line: editableLine,
155
+ snippet,
156
+ openingTagSnippet,
157
+ type: bestMatch.type,
158
+ variableName: bestMatch.variableName,
159
+ definitionLine: bestMatch.type === 'variable' ? bestMatch.definitionLine : undefined,
160
+ }
161
+ }
162
+
163
+ // Try all prop candidates - verify each one to find the correct match
164
+ // (handles multiple same-tag elements with different prop values)
165
+ for (const propCandidate of propCandidates) {
166
+ if (propCandidate.propName && propCandidate.expressionPath) {
167
+ const componentFileName = path.basename(filePath)
168
+ const exprPropResult = await searchForExpressionProp(
169
+ componentFileName,
170
+ propCandidate.propName,
171
+ propCandidate.expressionPath,
172
+ textContent,
173
+ )
174
+ if (exprPropResult) {
175
+ return exprPropResult
176
+ }
177
+ }
178
+ }
179
+
180
+ // Try all import candidates - verify each one to find the correct match
181
+ // (handles multiple same-tag elements with different imported values)
182
+ for (const importCandidate of importCandidates) {
183
+ if (importCandidate.importInfo && importCandidate.expressionPath) {
184
+ const importResult = await searchForImportedValue(
185
+ filePath,
186
+ importCandidate.importInfo,
187
+ importCandidate.expressionPath,
188
+ textContent,
189
+ )
190
+ if (importResult) {
191
+ return importResult
192
+ }
193
+ }
194
+ }
195
+ } catch {
196
+ // Error reading/parsing file
197
+ }
198
+
199
+ return undefined
200
+ }
@@ -0,0 +1,210 @@
1
+ import type { Node as AstroNode } from '@astrojs/compiler/types'
2
+
3
+ // ============================================================================
4
+ // Import and Variable Information
5
+ // ============================================================================
6
+
7
+ /** Import information from frontmatter */
8
+ export interface ImportInfo {
9
+ /** Local name of the imported binding */
10
+ localName: string
11
+ /** Original exported name (or 'default' for default imports) */
12
+ importedName: string
13
+ /** The import source path (e.g., './config', '../data/nav') */
14
+ source: string
15
+ }
16
+
17
+ export interface VariableDefinition {
18
+ name: string
19
+ value: string
20
+ line: number
21
+ /** For object properties, the parent variable name */
22
+ parentName?: string
23
+ }
24
+
25
+ // ============================================================================
26
+ // Cached File Types
27
+ // ============================================================================
28
+
29
+ export interface CachedParsedFile {
30
+ content: string
31
+ lines: string[]
32
+ ast: AstroNode
33
+ frontmatterContent: string | null
34
+ frontmatterStartLine: number
35
+ variableDefinitions: VariableDefinition[]
36
+ /** Mapping of local variable names to prop names from Astro.props destructuring
37
+ * e.g., { navItems: 'items' } for `const { items: navItems } = Astro.props` */
38
+ propAliases: Map<string, string>
39
+ /** Import information from frontmatter */
40
+ imports: ImportInfo[]
41
+ }
42
+
43
+ // ============================================================================
44
+ // Search Index Types
45
+ // ============================================================================
46
+
47
+ /** Pre-built search index for fast lookups */
48
+ export interface SearchIndexEntry {
49
+ file: string
50
+ line: number
51
+ snippet: string
52
+ /** Just the opening tag with attributes (for attribute/class updates) */
53
+ openingTagSnippet?: string
54
+ type: 'static' | 'variable' | 'prop' | 'computed'
55
+ variableName?: string
56
+ definitionLine?: number
57
+ normalizedText: string
58
+ tag: string
59
+ }
60
+
61
+ export interface ImageIndexEntry {
62
+ file: string
63
+ line: number
64
+ snippet: string
65
+ src: string
66
+ }
67
+
68
+ // ============================================================================
69
+ // Source Location Types (Public API)
70
+ // ============================================================================
71
+
72
+ export interface SourceLocation {
73
+ file: string
74
+ line: number
75
+ snippet?: string
76
+ /** Just the opening tag with attributes (for attribute/class updates) */
77
+ openingTagSnippet?: string
78
+ type?: 'static' | 'variable' | 'prop' | 'computed' | 'collection'
79
+ variableName?: string
80
+ definitionLine?: number
81
+ /** Collection name for collection entries */
82
+ collectionName?: string
83
+ /** Entry slug for collection entries */
84
+ collectionSlug?: string
85
+ }
86
+
87
+ export interface VariableReference {
88
+ name: string
89
+ pattern: string
90
+ definitionLine: number
91
+ }
92
+
93
+ export interface CollectionInfo {
94
+ name: string
95
+ slug: string
96
+ file: string
97
+ }
98
+
99
+ export interface MarkdownContent {
100
+ /** Frontmatter fields as key-value pairs with line numbers */
101
+ frontmatter: Record<string, { value: string; line: number }>
102
+ /** The full markdown body content */
103
+ body: string
104
+ /** Line number where body starts */
105
+ bodyStartLine: number
106
+ /** File path relative to cwd */
107
+ file: string
108
+ /** Collection name */
109
+ collectionName: string
110
+ /** Collection slug */
111
+ collectionSlug: string
112
+ }
113
+
114
+ // ============================================================================
115
+ // AST Parsing Types
116
+ // ============================================================================
117
+
118
+ export interface ParsedAstroFile {
119
+ ast: AstroNode
120
+ frontmatterContent: string | null
121
+ frontmatterStartLine: number
122
+ }
123
+
124
+ /** Minimal Babel AST node type for our usage */
125
+ export interface BabelNode {
126
+ type: string
127
+ [key: string]: unknown
128
+ }
129
+
130
+ /** Minimal Babel File type */
131
+ export interface BabelFile {
132
+ type: 'File'
133
+ program: BabelNode & { body: BabelNode[] }
134
+ }
135
+
136
+ // ============================================================================
137
+ // Match Result Types
138
+ // ============================================================================
139
+
140
+ export interface TemplateMatch {
141
+ line: number
142
+ type: 'static' | 'variable' | 'computed'
143
+ variableName?: string
144
+ /** For variables, the definition line in frontmatter */
145
+ definitionLine?: number
146
+ /** If true, the expression uses a variable from props that needs cross-file tracking */
147
+ usesProp?: boolean
148
+ /** The prop name if usesProp is true */
149
+ propName?: string
150
+ /** The full expression path if usesProp is true (e.g., 'items[0]') */
151
+ expressionPath?: string
152
+ /** If true, the expression uses a variable from an import */
153
+ usesImport?: boolean
154
+ /** The import info if usesImport is true */
155
+ importInfo?: ImportInfo
156
+ }
157
+
158
+ /** Result type for findElementWithText - returns best match and all prop/import candidates */
159
+ export interface FindElementResult {
160
+ /** The best match found (local variables or static content) */
161
+ bestMatch: TemplateMatch | null
162
+ /** All prop-based matches for the tag (need cross-file verification) */
163
+ propCandidates: TemplateMatch[]
164
+ /** All import-based matches for the tag (need cross-file verification) */
165
+ importCandidates: TemplateMatch[]
166
+ }
167
+
168
+ export interface ComponentPropMatch {
169
+ line: number
170
+ propName: string
171
+ propValue: string
172
+ }
173
+
174
+ export interface ExpressionPropMatch {
175
+ componentName: string
176
+ propName: string
177
+ /** The expression text (e.g., 'navItems' from items={navItems}) */
178
+ expressionText: string
179
+ line: number
180
+ }
181
+
182
+ export interface SpreadPropMatch {
183
+ componentName: string
184
+ /** The variable name being spread (e.g., 'cardProps' from {...cardProps}) */
185
+ spreadVarName: string
186
+ line: number
187
+ }
188
+
189
+ export interface ImageMatch {
190
+ line: number
191
+ src: string
192
+ snippet: string
193
+ }
194
+
195
+ // ============================================================================
196
+ // Line Transformer for AST Extraction
197
+ // ============================================================================
198
+
199
+ /**
200
+ * Transforms Babel line numbers to actual file line numbers.
201
+ * Babel parses content starting at line 1, but frontmatter content
202
+ * may start at a different line in the actual file.
203
+ */
204
+ export type LineTransformer = (babelLine: number) => number
205
+
206
+ /** Identity transformer - use for standalone files where Babel line = file line */
207
+ export const identityLine: LineTransformer = (line) => line
208
+
209
+ /** Create a transformer for frontmatter content that starts at a specific line */
210
+ export const createFrontmatterLineTransformer = (startLine: number): LineTransformer => (babelLine) => (babelLine - 1) + startLine