@nuasite/cms-marker 0.0.65 → 0.0.66
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/dist/types/build-processor.d.ts +2 -1
- package/dist/types/build-processor.d.ts.map +1 -1
- package/dist/types/component-registry.d.ts.map +1 -1
- package/dist/types/config.d.ts +19 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/dev-middleware.d.ts +10 -2
- package/dist/types/dev-middleware.d.ts.map +1 -1
- package/dist/types/error-collector.d.ts +56 -0
- package/dist/types/error-collector.d.ts.map +1 -0
- package/dist/types/html-processor.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/manifest-writer.d.ts.map +1 -1
- package/dist/types/source-finder.d.ts +18 -3
- package/dist/types/source-finder.d.ts.map +1 -1
- package/dist/types/tailwind-colors.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/types.d.ts +0 -4
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/vite-plugin.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/build-processor.ts +73 -19
- package/src/component-registry.ts +2 -0
- package/src/config.ts +29 -0
- package/src/dev-middleware.ts +12 -4
- package/src/error-collector.ts +106 -0
- package/src/html-processor.ts +55 -37
- package/src/index.ts +20 -4
- package/src/manifest-writer.ts +12 -2
- package/src/source-finder.ts +1003 -295
- package/src/tailwind-colors.ts +248 -48
- package/src/types.ts +0 -4
- package/src/vite-plugin.ts +4 -12
- package/dist/types/astro-transform.d.ts +0 -21
- package/dist/types/astro-transform.d.ts.map +0 -1
- package/src/astro-transform.ts +0 -205
package/dist/types/types.d.ts
CHANGED
|
@@ -139,10 +139,6 @@ export interface ManifestEntry {
|
|
|
139
139
|
collectionSlug?: string;
|
|
140
140
|
/** Path to the markdown content file (e.g., 'src/content/blog/my-post.md') */
|
|
141
141
|
contentPath?: string;
|
|
142
|
-
/** Image source URL (for image entries) - deprecated, use imageMetadata */
|
|
143
|
-
imageSrc?: string;
|
|
144
|
-
/** Image alt text (for image entries) - deprecated, use imageMetadata */
|
|
145
|
-
imageAlt?: string;
|
|
146
142
|
/** Stable ID derived from content + context hash, survives rebuilds */
|
|
147
143
|
stableId?: string;
|
|
148
144
|
/** SHA256 hash of sourceSnippet at generation time for conflict detection */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC7B,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC7B,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,eAAe;IACf,GAAG,EAAE,MAAM,CAAA;IACX,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9C,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IAClC,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC7B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC5B,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC/B,6CAA6C;IAC7C,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,mCAAmC;IACnC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,0DAA0D;AAC1D,MAAM,WAAW,cAAc;IAC9B,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC3B;AAED,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IACnC,yDAAyD;IACzD,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,4DAA4D;IAC5D,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,8DAA8D;IAC9D,cAAc,EAAE,cAAc,EAAE,CAAA;IAChC,8CAA8C;IAC9C,SAAS,EAAE,cAAc,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,CAAA;IACjF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAEpE,MAAM,WAAW,iBAAiB;IACjC,cAAc,EAAE,cAAc,CAAA;IAC9B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;IACzD,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IAClC,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5B,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAA;CAC7C;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,EAAE,CA6BrE"}
|
package/package.json
CHANGED
|
@@ -14,12 +14,13 @@
|
|
|
14
14
|
"directory": "packages/cms-marker"
|
|
15
15
|
},
|
|
16
16
|
"license": "Apache-2.0",
|
|
17
|
-
"version": "0.0.
|
|
17
|
+
"version": "0.0.66",
|
|
18
18
|
"module": "src/index.ts",
|
|
19
19
|
"types": "src/index.ts",
|
|
20
20
|
"type": "module",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@astrojs/compiler": "^2.13.0",
|
|
23
|
+
"@babel/parser": "^7.24.0",
|
|
23
24
|
"astro": "^5.16.6",
|
|
24
25
|
"node-html-parser": "^6.1.13"
|
|
25
26
|
},
|
package/src/build-processor.ts
CHANGED
|
@@ -4,7 +4,15 @@ import path from 'node:path'
|
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
import { processHtml } from './html-processor'
|
|
6
6
|
import type { ManifestWriter } from './manifest-writer'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
clearSourceFinderCache,
|
|
9
|
+
findCollectionSource,
|
|
10
|
+
findImageSourceLocation,
|
|
11
|
+
findMarkdownSourceLocation,
|
|
12
|
+
findSourceLocation,
|
|
13
|
+
initializeSearchIndex,
|
|
14
|
+
parseMarkdownContent,
|
|
15
|
+
} from './source-finder'
|
|
8
16
|
import type { CmsMarkerOptions, CollectionEntry } from './types'
|
|
9
17
|
|
|
10
18
|
// Concurrency limit for parallel processing
|
|
@@ -110,22 +118,23 @@ async function processFile(
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
|
|
113
|
-
|
|
121
|
+
// Process entries in parallel for better performance
|
|
122
|
+
const entryLookups = Object.values(result.entries).map(async (entry) => {
|
|
114
123
|
// Skip entries that already have source info from component detection
|
|
115
124
|
if (entry.sourcePath && !entry.sourcePath.endsWith('.html')) {
|
|
116
|
-
|
|
125
|
+
return
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
// Handle image entries specially - search by image src
|
|
120
|
-
if (entry.sourceType === 'image' && entry.
|
|
121
|
-
const imageSource = await findImageSourceLocation(entry.
|
|
129
|
+
if (entry.sourceType === 'image' && entry.imageMetadata?.src) {
|
|
130
|
+
const imageSource = await findImageSourceLocation(entry.imageMetadata.src)
|
|
122
131
|
if (imageSource) {
|
|
123
132
|
entry.sourcePath = imageSource.file
|
|
124
133
|
entry.sourceLine = imageSource.line
|
|
125
134
|
entry.sourceSnippet = imageSource.snippet
|
|
126
135
|
entry.sourceType = 'image'
|
|
127
136
|
}
|
|
128
|
-
|
|
137
|
+
return
|
|
129
138
|
}
|
|
130
139
|
|
|
131
140
|
// Try to find source in collection markdown frontmatter first
|
|
@@ -139,7 +148,7 @@ async function processFile(
|
|
|
139
148
|
entry.variableName = mdSource.variableName
|
|
140
149
|
entry.collectionName = mdSource.collectionName
|
|
141
150
|
entry.collectionSlug = mdSource.collectionSlug
|
|
142
|
-
|
|
151
|
+
return
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
154
|
|
|
@@ -152,7 +161,9 @@ async function processFile(
|
|
|
152
161
|
entry.sourceType = sourceLocation.type
|
|
153
162
|
entry.variableName = sourceLocation.variableName
|
|
154
163
|
}
|
|
155
|
-
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
await Promise.all(entryLookups)
|
|
156
167
|
|
|
157
168
|
// Add to manifest writer (handles per-page manifest writes)
|
|
158
169
|
manifestWriter.addPage(pagePath, result.entries, result.components, collectionEntry)
|
|
@@ -163,8 +174,15 @@ async function processFile(
|
|
|
163
174
|
return Object.keys(result.entries).length
|
|
164
175
|
}
|
|
165
176
|
|
|
177
|
+
/** Result of batch processing with error aggregation */
|
|
178
|
+
interface BatchProcessingResult {
|
|
179
|
+
totalEntries: number
|
|
180
|
+
errors: Array<{ file: string; error: Error }>
|
|
181
|
+
}
|
|
182
|
+
|
|
166
183
|
/**
|
|
167
|
-
* Process HTML files in parallel with concurrency limit
|
|
184
|
+
* Process HTML files in parallel with concurrency limit and error aggregation.
|
|
185
|
+
* Unlike Promise.all, this continues processing even if some files fail.
|
|
168
186
|
*/
|
|
169
187
|
async function processFilesInBatches(
|
|
170
188
|
files: string[],
|
|
@@ -172,23 +190,37 @@ async function processFilesInBatches(
|
|
|
172
190
|
config: Required<CmsMarkerOptions>,
|
|
173
191
|
manifestWriter: ManifestWriter,
|
|
174
192
|
idCounter: { value: number },
|
|
175
|
-
): Promise<
|
|
193
|
+
): Promise<BatchProcessingResult> {
|
|
176
194
|
let totalEntries = 0
|
|
195
|
+
const errors: Array<{ file: string; error: Error }> = []
|
|
177
196
|
|
|
178
197
|
// Process files in batches of MAX_CONCURRENT
|
|
179
198
|
for (let i = 0; i < files.length; i += MAX_CONCURRENT) {
|
|
180
199
|
const batch = files.slice(i, i + MAX_CONCURRENT)
|
|
181
|
-
const results = await Promise.
|
|
182
|
-
batch.map(file =>
|
|
200
|
+
const results = await Promise.allSettled(
|
|
201
|
+
batch.map(file =>
|
|
202
|
+
processFile(file, outDir, config, manifestWriter, idCounter)
|
|
203
|
+
.then(count => ({ file, count }))
|
|
204
|
+
.catch(err => Promise.reject({ file, error: err }))
|
|
205
|
+
),
|
|
183
206
|
)
|
|
184
|
-
|
|
207
|
+
|
|
208
|
+
for (const result of results) {
|
|
209
|
+
if (result.status === 'fulfilled') {
|
|
210
|
+
totalEntries += result.value.count
|
|
211
|
+
} else {
|
|
212
|
+
const { file, error } = result.reason as { file: string; error: Error }
|
|
213
|
+
errors.push({ file, error })
|
|
214
|
+
}
|
|
215
|
+
}
|
|
185
216
|
}
|
|
186
217
|
|
|
187
|
-
return totalEntries
|
|
218
|
+
return { totalEntries, errors }
|
|
188
219
|
}
|
|
189
220
|
|
|
190
221
|
/**
|
|
191
|
-
* Process build output - processes all HTML files in parallel
|
|
222
|
+
* Process build output - processes all HTML files in parallel.
|
|
223
|
+
* Uses error aggregation to continue processing even if some files fail.
|
|
192
224
|
*/
|
|
193
225
|
export async function processBuildOutput(
|
|
194
226
|
dir: URL,
|
|
@@ -200,6 +232,9 @@ export async function processBuildOutput(
|
|
|
200
232
|
const outDir = fileURLToPath(dir)
|
|
201
233
|
manifestWriter.setOutDir(outDir)
|
|
202
234
|
|
|
235
|
+
// Clear caches from previous builds and initialize search index
|
|
236
|
+
clearSourceFinderCache()
|
|
237
|
+
|
|
203
238
|
const htmlFiles = await findHtmlFiles(outDir)
|
|
204
239
|
|
|
205
240
|
if (htmlFiles.length === 0) {
|
|
@@ -209,17 +244,36 @@ export async function processBuildOutput(
|
|
|
209
244
|
|
|
210
245
|
const startTime = Date.now()
|
|
211
246
|
|
|
212
|
-
//
|
|
213
|
-
await
|
|
247
|
+
// Pre-build search index for fast source lookups (single pass through all source files)
|
|
248
|
+
await initializeSearchIndex()
|
|
249
|
+
|
|
250
|
+
// Process all files in parallel batches with error aggregation
|
|
251
|
+
const { totalEntries, errors } = await processFilesInBatches(htmlFiles, outDir, config, manifestWriter, idCounter)
|
|
252
|
+
|
|
253
|
+
// Report any errors that occurred during processing
|
|
254
|
+
if (errors.length > 0) {
|
|
255
|
+
const errorLog = logger?.error?.bind(logger) ?? console.error.bind(console)
|
|
256
|
+
errorLog(`[astro-cms-marker] ${errors.length} file(s) failed to process:`)
|
|
257
|
+
for (const { file, error } of errors) {
|
|
258
|
+
const relPath = path.relative(outDir, file)
|
|
259
|
+
errorLog(` - ${relPath}: ${error.message}`)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
214
262
|
|
|
215
263
|
// Finalize manifest (writes global manifest and waits for all per-page writes)
|
|
216
264
|
const stats = await manifestWriter.finalize()
|
|
217
265
|
|
|
218
266
|
const duration = Date.now() - startTime
|
|
219
|
-
const
|
|
267
|
+
const successCount = htmlFiles.length - errors.length
|
|
268
|
+
const msg =
|
|
269
|
+
`Processed ${successCount}/${htmlFiles.length} pages with ${stats.totalEntries} entries and ${stats.totalComponents} components in ${duration}ms`
|
|
220
270
|
|
|
221
271
|
if (logger) {
|
|
222
|
-
|
|
272
|
+
if (errors.length > 0) {
|
|
273
|
+
logger.warn(msg)
|
|
274
|
+
} else {
|
|
275
|
+
logger.info(msg)
|
|
276
|
+
}
|
|
223
277
|
} else {
|
|
224
278
|
console.log(`[astro-cms-marker] ${msg}`)
|
|
225
279
|
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global configuration for cms-marker.
|
|
3
|
+
* This allows overriding the project root for testing.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
let projectRootOverride: string | null = null
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get the current project root directory.
|
|
10
|
+
* Returns the override if set, otherwise process.cwd().
|
|
11
|
+
*/
|
|
12
|
+
export function getProjectRoot(): string {
|
|
13
|
+
return projectRootOverride ?? process.cwd()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Set the project root directory override.
|
|
18
|
+
* Call this to use a specific directory instead of process.cwd().
|
|
19
|
+
*/
|
|
20
|
+
export function setProjectRoot(root: string): void {
|
|
21
|
+
projectRootOverride = root
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Reset the project root to use process.cwd() again.
|
|
26
|
+
*/
|
|
27
|
+
export function resetProjectRoot(): void {
|
|
28
|
+
projectRootOverride = null
|
|
29
|
+
}
|
package/src/dev-middleware.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
2
2
|
import { processHtml } from './html-processor'
|
|
3
3
|
import type { ManifestWriter } from './manifest-writer'
|
|
4
4
|
import { findCollectionSource, findImageSourceLocation, parseMarkdownContent } from './source-finder'
|
|
5
5
|
import type { CmsMarkerOptions, CollectionEntry, ComponentDefinition } from './types'
|
|
6
6
|
|
|
7
|
+
/** Minimal ViteDevServer interface to avoid version conflicts between Astro's bundled Vite and root Vite */
|
|
8
|
+
interface ViteDevServerLike {
|
|
9
|
+
middlewares: {
|
|
10
|
+
use: (middleware: (req: IncomingMessage, res: ServerResponse, next: () => void) => void) => void
|
|
11
|
+
}
|
|
12
|
+
transformIndexHtml: (url: string, html: string) => Promise<string>
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* Get the normalized page path from a URL
|
|
9
17
|
* For example: /about/ -> /about
|
|
@@ -21,7 +29,7 @@ function normalizePagePath(url: string): string {
|
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
export function createDevMiddleware(
|
|
24
|
-
server:
|
|
32
|
+
server: ViteDevServerLike,
|
|
25
33
|
config: Required<CmsMarkerOptions>,
|
|
26
34
|
manifestWriter: ManifestWriter,
|
|
27
35
|
componentDefinitions: Record<string, ComponentDefinition>,
|
|
@@ -217,8 +225,8 @@ async function processHtmlForDev(
|
|
|
217
225
|
// However, images may not have source info if their ancestors don't have it
|
|
218
226
|
// In that case, fall back to searching for the image src
|
|
219
227
|
for (const entry of Object.values(result.entries)) {
|
|
220
|
-
if (entry.sourceType === 'image' && entry.
|
|
221
|
-
const imageSource = await findImageSourceLocation(entry.
|
|
228
|
+
if (entry.sourceType === 'image' && entry.imageMetadata?.src && !entry.sourcePath) {
|
|
229
|
+
const imageSource = await findImageSourceLocation(entry.imageMetadata.src)
|
|
222
230
|
if (imageSource) {
|
|
223
231
|
entry.sourcePath = imageSource.file
|
|
224
232
|
entry.sourceLine = imageSource.line
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collects errors during processing for aggregated reporting.
|
|
3
|
+
* This allows the build to continue while tracking what failed.
|
|
4
|
+
*/
|
|
5
|
+
export class ErrorCollector {
|
|
6
|
+
private errors: Array<{ context: string; error: Error }> = []
|
|
7
|
+
private warnings: Array<{ context: string; message: string }> = []
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Record an error with context about where it occurred.
|
|
11
|
+
*/
|
|
12
|
+
addError(context: string, error: Error): void {
|
|
13
|
+
this.errors.push({ context, error })
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Record a warning (non-fatal issue).
|
|
18
|
+
*/
|
|
19
|
+
addWarning(context: string, message: string): void {
|
|
20
|
+
this.warnings.push({ context, message })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if any errors were recorded.
|
|
25
|
+
*/
|
|
26
|
+
hasErrors(): boolean {
|
|
27
|
+
return this.errors.length > 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if any warnings were recorded.
|
|
32
|
+
*/
|
|
33
|
+
hasWarnings(): boolean {
|
|
34
|
+
return this.warnings.length > 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get all recorded errors.
|
|
39
|
+
*/
|
|
40
|
+
getErrors(): ReadonlyArray<{ context: string; error: Error }> {
|
|
41
|
+
return this.errors
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get all recorded warnings.
|
|
46
|
+
*/
|
|
47
|
+
getWarnings(): ReadonlyArray<{ context: string; message: string }> {
|
|
48
|
+
return this.warnings
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get a summary of all errors and warnings.
|
|
53
|
+
*/
|
|
54
|
+
getSummary(): string {
|
|
55
|
+
const lines: string[] = []
|
|
56
|
+
|
|
57
|
+
if (this.errors.length > 0) {
|
|
58
|
+
lines.push(`${this.errors.length} error(s):`)
|
|
59
|
+
for (const { context, error } of this.errors) {
|
|
60
|
+
lines.push(` - ${context}: ${error.message}`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.warnings.length > 0) {
|
|
65
|
+
lines.push(`${this.warnings.length} warning(s):`)
|
|
66
|
+
for (const { context, message } of this.warnings) {
|
|
67
|
+
lines.push(` - ${context}: ${message}`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return lines.join('\n')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Clear all recorded errors and warnings.
|
|
76
|
+
*/
|
|
77
|
+
clear(): void {
|
|
78
|
+
this.errors = []
|
|
79
|
+
this.warnings = []
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Singleton error collector for the build process */
|
|
84
|
+
let globalErrorCollector: ErrorCollector | null = null
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get the global error collector instance.
|
|
88
|
+
* Creates one if it doesn't exist.
|
|
89
|
+
*/
|
|
90
|
+
export function getErrorCollector(): ErrorCollector {
|
|
91
|
+
if (!globalErrorCollector) {
|
|
92
|
+
globalErrorCollector = new ErrorCollector()
|
|
93
|
+
}
|
|
94
|
+
return globalErrorCollector
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Reset the global error collector (call at start of each build).
|
|
99
|
+
*/
|
|
100
|
+
export function resetErrorCollector(): void {
|
|
101
|
+
if (globalErrorCollector) {
|
|
102
|
+
globalErrorCollector.clear()
|
|
103
|
+
} else {
|
|
104
|
+
globalErrorCollector = new ErrorCollector()
|
|
105
|
+
}
|
|
106
|
+
}
|
package/src/html-processor.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { parse } from 'node-html-parser'
|
|
1
|
+
import { type HTMLElement as ParsedHTMLElement, parse } from 'node-html-parser'
|
|
2
2
|
import { enhanceManifestWithSourceSnippets } from './source-finder'
|
|
3
3
|
import { extractColorClasses } from './tailwind-colors'
|
|
4
|
-
import type { ComponentInstance, ManifestEntry, SourceContext } from './types'
|
|
4
|
+
import type { ComponentInstance, ImageMetadata, ManifestEntry, SourceContext } from './types'
|
|
5
5
|
import { generateStableId } from './utils'
|
|
6
6
|
|
|
7
|
+
/** Type for parsed HTML element nodes from node-html-parser */
|
|
8
|
+
type HTMLNode = ParsedHTMLElement
|
|
9
|
+
|
|
7
10
|
/**
|
|
8
11
|
* Inline text styling elements that should NOT be marked with CMS IDs.
|
|
9
12
|
* These elements are text formatting and should be part of their parent's content.
|
|
@@ -187,7 +190,7 @@ export async function processHtml(
|
|
|
187
190
|
const entries: Record<string, ManifestEntry> = {}
|
|
188
191
|
const components: Record<string, ComponentInstance> = {}
|
|
189
192
|
const sourceLocationMap = new Map<string, { file: string; line: number }>()
|
|
190
|
-
const markedComponentRoots = new Set<
|
|
193
|
+
const markedComponentRoots = new Set<HTMLNode>()
|
|
191
194
|
let collectionWrapperId: string | undefined
|
|
192
195
|
|
|
193
196
|
// First pass: detect and mark component root elements
|
|
@@ -222,15 +225,15 @@ export async function processHtml(
|
|
|
222
225
|
|
|
223
226
|
// Check if any ancestor is already marked as a component root from the same file
|
|
224
227
|
// (we only want to mark the outermost element from each component)
|
|
225
|
-
let parent = node.parentNode
|
|
228
|
+
let parent = node.parentNode as HTMLNode | null
|
|
226
229
|
let ancestorFromSameComponent = false
|
|
227
230
|
while (parent) {
|
|
228
|
-
const parentSource =
|
|
231
|
+
const parentSource = parent.getAttribute?.('data-astro-source-file')
|
|
229
232
|
if (parentSource === sourceFile) {
|
|
230
233
|
ancestorFromSameComponent = true
|
|
231
234
|
break
|
|
232
235
|
}
|
|
233
|
-
parent = parent.parentNode
|
|
236
|
+
parent = parent.parentNode as HTMLNode | null
|
|
234
237
|
}
|
|
235
238
|
|
|
236
239
|
if (ancestorFromSameComponent) return
|
|
@@ -279,7 +282,12 @@ export async function processHtml(
|
|
|
279
282
|
|
|
280
283
|
// Image detection pass: mark img elements for CMS image replacement
|
|
281
284
|
// Store image entries separately to add to manifest later
|
|
282
|
-
|
|
285
|
+
interface ImageEntry {
|
|
286
|
+
metadata: ImageMetadata
|
|
287
|
+
sourceFile?: string
|
|
288
|
+
sourceLine?: number
|
|
289
|
+
}
|
|
290
|
+
const imageEntries = new Map<string, ImageEntry>()
|
|
283
291
|
root.querySelectorAll('img').forEach((node) => {
|
|
284
292
|
// Skip if already marked
|
|
285
293
|
if (node.getAttribute(attributeName)) return
|
|
@@ -294,7 +302,7 @@ export async function processHtml(
|
|
|
294
302
|
// Try to get source location from the image itself or ancestors
|
|
295
303
|
let sourceFile: string | undefined
|
|
296
304
|
let sourceLine: number | undefined
|
|
297
|
-
let current:
|
|
305
|
+
let current: HTMLNode | null = node
|
|
298
306
|
while (current && !sourceFile) {
|
|
299
307
|
const file = current.getAttribute?.('data-astro-source-file')
|
|
300
308
|
const line = current.getAttribute?.('data-astro-source-loc') || current.getAttribute?.('data-astro-source-line')
|
|
@@ -307,13 +315,20 @@ export async function processHtml(
|
|
|
307
315
|
}
|
|
308
316
|
}
|
|
309
317
|
}
|
|
310
|
-
current = current.parentNode
|
|
318
|
+
current = current.parentNode as HTMLNode | null
|
|
311
319
|
}
|
|
312
320
|
|
|
313
|
-
//
|
|
314
|
-
|
|
321
|
+
// Build image metadata
|
|
322
|
+
const metadata: ImageMetadata = {
|
|
315
323
|
src,
|
|
316
324
|
alt: node.getAttribute('alt') || '',
|
|
325
|
+
srcSet: node.getAttribute('srcset') || undefined,
|
|
326
|
+
sizes: node.getAttribute('sizes') || undefined,
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Store image info for manifest
|
|
330
|
+
imageEntries.set(id, {
|
|
331
|
+
metadata,
|
|
317
332
|
sourceFile,
|
|
318
333
|
sourceLine,
|
|
319
334
|
})
|
|
@@ -335,23 +350,23 @@ export async function processHtml(
|
|
|
335
350
|
// Check if this element has any direct child elements without source file attribute
|
|
336
351
|
// These would be markdown-rendered elements
|
|
337
352
|
const childElements = node.childNodes.filter(
|
|
338
|
-
(child:
|
|
353
|
+
(child): child is HTMLNode => child.nodeType === 1 && 'tagName' in child,
|
|
339
354
|
)
|
|
340
355
|
const hasMarkdownChildren = childElements.some(
|
|
341
|
-
(child
|
|
356
|
+
(child) => !child.getAttribute?.('data-astro-source-file'),
|
|
342
357
|
)
|
|
343
358
|
|
|
344
359
|
if (hasMarkdownChildren) {
|
|
345
360
|
// Check if any ancestor already has been marked as a collection wrapper
|
|
346
361
|
// We want the innermost wrapper
|
|
347
|
-
let parent = node.parentNode
|
|
362
|
+
let parent = node.parentNode as HTMLNode | null
|
|
348
363
|
let hasAncestorWrapper = false
|
|
349
364
|
while (parent) {
|
|
350
|
-
if (
|
|
365
|
+
if (parent.getAttribute?.(attributeName)?.startsWith('cms-collection-')) {
|
|
351
366
|
hasAncestorWrapper = true
|
|
352
367
|
break
|
|
353
368
|
}
|
|
354
|
-
parent = parent.parentNode
|
|
369
|
+
parent = parent.parentNode as HTMLNode | null
|
|
355
370
|
}
|
|
356
371
|
|
|
357
372
|
if (!hasAncestorWrapper) {
|
|
@@ -382,7 +397,7 @@ export async function processHtml(
|
|
|
382
397
|
|
|
383
398
|
if (bodyStart.length > 10) {
|
|
384
399
|
// Store all candidates that match the body start
|
|
385
|
-
const candidates: Array<{ node:
|
|
400
|
+
const candidates: Array<{ node: HTMLNode; blockChildCount: number }> = []
|
|
386
401
|
|
|
387
402
|
for (const node of allElements) {
|
|
388
403
|
const tag = node.tagName?.toLowerCase?.() ?? ''
|
|
@@ -391,8 +406,8 @@ export async function processHtml(
|
|
|
391
406
|
|
|
392
407
|
// Check if this element's first text content starts with the markdown body
|
|
393
408
|
const firstChild = node.childNodes.find(
|
|
394
|
-
(child:
|
|
395
|
-
)
|
|
409
|
+
(child): child is HTMLNode => child.nodeType === 1 && 'tagName' in child,
|
|
410
|
+
)
|
|
396
411
|
|
|
397
412
|
if (firstChild) {
|
|
398
413
|
const firstChildText = (firstChild.innerText || '').trim().substring(0, 80)
|
|
@@ -401,7 +416,8 @@ export async function processHtml(
|
|
|
401
416
|
// Markdown typically renders to multiple block elements (p, h2, h3, ul, ol, etc.)
|
|
402
417
|
const blockTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'blockquote', 'pre', 'table', 'hr']
|
|
403
418
|
const blockChildCount = node.childNodes.filter(
|
|
404
|
-
(child:
|
|
419
|
+
(child): child is HTMLNode =>
|
|
420
|
+
child.nodeType === 1 && 'tagName' in child && blockTags.includes((child as HTMLNode).tagName?.toLowerCase?.() ?? ''),
|
|
405
421
|
).length
|
|
406
422
|
|
|
407
423
|
candidates.push({ node, blockChildCount })
|
|
@@ -495,11 +511,14 @@ export async function processHtml(
|
|
|
495
511
|
|
|
496
512
|
// Get child CMS elements
|
|
497
513
|
const childCmsElements = node.querySelectorAll(`[${attributeName}]`)
|
|
498
|
-
const childCmsIds = Array.from(childCmsElements)
|
|
514
|
+
const childCmsIds = Array.from(childCmsElements)
|
|
515
|
+
.map((child) => child.getAttribute(attributeName))
|
|
516
|
+
.filter((id): id is string => id !== null)
|
|
499
517
|
|
|
500
518
|
// Build text with placeholders for child CMS elements
|
|
501
519
|
// Recursively process child nodes to handle nested CMS elements correctly
|
|
502
|
-
|
|
520
|
+
type ChildNode = { nodeType: number; text?: string; childNodes?: ChildNode[]; getAttribute?: (name: string) => string | null }
|
|
521
|
+
const buildTextWithPlaceholders = (nodes: ChildNode[]): string => {
|
|
503
522
|
let text = ''
|
|
504
523
|
for (const child of nodes) {
|
|
505
524
|
if (child.nodeType === 3) {
|
|
@@ -507,21 +526,21 @@ export async function processHtml(
|
|
|
507
526
|
text += child.text || ''
|
|
508
527
|
} else if (child.nodeType === 1) {
|
|
509
528
|
// Element node
|
|
510
|
-
const directCmsId =
|
|
529
|
+
const directCmsId = child.getAttribute?.(attributeName)
|
|
511
530
|
|
|
512
531
|
if (directCmsId) {
|
|
513
532
|
// Child has a direct CMS ID - use placeholder
|
|
514
533
|
text += `{{cms:${directCmsId}}}`
|
|
515
534
|
} else {
|
|
516
535
|
// Child doesn't have a CMS ID - recursively process its children
|
|
517
|
-
text += buildTextWithPlaceholders(child.childNodes || [])
|
|
536
|
+
text += buildTextWithPlaceholders((child.childNodes || []) as ChildNode[])
|
|
518
537
|
}
|
|
519
538
|
}
|
|
520
539
|
}
|
|
521
540
|
return text
|
|
522
541
|
}
|
|
523
542
|
|
|
524
|
-
const textWithPlaceholders = buildTextWithPlaceholders(node.childNodes || [])
|
|
543
|
+
const textWithPlaceholders = buildTextWithPlaceholders((node.childNodes || []) as ChildNode[])
|
|
525
544
|
|
|
526
545
|
// Get direct text content (without placeholders)
|
|
527
546
|
const directText = textWithPlaceholders.replace(/\{\{cms:[^}]+\}\}/g, '').trim()
|
|
@@ -540,14 +559,14 @@ export async function processHtml(
|
|
|
540
559
|
|
|
541
560
|
// Find parent component if any
|
|
542
561
|
let parentComponentId: string | undefined
|
|
543
|
-
let parent = node.parentNode
|
|
562
|
+
let parent = node.parentNode as HTMLNode | null
|
|
544
563
|
while (parent) {
|
|
545
|
-
const parentCompId =
|
|
564
|
+
const parentCompId = parent.getAttribute?.('data-cms-component-id')
|
|
546
565
|
if (parentCompId) {
|
|
547
566
|
parentComponentId = parentCompId
|
|
548
567
|
break
|
|
549
568
|
}
|
|
550
|
-
parent = parent.parentNode
|
|
569
|
+
parent = parent.parentNode as HTMLNode | null
|
|
551
570
|
}
|
|
552
571
|
|
|
553
572
|
// Extract source context for resilient matching
|
|
@@ -564,7 +583,7 @@ export async function processHtml(
|
|
|
564
583
|
const imageInfo = imageEntries.get(id)
|
|
565
584
|
const isImage = !!imageInfo
|
|
566
585
|
|
|
567
|
-
const entryText = isImage ? (imageInfo.alt || imageInfo.src) : textWithPlaceholders.trim()
|
|
586
|
+
const entryText = isImage ? (imageInfo.metadata.alt || imageInfo.metadata.src) : textWithPlaceholders.trim()
|
|
568
587
|
// For images, use the source file we captured from ancestors if not in sourceLocationMap
|
|
569
588
|
const entrySourcePath = sourceLocation?.file || imageInfo?.sourceFile || sourcePath
|
|
570
589
|
|
|
@@ -591,12 +610,11 @@ export async function processHtml(
|
|
|
591
610
|
collectionName: isCollectionWrapper ? collectionInfo?.name : undefined,
|
|
592
611
|
collectionSlug: isCollectionWrapper ? collectionInfo?.slug : undefined,
|
|
593
612
|
contentPath: isCollectionWrapper ? collectionInfo?.contentPath : undefined,
|
|
594
|
-
// Add image info for image entries
|
|
595
|
-
imageSrc: imageInfo?.src,
|
|
596
|
-
imageAlt: imageInfo?.alt,
|
|
597
613
|
// Robustness fields
|
|
598
614
|
stableId,
|
|
599
615
|
sourceContext,
|
|
616
|
+
// Image metadata for image entries
|
|
617
|
+
imageMetadata: imageInfo?.metadata,
|
|
600
618
|
// Color classes for buttons/styled elements
|
|
601
619
|
colorClasses,
|
|
602
620
|
}
|
|
@@ -604,7 +622,7 @@ export async function processHtml(
|
|
|
604
622
|
}
|
|
605
623
|
|
|
606
624
|
// Clean up any remaining source attributes from component-marked elements
|
|
607
|
-
markedComponentRoots.forEach((node
|
|
625
|
+
markedComponentRoots.forEach((node) => {
|
|
608
626
|
node.removeAttribute('data-astro-source-file')
|
|
609
627
|
node.removeAttribute('data-astro-source-loc')
|
|
610
628
|
node.removeAttribute('data-astro-source-line')
|
|
@@ -645,13 +663,13 @@ export function cleanText(text: string): string {
|
|
|
645
663
|
* This captures information about the element's position in the DOM
|
|
646
664
|
* that can be used as fallback when exact matching fails.
|
|
647
665
|
*/
|
|
648
|
-
function extractSourceContext(node:
|
|
649
|
-
const parent = node.parentNode
|
|
666
|
+
function extractSourceContext(node: HTMLNode, attributeName: string): SourceContext | undefined {
|
|
667
|
+
const parent = node.parentNode as HTMLNode | null
|
|
650
668
|
if (!parent) return undefined
|
|
651
669
|
|
|
652
|
-
const siblings = parent.childNodes?.filter((child:
|
|
670
|
+
const siblings = parent.childNodes?.filter((child): child is HTMLNode => {
|
|
653
671
|
// Only consider element nodes, not text nodes
|
|
654
|
-
return child.nodeType === 1 && child
|
|
672
|
+
return child.nodeType === 1 && 'tagName' in child
|
|
655
673
|
}) || []
|
|
656
674
|
|
|
657
675
|
const siblingIndex = siblings.indexOf(node)
|