@nuasite/cms 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -0
- package/dist/src/build-processor.d.ts +20 -0
- package/dist/src/build-processor.d.ts.map +1 -0
- package/dist/src/collection-scanner.d.ts +6 -0
- package/dist/src/collection-scanner.d.ts.map +1 -0
- package/dist/src/component-registry.d.ts +63 -0
- package/dist/src/component-registry.d.ts.map +1 -0
- package/dist/src/config.d.ts +24 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/dev-middleware.d.ts +20 -0
- package/dist/src/dev-middleware.d.ts.map +1 -0
- package/dist/src/editor/ai.d.ts +60 -0
- package/dist/src/editor/ai.d.ts.map +1 -0
- package/dist/src/editor/api.d.ts +140 -0
- package/dist/src/editor/api.d.ts.map +1 -0
- package/dist/src/editor/color-utils.d.ts +106 -0
- package/dist/src/editor/color-utils.d.ts.map +1 -0
- package/dist/src/editor/components/ai-chat.d.ts +11 -0
- package/dist/src/editor/components/ai-chat.d.ts.map +1 -0
- package/dist/src/editor/components/ai-tooltip.d.ts +12 -0
- package/dist/src/editor/components/ai-tooltip.d.ts.map +1 -0
- package/dist/src/editor/components/attribute-editor.d.ts +5 -0
- package/dist/src/editor/components/attribute-editor.d.ts.map +1 -0
- package/dist/src/editor/components/block-editor.d.ts +12 -0
- package/dist/src/editor/components/block-editor.d.ts.map +1 -0
- package/dist/src/editor/components/collections-browser.d.ts +2 -0
- package/dist/src/editor/components/collections-browser.d.ts.map +1 -0
- package/dist/src/editor/components/color-toolbar.d.ts +12 -0
- package/dist/src/editor/components/color-toolbar.d.ts.map +1 -0
- package/dist/src/editor/components/confirm-dialog.d.ts +2 -0
- package/dist/src/editor/components/confirm-dialog.d.ts.map +1 -0
- package/dist/src/editor/components/create-page-modal.d.ts +2 -0
- package/dist/src/editor/components/create-page-modal.d.ts.map +1 -0
- package/dist/src/editor/components/editable-highlights.d.ts +9 -0
- package/dist/src/editor/components/editable-highlights.d.ts.map +1 -0
- package/dist/src/editor/components/error-boundary.d.ts +32 -0
- package/dist/src/editor/components/error-boundary.d.ts.map +1 -0
- package/dist/src/editor/components/fields.d.ts +75 -0
- package/dist/src/editor/components/fields.d.ts.map +1 -0
- package/dist/src/editor/components/frontmatter-fields.d.ts +29 -0
- package/dist/src/editor/components/frontmatter-fields.d.ts.map +1 -0
- package/dist/src/editor/components/highlight-overlay.d.ts +64 -0
- package/dist/src/editor/components/highlight-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/image-overlay.d.ts +12 -0
- package/dist/src/editor/components/image-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/markdown-editor-overlay.d.ts +6 -0
- package/dist/src/editor/components/markdown-editor-overlay.d.ts.map +1 -0
- package/dist/src/editor/components/markdown-inline-editor.d.ts +10 -0
- package/dist/src/editor/components/markdown-inline-editor.d.ts.map +1 -0
- package/dist/src/editor/components/media-library.d.ts +2 -0
- package/dist/src/editor/components/media-library.d.ts.map +1 -0
- package/dist/src/editor/components/outline.d.ts +21 -0
- package/dist/src/editor/components/outline.d.ts.map +1 -0
- package/dist/src/editor/components/redirect-countdown.d.ts +2 -0
- package/dist/src/editor/components/redirect-countdown.d.ts.map +1 -0
- package/dist/src/editor/components/seo-editor.d.ts +2 -0
- package/dist/src/editor/components/seo-editor.d.ts.map +1 -0
- package/dist/src/editor/components/text-style-toolbar.d.ts +8 -0
- package/dist/src/editor/components/text-style-toolbar.d.ts.map +1 -0
- package/dist/src/editor/components/toast/toast-container.d.ts +7 -0
- package/dist/src/editor/components/toast/toast-container.d.ts.map +1 -0
- package/dist/src/editor/components/toast/toast.d.ts +7 -0
- package/dist/src/editor/components/toast/toast.d.ts.map +1 -0
- package/dist/src/editor/components/toast/types.d.ts +7 -0
- package/dist/src/editor/components/toast/types.d.ts.map +1 -0
- package/dist/src/editor/components/toolbar.d.ts +21 -0
- package/dist/src/editor/components/toolbar.d.ts.map +1 -0
- package/dist/src/editor/config.d.ts +4 -0
- package/dist/src/editor/config.d.ts.map +1 -0
- package/dist/src/editor/constants.d.ts +101 -0
- package/dist/src/editor/constants.d.ts.map +1 -0
- package/dist/src/editor/context.d.ts +14 -0
- package/dist/src/editor/context.d.ts.map +1 -0
- package/dist/src/editor/dom.d.ts +77 -0
- package/dist/src/editor/dom.d.ts.map +1 -0
- package/dist/src/editor/editor.d.ts +64 -0
- package/dist/src/editor/editor.d.ts.map +1 -0
- package/dist/src/editor/history.d.ts +20 -0
- package/dist/src/editor/history.d.ts.map +1 -0
- package/dist/src/editor/hooks/index.d.ts +14 -0
- package/dist/src/editor/hooks/index.d.ts.map +1 -0
- package/dist/src/editor/hooks/useAIHandlers.d.ts +22 -0
- package/dist/src/editor/hooks/useAIHandlers.d.ts.map +1 -0
- package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts +18 -0
- package/dist/src/editor/hooks/useBlockEditorHandlers.d.ts.map +1 -0
- package/dist/src/editor/hooks/useElementDetection.d.ts +26 -0
- package/dist/src/editor/hooks/useElementDetection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useImageHoverDetection.d.ts +12 -0
- package/dist/src/editor/hooks/useImageHoverDetection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useTextSelection.d.ts +23 -0
- package/dist/src/editor/hooks/useTextSelection.d.ts.map +1 -0
- package/dist/src/editor/hooks/useTooltipState.d.ts +19 -0
- package/dist/src/editor/hooks/useTooltipState.d.ts.map +1 -0
- package/dist/src/editor/hooks/utils.d.ts +32 -0
- package/dist/src/editor/hooks/utils.d.ts.map +1 -0
- package/dist/src/editor/index.d.ts +12 -0
- package/dist/src/editor/index.d.ts.map +1 -0
- package/dist/src/editor/lib/cn.d.ts +3 -0
- package/dist/src/editor/lib/cn.d.ts.map +1 -0
- package/dist/src/editor/manifest.d.ts +19 -0
- package/dist/src/editor/manifest.d.ts.map +1 -0
- package/dist/src/editor/markdown-api.d.ts +36 -0
- package/dist/src/editor/markdown-api.d.ts.map +1 -0
- package/dist/src/editor/signals.d.ts +242 -0
- package/dist/src/editor/signals.d.ts.map +1 -0
- package/dist/src/editor/storage.d.ts +27 -0
- package/dist/src/editor/storage.d.ts.map +1 -0
- package/dist/src/editor/text-styling.d.ts +350 -0
- package/dist/src/editor/text-styling.d.ts.map +1 -0
- package/dist/src/editor/themes.d.ts +38 -0
- package/dist/src/editor/themes.d.ts.map +1 -0
- package/dist/src/editor/types.d.ts +454 -0
- package/dist/src/editor/types.d.ts.map +1 -0
- package/dist/src/error-collector.d.ts +56 -0
- package/dist/src/error-collector.d.ts.map +1 -0
- package/dist/src/handlers/component-ops.d.ts +34 -0
- package/dist/src/handlers/component-ops.d.ts.map +1 -0
- package/dist/src/handlers/markdown-ops.d.ts +41 -0
- package/dist/src/handlers/markdown-ops.d.ts.map +1 -0
- package/dist/src/handlers/request-utils.d.ts +20 -0
- package/dist/src/handlers/request-utils.d.ts.map +1 -0
- package/dist/src/handlers/source-writer.d.ts +51 -0
- package/dist/src/handlers/source-writer.d.ts.map +1 -0
- package/dist/src/html-processor.d.ts +63 -0
- package/dist/src/html-processor.d.ts.map +1 -0
- package/dist/src/index.d.ts +41 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/manifest-writer.d.ts +111 -0
- package/dist/src/manifest-writer.d.ts.map +1 -0
- package/dist/src/media/contember.d.ts +15 -0
- package/dist/src/media/contember.d.ts.map +1 -0
- package/dist/src/media/local.d.ts +9 -0
- package/dist/src/media/local.d.ts.map +1 -0
- package/dist/src/media/s3.d.ts +12 -0
- package/dist/src/media/s3.d.ts.map +1 -0
- package/dist/src/media/types.d.ts +40 -0
- package/dist/src/media/types.d.ts.map +1 -0
- package/dist/src/preview-generator.d.ts +19 -0
- package/dist/src/preview-generator.d.ts.map +1 -0
- package/dist/src/seo-processor.d.ts +23 -0
- package/dist/src/seo-processor.d.ts.map +1 -0
- package/dist/src/source-finder/ast-extractors.d.ts +35 -0
- package/dist/src/source-finder/ast-extractors.d.ts.map +1 -0
- package/dist/src/source-finder/ast-parser.d.ts +16 -0
- package/dist/src/source-finder/ast-parser.d.ts.map +1 -0
- package/dist/src/source-finder/cache.d.ts +18 -0
- package/dist/src/source-finder/cache.d.ts.map +1 -0
- package/dist/src/source-finder/collection-finder.d.ts +29 -0
- package/dist/src/source-finder/collection-finder.d.ts.map +1 -0
- package/dist/src/source-finder/cross-file-tracker.d.ts +39 -0
- package/dist/src/source-finder/cross-file-tracker.d.ts.map +1 -0
- package/dist/src/source-finder/element-finder.d.ts +42 -0
- package/dist/src/source-finder/element-finder.d.ts.map +1 -0
- package/dist/src/source-finder/image-finder.d.ts +24 -0
- package/dist/src/source-finder/image-finder.d.ts.map +1 -0
- package/dist/src/source-finder/index.d.ts +9 -0
- package/dist/src/source-finder/index.d.ts.map +1 -0
- package/dist/src/source-finder/search-index.d.ts +27 -0
- package/dist/src/source-finder/search-index.d.ts.map +1 -0
- package/dist/src/source-finder/snippet-utils.d.ts +90 -0
- package/dist/src/source-finder/snippet-utils.d.ts.map +1 -0
- package/dist/src/source-finder/source-lookup.d.ts +16 -0
- package/dist/src/source-finder/source-lookup.d.ts.map +1 -0
- package/dist/src/source-finder/types.d.ts +167 -0
- package/dist/src/source-finder/types.d.ts.map +1 -0
- package/dist/src/source-finder/variable-extraction.d.ts +37 -0
- package/dist/src/source-finder/variable-extraction.d.ts.map +1 -0
- package/dist/src/tailwind-colors.d.ts +54 -0
- package/dist/src/tailwind-colors.d.ts.map +1 -0
- package/dist/src/tsconfig.tsbuildinfo +1 -0
- package/dist/src/types.d.ts +367 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +61 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/vite-plugin.d.ts +14 -0
- package/dist/src/vite-plugin.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +80 -0
- package/src/build-processor.ts +784 -0
- package/src/collection-scanner.ts +304 -0
- package/src/component-registry.ts +393 -0
- package/src/config.ts +74 -0
- package/src/dev-middleware.ts +525 -0
- package/src/dist/src/tsconfig.tsbuildinfo +1 -0
- package/src/editor/ai.ts +185 -0
- package/src/editor/api.ts +513 -0
- package/src/editor/color-utils.ts +556 -0
- package/src/editor/components/ai-chat.tsx +632 -0
- package/src/editor/components/ai-tooltip.tsx +179 -0
- package/src/editor/components/attribute-editor.tsx +596 -0
- package/src/editor/components/block-editor.tsx +546 -0
- package/src/editor/components/collections-browser.tsx +248 -0
- package/src/editor/components/color-toolbar.tsx +314 -0
- package/src/editor/components/confirm-dialog.tsx +69 -0
- package/src/editor/components/create-page-modal.tsx +163 -0
- package/src/editor/components/editable-highlights.tsx +260 -0
- package/src/editor/components/error-boundary.tsx +87 -0
- package/src/editor/components/fields.tsx +387 -0
- package/src/editor/components/frontmatter-fields.tsx +469 -0
- package/src/editor/components/highlight-overlay.ts +229 -0
- package/src/editor/components/image-overlay.tsx +230 -0
- package/src/editor/components/markdown-editor-overlay.tsx +505 -0
- package/src/editor/components/markdown-inline-editor.tsx +780 -0
- package/src/editor/components/media-library.tsx +297 -0
- package/src/editor/components/outline.tsx +402 -0
- package/src/editor/components/redirect-countdown.tsx +45 -0
- package/src/editor/components/seo-editor.tsx +498 -0
- package/src/editor/components/text-style-toolbar.tsx +362 -0
- package/src/editor/components/toast/toast-container.tsx +15 -0
- package/src/editor/components/toast/toast.tsx +49 -0
- package/src/editor/components/toast/types.ts +7 -0
- package/src/editor/components/toolbar.tsx +366 -0
- package/src/editor/config.ts +12 -0
- package/src/editor/constants.ts +106 -0
- package/src/editor/context.tsx +38 -0
- package/src/editor/dom.ts +357 -0
- package/src/editor/editor.ts +1510 -0
- package/src/editor/env.d.ts +4 -0
- package/src/editor/history.ts +355 -0
- package/src/editor/hooks/index.ts +19 -0
- package/src/editor/hooks/useAIHandlers.ts +345 -0
- package/src/editor/hooks/useBlockEditorHandlers.ts +206 -0
- package/src/editor/hooks/useElementDetection.ts +284 -0
- package/src/editor/hooks/useImageHoverDetection.ts +102 -0
- package/src/editor/hooks/useTextSelection.ts +187 -0
- package/src/editor/hooks/useTooltipState.ts +126 -0
- package/src/editor/hooks/utils.ts +101 -0
- package/src/editor/index.tsx +481 -0
- package/src/editor/lib/cn.ts +4 -0
- package/src/editor/manifest.ts +25 -0
- package/src/editor/markdown-api.ts +209 -0
- package/src/editor/signals.ts +1351 -0
- package/src/editor/storage.ts +266 -0
- package/src/editor/styles.css +465 -0
- package/src/editor/text-styling.ts +773 -0
- package/src/editor/themes.ts +210 -0
- package/src/editor/types.ts +591 -0
- package/src/error-collector.ts +106 -0
- package/src/handlers/component-ops.ts +463 -0
- package/src/handlers/markdown-ops.ts +202 -0
- package/src/handlers/request-utils.ts +151 -0
- package/src/handlers/source-writer.ts +649 -0
- package/src/html-processor.ts +1108 -0
- package/src/index.ts +284 -0
- package/src/manifest-writer.ts +371 -0
- package/src/media/contember.ts +84 -0
- package/src/media/local.ts +114 -0
- package/src/media/s3.ts +133 -0
- package/src/media/types.ts +33 -0
- package/src/preview-generator.ts +293 -0
- package/src/seo-processor.ts +567 -0
- package/src/source-finder/ast-extractors.ts +185 -0
- package/src/source-finder/ast-parser.ts +150 -0
- package/src/source-finder/cache.ts +76 -0
- package/src/source-finder/collection-finder.ts +335 -0
- package/src/source-finder/cross-file-tracker.ts +741 -0
- package/src/source-finder/element-finder.ts +387 -0
- package/src/source-finder/image-finder.ts +283 -0
- package/src/source-finder/index.ts +37 -0
- package/src/source-finder/search-index.ts +525 -0
- package/src/source-finder/snippet-utils.ts +668 -0
- package/src/source-finder/source-lookup.ts +200 -0
- package/src/source-finder/types.ts +210 -0
- package/src/source-finder/variable-extraction.ts +406 -0
- package/src/tailwind-colors.ts +874 -0
- package/src/tsconfig.json +25 -0
- package/src/types.ts +406 -0
- package/src/utils.ts +186 -0
- package/src/vite-plugin.ts +42 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import type { AstroIntegration } from 'astro'
|
|
2
|
+
import { dirname, join } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import tailwindcss from '@tailwindcss/vite'
|
|
5
|
+
|
|
6
|
+
import { processBuildOutput } from './build-processor'
|
|
7
|
+
import { scanCollections } from './collection-scanner'
|
|
8
|
+
import { ComponentRegistry } from './component-registry'
|
|
9
|
+
import { resetProjectRoot } from './config'
|
|
10
|
+
import { createDevMiddleware } from './dev-middleware'
|
|
11
|
+
import { getErrorCollector, resetErrorCollector } from './error-collector'
|
|
12
|
+
import { ManifestWriter } from './manifest-writer'
|
|
13
|
+
import { createLocalStorageAdapter } from './media/local'
|
|
14
|
+
import type { MediaStorageAdapter } from './media/types'
|
|
15
|
+
import type { CmsMarkerOptions, ComponentDefinition } from './types'
|
|
16
|
+
import { createVitePlugin } from './vite-plugin'
|
|
17
|
+
|
|
18
|
+
export interface NuaCmsOptions extends CmsMarkerOptions {
|
|
19
|
+
/**
|
|
20
|
+
* URL to the CMS editor script.
|
|
21
|
+
* If not set, the built-in editor bundle is served from the dev server.
|
|
22
|
+
*/
|
|
23
|
+
src?: string
|
|
24
|
+
/**
|
|
25
|
+
* CMS configuration passed as window.NuaCmsConfig.
|
|
26
|
+
*/
|
|
27
|
+
cmsConfig?: {
|
|
28
|
+
apiBase?: string
|
|
29
|
+
highlightColor?: string
|
|
30
|
+
debug?: boolean
|
|
31
|
+
theme?: Record<string, string>
|
|
32
|
+
themePreset?: string
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Proxy /_nua/cms requests to this target URL during dev.
|
|
36
|
+
* Example: 'http://localhost:8787'
|
|
37
|
+
*/
|
|
38
|
+
proxy?: string
|
|
39
|
+
/**
|
|
40
|
+
* Media storage adapter for file uploads.
|
|
41
|
+
* Defaults to local filesystem (public/uploads) when no proxy is configured.
|
|
42
|
+
*/
|
|
43
|
+
media?: MediaStorageAdapter
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const VIRTUAL_CMS_PATH = '/@nuasite/cms-editor.js'
|
|
47
|
+
|
|
48
|
+
export default function nuaCms(options: NuaCmsOptions = {}): AstroIntegration {
|
|
49
|
+
const {
|
|
50
|
+
// CMS editor options
|
|
51
|
+
src,
|
|
52
|
+
cmsConfig,
|
|
53
|
+
proxy,
|
|
54
|
+
media,
|
|
55
|
+
// CMS marker options
|
|
56
|
+
attributeName = 'data-cms-id',
|
|
57
|
+
includeTags = null,
|
|
58
|
+
excludeTags = ['html', 'head', 'body', 'script', 'style'],
|
|
59
|
+
includeEmptyText = false,
|
|
60
|
+
generateManifest = true,
|
|
61
|
+
manifestFile = 'cms-manifest.json',
|
|
62
|
+
markComponents = true,
|
|
63
|
+
componentDirs = ['src/components'],
|
|
64
|
+
contentDir = 'src/content',
|
|
65
|
+
seo = { trackSeo: true, markTitle: true, parseJsonLd: true },
|
|
66
|
+
} = options
|
|
67
|
+
|
|
68
|
+
// When no proxy, enable local CMS API with default media adapter
|
|
69
|
+
const enableCmsApi = !proxy
|
|
70
|
+
const mediaAdapter = media ?? (enableCmsApi ? createLocalStorageAdapter() : undefined)
|
|
71
|
+
|
|
72
|
+
// Default apiBase to local dev server when no proxy
|
|
73
|
+
const resolvedCmsConfig = enableCmsApi && !cmsConfig?.apiBase
|
|
74
|
+
? { ...cmsConfig, apiBase: '/_nua/cms' }
|
|
75
|
+
: cmsConfig
|
|
76
|
+
|
|
77
|
+
let componentDefinitions: Record<string, ComponentDefinition> = {}
|
|
78
|
+
|
|
79
|
+
const idCounter = { value: 0 }
|
|
80
|
+
const manifestWriter = new ManifestWriter(manifestFile, componentDefinitions)
|
|
81
|
+
|
|
82
|
+
const markerConfig = {
|
|
83
|
+
attributeName,
|
|
84
|
+
includeTags,
|
|
85
|
+
excludeTags,
|
|
86
|
+
includeEmptyText,
|
|
87
|
+
generateManifest,
|
|
88
|
+
manifestFile,
|
|
89
|
+
markComponents,
|
|
90
|
+
componentDirs,
|
|
91
|
+
contentDir,
|
|
92
|
+
seo,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
name: '@nuasite/astro-cms',
|
|
97
|
+
hooks: {
|
|
98
|
+
'astro:config:setup': async ({ updateConfig, command, injectScript, logger }) => {
|
|
99
|
+
// --- CMS Marker setup ---
|
|
100
|
+
idCounter.value = 0
|
|
101
|
+
manifestWriter.reset()
|
|
102
|
+
resetErrorCollector()
|
|
103
|
+
resetProjectRoot()
|
|
104
|
+
|
|
105
|
+
await manifestWriter.loadAvailableColors()
|
|
106
|
+
|
|
107
|
+
if (markComponents) {
|
|
108
|
+
const registry = new ComponentRegistry(componentDirs)
|
|
109
|
+
await registry.scan()
|
|
110
|
+
componentDefinitions = registry.getComponents()
|
|
111
|
+
manifestWriter.setComponentDefinitions(componentDefinitions)
|
|
112
|
+
|
|
113
|
+
const componentCount = Object.keys(componentDefinitions).length
|
|
114
|
+
if (componentCount > 0) {
|
|
115
|
+
logger.info(`Found ${componentCount} component definitions`)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const collectionDefinitions = await scanCollections(contentDir)
|
|
120
|
+
manifestWriter.setCollectionDefinitions(collectionDefinitions)
|
|
121
|
+
|
|
122
|
+
const collectionCount = Object.keys(collectionDefinitions).length
|
|
123
|
+
if (collectionCount > 0) {
|
|
124
|
+
logger.info(`Found ${collectionCount} content collection(s)`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const pluginContext = {
|
|
128
|
+
manifestWriter,
|
|
129
|
+
componentDefinitions,
|
|
130
|
+
config: markerConfig,
|
|
131
|
+
idCounter,
|
|
132
|
+
command,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const vitePlugins: any[] = [...(createVitePlugin(pluginContext) as any)]
|
|
136
|
+
|
|
137
|
+
// --- CMS Editor setup (dev only) ---
|
|
138
|
+
if (command === 'dev') {
|
|
139
|
+
const editorSrc = src ?? VIRTUAL_CMS_PATH
|
|
140
|
+
|
|
141
|
+
const configScript = resolvedCmsConfig
|
|
142
|
+
? `window.NuaCmsConfig = ${JSON.stringify(resolvedCmsConfig)};`
|
|
143
|
+
: ''
|
|
144
|
+
|
|
145
|
+
injectScript('page', `
|
|
146
|
+
${configScript}
|
|
147
|
+
if (!document.querySelector('script[data-nuasite-cms]')) {
|
|
148
|
+
const s = document.createElement('script');
|
|
149
|
+
s.type = 'module';
|
|
150
|
+
s.src = ${JSON.stringify(editorSrc)};
|
|
151
|
+
s.dataset.nuasiteCms = '';
|
|
152
|
+
document.head.appendChild(s);
|
|
153
|
+
}
|
|
154
|
+
`)
|
|
155
|
+
|
|
156
|
+
// Resolve the virtual CMS editor path to the actual source file.
|
|
157
|
+
// Vite's dev server transforms the TSX, resolves imports, and serves it.
|
|
158
|
+
if (!src) {
|
|
159
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
160
|
+
|
|
161
|
+
vitePlugins.push({
|
|
162
|
+
name: 'nuasite-cms-editor',
|
|
163
|
+
resolveId(id: string) {
|
|
164
|
+
if (id === VIRTUAL_CMS_PATH) {
|
|
165
|
+
return join(__dirname, 'editor/index.tsx')
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
// Prepend @jsxImportSource pragma for editor .tsx files
|
|
171
|
+
// so Vite's esbuild uses Preact's h function
|
|
172
|
+
vitePlugins.push({
|
|
173
|
+
name: 'nuasite-cms-preact-jsx',
|
|
174
|
+
transform(code: string, id: string) {
|
|
175
|
+
if (id.includes('/src/editor/') && id.endsWith('.tsx') && !code.includes('@jsxImportSource')) {
|
|
176
|
+
return `/** @jsxImportSource preact */\n${code}`
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Add Tailwind CSS Vite plugin for editor styles
|
|
182
|
+
vitePlugins.push(tailwindcss())
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Proxy API requests to the backend
|
|
187
|
+
const proxyConfig: Record<string, any> = {}
|
|
188
|
+
if (proxy) {
|
|
189
|
+
proxyConfig['/_nua'] = {
|
|
190
|
+
target: proxy,
|
|
191
|
+
changeOrigin: true,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
updateConfig({
|
|
196
|
+
vite: {
|
|
197
|
+
plugins: vitePlugins,
|
|
198
|
+
resolve: !src ? {
|
|
199
|
+
alias: {
|
|
200
|
+
'react': 'preact/compat',
|
|
201
|
+
'react-dom': 'preact/compat',
|
|
202
|
+
'react/jsx-runtime': 'preact/jsx-runtime',
|
|
203
|
+
},
|
|
204
|
+
} : undefined,
|
|
205
|
+
server: {
|
|
206
|
+
proxy: proxyConfig,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
})
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
'astro:server:setup': ({ server, logger }) => {
|
|
213
|
+
createDevMiddleware(
|
|
214
|
+
server,
|
|
215
|
+
markerConfig,
|
|
216
|
+
manifestWriter,
|
|
217
|
+
componentDefinitions,
|
|
218
|
+
idCounter,
|
|
219
|
+
{ enableCmsApi, mediaAdapter },
|
|
220
|
+
)
|
|
221
|
+
logger.info('CMS dev middleware initialized')
|
|
222
|
+
if (enableCmsApi) {
|
|
223
|
+
logger.info('CMS API enabled at /_nua/cms/')
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
'astro:build:done': async ({ dir, logger }) => {
|
|
228
|
+
if (generateManifest) {
|
|
229
|
+
await processBuildOutput(dir, markerConfig, manifestWriter, idCounter, logger)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const errorCollector = getErrorCollector()
|
|
233
|
+
if (errorCollector.hasWarnings()) {
|
|
234
|
+
const warnings = errorCollector.getWarnings()
|
|
235
|
+
logger.warn(`${warnings.length} warning(s) during processing:`)
|
|
236
|
+
for (const { context, message } of warnings) {
|
|
237
|
+
logger.warn(` - ${context}: ${message}`)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export { createContemberStorageAdapter as contemberMedia } from './media/contember'
|
|
246
|
+
export { createLocalStorageAdapter as localMedia } from './media/local'
|
|
247
|
+
export { createS3StorageAdapter as s3Media } from './media/s3'
|
|
248
|
+
export type { MediaItem, MediaStorageAdapter } from './media/types'
|
|
249
|
+
|
|
250
|
+
export { scanCollections } from './collection-scanner'
|
|
251
|
+
export { getProjectRoot, resetProjectRoot, setProjectRoot } from './config'
|
|
252
|
+
export type { CollectionInfo, MarkdownContent, SourceLocation, VariableReference } from './source-finder'
|
|
253
|
+
export { findCollectionSource, parseMarkdownContent } from './source-finder'
|
|
254
|
+
export type {
|
|
255
|
+
Attribute,
|
|
256
|
+
AvailableColors,
|
|
257
|
+
AvailableTextStyles,
|
|
258
|
+
CanonicalUrl,
|
|
259
|
+
CmsManifest,
|
|
260
|
+
CmsMarkerOptions,
|
|
261
|
+
CollectionDefinition,
|
|
262
|
+
CollectionEntry,
|
|
263
|
+
ComponentDefinition,
|
|
264
|
+
ComponentInstance,
|
|
265
|
+
ComponentProp,
|
|
266
|
+
ContentConstraints,
|
|
267
|
+
FieldDefinition,
|
|
268
|
+
FieldType,
|
|
269
|
+
ImageMetadata,
|
|
270
|
+
JsonLdEntry,
|
|
271
|
+
ManifestEntry,
|
|
272
|
+
ManifestMetadata,
|
|
273
|
+
OpenGraphData,
|
|
274
|
+
PageEntry,
|
|
275
|
+
PageSeoData,
|
|
276
|
+
SeoKeywords,
|
|
277
|
+
SeoMetaTag,
|
|
278
|
+
SeoOptions,
|
|
279
|
+
SeoSourceInfo,
|
|
280
|
+
SeoTitle,
|
|
281
|
+
TailwindColor,
|
|
282
|
+
TextStyleValue,
|
|
283
|
+
TwitterCardData,
|
|
284
|
+
} from './types'
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { getProjectRoot } from './config'
|
|
4
|
+
import { parseTailwindConfig, parseTextStyles } from './tailwind-colors'
|
|
5
|
+
import type {
|
|
6
|
+
AvailableColors,
|
|
7
|
+
AvailableTextStyles,
|
|
8
|
+
CmsManifest,
|
|
9
|
+
CollectionDefinition,
|
|
10
|
+
CollectionEntry,
|
|
11
|
+
ComponentDefinition,
|
|
12
|
+
ComponentInstance,
|
|
13
|
+
ManifestEntry,
|
|
14
|
+
ManifestMetadata,
|
|
15
|
+
PageEntry,
|
|
16
|
+
PageSeoData,
|
|
17
|
+
} from './types'
|
|
18
|
+
import { generateManifestContentHash, generateSourceFileHashes } from './utils'
|
|
19
|
+
|
|
20
|
+
/** Current manifest schema version */
|
|
21
|
+
const MANIFEST_VERSION = '1.0'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Manages streaming manifest writes during build.
|
|
25
|
+
* Accumulates entries and writes per-page manifests as pages are processed.
|
|
26
|
+
*/
|
|
27
|
+
export class ManifestWriter {
|
|
28
|
+
private globalManifest: CmsManifest
|
|
29
|
+
private pageManifests: Map<string, {
|
|
30
|
+
entries: Record<string, ManifestEntry>
|
|
31
|
+
components: Record<string, ComponentInstance>
|
|
32
|
+
collection?: CollectionEntry
|
|
33
|
+
seo?: PageSeoData
|
|
34
|
+
}> = new Map()
|
|
35
|
+
private outDir: string = ''
|
|
36
|
+
private manifestFile: string
|
|
37
|
+
private componentDefinitions: Record<string, ComponentDefinition>
|
|
38
|
+
private collectionDefinitions: Record<string, CollectionDefinition> = {}
|
|
39
|
+
private availableColors: AvailableColors | undefined
|
|
40
|
+
private availableTextStyles: AvailableTextStyles | undefined
|
|
41
|
+
private writeQueue: Promise<void> = Promise.resolve()
|
|
42
|
+
|
|
43
|
+
constructor(manifestFile: string, componentDefinitions: Record<string, ComponentDefinition> = {}) {
|
|
44
|
+
this.manifestFile = manifestFile
|
|
45
|
+
this.componentDefinitions = componentDefinitions
|
|
46
|
+
this.globalManifest = {
|
|
47
|
+
entries: {},
|
|
48
|
+
components: {},
|
|
49
|
+
componentDefinitions,
|
|
50
|
+
collections: {},
|
|
51
|
+
collectionDefinitions: {},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Set the output directory for manifest files
|
|
57
|
+
*/
|
|
58
|
+
setOutDir(dir: string): void {
|
|
59
|
+
this.outDir = dir
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Update component definitions (called after initial scan)
|
|
64
|
+
*/
|
|
65
|
+
setComponentDefinitions(definitions: Record<string, ComponentDefinition>): void {
|
|
66
|
+
this.componentDefinitions = definitions
|
|
67
|
+
this.globalManifest.componentDefinitions = definitions
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Load available Tailwind colors and text styles from the project's CSS config
|
|
72
|
+
*/
|
|
73
|
+
async loadAvailableColors(projectRoot: string = getProjectRoot()): Promise<void> {
|
|
74
|
+
this.availableColors = await parseTailwindConfig(projectRoot)
|
|
75
|
+
this.availableTextStyles = await parseTextStyles(projectRoot)
|
|
76
|
+
this.globalManifest.availableColors = this.availableColors
|
|
77
|
+
this.globalManifest.availableTextStyles = this.availableTextStyles
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Set available colors directly (for testing or custom colors)
|
|
82
|
+
*/
|
|
83
|
+
setAvailableColors(colors: AvailableColors): void {
|
|
84
|
+
this.availableColors = colors
|
|
85
|
+
this.globalManifest.availableColors = colors
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Set available text styles directly (for testing or custom styles)
|
|
90
|
+
*/
|
|
91
|
+
setAvailableTextStyles(textStyles: AvailableTextStyles): void {
|
|
92
|
+
this.availableTextStyles = textStyles
|
|
93
|
+
this.globalManifest.availableTextStyles = textStyles
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Set collection definitions (inferred schemas for content collections)
|
|
98
|
+
*/
|
|
99
|
+
setCollectionDefinitions(definitions: Record<string, CollectionDefinition>): void {
|
|
100
|
+
this.collectionDefinitions = definitions
|
|
101
|
+
this.globalManifest.collectionDefinitions = definitions
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get collection definitions
|
|
106
|
+
*/
|
|
107
|
+
getCollectionDefinitions(): Record<string, CollectionDefinition> {
|
|
108
|
+
return this.collectionDefinitions
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the manifest path for a given page
|
|
113
|
+
* Places manifest next to the page: /about -> /about.json, / -> /index.json
|
|
114
|
+
*/
|
|
115
|
+
private getPageManifestPath(pagePath: string): string {
|
|
116
|
+
if (pagePath === '/' || pagePath === '') {
|
|
117
|
+
return path.join(this.outDir, 'index.json')
|
|
118
|
+
}
|
|
119
|
+
const cleanPath = pagePath.replace(/^\//, '')
|
|
120
|
+
return path.join(this.outDir, `${cleanPath}.json`)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Add a page's entries to the manifest (called after each page is processed)
|
|
125
|
+
* This is non-blocking - writes are queued
|
|
126
|
+
*/
|
|
127
|
+
addPage(
|
|
128
|
+
pagePath: string,
|
|
129
|
+
entries: Record<string, ManifestEntry>,
|
|
130
|
+
components: Record<string, ComponentInstance>,
|
|
131
|
+
collection?: CollectionEntry,
|
|
132
|
+
seo?: PageSeoData,
|
|
133
|
+
): void {
|
|
134
|
+
// Store in memory
|
|
135
|
+
this.pageManifests.set(pagePath, { entries, components, collection, seo })
|
|
136
|
+
|
|
137
|
+
// Update global manifest
|
|
138
|
+
Object.assign(this.globalManifest.entries, entries)
|
|
139
|
+
Object.assign(this.globalManifest.components, components)
|
|
140
|
+
|
|
141
|
+
// Add collection entry to global manifest
|
|
142
|
+
if (collection) {
|
|
143
|
+
const collectionKey = `${collection.collectionName}/${collection.collectionSlug}`
|
|
144
|
+
this.globalManifest.collections = this.globalManifest.collections || {}
|
|
145
|
+
this.globalManifest.collections[collectionKey] = collection
|
|
146
|
+
|
|
147
|
+
// Update pathname on collection definition entry (needed for dev mode
|
|
148
|
+
// where finalize() doesn't run to populate pathnames)
|
|
149
|
+
const def = this.collectionDefinitions[collection.collectionName]
|
|
150
|
+
if (def?.entries) {
|
|
151
|
+
const entry = def.entries.find(e => e.slug === collection.collectionSlug)
|
|
152
|
+
if (entry) {
|
|
153
|
+
entry.pathname = pagePath
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Queue the write operation (non-blocking, isolated errors)
|
|
159
|
+
if (this.outDir) {
|
|
160
|
+
this.writeQueue = this.writeQueue.then(() =>
|
|
161
|
+
this.writePageManifest(pagePath, entries, components, collection, seo)
|
|
162
|
+
.catch((err) => {
|
|
163
|
+
console.error(`[astro-cms] Failed to write manifest for ${pagePath}:`, err)
|
|
164
|
+
}),
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Write a single page manifest to disk
|
|
171
|
+
*/
|
|
172
|
+
private async writePageManifest(
|
|
173
|
+
pagePath: string,
|
|
174
|
+
entries: Record<string, ManifestEntry>,
|
|
175
|
+
components: Record<string, ComponentInstance>,
|
|
176
|
+
collection?: CollectionEntry,
|
|
177
|
+
seo?: PageSeoData,
|
|
178
|
+
): Promise<void> {
|
|
179
|
+
const manifestPath = this.getPageManifestPath(pagePath)
|
|
180
|
+
const manifestDir = path.dirname(manifestPath)
|
|
181
|
+
|
|
182
|
+
await fs.mkdir(manifestDir, { recursive: true })
|
|
183
|
+
|
|
184
|
+
// Generate metadata for this page manifest
|
|
185
|
+
const metadata: ManifestMetadata = {
|
|
186
|
+
version: MANIFEST_VERSION,
|
|
187
|
+
generatedAt: new Date().toISOString(),
|
|
188
|
+
generatedBy: 'cms',
|
|
189
|
+
contentHash: generateManifestContentHash(entries),
|
|
190
|
+
sourceFileHashes: generateSourceFileHashes(entries),
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const pageManifest: {
|
|
194
|
+
metadata: ManifestMetadata
|
|
195
|
+
page: string
|
|
196
|
+
entries: Record<string, ManifestEntry>
|
|
197
|
+
components: Record<string, ComponentInstance>
|
|
198
|
+
componentDefinitions: Record<string, ComponentDefinition>
|
|
199
|
+
collection?: CollectionEntry
|
|
200
|
+
seo?: PageSeoData
|
|
201
|
+
} = {
|
|
202
|
+
metadata,
|
|
203
|
+
page: pagePath,
|
|
204
|
+
entries,
|
|
205
|
+
components,
|
|
206
|
+
componentDefinitions: this.componentDefinitions,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (collection) {
|
|
210
|
+
pageManifest.collection = collection
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (seo) {
|
|
214
|
+
pageManifest.seo = seo
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
await fs.writeFile(manifestPath, JSON.stringify(pageManifest, null, 2), 'utf-8')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Finalize manifest writes
|
|
222
|
+
* Call this in astro:build:done to ensure all writes complete
|
|
223
|
+
*/
|
|
224
|
+
async finalize(): Promise<{ totalEntries: number; totalPages: number; totalComponents: number }> {
|
|
225
|
+
// Wait for all queued writes to complete
|
|
226
|
+
await this.writeQueue
|
|
227
|
+
|
|
228
|
+
// Build pages array with pathname and title, sorted by pathname
|
|
229
|
+
const pages: PageEntry[] = Array.from(this.pageManifests.entries())
|
|
230
|
+
.map(([pathname, data]) => {
|
|
231
|
+
const entry: PageEntry = { pathname }
|
|
232
|
+
if (data.seo?.title?.content) {
|
|
233
|
+
entry.title = data.seo.title.content
|
|
234
|
+
}
|
|
235
|
+
return entry
|
|
236
|
+
})
|
|
237
|
+
.sort((a, b) => a.pathname.localeCompare(b.pathname))
|
|
238
|
+
|
|
239
|
+
// Build a map from "collectionName/slug" → pagePath using page collections
|
|
240
|
+
const collectionPathMap = new Map<string, string>()
|
|
241
|
+
for (const [pagePath, data] of this.pageManifests) {
|
|
242
|
+
if (data.collection) {
|
|
243
|
+
const key = `${data.collection.collectionName}/${data.collection.collectionSlug}`
|
|
244
|
+
collectionPathMap.set(key, pagePath)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Populate pathname on collection definition entries
|
|
249
|
+
for (const def of Object.values(this.collectionDefinitions)) {
|
|
250
|
+
if (def.entries) {
|
|
251
|
+
for (const entry of def.entries) {
|
|
252
|
+
const pathname = collectionPathMap.get(`${def.name}/${entry.slug}`)
|
|
253
|
+
if (pathname) {
|
|
254
|
+
entry.pathname = pathname
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Write global manifest with settings (component definitions, colors, text styles, collection definitions, and pages)
|
|
261
|
+
if (this.outDir) {
|
|
262
|
+
const globalManifestPath = path.join(this.outDir, this.manifestFile)
|
|
263
|
+
const globalSettings: {
|
|
264
|
+
componentDefinitions: Record<string, ComponentDefinition>
|
|
265
|
+
collectionDefinitions?: Record<string, CollectionDefinition>
|
|
266
|
+
availableColors?: AvailableColors
|
|
267
|
+
availableTextStyles?: AvailableTextStyles
|
|
268
|
+
pages: PageEntry[]
|
|
269
|
+
} = {
|
|
270
|
+
componentDefinitions: this.componentDefinitions,
|
|
271
|
+
pages,
|
|
272
|
+
}
|
|
273
|
+
if (Object.keys(this.collectionDefinitions).length > 0) {
|
|
274
|
+
globalSettings.collectionDefinitions = this.collectionDefinitions
|
|
275
|
+
}
|
|
276
|
+
if (this.availableColors) {
|
|
277
|
+
globalSettings.availableColors = this.availableColors
|
|
278
|
+
}
|
|
279
|
+
if (this.availableTextStyles) {
|
|
280
|
+
globalSettings.availableTextStyles = this.availableTextStyles
|
|
281
|
+
}
|
|
282
|
+
await fs.writeFile(
|
|
283
|
+
globalManifestPath,
|
|
284
|
+
JSON.stringify(globalSettings, null, 2),
|
|
285
|
+
'utf-8',
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
totalEntries: Object.keys(this.globalManifest.entries).length,
|
|
291
|
+
totalPages: this.pageManifests.size,
|
|
292
|
+
totalComponents: Object.keys(this.globalManifest.components).length,
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get the global manifest (for virtual module support)
|
|
298
|
+
*/
|
|
299
|
+
getGlobalManifest(): CmsManifest {
|
|
300
|
+
return this.globalManifest
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Get a page's manifest data (for dev mode)
|
|
305
|
+
*/
|
|
306
|
+
getPageManifest(pagePath: string): {
|
|
307
|
+
entries: Record<string, ManifestEntry>
|
|
308
|
+
components: Record<string, ComponentInstance>
|
|
309
|
+
collection?: CollectionEntry
|
|
310
|
+
seo?: PageSeoData
|
|
311
|
+
} | undefined {
|
|
312
|
+
return this.pageManifests.get(pagePath)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Reset state (for dev mode reloads)
|
|
317
|
+
*/
|
|
318
|
+
reset(): void {
|
|
319
|
+
this.pageManifests.clear()
|
|
320
|
+
this.globalManifest = {
|
|
321
|
+
entries: {},
|
|
322
|
+
components: {},
|
|
323
|
+
componentDefinitions: this.componentDefinitions,
|
|
324
|
+
collections: {},
|
|
325
|
+
collectionDefinitions: this.collectionDefinitions,
|
|
326
|
+
availableColors: this.availableColors,
|
|
327
|
+
availableTextStyles: this.availableTextStyles,
|
|
328
|
+
}
|
|
329
|
+
this.writeQueue = Promise.resolve()
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get page data for preview generation (pages and their components)
|
|
334
|
+
*/
|
|
335
|
+
getPageDataForPreviews(): Map<string, {
|
|
336
|
+
entries: Record<string, ManifestEntry>
|
|
337
|
+
components: Record<string, ComponentInstance>
|
|
338
|
+
collection?: CollectionEntry
|
|
339
|
+
seo?: PageSeoData
|
|
340
|
+
}> {
|
|
341
|
+
return this.pageManifests
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Get component definitions
|
|
346
|
+
*/
|
|
347
|
+
getComponentDefinitions(): Record<string, ComponentDefinition> {
|
|
348
|
+
return this.componentDefinitions
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Get the output directory
|
|
353
|
+
*/
|
|
354
|
+
getOutDir(): string {
|
|
355
|
+
return this.outDir
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Get available colors (for use in dev middleware)
|
|
360
|
+
*/
|
|
361
|
+
getAvailableColors(): AvailableColors | undefined {
|
|
362
|
+
return this.availableColors
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Get available text styles (for use in dev middleware)
|
|
367
|
+
*/
|
|
368
|
+
getAvailableTextStyles(): AvailableTextStyles | undefined {
|
|
369
|
+
return this.availableTextStyles
|
|
370
|
+
}
|
|
371
|
+
}
|