@setzkasten-cms/astro-admin 1.4.6 → 1.5.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/dist/api-routes/_auth-guard.d.ts +27 -3
- package/dist/api-routes/_auth-guard.js +5 -2
- package/dist/api-routes/_dev-session-secret.d.ts +8 -0
- package/dist/api-routes/_dev-session-secret.js +8 -0
- package/dist/api-routes/_github-token.js +1 -1
- package/dist/api-routes/_role-resolver.js +6 -3
- package/dist/api-routes/_session-secret.d.ts +19 -0
- package/dist/api-routes/_session-secret.js +7 -0
- package/dist/api-routes/_session-signing.d.ts +45 -0
- package/dist/api-routes/_session-signing.js +8 -0
- package/dist/api-routes/_webhook-dispatcher.js +4 -4
- package/dist/api-routes/asset-proxy.js +1 -1
- package/dist/api-routes/auth-callback.js +12 -5
- package/dist/api-routes/auth-logout.d.ts +4 -4
- package/dist/api-routes/auth-logout.js +8 -2
- package/dist/api-routes/auth-session.d.ts +6 -0
- package/dist/api-routes/auth-session.js +19 -19
- package/dist/api-routes/auth-setzkasten-login.js +14 -7
- package/dist/api-routes/catalog-add.js +59 -17
- package/dist/api-routes/catalog-export.js +14 -4
- package/dist/api-routes/config.d.ts +10 -3
- package/dist/api-routes/config.js +26 -4
- package/dist/api-routes/deploy-hook.js +8 -8
- package/dist/api-routes/editors.d.ts +1 -1
- package/dist/api-routes/editors.js +5 -2
- package/dist/api-routes/github-proxy.js +30 -8
- package/dist/api-routes/global-config.js +6 -3
- package/dist/api-routes/history-rollback.js +31 -14
- package/dist/api-routes/history-version.js +8 -6
- package/dist/api-routes/history.js +5 -2
- package/dist/api-routes/icons-local.js +1 -1
- package/dist/api-routes/init-add-section.js +113 -47
- package/dist/api-routes/init-apply.js +56 -42
- package/dist/api-routes/init-migrate.js +43 -36
- package/dist/api-routes/init-scan-page.d.ts +1 -1
- package/dist/api-routes/init-scan-page.js +59 -13
- package/dist/api-routes/init-scan.js +22 -7
- package/dist/api-routes/migrate-to-multi.js +5 -2
- package/dist/api-routes/pages.js +15 -4
- package/dist/api-routes/section-add.js +68 -16
- package/dist/api-routes/section-commit-pending.js +70 -22
- package/dist/api-routes/section-delete.js +49 -14
- package/dist/api-routes/section-duplicate.js +65 -16
- package/dist/api-routes/section-prepare-copy.js +15 -2
- package/dist/api-routes/section-prepare.js +25 -4
- package/dist/api-routes/setup-github-app-bounce.js +15 -1
- package/dist/api-routes/setup-github-app-branches.js +9 -6
- package/dist/api-routes/setup-github-app-callback.js +24 -1
- package/dist/api-routes/setup-github-app-credentials.d.ts +27 -0
- package/dist/api-routes/setup-github-app-credentials.js +43 -0
- package/dist/api-routes/setup-github-app-installed.js +22 -1
- package/dist/api-routes/setup-github-app-repos.js +5 -2
- package/dist/api-routes/setup-github-app.d.ts +4 -0
- package/dist/api-routes/setup-github-app.js +19 -2
- package/dist/api-routes/updater-register.js +7 -1
- package/dist/api-routes/webhooks-status.js +5 -2
- package/dist/api-routes/webhooks-test.js +9 -8
- package/dist/api-routes/webhooks.js +12 -14
- package/dist/api-routes/websites-add.js +5 -2
- package/dist/api-routes/websites-remove.js +5 -2
- package/dist/{chunk-ZQDGGWJP.js → chunk-5KMGSFCZ.js} +2 -2
- package/dist/{chunk-Q3N336KR.js → chunk-CDXCYYQR.js} +29 -24
- package/dist/{chunk-NKDATSPA.js → chunk-DP6RTINQ.js} +1 -1
- package/dist/chunk-KENFINT4.js +76 -0
- package/dist/chunk-ONP6BRZO.js +47 -0
- package/dist/{chunk-INIWFKQ3.js → chunk-Q5HV47DW.js} +33 -19
- package/dist/chunk-QVCW6EF3.js +26 -0
- package/dist/{chunk-TD76R3A6.js → chunk-UHI6323G.js} +293 -174
- package/dist/{chunk-AM4DZXXM.js → chunk-UJAFZEX2.js} +76 -9
- package/package.json +12 -6
- package/src/api-routes/__tests__/_session-signing.test.ts +114 -0
- package/src/api-routes/__tests__/_session-test-helper.ts +27 -0
- package/src/api-routes/__tests__/add-section-helpers.test.ts +59 -25
- package/src/api-routes/__tests__/auth-guard.test.ts +46 -7
- package/src/api-routes/__tests__/catalog-api.test.ts +14 -6
- package/src/api-routes/__tests__/commit-trailers.test.ts +5 -5
- package/src/api-routes/__tests__/deferred-operations.test.ts +9 -12
- package/src/api-routes/__tests__/deploy-hook.test.ts +3 -8
- package/src/api-routes/__tests__/feature-gate.test.ts +1 -1
- package/src/api-routes/__tests__/github-cache.test.ts +1 -1
- package/src/api-routes/__tests__/github-token.test.ts +1 -1
- package/src/api-routes/__tests__/global-config-theme.test.ts +4 -4
- package/src/api-routes/__tests__/history-rollback.test.ts +6 -3
- package/src/api-routes/__tests__/history.test.ts +9 -6
- package/src/api-routes/__tests__/init-scan-page-resolve-config.test.ts +11 -3
- package/src/api-routes/__tests__/migrate-to-multi.test.ts +5 -1
- package/src/api-routes/__tests__/pages-meta-store.test.ts +10 -5
- package/src/api-routes/__tests__/pages.test.ts +7 -2
- package/src/api-routes/__tests__/patch-page-file.test.ts +71 -19
- package/src/api-routes/__tests__/route-registry.test.ts +11 -18
- package/src/api-routes/__tests__/scan-page-helpers.test.ts +13 -10
- package/src/api-routes/__tests__/section-management.test.ts +28 -28
- package/src/api-routes/__tests__/setup-github-app-callback.test.ts +58 -16
- package/src/api-routes/__tests__/setup-github-app-repos.test.ts +4 -5
- package/src/api-routes/__tests__/setup-github-app.test.ts +27 -7
- package/src/api-routes/__tests__/storage-config-for-request.test.ts +83 -0
- package/src/api-routes/__tests__/updater-register.test.ts +230 -0
- package/src/api-routes/__tests__/webhook-signing.test.ts +1 -1
- package/src/api-routes/__tests__/webhooks.test.ts +19 -7
- package/src/api-routes/__tests__/websites-add.test.ts +2 -1
- package/src/api-routes/__tests__/websites-remove.test.ts +2 -1
- package/src/api-routes/_auth-guard.ts +47 -15
- package/src/api-routes/_commit-trailers.ts +3 -2
- package/src/api-routes/_dev-session-secret.ts +79 -0
- package/src/api-routes/_github-token.ts +1 -1
- package/src/api-routes/_pages-meta-store.ts +2 -2
- package/src/api-routes/_role-resolver.ts +7 -5
- package/src/api-routes/_session-secret.ts +46 -0
- package/src/api-routes/_session-signing.ts +135 -0
- package/src/api-routes/_vercel-origin.ts +2 -6
- package/src/api-routes/_webhook-dispatcher.ts +12 -16
- package/src/api-routes/_website-resolver.ts +3 -10
- package/src/api-routes/auth-callback.ts +9 -5
- package/src/api-routes/auth-login.ts +5 -3
- package/src/api-routes/auth-logout.ts +18 -1
- package/src/api-routes/auth-session.ts +13 -21
- package/src/api-routes/auth-setzkasten-login.ts +12 -9
- package/src/api-routes/catalog-add.ts +89 -31
- package/src/api-routes/catalog-export.ts +30 -10
- package/src/api-routes/config.ts +39 -6
- package/src/api-routes/deploy-hook.ts +13 -11
- package/src/api-routes/editors.ts +33 -22
- package/src/api-routes/github-proxy.ts +25 -11
- package/src/api-routes/global-config.ts +103 -18
- package/src/api-routes/history-rollback.ts +41 -14
- package/src/api-routes/history-version.ts +5 -6
- package/src/api-routes/history.ts +3 -3
- package/src/api-routes/icons-local.ts +2 -2
- package/src/api-routes/init-add-section.ts +174 -79
- package/src/api-routes/init-apply.ts +71 -56
- package/src/api-routes/init-migrate.ts +54 -48
- package/src/api-routes/init-scan-page.ts +77 -30
- package/src/api-routes/init-scan.ts +19 -11
- package/src/api-routes/pages.ts +16 -11
- package/src/api-routes/section-add.ts +98 -27
- package/src/api-routes/section-commit-pending.ts +87 -34
- package/src/api-routes/section-delete.ts +76 -27
- package/src/api-routes/section-duplicate.ts +95 -28
- package/src/api-routes/section-management.ts +3 -7
- package/src/api-routes/section-prepare-copy.ts +29 -8
- package/src/api-routes/section-prepare.ts +38 -10
- package/src/api-routes/setup-github-app-bounce.ts +7 -1
- package/src/api-routes/setup-github-app-branches.ts +6 -7
- package/src/api-routes/setup-github-app-callback.ts +18 -1
- package/src/api-routes/setup-github-app-credentials.ts +55 -0
- package/src/api-routes/setup-github-app-installed.ts +12 -1
- package/src/api-routes/setup-github-app-repos.ts +2 -3
- package/src/api-routes/setup-github-app.ts +14 -5
- package/src/api-routes/updater-check.ts +6 -4
- package/src/api-routes/updater-register.ts +34 -20
- package/src/api-routes/updater-transfer.ts +8 -6
- package/src/api-routes/updater-unbind.ts +14 -10
- package/src/api-routes/webhooks-test.ts +9 -11
- package/src/api-routes/webhooks.ts +15 -19
- package/src/init/__tests__/page-level.test.ts +279 -105
- package/src/init/__tests__/page-list-coverage.test.ts +70 -70
- package/src/init/__tests__/patcher-child-component.test.ts +12 -3
- package/src/init/__tests__/patcher-edge-cases.test.ts +47 -23
- package/src/init/__tests__/patcher-mixed-content-wrapper.test.ts +16 -6
- package/src/init/__tests__/patcher-page-mode.test.ts +30 -20
- package/src/init/__tests__/section-pipeline.test.ts +53 -19
- package/src/init/astro-config-patcher.ts +4 -18
- package/src/init/astro-detector.ts +2 -7
- package/src/init/astro-section-analyzer-v2.ts +475 -193
- package/src/init/field-label-enricher.ts +6 -6
- package/src/init/template-patcher-v2.ts +218 -97
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* 5. removeOldVarDeclarations causes TDZ (alias placed before skData declaration)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { describe,
|
|
12
|
+
import { describe, expect, it } from 'vitest'
|
|
13
13
|
import { patchTemplateForFields } from '../../init/template-patcher-v2'
|
|
14
14
|
import type { PatchField } from '../../init/template-patcher-v2'
|
|
15
15
|
|
|
@@ -60,14 +60,22 @@ import BaseLayout from '../layouts/BaseLayout.astro';
|
|
|
60
60
|
`
|
|
61
61
|
|
|
62
62
|
const fields: PatchField[] = [
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
{
|
|
64
|
+
key: 'items',
|
|
65
|
+
type: 'array',
|
|
66
|
+
defaultValue: [
|
|
67
|
+
{ name: '@setzkasten-cms/core', desc: 'Schema, Feldtypen, Validation' },
|
|
68
|
+
{ name: '@setzkasten-cms/ui', desc: 'React-UI: Provider, FormStore' },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: 'items2',
|
|
73
|
+
type: 'array',
|
|
74
|
+
defaultValue: [
|
|
75
|
+
{ title: 'Dependency Inversion', desc: 'UI haengt nur von Ports ab' },
|
|
76
|
+
{ title: 'Schema-First', desc: 'Alles leitet sich vom TypeScript-Schema ab' },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
71
79
|
]
|
|
72
80
|
|
|
73
81
|
it('should reference skData?.items for the first array', async () => {
|
|
@@ -111,9 +119,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
|
|
|
111
119
|
</BaseLayout>
|
|
112
120
|
`
|
|
113
121
|
|
|
114
|
-
const fields: PatchField[] = [
|
|
115
|
-
{ key: 'heading', type: 'text', defaultValue: 'Titel' },
|
|
116
|
-
]
|
|
122
|
+
const fields: PatchField[] = [{ key: 'heading', type: 'text', defaultValue: 'Titel' }]
|
|
117
123
|
|
|
118
124
|
it('should add id="section-_page_test" to the <section> element', async () => {
|
|
119
125
|
const patched = await patchTemplateForFields(source, '_page_test', fields, [], { mode: 'page' })
|
|
@@ -147,9 +153,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
|
|
|
147
153
|
</BaseLayout>
|
|
148
154
|
`
|
|
149
155
|
|
|
150
|
-
const fields: PatchField[] = [
|
|
151
|
-
{ key: 'heading', type: 'text', defaultValue: 'Architektur' },
|
|
152
|
-
]
|
|
156
|
+
const fields: PatchField[] = [{ key: 'heading', type: 'text', defaultValue: 'Architektur' }]
|
|
153
157
|
|
|
154
158
|
it('should add data-sk-field to the <h1> element', async () => {
|
|
155
159
|
const patched = await patchTemplateForFields(source, '_page_test', fields, [], { mode: 'page' })
|
|
@@ -203,7 +207,7 @@ const fields = ['Alpha', 'Beta', 'Gamma'];
|
|
|
203
207
|
const fmMatch = patched.match(/^---\n([\s\S]*?)\n---/)
|
|
204
208
|
const frontmatter = fmMatch ? fmMatch[1]! : patched
|
|
205
209
|
|
|
206
|
-
const lines = frontmatter.split('\n').map(l => l.trim())
|
|
210
|
+
const lines = frontmatter.split('\n').map((l) => l.trim())
|
|
207
211
|
expect(lines).not.toContain(';')
|
|
208
212
|
})
|
|
209
213
|
})
|
|
@@ -239,7 +243,9 @@ const fields = ['Alpha', 'Beta', 'Gamma'];
|
|
|
239
243
|
]
|
|
240
244
|
|
|
241
245
|
it('should place the fields alias AFTER the skData declaration', async () => {
|
|
242
|
-
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
246
|
+
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
247
|
+
mode: 'page',
|
|
248
|
+
})
|
|
243
249
|
|
|
244
250
|
const fmMatch = patched.match(/^---\n([\s\S]*?)\n---/)
|
|
245
251
|
const frontmatter = fmMatch ? fmMatch[1]! : patched
|
|
@@ -253,17 +259,21 @@ const fields = ['Alpha', 'Beta', 'Gamma'];
|
|
|
253
259
|
})
|
|
254
260
|
|
|
255
261
|
it('should not contain a stray semicolon line in frontmatter', async () => {
|
|
256
|
-
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
262
|
+
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
263
|
+
mode: 'page',
|
|
264
|
+
})
|
|
257
265
|
|
|
258
266
|
const fmMatch = patched.match(/^---\n([\s\S]*?)\n---/)
|
|
259
267
|
const frontmatter = fmMatch ? fmMatch[1]! : patched
|
|
260
268
|
|
|
261
|
-
const lines = frontmatter.split('\n').map(l => l.trim())
|
|
269
|
+
const lines = frontmatter.split('\n').map((l) => l.trim())
|
|
262
270
|
expect(lines).not.toContain(';')
|
|
263
271
|
})
|
|
264
272
|
|
|
265
273
|
it('should preserve fields.length in the template', async () => {
|
|
266
|
-
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
274
|
+
const patched = await patchTemplateForFields(source, '_page_test', patchFields, [], {
|
|
275
|
+
mode: 'page',
|
|
276
|
+
})
|
|
267
277
|
|
|
268
278
|
// Extract template (after closing ---)
|
|
269
279
|
const templatePart = patched.split('\n---\n').slice(1).join('\n---\n')
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* - Stale frontmatter var cleanup
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { describe, it, expect, beforeAll } from 'vitest'
|
|
16
15
|
import { readFileSync, readdirSync } from 'fs'
|
|
17
|
-
import {
|
|
16
|
+
import { basename, join } from 'path'
|
|
17
|
+
import { beforeAll, describe, expect, it } from 'vitest'
|
|
18
18
|
import { analyzeAstroSection } from '../../init/astro-section-analyzer-v2'
|
|
19
19
|
import { patchTemplateForFields } from '../../init/template-patcher-v2'
|
|
20
20
|
|
|
@@ -23,7 +23,9 @@ import { patchTemplateForFields } from '../../init/template-patcher-v2'
|
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
|
|
25
25
|
const SECTIONS_DIR = join(import.meta.dirname!, '..', '..', '..', '..', '..', 'test-sections')
|
|
26
|
-
const files = readdirSync(SECTIONS_DIR)
|
|
26
|
+
const files = readdirSync(SECTIONS_DIR)
|
|
27
|
+
.filter((f) => f.endsWith('.astro'))
|
|
28
|
+
.sort()
|
|
27
29
|
|
|
28
30
|
// ---------------------------------------------------------------------------
|
|
29
31
|
// Helpers (ported from test-sections-runner.mts)
|
|
@@ -40,12 +42,16 @@ function extractClassValues(src: string): string[] {
|
|
|
40
42
|
function checkCssIntegrity(
|
|
41
43
|
source: string,
|
|
42
44
|
patched: string,
|
|
43
|
-
groups: Array<{
|
|
45
|
+
groups: Array<{
|
|
46
|
+
tag: string
|
|
47
|
+
instances: Array<{ start: number; end: number }>
|
|
48
|
+
fields?: Array<{ key: string; defaultValues?: unknown[] }>
|
|
49
|
+
}>,
|
|
44
50
|
): { ok: boolean; lost: string[] } {
|
|
45
51
|
const lost: string[] = []
|
|
46
52
|
const dynamicClassValues = new Set<string>()
|
|
47
53
|
for (const g of groups) {
|
|
48
|
-
for (const f of
|
|
54
|
+
for (const f of g.fields ?? []) {
|
|
49
55
|
if (f.key.startsWith('_class') && f.defaultValues) {
|
|
50
56
|
for (const dv of f.defaultValues) {
|
|
51
57
|
if (typeof dv === 'string') dynamicClassValues.add(dv)
|
|
@@ -133,9 +139,18 @@ function checkSkFieldBindings(
|
|
|
133
139
|
|
|
134
140
|
for (const g of groups) {
|
|
135
141
|
for (const innerField of g.fields) {
|
|
136
|
-
if (innerField.type === 'array') {
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
if (innerField.type === 'array') {
|
|
143
|
+
skipped.push(`${sectionKey}.${g.fieldKey}.*.${innerField.key} (array)`)
|
|
144
|
+
continue
|
|
145
|
+
}
|
|
146
|
+
if (!fieldNeedsSkBinding(innerField)) {
|
|
147
|
+
skipped.push(`${sectionKey}.${g.fieldKey}.*.${innerField.key} (${innerField.type})`)
|
|
148
|
+
continue
|
|
149
|
+
}
|
|
150
|
+
if (!patched.includes(`item.${innerField.key}`)) {
|
|
151
|
+
skipped.push(`${sectionKey}.${g.fieldKey}.*.${innerField.key} (not replaced)`)
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
139
154
|
const innerBinding = `${sectionKey}.${g.fieldKey}.\${_i}.${innerField.key}`
|
|
140
155
|
if (patched.includes(innerBinding)) {
|
|
141
156
|
found.push(`${sectionKey}.${g.fieldKey}.*.${innerField.key}`)
|
|
@@ -173,7 +188,13 @@ describe('Section Pipeline', () => {
|
|
|
173
188
|
const getSectionMatch = isPageMode ? source.match(/getSection\(['"]([^'"]+)['"]\)/) : null
|
|
174
189
|
sectionKey = getSectionMatch?.[1] ?? filenameKey
|
|
175
190
|
const options = isPageMode ? { mode: 'page' as const } : undefined
|
|
176
|
-
section = await analyzeAstroSection(
|
|
191
|
+
section = await analyzeAstroSection(
|
|
192
|
+
source,
|
|
193
|
+
sectionKey,
|
|
194
|
+
name,
|
|
195
|
+
`src/components/sections/${file}`,
|
|
196
|
+
options,
|
|
197
|
+
)
|
|
177
198
|
groups = (section as any)._analyzerResult?.repeatedGroups ?? []
|
|
178
199
|
patched = await patchTemplateForFields(source, sectionKey, section.fields, groups, options)
|
|
179
200
|
})
|
|
@@ -217,10 +238,13 @@ describe('Section Pipeline', () => {
|
|
|
217
238
|
}
|
|
218
239
|
}
|
|
219
240
|
}
|
|
220
|
-
const duplicateArrays = section.fields.filter(
|
|
221
|
-
f.type === 'array' && innerArraySources.has(f.key),
|
|
241
|
+
const duplicateArrays = section.fields.filter(
|
|
242
|
+
(f: any) => f.type === 'array' && innerArraySources.has(f.key),
|
|
222
243
|
)
|
|
223
|
-
expect(
|
|
244
|
+
expect(
|
|
245
|
+
duplicateArrays,
|
|
246
|
+
`Duplicate arrays: ${duplicateArrays.map((f: any) => f.key).join(', ')}`,
|
|
247
|
+
).toHaveLength(0)
|
|
224
248
|
})
|
|
225
249
|
|
|
226
250
|
it('should remove consumed frontmatter vars', () => {
|
|
@@ -267,7 +291,10 @@ describe('Section Pipeline', () => {
|
|
|
267
291
|
|
|
268
292
|
for (const g of groups) {
|
|
269
293
|
const arrayField = section.fields.find((f: any) => f.key === g.fieldKey)
|
|
270
|
-
if (!arrayField) {
|
|
294
|
+
if (!arrayField) {
|
|
295
|
+
issues.push(`No top-level field for group ${g.fieldKey}`)
|
|
296
|
+
continue
|
|
297
|
+
}
|
|
271
298
|
|
|
272
299
|
const items = arrayField.defaultValue as Array<Record<string, unknown>> | undefined
|
|
273
300
|
if (!Array.isArray(items) || items.length === 0) {
|
|
@@ -294,7 +321,7 @@ describe('Section Pipeline', () => {
|
|
|
294
321
|
}
|
|
295
322
|
for (const refKey of referencedKeys) {
|
|
296
323
|
if (['map', 'length', 'filter', 'forEach', 'join', 'slice'].includes(refKey)) continue
|
|
297
|
-
const hasInAnyItem = items.some(item => refKey in item)
|
|
324
|
+
const hasInAnyItem = items.some((item) => refKey in item)
|
|
298
325
|
if (!hasInAnyItem) {
|
|
299
326
|
issues.push(`{item.${refKey}} used in template but missing in content JSON`)
|
|
300
327
|
}
|
|
@@ -335,7 +362,9 @@ describe('Section Pipeline', () => {
|
|
|
335
362
|
const origCount = originalClassCounts.get(val) ?? 0
|
|
336
363
|
if (keys.length > origCount) {
|
|
337
364
|
const label = instIdx === 0 ? 'template' : `instance ${instIdx}`
|
|
338
|
-
issues.push(
|
|
365
|
+
issues.push(
|
|
366
|
+
`${g.fieldKey} ${label}: "${val.slice(0, 40)}" assigned to [${keys.join(', ')}] but appears ${origCount}×`,
|
|
367
|
+
)
|
|
339
368
|
}
|
|
340
369
|
}
|
|
341
370
|
}
|
|
@@ -380,7 +409,9 @@ describe('Section Pipeline', () => {
|
|
|
380
409
|
const actualTag = lastPart.replace(/:\d+$/, '') || g.tag
|
|
381
410
|
|
|
382
411
|
if (actualTag !== expectedTag) {
|
|
383
|
-
issues.push(
|
|
412
|
+
issues.push(
|
|
413
|
+
`${cf.key} instance ${instIdx}: expected <${expectedTag}> but on <${actualTag}>`,
|
|
414
|
+
)
|
|
384
415
|
}
|
|
385
416
|
}
|
|
386
417
|
}
|
|
@@ -422,7 +453,8 @@ describe('Section Pipeline', () => {
|
|
|
422
453
|
|
|
423
454
|
it('should remove stale frontmatter vars from repeated component props', () => {
|
|
424
455
|
const componentArrayFields = section.fields.filter(
|
|
425
|
-
(f: any) =>
|
|
456
|
+
(f: any) =>
|
|
457
|
+
f.type === 'array' && f.options?.sourceComponent && Array.isArray(f.defaultValue),
|
|
426
458
|
)
|
|
427
459
|
if (componentArrayFields.length === 0) return
|
|
428
460
|
const fmEnd = patched.indexOf('---', patched.indexOf('---') + 3)
|
|
@@ -430,9 +462,11 @@ describe('Section Pipeline', () => {
|
|
|
430
462
|
const staleVars: string[] = []
|
|
431
463
|
for (const field of componentArrayFields) {
|
|
432
464
|
const items = (field as any).defaultValue as Array<Record<string, unknown>>
|
|
433
|
-
for (const innerField of ((field as any).options?.arrayItem?.fields ?? []) as Array<{
|
|
465
|
+
for (const innerField of ((field as any).options?.arrayItem?.fields ?? []) as Array<{
|
|
466
|
+
key: string
|
|
467
|
+
}>) {
|
|
434
468
|
// Only string-array props might have been declared as frontmatter vars
|
|
435
|
-
const allVarLike = items.every(item => Array.isArray(item[innerField.key]))
|
|
469
|
+
const allVarLike = items.every((item) => Array.isArray(item[innerField.key]))
|
|
436
470
|
if (!allVarLike) continue
|
|
437
471
|
const varNames = items.map((_, i) => `${innerField.key}${i === 0 ? '' : i + 1}`)
|
|
438
472
|
for (const v of varNames) {
|
|
@@ -21,11 +21,7 @@ export function patchAstroConfig(source: string): string | null {
|
|
|
21
21
|
// Find the last import statement
|
|
22
22
|
const lastImportIndex = findLastImportEnd(result)
|
|
23
23
|
if (lastImportIndex >= 0) {
|
|
24
|
-
result =
|
|
25
|
-
result.slice(0, lastImportIndex) +
|
|
26
|
-
'\n' +
|
|
27
|
-
importLine +
|
|
28
|
-
result.slice(lastImportIndex)
|
|
24
|
+
result = result.slice(0, lastImportIndex) + '\n' + importLine + result.slice(lastImportIndex)
|
|
29
25
|
} else {
|
|
30
26
|
// No imports found — add at the very top
|
|
31
27
|
result = importLine + '\n' + result
|
|
@@ -67,19 +63,11 @@ function addToIntegrations(source: string): string {
|
|
|
67
63
|
|
|
68
64
|
// Check if array is empty
|
|
69
65
|
if (after.startsWith(']')) {
|
|
70
|
-
return (
|
|
71
|
-
source.slice(0, insertPos) +
|
|
72
|
-
'setzkasten()' +
|
|
73
|
-
source.slice(insertPos)
|
|
74
|
-
)
|
|
66
|
+
return source.slice(0, insertPos) + 'setzkasten()' + source.slice(insertPos)
|
|
75
67
|
}
|
|
76
68
|
|
|
77
69
|
// Array has items — prepend
|
|
78
|
-
return (
|
|
79
|
-
source.slice(0, insertPos) +
|
|
80
|
-
'\n setzkasten(),\n ' +
|
|
81
|
-
source.slice(insertPos)
|
|
82
|
-
)
|
|
70
|
+
return source.slice(0, insertPos) + '\n setzkasten(),\n ' + source.slice(insertPos)
|
|
83
71
|
}
|
|
84
72
|
|
|
85
73
|
// Case 2: No integrations array — add it to defineConfig
|
|
@@ -87,9 +75,7 @@ function addToIntegrations(source: string): string {
|
|
|
87
75
|
if (defineConfigMatch && defineConfigMatch.index !== undefined) {
|
|
88
76
|
const insertPos = defineConfigMatch.index + defineConfigMatch[0].length
|
|
89
77
|
return (
|
|
90
|
-
source.slice(0, insertPos) +
|
|
91
|
-
'\n integrations: [setzkasten()],\n' +
|
|
92
|
-
source.slice(insertPos)
|
|
78
|
+
source.slice(0, insertPos) + '\n integrations: [setzkasten()],\n' + source.slice(insertPos)
|
|
93
79
|
)
|
|
94
80
|
}
|
|
95
81
|
|
|
@@ -47,9 +47,7 @@ export function findAstroPages(files: RepoFile[], projectRoot: string): AstroPag
|
|
|
47
47
|
|
|
48
48
|
const name = relativePath.replace(/\.astro$/, '')
|
|
49
49
|
const isIndex = name === 'index' || name.endsWith('/index')
|
|
50
|
-
const pageKey = isIndex
|
|
51
|
-
? name === 'index' ? 'index' : name.replace(/\/index$/, '')
|
|
52
|
-
: name
|
|
50
|
+
const pageKey = isIndex ? (name === 'index' ? 'index' : name.replace(/\/index$/, '')) : name
|
|
53
51
|
|
|
54
52
|
pages.push({
|
|
55
53
|
filePath: file.path,
|
|
@@ -170,10 +168,7 @@ function resolveImportPath(
|
|
|
170
168
|
// Handle alias imports like @/components/... or ~/components/...
|
|
171
169
|
if (importPath.startsWith('@/') || importPath.startsWith('~/')) {
|
|
172
170
|
const aliasPath = importPath.replace(/^[@~]\//, '')
|
|
173
|
-
const candidates = [
|
|
174
|
-
`${projectRoot}/src/${aliasPath}`,
|
|
175
|
-
`${projectRoot}/src/${aliasPath}.astro`,
|
|
176
|
-
]
|
|
171
|
+
const candidates = [`${projectRoot}/src/${aliasPath}`, `${projectRoot}/src/${aliasPath}.astro`]
|
|
177
172
|
for (const candidate of candidates) {
|
|
178
173
|
if (allFiles.some((f) => f.path === candidate)) return candidate
|
|
179
174
|
}
|