@nuasite/cms 0.19.1 → 0.20.2
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 +12615 -12689
- package/package.json +3 -3
- package/src/build-processor.ts +4 -4
- package/src/dev-middleware.ts +185 -189
- package/src/editor/api.ts +0 -251
- package/src/editor/components/fields.tsx +6 -6
- package/src/editor/components/markdown-editor-overlay.tsx +46 -70
- package/src/editor/components/markdown-inline-editor.tsx +34 -165
- package/src/editor/components/mdx-block-view.tsx +351 -47
- package/src/editor/components/mdx-component-picker.tsx +35 -11
- package/src/editor/components/media-library.tsx +1 -15
- package/src/editor/components/modal-shell.tsx +1 -1
- package/src/editor/components/toolbar.tsx +0 -75
- package/src/editor/constants.ts +0 -4
- package/src/editor/editor.ts +2 -192
- package/src/editor/hooks/index.ts +0 -3
- package/src/editor/hooks/useBlockEditorHandlers.ts +1 -8
- package/src/editor/hooks/useTooltipState.ts +1 -2
- package/src/editor/index.tsx +2 -18
- package/src/editor/milkdown-mdx-plugin.tsx +116 -19
- package/src/editor/milkdown-utils.ts +174 -0
- package/src/editor/post-message.ts +0 -6
- package/src/editor/signals.ts +0 -183
- package/src/editor/styles.css +0 -108
- package/src/editor/types.ts +0 -76
- package/src/html-processor.ts +9 -7
- package/src/source-finder/cache.ts +47 -0
- package/src/source-finder/collection-finder.ts +181 -0
- package/src/source-finder/index.ts +5 -2
- package/src/source-finder/search-index.ts +79 -0
- package/src/source-finder/snippet-utils.ts +36 -61
- package/src/types.ts +0 -4
- package/src/utils.ts +10 -0
- package/src/vite-plugin.ts +24 -4
- package/src/editor/ai.ts +0 -185
- package/src/editor/components/ai-chat.tsx +0 -631
- package/src/editor/components/ai-tooltip.tsx +0 -180
- package/src/editor/components/mdx-props-editor.tsx +0 -94
- package/src/editor/hooks/useAIHandlers.ts +0 -345
package/src/editor/signals.ts
CHANGED
|
@@ -4,11 +4,8 @@ import { fetchManifest, getMarkdownContent } from './api'
|
|
|
4
4
|
import type { ToastMessage, ToastType } from './components/toast/types'
|
|
5
5
|
import { getConfig } from './config'
|
|
6
6
|
import type {
|
|
7
|
-
AIState,
|
|
8
|
-
AIStatusType,
|
|
9
7
|
AttributeEditorState,
|
|
10
8
|
BlockEditorState,
|
|
11
|
-
ChatMessage,
|
|
12
9
|
CmsConfig,
|
|
13
10
|
CmsManifest,
|
|
14
11
|
CmsSettings,
|
|
@@ -20,13 +17,10 @@ import type {
|
|
|
20
17
|
ConfirmDialogState,
|
|
21
18
|
CreatePageState,
|
|
22
19
|
DeletePageState,
|
|
23
|
-
DeploymentState,
|
|
24
|
-
DeploymentStatusType,
|
|
25
20
|
EditorState,
|
|
26
21
|
FieldDefinition,
|
|
27
22
|
MarkdownEditorState,
|
|
28
23
|
MarkdownPageEntry,
|
|
29
|
-
MdxPropsEditorState,
|
|
30
24
|
MediaItem,
|
|
31
25
|
MediaLibraryState,
|
|
32
26
|
PendingAttributeChange,
|
|
@@ -104,21 +98,6 @@ function createDirtyTracking<T extends { isDirty: boolean }>(
|
|
|
104
98
|
}
|
|
105
99
|
|
|
106
100
|
// Initial state factories
|
|
107
|
-
function createInitialAIState(): AIState {
|
|
108
|
-
return {
|
|
109
|
-
isPromptVisible: false,
|
|
110
|
-
isProcessing: false,
|
|
111
|
-
targetElementId: null,
|
|
112
|
-
streamingContent: null,
|
|
113
|
-
error: null,
|
|
114
|
-
isChatOpen: false,
|
|
115
|
-
chatMessages: [],
|
|
116
|
-
chatContextElementId: null,
|
|
117
|
-
currentStatus: null,
|
|
118
|
-
statusMessage: null,
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
101
|
function createInitialBlockEditorState(): BlockEditorState {
|
|
123
102
|
return {
|
|
124
103
|
isOpen: false,
|
|
@@ -181,15 +160,6 @@ function createInitialCollectionsBrowserState(): CollectionsBrowserState {
|
|
|
181
160
|
}
|
|
182
161
|
}
|
|
183
162
|
|
|
184
|
-
function createInitialDeploymentState(): DeploymentState {
|
|
185
|
-
return {
|
|
186
|
-
status: null,
|
|
187
|
-
lastDeployedAt: null,
|
|
188
|
-
isPolling: false,
|
|
189
|
-
error: null,
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
163
|
function createInitialColorEditorState(): ColorEditorState {
|
|
194
164
|
return {
|
|
195
165
|
isOpen: false,
|
|
@@ -297,22 +267,6 @@ const _pendingImageChangesHelpers = createMapHelpers(pendingImageChanges)
|
|
|
297
267
|
const _pendingColorChangesHelpers = createMapHelpers(pendingColorChanges)
|
|
298
268
|
const _pendingBgImageChangesHelpers = createMapHelpers(pendingBgImageChanges)
|
|
299
269
|
|
|
300
|
-
// ============================================================================
|
|
301
|
-
// AI State Signals
|
|
302
|
-
// ============================================================================
|
|
303
|
-
|
|
304
|
-
export const aiState = signal<AIState>(createInitialAIState())
|
|
305
|
-
|
|
306
|
-
// Convenience computed signals for AI state
|
|
307
|
-
export const isAIProcessing = computed(() => aiState.value.isProcessing)
|
|
308
|
-
export const isChatOpen = computed(() => aiState.value.isChatOpen)
|
|
309
|
-
export const chatMessages = computed(() => aiState.value.chatMessages)
|
|
310
|
-
export const chatContextElementId = computed(
|
|
311
|
-
() => aiState.value.chatContextElementId,
|
|
312
|
-
)
|
|
313
|
-
export const currentStatus = computed(() => aiState.value.currentStatus)
|
|
314
|
-
export const statusMessage = computed(() => aiState.value.statusMessage)
|
|
315
|
-
|
|
316
270
|
// ============================================================================
|
|
317
271
|
// Block Editor State Signals
|
|
318
272
|
// ============================================================================
|
|
@@ -346,24 +300,8 @@ export const isMarkdownPreview = signal(false)
|
|
|
346
300
|
// MDX Component Block State Signals
|
|
347
301
|
// ============================================================================
|
|
348
302
|
|
|
349
|
-
export const mdxPropsEditorState = signal<MdxPropsEditorState>({
|
|
350
|
-
isOpen: false,
|
|
351
|
-
nodePos: null,
|
|
352
|
-
componentName: null,
|
|
353
|
-
props: {},
|
|
354
|
-
cursorPos: null,
|
|
355
|
-
})
|
|
356
|
-
|
|
357
303
|
export const mdxComponentPickerOpen = signal(false)
|
|
358
304
|
|
|
359
|
-
export function openMdxPropsEditor(nodePos: number, componentName: string, props: Record<string, string>, cursorPos: { x: number; y: number }): void {
|
|
360
|
-
mdxPropsEditorState.value = { isOpen: true, nodePos, componentName, props, cursorPos }
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
export function closeMdxPropsEditor(): void {
|
|
364
|
-
mdxPropsEditorState.value = { isOpen: false, nodePos: null, componentName: null, props: {}, cursorPos: null }
|
|
365
|
-
}
|
|
366
|
-
|
|
367
305
|
// ============================================================================
|
|
368
306
|
// Reference Picker State Signals
|
|
369
307
|
// ============================================================================
|
|
@@ -467,19 +405,6 @@ export const collectionsBrowserState = signal<CollectionsBrowserState>(
|
|
|
467
405
|
export const isCollectionsBrowserOpen = computed(() => collectionsBrowserState.value.isOpen)
|
|
468
406
|
export const selectedBrowserCollection = computed(() => collectionsBrowserState.value.selectedCollection)
|
|
469
407
|
|
|
470
|
-
// ============================================================================
|
|
471
|
-
// Deployment State Signals
|
|
472
|
-
// ============================================================================
|
|
473
|
-
|
|
474
|
-
export const deploymentState = signal<DeploymentState>(
|
|
475
|
-
createInitialDeploymentState(),
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
// Convenience computed signals for deployment
|
|
479
|
-
export const deploymentStatus = computed(() => deploymentState.value.status)
|
|
480
|
-
export const isDeploymentPolling = computed(() => deploymentState.value.isPolling)
|
|
481
|
-
export const lastDeployedAt = computed(() => deploymentState.value.lastDeployedAt)
|
|
482
|
-
|
|
483
408
|
// ============================================================================
|
|
484
409
|
// Redirect Countdown State
|
|
485
410
|
// ============================================================================
|
|
@@ -788,83 +713,6 @@ export const deletePendingAttributeChange = _pendingAttributeChangesHelpers.dele
|
|
|
788
713
|
export const clearPendingAttributeChanges = _pendingAttributeChangesHelpers.clear
|
|
789
714
|
export const getPendingAttributeChange = _pendingAttributeChangesHelpers.get
|
|
790
715
|
|
|
791
|
-
// ============================================================================
|
|
792
|
-
// AI State Mutations
|
|
793
|
-
// ============================================================================
|
|
794
|
-
|
|
795
|
-
export function setAIPromptVisible(visible: boolean): void {
|
|
796
|
-
aiState.value = { ...aiState.value, isPromptVisible: visible }
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
export function setAIProcessing(processing: boolean): void {
|
|
800
|
-
aiState.value = { ...aiState.value, isProcessing: processing }
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
export function setAIStatus(status: AIStatusType, message?: string): void {
|
|
804
|
-
aiState.value = {
|
|
805
|
-
...aiState.value,
|
|
806
|
-
currentStatus: status,
|
|
807
|
-
statusMessage: message ?? null,
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
export function clearAIStatus(): void {
|
|
812
|
-
aiState.value = {
|
|
813
|
-
...aiState.value,
|
|
814
|
-
currentStatus: null,
|
|
815
|
-
statusMessage: null,
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
export function setAITargetElement(elementId: string | null): void {
|
|
820
|
-
aiState.value = { ...aiState.value, targetElementId: elementId }
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
export function setAIStreamingContent(content: string | null): void {
|
|
824
|
-
aiState.value = { ...aiState.value, streamingContent: content }
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
export function setAIError(error: string | null): void {
|
|
828
|
-
aiState.value = { ...aiState.value, error: error }
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
export function resetAIState(): void {
|
|
832
|
-
aiState.value = createInitialAIState()
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
export function setAIChatOpen(open: boolean): void {
|
|
836
|
-
aiState.value = { ...aiState.value, isChatOpen: open }
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
export function addChatMessage(message: ChatMessage): void {
|
|
840
|
-
aiState.value = {
|
|
841
|
-
...aiState.value,
|
|
842
|
-
chatMessages: [...aiState.value.chatMessages, message],
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
export function setChatMessages(messages: ChatMessage[]): void {
|
|
847
|
-
aiState.value = {
|
|
848
|
-
...aiState.value,
|
|
849
|
-
chatMessages: messages,
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
export function updateChatMessage(messageId: string, content: string): void {
|
|
854
|
-
aiState.value = {
|
|
855
|
-
...aiState.value,
|
|
856
|
-
chatMessages: aiState.value.chatMessages.map((msg) => msg.id === messageId ? { ...msg, content } : msg),
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
export function setChatContextElement(elementId: string | null): void {
|
|
861
|
-
aiState.value = { ...aiState.value, chatContextElementId: elementId }
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
export function clearChatMessages(): void {
|
|
865
|
-
aiState.value = { ...aiState.value, chatMessages: [] }
|
|
866
|
-
}
|
|
867
|
-
|
|
868
716
|
// ============================================================================
|
|
869
717
|
// Block Editor State Mutations
|
|
870
718
|
// ============================================================================
|
|
@@ -1266,34 +1114,6 @@ export async function openMarkdownEditorForEntry(
|
|
|
1266
1114
|
}
|
|
1267
1115
|
}
|
|
1268
1116
|
|
|
1269
|
-
// ============================================================================
|
|
1270
|
-
// Deployment State Mutations
|
|
1271
|
-
// ============================================================================
|
|
1272
|
-
|
|
1273
|
-
export function setDeploymentStatus(status: DeploymentStatusType | null): void {
|
|
1274
|
-
deploymentState.value = { ...deploymentState.value, status }
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
export function setDeploymentPolling(isPolling: boolean): void {
|
|
1278
|
-
deploymentState.value = { ...deploymentState.value, isPolling }
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
export function setLastDeployedAt(timestamp: string | null): void {
|
|
1282
|
-
deploymentState.value = { ...deploymentState.value, lastDeployedAt: timestamp }
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
export function setDeploymentError(error: string | null): void {
|
|
1286
|
-
deploymentState.value = { ...deploymentState.value, error }
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
export function updateDeploymentState(update: Partial<DeploymentState>): void {
|
|
1290
|
-
deploymentState.value = { ...deploymentState.value, ...update }
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
export function resetDeploymentState(): void {
|
|
1294
|
-
deploymentState.value = createInitialDeploymentState()
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
1117
|
// ============================================================================
|
|
1298
1118
|
// Color Editor State Mutations
|
|
1299
1119
|
// ============================================================================
|
|
@@ -1547,7 +1367,6 @@ export function getStateSnapshot(): EditorState {
|
|
|
1547
1367
|
pendingComponentChanges: pendingComponentChanges.value,
|
|
1548
1368
|
pendingInserts: pendingInserts.value,
|
|
1549
1369
|
manifest: manifest.value,
|
|
1550
|
-
ai: aiState.value,
|
|
1551
1370
|
blockEditor: blockEditorState.value,
|
|
1552
1371
|
}
|
|
1553
1372
|
}
|
|
@@ -1575,7 +1394,6 @@ export function resetAllState(): void {
|
|
|
1575
1394
|
pendingComponentChanges.value = new Map()
|
|
1576
1395
|
pendingInserts.value = new Map()
|
|
1577
1396
|
manifest.value = { entries: {}, components: {}, componentDefinitions: {} }
|
|
1578
|
-
aiState.value = createInitialAIState()
|
|
1579
1397
|
blockEditorState.value = createInitialBlockEditorState()
|
|
1580
1398
|
markdownEditorState.value = createInitialMarkdownEditorState()
|
|
1581
1399
|
mediaLibraryState.value = createInitialMediaLibraryState()
|
|
@@ -1583,7 +1401,6 @@ export function resetAllState(): void {
|
|
|
1583
1401
|
deletePageState.value = createInitialDeletePageState()
|
|
1584
1402
|
redirectsManagerState.value = createInitialRedirectsManagerState()
|
|
1585
1403
|
collectionsBrowserState.value = createInitialCollectionsBrowserState()
|
|
1586
|
-
deploymentState.value = createInitialDeploymentState()
|
|
1587
1404
|
colorEditorState.value = createInitialColorEditorState()
|
|
1588
1405
|
confirmDialogState.value = createInitialConfirmDialogState()
|
|
1589
1406
|
seoEditorState.value = createInitialSeoEditorState()
|
package/src/editor/styles.css
CHANGED
|
@@ -87,114 +87,6 @@
|
|
|
87
87
|
animation: spin 1s linear infinite;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/* Markdown styles for AI chat messages */
|
|
91
|
-
.cms-markdown p {
|
|
92
|
-
margin: 0 0 0.5em 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.cms-markdown p:last-child {
|
|
96
|
-
margin-bottom: 0;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.cms-markdown strong {
|
|
100
|
-
font-weight: 700;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.cms-markdown em {
|
|
104
|
-
font-style: italic;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.cms-markdown code {
|
|
108
|
-
background: rgba(255, 255, 255, 0.1);
|
|
109
|
-
padding: 0.1em 0.3em;
|
|
110
|
-
border-radius: 3px;
|
|
111
|
-
font-family: ui-monospace, monospace;
|
|
112
|
-
font-size: 0.9em;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.cms-markdown pre {
|
|
116
|
-
background: rgba(0, 0, 0, 0.3);
|
|
117
|
-
padding: 0.75em;
|
|
118
|
-
border-radius: 4px;
|
|
119
|
-
overflow-x: auto;
|
|
120
|
-
margin: 0.5em 0;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.cms-markdown pre code {
|
|
124
|
-
background: none;
|
|
125
|
-
padding: 0;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.cms-markdown ul {
|
|
129
|
-
margin: 0.5em 0;
|
|
130
|
-
padding-left: 1.5em;
|
|
131
|
-
list-style-type: disc;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.cms-markdown ol {
|
|
135
|
-
margin: 0.5em 0;
|
|
136
|
-
padding-left: 1.5em;
|
|
137
|
-
list-style-type: decimal;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.cms-markdown ul ul {
|
|
141
|
-
list-style-type: circle;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.cms-markdown ul ul ul {
|
|
145
|
-
list-style-type: square;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.cms-markdown li {
|
|
149
|
-
margin: 0.25em 0;
|
|
150
|
-
display: list-item;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.cms-markdown h1, .cms-markdown h2, .cms-markdown h3,
|
|
154
|
-
.cms-markdown h4, .cms-markdown h5, .cms-markdown h6 {
|
|
155
|
-
margin: 0.75em 0 0.25em 0;
|
|
156
|
-
font-weight: 600;
|
|
157
|
-
line-height: 1.3;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.cms-markdown h1 {
|
|
161
|
-
font-size: 1.4em;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.cms-markdown h2 {
|
|
165
|
-
font-size: 1.2em;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.cms-markdown h3 {
|
|
169
|
-
font-size: 1.1em;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.cms-markdown h1:first-child, .cms-markdown h2:first-child, .cms-markdown h3:first-child {
|
|
173
|
-
margin-top: 0;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.cms-markdown hr {
|
|
177
|
-
border: none;
|
|
178
|
-
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
|
179
|
-
margin: 0.75em 0;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.cms-markdown a {
|
|
183
|
-
color: #93c5fd;
|
|
184
|
-
text-decoration: underline;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.cms-markdown a:hover {
|
|
188
|
-
color: #bfdbfe;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.cms-markdown blockquote {
|
|
192
|
-
border-left: 3px solid #93c5fd;
|
|
193
|
-
margin: 0.5em 0;
|
|
194
|
-
padding-left: 1em;
|
|
195
|
-
color: rgba(255, 255, 255, 0.7);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
90
|
/* Soft Design System Card Component */
|
|
199
91
|
.cms-card {
|
|
200
92
|
background: var(--color-cms-card);
|
package/src/editor/types.ts
CHANGED
|
@@ -240,35 +240,6 @@ export interface SaveBatchResponse {
|
|
|
240
240
|
errors?: Array<{ cmsId: string; error: string }>
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
export interface ChatMessage {
|
|
244
|
-
id: string
|
|
245
|
-
role: 'user' | 'assistant'
|
|
246
|
-
content: string
|
|
247
|
-
elementId?: string
|
|
248
|
-
timestamp: number
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export type AIStatusType =
|
|
252
|
-
| 'thinking'
|
|
253
|
-
| 'coding'
|
|
254
|
-
| 'building'
|
|
255
|
-
| 'deploying'
|
|
256
|
-
| 'complete'
|
|
257
|
-
| null
|
|
258
|
-
|
|
259
|
-
export interface AIState {
|
|
260
|
-
isPromptVisible: boolean
|
|
261
|
-
isProcessing: boolean
|
|
262
|
-
targetElementId: string | null
|
|
263
|
-
streamingContent: string | null
|
|
264
|
-
error: string | null
|
|
265
|
-
isChatOpen: boolean
|
|
266
|
-
chatMessages: ChatMessage[]
|
|
267
|
-
chatContextElementId: string | null
|
|
268
|
-
currentStatus: AIStatusType
|
|
269
|
-
statusMessage: string | null
|
|
270
|
-
}
|
|
271
|
-
|
|
272
243
|
export interface BlockEditorState {
|
|
273
244
|
isOpen: boolean
|
|
274
245
|
currentComponentId: string | null
|
|
@@ -322,7 +293,6 @@ export interface EditorState {
|
|
|
322
293
|
pendingComponentChanges: Map<string, ComponentInstance>
|
|
323
294
|
pendingInserts: Map<string, PendingComponentInsert>
|
|
324
295
|
manifest: CmsManifest
|
|
325
|
-
ai: AIState
|
|
326
296
|
blockEditor: BlockEditorState
|
|
327
297
|
}
|
|
328
298
|
|
|
@@ -481,42 +451,6 @@ export interface MediaUploadResponse {
|
|
|
481
451
|
error?: string
|
|
482
452
|
}
|
|
483
453
|
|
|
484
|
-
// ============================================================================
|
|
485
|
-
// Deployment Status Types
|
|
486
|
-
// ============================================================================
|
|
487
|
-
|
|
488
|
-
export type DeploymentStatusType =
|
|
489
|
-
| 'pending'
|
|
490
|
-
| 'queued'
|
|
491
|
-
| 'running'
|
|
492
|
-
| 'completed'
|
|
493
|
-
| 'failed'
|
|
494
|
-
| 'cancelled'
|
|
495
|
-
|
|
496
|
-
export interface DeploymentStatusResponse {
|
|
497
|
-
currentDeployment: {
|
|
498
|
-
id: string
|
|
499
|
-
status: DeploymentStatusType
|
|
500
|
-
createdAt: string
|
|
501
|
-
startedAt: string | null
|
|
502
|
-
commitMessage: string | null
|
|
503
|
-
} | null
|
|
504
|
-
lastSuccessfulDeployment: {
|
|
505
|
-
completedAt: string
|
|
506
|
-
publishedUrl: string
|
|
507
|
-
} | null
|
|
508
|
-
pendingCount: number
|
|
509
|
-
/** When false, deployment is not available (e.g. local dev) and polling should be skipped */
|
|
510
|
-
deploymentEnabled?: boolean
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
export interface DeploymentState {
|
|
514
|
-
status: DeploymentStatusType | null
|
|
515
|
-
lastDeployedAt: string | null
|
|
516
|
-
isPolling: boolean
|
|
517
|
-
error: string | null
|
|
518
|
-
}
|
|
519
|
-
|
|
520
454
|
// ============================================================================
|
|
521
455
|
// Confirm Dialog Types
|
|
522
456
|
// ============================================================================
|
|
@@ -698,16 +632,6 @@ export type UndoAction =
|
|
|
698
632
|
// MDX Component Block Types
|
|
699
633
|
// ============================================================================
|
|
700
634
|
|
|
701
|
-
export interface MdxPropsEditorState {
|
|
702
|
-
isOpen: boolean
|
|
703
|
-
/** ProseMirror document position of the node being edited */
|
|
704
|
-
nodePos: number | null
|
|
705
|
-
componentName: string | null
|
|
706
|
-
props: Record<string, string>
|
|
707
|
-
/** Position for the floating editor panel */
|
|
708
|
-
cursorPos: { x: number; y: number } | null
|
|
709
|
-
}
|
|
710
|
-
|
|
711
635
|
declare global {
|
|
712
636
|
interface Window {
|
|
713
637
|
NuaCmsConfig?: Partial<CmsConfig>
|
package/src/html-processor.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HTMLElement as ParsedHTMLElement, parse } from 'node-html-parser'
|
|
2
2
|
import { processSeoFromHtml } from './seo-processor'
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import { extractBackgroundImageClasses, extractColorClasses, extractTextStyleClasses } from './tailwind-colors'
|
|
5
5
|
import type {
|
|
6
6
|
Attribute,
|
|
@@ -90,6 +90,8 @@ export interface ProcessHtmlResult {
|
|
|
90
90
|
collectionWrapperId?: string
|
|
91
91
|
/** Extracted SEO data from the page */
|
|
92
92
|
seo?: PageSeoData
|
|
93
|
+
/** Collection definitions passed through for deferred enhancement */
|
|
94
|
+
collectionDefinitions?: Record<string, CollectionDefinition>
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
/**
|
|
@@ -440,7 +442,10 @@ export async function processHtml(
|
|
|
440
442
|
let foundWrapper = false
|
|
441
443
|
|
|
442
444
|
// Strategy 1: Dev mode - look for source file attributes
|
|
445
|
+
const SKIP_WRAPPER_TAGS = new Set(['html', 'head', 'body', 'script', 'style', 'meta', 'link'])
|
|
443
446
|
for (const node of allElements) {
|
|
447
|
+
const tag = node.tagName?.toLowerCase?.() ?? ''
|
|
448
|
+
if (SKIP_WRAPPER_TAGS.has(tag)) continue
|
|
444
449
|
const sourceFile = node.getAttribute('data-astro-source-file')
|
|
445
450
|
if (!sourceFile) continue
|
|
446
451
|
|
|
@@ -1023,10 +1028,6 @@ export async function processHtml(
|
|
|
1023
1028
|
node.removeAttribute('data-astro-source-line')
|
|
1024
1029
|
})
|
|
1025
1030
|
|
|
1026
|
-
// Enhance manifest entries with actual source snippets from source files
|
|
1027
|
-
// This allows the CMS to match and replace dynamic content in source files
|
|
1028
|
-
const enhancedEntries = await enhanceManifestWithSourceSnippets(entries, collectionDefinitions)
|
|
1029
|
-
|
|
1030
1031
|
// Get the current HTML for SEO processing
|
|
1031
1032
|
let finalHtml = root.toString()
|
|
1032
1033
|
|
|
@@ -1048,7 +1049,7 @@ export async function processHtml(
|
|
|
1048
1049
|
|
|
1049
1050
|
// If title was marked with CMS ID, add it to entries
|
|
1050
1051
|
if (seoResult.titleId && seo.title) {
|
|
1051
|
-
|
|
1052
|
+
entries[seoResult.titleId] = {
|
|
1052
1053
|
id: seoResult.titleId,
|
|
1053
1054
|
tag: 'title',
|
|
1054
1055
|
text: seo.title.content,
|
|
@@ -1061,10 +1062,11 @@ export async function processHtml(
|
|
|
1061
1062
|
|
|
1062
1063
|
return {
|
|
1063
1064
|
html: finalHtml,
|
|
1064
|
-
entries
|
|
1065
|
+
entries,
|
|
1065
1066
|
components,
|
|
1066
1067
|
collectionWrapperId,
|
|
1067
1068
|
seo,
|
|
1069
|
+
collectionDefinitions,
|
|
1068
1070
|
}
|
|
1069
1071
|
}
|
|
1070
1072
|
|
|
@@ -18,6 +18,9 @@ const textSearchIndex: SearchIndexEntry[] = []
|
|
|
18
18
|
const imageSearchIndex: ImageIndexEntry[] = []
|
|
19
19
|
let searchIndexInitialized = false
|
|
20
20
|
|
|
21
|
+
/** Files that changed since last indexing — tracked by Vite watcher */
|
|
22
|
+
const dirtyFiles = new Set<string>()
|
|
23
|
+
|
|
21
24
|
// ============================================================================
|
|
22
25
|
// Cache Access Functions
|
|
23
26
|
// ============================================================================
|
|
@@ -58,6 +61,49 @@ export function addToImageSearchIndex(entry: ImageIndexEntry): void {
|
|
|
58
61
|
imageSearchIndex.push(entry)
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// Dirty File Tracking (incremental re-indexing)
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Mark a file as dirty so its index entries are refreshed on next page load.
|
|
70
|
+
* Called by the Vite file watcher when source files change.
|
|
71
|
+
* @param absPath - Absolute path to the changed file
|
|
72
|
+
*/
|
|
73
|
+
export function markFileDirty(absPath: string): void {
|
|
74
|
+
dirtyFiles.add(absPath)
|
|
75
|
+
// Also evict the parsed file cache so it's re-read from disk
|
|
76
|
+
parsedFileCache.delete(absPath)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getDirtyFiles(): Set<string> {
|
|
80
|
+
return dirtyFiles
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function clearDirtyFiles(): void {
|
|
84
|
+
dirtyFiles.clear()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Remove all index entries for a specific file (by relative path).
|
|
89
|
+
* Used before re-indexing a changed file to avoid duplicates.
|
|
90
|
+
*/
|
|
91
|
+
export function removeFileFromIndexes(relFile: string): void {
|
|
92
|
+
filterInPlace(textSearchIndex, (e) => e.file !== relFile)
|
|
93
|
+
filterInPlace(imageSearchIndex, (e) => e.file !== relFile)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Remove non-matching elements in-place (single pass, no per-element splice). */
|
|
97
|
+
function filterInPlace<T>(arr: T[], keep: (item: T) => boolean): void {
|
|
98
|
+
let write = 0
|
|
99
|
+
for (const item of arr) {
|
|
100
|
+
if (keep(item)) {
|
|
101
|
+
arr[write++] = item
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
arr.length = write
|
|
105
|
+
}
|
|
106
|
+
|
|
61
107
|
// ============================================================================
|
|
62
108
|
// Cache Clear Function
|
|
63
109
|
// ============================================================================
|
|
@@ -69,6 +115,7 @@ export function clearSourceFinderCache(): void {
|
|
|
69
115
|
parsedFileCache.clear()
|
|
70
116
|
directoryCache.clear()
|
|
71
117
|
markdownFileCache.clear()
|
|
118
|
+
dirtyFiles.clear()
|
|
72
119
|
// Clear arrays in-place to avoid stale references from consumers
|
|
73
120
|
textSearchIndex.length = 0
|
|
74
121
|
imageSearchIndex.length = 0
|