@nuasite/cms-marker 0.0.52 → 0.0.54
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 +0 -4
- package/dist/types/astro-transform.d.ts +21 -0
- package/dist/types/astro-transform.d.ts.map +1 -0
- package/dist/types/build-processor.d.ts +10 -0
- package/dist/types/build-processor.d.ts.map +1 -0
- package/dist/types/component-registry.d.ts +63 -0
- package/dist/types/component-registry.d.ts.map +1 -0
- package/dist/types/dev-middleware.d.ts +7 -0
- package/dist/types/dev-middleware.d.ts.map +1 -0
- package/dist/types/html-processor.d.ts +51 -0
- package/dist/types/html-processor.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/manifest-writer.d.ts +75 -0
- package/dist/types/manifest-writer.d.ts.map +1 -0
- package/dist/types/source-finder.d.ts +97 -0
- package/dist/types/source-finder.d.ts.map +1 -0
- package/dist/types/tailwind-colors.d.ts +66 -0
- package/dist/types/tailwind-colors.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/dist/types/types.d.ts +195 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +38 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/vite-plugin.d.ts +14 -0
- package/dist/types/vite-plugin.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/astro-transform.ts +4 -4
- package/src/build-processor.ts +1 -1
- package/src/component-registry.ts +2 -2
- package/src/dev-middleware.ts +6 -6
- package/src/html-processor.ts +180 -6
- package/src/index.ts +0 -1
- package/src/manifest-writer.ts +47 -1
- package/src/source-finder.ts +142 -9
- package/src/tailwind-colors.ts +338 -0
- package/src/tsconfig.json +1 -1
- package/src/types.ts +123 -1
- package/src/utils.ts +99 -0
package/src/types.ts
CHANGED
|
@@ -27,14 +27,95 @@ export interface ComponentDefinition {
|
|
|
27
27
|
slots?: string[]
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/** Context around an element for resilient matching when exact match fails */
|
|
31
|
+
export interface SourceContext {
|
|
32
|
+
/** Text content of the preceding sibling element */
|
|
33
|
+
precedingText?: string
|
|
34
|
+
/** Text content of the following sibling element */
|
|
35
|
+
followingText?: string
|
|
36
|
+
/** Parent element's tag name */
|
|
37
|
+
parentTag?: string
|
|
38
|
+
/** Position among siblings (0-indexed) */
|
|
39
|
+
siblingIndex?: number
|
|
40
|
+
/** Parent element's class attribute */
|
|
41
|
+
parentClasses?: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Image metadata for better tracking and integrity */
|
|
45
|
+
export interface ImageMetadata {
|
|
46
|
+
/** Image source URL */
|
|
47
|
+
src: string
|
|
48
|
+
/** Alt text */
|
|
49
|
+
alt: string
|
|
50
|
+
/** SHA256 hash of image content (for integrity checking) */
|
|
51
|
+
hash?: string
|
|
52
|
+
/** Image dimensions */
|
|
53
|
+
dimensions?: { width: number; height: number }
|
|
54
|
+
/** Responsive image srcset */
|
|
55
|
+
srcSet?: string
|
|
56
|
+
/** Image sizes attribute */
|
|
57
|
+
sizes?: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Content constraints for validation */
|
|
61
|
+
export interface ContentConstraints {
|
|
62
|
+
/** Maximum content length */
|
|
63
|
+
maxLength?: number
|
|
64
|
+
/** Minimum content length */
|
|
65
|
+
minLength?: number
|
|
66
|
+
/** Regex pattern for validation */
|
|
67
|
+
pattern?: string
|
|
68
|
+
/** Allowed HTML tags for rich text content */
|
|
69
|
+
allowedTags?: string[]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Represents a single Tailwind color with its shades */
|
|
73
|
+
export interface TailwindColor {
|
|
74
|
+
/** Color name (e.g., 'red', 'blue', 'primary') */
|
|
75
|
+
name: string
|
|
76
|
+
/** Available shades (e.g., ['50', '100', '200', ..., '900', '950']) */
|
|
77
|
+
shades: string[]
|
|
78
|
+
/** Whether this is a custom/theme color vs default Tailwind */
|
|
79
|
+
isCustom?: boolean
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Color classes currently applied to an element */
|
|
83
|
+
export interface ColorClasses {
|
|
84
|
+
/** Background color class (e.g., 'bg-blue-500') */
|
|
85
|
+
bg?: string
|
|
86
|
+
/** Text color class (e.g., 'text-white') */
|
|
87
|
+
text?: string
|
|
88
|
+
/** Border color class (e.g., 'border-blue-600') */
|
|
89
|
+
border?: string
|
|
90
|
+
/** Hover background color class (e.g., 'hover:bg-blue-600') */
|
|
91
|
+
hoverBg?: string
|
|
92
|
+
/** Hover text color class (e.g., 'hover:text-gray-100') */
|
|
93
|
+
hoverText?: string
|
|
94
|
+
/** All color-related classes as found in the element */
|
|
95
|
+
allColorClasses?: string[]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Available colors palette from Tailwind config */
|
|
99
|
+
export interface AvailableColors {
|
|
100
|
+
/** All available colors with their shades */
|
|
101
|
+
colors: TailwindColor[]
|
|
102
|
+
/** Default Tailwind color names */
|
|
103
|
+
defaultColors: string[]
|
|
104
|
+
/** Custom/theme color names */
|
|
105
|
+
customColors: string[]
|
|
106
|
+
}
|
|
107
|
+
|
|
30
108
|
export interface ManifestEntry {
|
|
31
109
|
id: string
|
|
32
110
|
tag: string
|
|
111
|
+
/** Plain text content (for display/search) */
|
|
33
112
|
text: string
|
|
113
|
+
/** HTML content when element contains inline styling (strong, em, etc.) */
|
|
114
|
+
html?: string
|
|
34
115
|
sourcePath?: string
|
|
35
116
|
sourceLine?: number
|
|
36
117
|
sourceSnippet?: string
|
|
37
|
-
sourceType?: 'static' | 'variable' | 'prop' | 'computed' | 'collection'
|
|
118
|
+
sourceType?: 'static' | 'variable' | 'prop' | 'computed' | 'collection' | 'image'
|
|
38
119
|
variableName?: string
|
|
39
120
|
childCmsIds?: string[]
|
|
40
121
|
parentComponentId?: string
|
|
@@ -42,6 +123,27 @@ export interface ManifestEntry {
|
|
|
42
123
|
collectionName?: string
|
|
43
124
|
/** Entry slug for collection entries (e.g., '3d-tisk') */
|
|
44
125
|
collectionSlug?: string
|
|
126
|
+
/** Path to the markdown content file (e.g., 'src/content/blog/my-post.md') */
|
|
127
|
+
contentPath?: string
|
|
128
|
+
/** Image source URL (for image entries) - deprecated, use imageMetadata */
|
|
129
|
+
imageSrc?: string
|
|
130
|
+
/** Image alt text (for image entries) - deprecated, use imageMetadata */
|
|
131
|
+
imageAlt?: string
|
|
132
|
+
|
|
133
|
+
// === Robustness fields ===
|
|
134
|
+
|
|
135
|
+
/** Stable ID derived from content + context hash, survives rebuilds */
|
|
136
|
+
stableId?: string
|
|
137
|
+
/** SHA256 hash of sourceSnippet at generation time for conflict detection */
|
|
138
|
+
sourceHash?: string
|
|
139
|
+
/** Context around the element for resilient matching */
|
|
140
|
+
sourceContext?: SourceContext
|
|
141
|
+
/** Image metadata for img elements (replaces imageSrc/imageAlt) */
|
|
142
|
+
imageMetadata?: ImageMetadata
|
|
143
|
+
/** Content validation constraints */
|
|
144
|
+
constraints?: ContentConstraints
|
|
145
|
+
/** Color classes applied to this element (for buttons, etc.) */
|
|
146
|
+
colorClasses?: ColorClasses
|
|
45
147
|
}
|
|
46
148
|
|
|
47
149
|
export interface ComponentInstance {
|
|
@@ -73,10 +175,30 @@ export interface CollectionEntry {
|
|
|
73
175
|
wrapperId?: string
|
|
74
176
|
}
|
|
75
177
|
|
|
178
|
+
/** Manifest metadata for versioning and conflict detection */
|
|
179
|
+
export interface ManifestMetadata {
|
|
180
|
+
/** Manifest schema version */
|
|
181
|
+
version: string
|
|
182
|
+
/** ISO timestamp when manifest was generated */
|
|
183
|
+
generatedAt: string
|
|
184
|
+
/** Build system that generated the manifest (e.g., 'astro', 'vite') */
|
|
185
|
+
generatedBy?: string
|
|
186
|
+
/** Build ID for correlation */
|
|
187
|
+
buildId?: string
|
|
188
|
+
/** SHA256 hash of all entry content for quick drift detection */
|
|
189
|
+
contentHash?: string
|
|
190
|
+
/** Per-source-file hashes for granular conflict detection */
|
|
191
|
+
sourceFileHashes?: Record<string, string>
|
|
192
|
+
}
|
|
193
|
+
|
|
76
194
|
export interface CmsManifest {
|
|
195
|
+
/** Manifest metadata for versioning and conflict detection */
|
|
196
|
+
metadata?: ManifestMetadata
|
|
77
197
|
entries: Record<string, ManifestEntry>
|
|
78
198
|
components: Record<string, ComponentInstance>
|
|
79
199
|
componentDefinitions: Record<string, ComponentDefinition>
|
|
80
200
|
/** Content collection entries indexed by "collectionName/slug" */
|
|
81
201
|
collections?: Record<string, CollectionEntry>
|
|
202
|
+
/** Available Tailwind colors from the project's config */
|
|
203
|
+
availableColors?: AvailableColors
|
|
82
204
|
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import type { ManifestEntry, SourceContext } from './types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate a SHA256 hash of the given content
|
|
6
|
+
*/
|
|
7
|
+
export function sha256(content: string): string {
|
|
8
|
+
return createHash('sha256').update(content, 'utf8').digest('hex')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generate a short hash (first 12 characters of SHA256)
|
|
13
|
+
* Used for stableId to keep it reasonably short but still unique
|
|
14
|
+
*/
|
|
15
|
+
export function shortHash(content: string): string {
|
|
16
|
+
return sha256(content).substring(0, 12)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate a stable ID for an element based on its content and context.
|
|
21
|
+
* This ID survives rebuilds as long as the content and structure remain similar.
|
|
22
|
+
*
|
|
23
|
+
* Components:
|
|
24
|
+
* - tag name
|
|
25
|
+
* - first 50 chars of text content
|
|
26
|
+
* - source path (if available)
|
|
27
|
+
* - parent tag
|
|
28
|
+
* - sibling index
|
|
29
|
+
*/
|
|
30
|
+
export function generateStableId(
|
|
31
|
+
tag: string,
|
|
32
|
+
text: string,
|
|
33
|
+
sourcePath?: string,
|
|
34
|
+
context?: SourceContext,
|
|
35
|
+
): string {
|
|
36
|
+
const components = [
|
|
37
|
+
tag,
|
|
38
|
+
text.substring(0, 50).trim(),
|
|
39
|
+
sourcePath || '',
|
|
40
|
+
context?.parentTag || '',
|
|
41
|
+
context?.siblingIndex?.toString() || '',
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
return shortHash(components.join('|'))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generate a hash of the source snippet for conflict detection.
|
|
49
|
+
* If the source file changes, this hash will differ from what's stored in manifest.
|
|
50
|
+
*/
|
|
51
|
+
export function generateSourceHash(sourceSnippet: string): string {
|
|
52
|
+
return sha256(sourceSnippet)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generate a content hash for the entire manifest (all entries).
|
|
57
|
+
* Used for quick drift detection without comparing individual entries.
|
|
58
|
+
*/
|
|
59
|
+
export function generateManifestContentHash(entries: Record<string, ManifestEntry>): string {
|
|
60
|
+
// Sort keys for deterministic hashing
|
|
61
|
+
const sortedKeys = Object.keys(entries).sort()
|
|
62
|
+
const content = sortedKeys.map(key => {
|
|
63
|
+
const entry = entries[key]!
|
|
64
|
+
// Hash only content-relevant fields, not generated IDs
|
|
65
|
+
return `${entry.tag}|${entry.text}|${entry.html || ''}|${entry.sourcePath || ''}`
|
|
66
|
+
}).join('\n')
|
|
67
|
+
|
|
68
|
+
return sha256(content)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate per-source-file hashes for granular conflict detection.
|
|
73
|
+
* Maps source file path -> hash of all entries from that file.
|
|
74
|
+
*/
|
|
75
|
+
export function generateSourceFileHashes(entries: Record<string, ManifestEntry>): Record<string, string> {
|
|
76
|
+
// Group entries by source file
|
|
77
|
+
const entriesByFile: Record<string, ManifestEntry[]> = {}
|
|
78
|
+
|
|
79
|
+
for (const entry of Object.values(entries)) {
|
|
80
|
+
const sourcePath = entry.sourcePath
|
|
81
|
+
if (sourcePath) {
|
|
82
|
+
if (!entriesByFile[sourcePath]) {
|
|
83
|
+
entriesByFile[sourcePath] = []
|
|
84
|
+
}
|
|
85
|
+
entriesByFile[sourcePath].push(entry)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Generate hash for each file
|
|
90
|
+
const hashes: Record<string, string> = {}
|
|
91
|
+
for (const [filePath, fileEntries] of Object.entries(entriesByFile)) {
|
|
92
|
+
// Sort entries by line number for determinism
|
|
93
|
+
const sorted = fileEntries.sort((a, b) => (a.sourceLine || 0) - (b.sourceLine || 0))
|
|
94
|
+
const content = sorted.map(e => `${e.sourceLine || 0}|${e.text}|${e.sourceSnippet || ''}`).join('\n')
|
|
95
|
+
hashes[filePath] = sha256(content)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return hashes
|
|
99
|
+
}
|