@nuasite/cms 0.13.1 → 0.14.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/editor.js +3944 -3899
- package/package.json +6 -6
- package/src/dev-middleware.ts +8 -1
- package/src/editor/components/collections-browser.tsx +62 -55
- package/src/handlers/source-writer.ts +2 -2
- package/src/vite-plugin.ts +2 -2
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"directory": "packages/astro-cms"
|
|
15
15
|
},
|
|
16
16
|
"license": "Apache-2.0",
|
|
17
|
-
"version": "0.
|
|
17
|
+
"version": "0.14.0",
|
|
18
18
|
"module": "src/index.ts",
|
|
19
19
|
"types": "src/index.ts",
|
|
20
20
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@astrojs/compiler": "^
|
|
29
|
+
"@astrojs/compiler": "^3.0.0",
|
|
30
30
|
"@babel/parser": "^7.29.0",
|
|
31
31
|
"node-html-parser": "^7.1.0",
|
|
32
32
|
"yaml": "^2.8.2"
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"@milkdown/preset-gfm": "^7.19.0",
|
|
40
40
|
"@milkdown/prose": "^7.19.0",
|
|
41
41
|
"@milkdown/utils": "^7.19.0",
|
|
42
|
-
"@preact/signals": "^2.8.
|
|
42
|
+
"@preact/signals": "^2.8.2",
|
|
43
43
|
"@tailwindcss/vite": "^4.2.1",
|
|
44
44
|
"@types/bun": "1.3.10",
|
|
45
45
|
"clsx": "^2.1.1",
|
|
46
|
-
"marked": "^17.0.
|
|
47
|
-
"preact": "^10.
|
|
46
|
+
"marked": "^17.0.4",
|
|
47
|
+
"preact": "^10.29.0",
|
|
48
48
|
"prosemirror-commands": "^1.7.1",
|
|
49
49
|
"prosemirror-inputrules": "^1.5.1",
|
|
50
50
|
"prosemirror-keymap": "^1.2.3",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"tailwind-merge": "^3.5.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"astro": "^
|
|
60
|
+
"astro": "^6.0.2",
|
|
61
61
|
"typescript": "^5",
|
|
62
62
|
"vite": "^7.3.1",
|
|
63
63
|
"@aws-sdk/client-s3": "^3.0.0"
|
package/src/dev-middleware.ts
CHANGED
|
@@ -4,7 +4,14 @@ import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import { scanCollections } from './collection-scanner'
|
|
6
6
|
import { getProjectRoot } from './config'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
buildMapPattern,
|
|
9
|
+
detectArrayPattern,
|
|
10
|
+
extractArrayElementProps,
|
|
11
|
+
handleAddArrayItem,
|
|
12
|
+
handleRemoveArrayItem,
|
|
13
|
+
parseInlineArrayName,
|
|
14
|
+
} from './handlers/array-ops'
|
|
8
15
|
import {
|
|
9
16
|
extractPropsFromSource,
|
|
10
17
|
findComponentInvocationLine,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useMemo } from 'preact/hooks'
|
|
2
1
|
import { signal } from '@preact/signals'
|
|
2
|
+
import { useMemo } from 'preact/hooks'
|
|
3
3
|
import { deleteMarkdownPage } from '../markdown-api'
|
|
4
4
|
import {
|
|
5
5
|
closeCollectionsBrowser,
|
|
@@ -144,66 +144,68 @@ export function CollectionsBrowser() {
|
|
|
144
144
|
)}
|
|
145
145
|
{entries.map((entry) => (
|
|
146
146
|
<div key={entry.slug} class="relative" data-cms-ui>
|
|
147
|
-
{confirmDeleteSlug.value === entry.slug
|
|
148
|
-
|
|
149
|
-
<div class="flex-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<button
|
|
153
|
-
type="button"
|
|
154
|
-
onClick={() => handleConfirmDelete(entry.slug, entry.sourcePath)}
|
|
155
|
-
disabled={deletingEntry.value === entry.slug}
|
|
156
|
-
class="px-3 py-1 text-xs font-medium text-white bg-red-600 hover:bg-red-700 rounded-cms-pill transition-colors disabled:opacity-50"
|
|
157
|
-
data-cms-ui
|
|
158
|
-
>
|
|
159
|
-
{deletingEntry.value === entry.slug ? 'Deleting...' : 'Delete'}
|
|
160
|
-
</button>
|
|
161
|
-
<button
|
|
162
|
-
type="button"
|
|
163
|
-
onClick={handleCancelDelete}
|
|
164
|
-
class="px-3 py-1 text-xs font-medium text-white/60 hover:text-white bg-white/10 hover:bg-white/20 rounded-cms-pill transition-colors"
|
|
165
|
-
data-cms-ui
|
|
166
|
-
>
|
|
167
|
-
Cancel
|
|
168
|
-
</button>
|
|
169
|
-
</div>
|
|
170
|
-
) : (
|
|
171
|
-
<button
|
|
172
|
-
type="button"
|
|
173
|
-
onClick={() => handleEntryClick(entry.slug, entry.sourcePath, entry.pathname)}
|
|
174
|
-
class="w-full flex items-center gap-3 px-4 py-3 hover:bg-white/10 rounded-cms-lg transition-colors text-left group"
|
|
175
|
-
data-cms-ui
|
|
176
|
-
>
|
|
177
|
-
<div class="flex-1 min-w-0">
|
|
178
|
-
<div class={`font-medium truncate ${entry.draft ? 'text-white/40' : 'text-white'}`}>
|
|
179
|
-
{entry.title || entry.slug}
|
|
147
|
+
{confirmDeleteSlug.value === entry.slug
|
|
148
|
+
? (
|
|
149
|
+
<div class="flex items-center gap-2 px-4 py-3 bg-red-500/10 border border-red-500/20 rounded-cms-lg" data-cms-ui>
|
|
150
|
+
<div class="flex-1 min-w-0 text-sm text-white/70">
|
|
151
|
+
Delete "{entry.title || entry.slug}"?
|
|
180
152
|
</div>
|
|
181
|
-
|
|
153
|
+
<button
|
|
154
|
+
type="button"
|
|
155
|
+
onClick={() => handleConfirmDelete(entry.slug, entry.sourcePath)}
|
|
156
|
+
disabled={deletingEntry.value === entry.slug}
|
|
157
|
+
class="px-3 py-1 text-xs font-medium text-white bg-red-600 hover:bg-red-700 rounded-cms-pill transition-colors disabled:opacity-50"
|
|
158
|
+
data-cms-ui
|
|
159
|
+
>
|
|
160
|
+
{deletingEntry.value === entry.slug ? 'Deleting...' : 'Delete'}
|
|
161
|
+
</button>
|
|
162
|
+
<button
|
|
163
|
+
type="button"
|
|
164
|
+
onClick={handleCancelDelete}
|
|
165
|
+
class="px-3 py-1 text-xs font-medium text-white/60 hover:text-white bg-white/10 hover:bg-white/20 rounded-cms-pill transition-colors"
|
|
166
|
+
data-cms-ui
|
|
167
|
+
>
|
|
168
|
+
Cancel
|
|
169
|
+
</button>
|
|
182
170
|
</div>
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Draft
|
|
186
|
-
</span>
|
|
187
|
-
)}
|
|
171
|
+
)
|
|
172
|
+
: (
|
|
188
173
|
<button
|
|
189
174
|
type="button"
|
|
190
|
-
onClick={(
|
|
191
|
-
class="
|
|
192
|
-
title="Delete entry"
|
|
175
|
+
onClick={() => handleEntryClick(entry.slug, entry.sourcePath, entry.pathname)}
|
|
176
|
+
class="w-full flex items-center gap-3 px-4 py-3 hover:bg-white/10 rounded-cms-lg transition-colors text-left group"
|
|
193
177
|
data-cms-ui
|
|
194
178
|
>
|
|
195
|
-
<
|
|
179
|
+
<div class="flex-1 min-w-0">
|
|
180
|
+
<div class={`font-medium truncate ${entry.draft ? 'text-white/40' : 'text-white'}`}>
|
|
181
|
+
{entry.title || entry.slug}
|
|
182
|
+
</div>
|
|
183
|
+
{entry.title && <div class="text-white/30 text-xs truncate">{entry.slug}</div>}
|
|
184
|
+
</div>
|
|
185
|
+
{entry.draft && (
|
|
186
|
+
<span class="shrink-0 px-2 py-0.5 text-xs font-medium text-amber-400/80 bg-amber-400/10 rounded-full border border-amber-400/20">
|
|
187
|
+
Draft
|
|
188
|
+
</span>
|
|
189
|
+
)}
|
|
190
|
+
<button
|
|
191
|
+
type="button"
|
|
192
|
+
onClick={(e) => handleDeleteClick(e, entry.slug)}
|
|
193
|
+
class="shrink-0 p-1 text-white/0 group-hover:text-white/30 hover:!text-red-400 rounded transition-colors"
|
|
194
|
+
title="Delete entry"
|
|
195
|
+
data-cms-ui
|
|
196
|
+
>
|
|
197
|
+
<TrashIcon />
|
|
198
|
+
</button>
|
|
199
|
+
<svg
|
|
200
|
+
class="w-4 h-4 text-white/20 group-hover:text-white/40 shrink-0 transition-colors"
|
|
201
|
+
fill="none"
|
|
202
|
+
stroke="currentColor"
|
|
203
|
+
viewBox="0 0 24 24"
|
|
204
|
+
>
|
|
205
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
206
|
+
</svg>
|
|
196
207
|
</button>
|
|
197
|
-
|
|
198
|
-
class="w-4 h-4 text-white/20 group-hover:text-white/40 shrink-0 transition-colors"
|
|
199
|
-
fill="none"
|
|
200
|
-
stroke="currentColor"
|
|
201
|
-
viewBox="0 0 24 24"
|
|
202
|
-
>
|
|
203
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
204
|
-
</svg>
|
|
205
|
-
</button>
|
|
206
|
-
)}
|
|
208
|
+
)}
|
|
207
209
|
</div>
|
|
208
210
|
))}
|
|
209
211
|
</div>
|
|
@@ -333,7 +335,12 @@ function BackArrowIcon() {
|
|
|
333
335
|
function TrashIcon() {
|
|
334
336
|
return (
|
|
335
337
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
336
|
-
<path
|
|
338
|
+
<path
|
|
339
|
+
stroke-linecap="round"
|
|
340
|
+
stroke-linejoin="round"
|
|
341
|
+
stroke-width="2"
|
|
342
|
+
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
343
|
+
/>
|
|
337
344
|
</svg>
|
|
338
345
|
)
|
|
339
346
|
}
|
|
@@ -152,7 +152,7 @@ function applyChanges(
|
|
|
152
152
|
return { newContent, appliedCount, failedChanges }
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
function applyImageChange(
|
|
155
|
+
export function applyImageChange(
|
|
156
156
|
content: string,
|
|
157
157
|
change: ChangePayload,
|
|
158
158
|
): { success: true; content: string } | { success: false; error: string } {
|
|
@@ -709,7 +709,7 @@ function resolveCmsPlaceholders(text: string, manifest: CmsManifest): string {
|
|
|
709
709
|
* Handles balanced braces for nested expressions.
|
|
710
710
|
* Returns the match with index and length, or null if not found.
|
|
711
711
|
*/
|
|
712
|
-
function findExpressionSrcAttribute(text: string): { index: number; length: number } | null {
|
|
712
|
+
export function findExpressionSrcAttribute(text: string): { index: number; length: number } | null {
|
|
713
713
|
// Find 'src=' followed by '{'
|
|
714
714
|
const srcExprStart = /src\s*=\s*\{/
|
|
715
715
|
const match = text.match(srcExprStart)
|
package/src/vite-plugin.ts
CHANGED
|
@@ -47,14 +47,14 @@ export function createVitePlugin(context: VitePluginContext): Plugin[] {
|
|
|
47
47
|
// processes them. We use prependListener so our handler runs first.
|
|
48
48
|
const watcher = server.watcher
|
|
49
49
|
const origEmit = watcher.emit.bind(watcher)
|
|
50
|
-
watcher.emit =
|
|
50
|
+
watcher.emit = ((event: string, filePath: string, ...args: any[]) => {
|
|
51
51
|
if ((event === 'unlink' || event === 'unlinkDir') && expectedDeletions.has(filePath)) {
|
|
52
52
|
expectedDeletions.delete(filePath)
|
|
53
53
|
// Swallow the event — don't let Vite/Astro see it
|
|
54
54
|
return true
|
|
55
55
|
}
|
|
56
56
|
return origEmit(event, filePath, ...args)
|
|
57
|
-
} as typeof watcher.emit
|
|
57
|
+
}) as typeof watcher.emit
|
|
58
58
|
},
|
|
59
59
|
}
|
|
60
60
|
|