@micropress/theme-sdk 0.0.1
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 +48 -0
- package/dist/cli/index.js +714 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.mts +618 -0
- package/dist/index.d.ts +618 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +125 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of html`` tagged template.
|
|
3
|
+
*/
|
|
4
|
+
interface HtmlResult {
|
|
5
|
+
html: string;
|
|
6
|
+
toString(): string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Escape HTML entities for safe insertion.
|
|
10
|
+
*/
|
|
11
|
+
declare function escapeHtml(unsafe: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Tagged template for HTML.
|
|
14
|
+
* Automatically escapes interpolated values unless they're HtmlResult.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const name = '<script>alert("xss")</script>';
|
|
19
|
+
* html`<div>${name}</div>` // Safe: <div><script>...</div>
|
|
20
|
+
*
|
|
21
|
+
* const inner = html`<span>safe</span>`;
|
|
22
|
+
* html`<div>${inner}</div>` // Nested HTML preserved
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function html(strings: TemplateStringsArray, ...values: unknown[]): HtmlResult;
|
|
26
|
+
/**
|
|
27
|
+
* Mark raw HTML as safe (use carefully!).
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const trusted = raw('<b>trusted content</b>');
|
|
32
|
+
* html`<div>${trusted}</div>`
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare function raw(htmlString: string): HtmlResult;
|
|
36
|
+
/**
|
|
37
|
+
* Join multiple HTML results.
|
|
38
|
+
*/
|
|
39
|
+
declare function join(items: HtmlResult[], separator?: string): HtmlResult;
|
|
40
|
+
/**
|
|
41
|
+
* Conditional HTML - returns empty if condition is false.
|
|
42
|
+
*/
|
|
43
|
+
declare function when(condition: boolean, content: HtmlResult | string): HtmlResult;
|
|
44
|
+
/**
|
|
45
|
+
* CSS tagged template - just returns the string.
|
|
46
|
+
* Useful for syntax highlighting in editors.
|
|
47
|
+
*/
|
|
48
|
+
declare function css(strings: TemplateStringsArray, ...values: unknown[]): string;
|
|
49
|
+
|
|
50
|
+
/** Mark types for inline text formatting */
|
|
51
|
+
type MarkType = 'bold' | 'italic' | 'code' | 'strike' | 'link';
|
|
52
|
+
/** A formatting mark applied to text */
|
|
53
|
+
interface TextMark {
|
|
54
|
+
type: MarkType;
|
|
55
|
+
attrs?: {
|
|
56
|
+
href?: string;
|
|
57
|
+
target?: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Inline text content with optional formatting */
|
|
61
|
+
interface TextBlock {
|
|
62
|
+
type: 'text';
|
|
63
|
+
content: string;
|
|
64
|
+
marks?: TextMark[];
|
|
65
|
+
}
|
|
66
|
+
/** A paragraph containing text */
|
|
67
|
+
interface ParagraphBlock {
|
|
68
|
+
type: 'paragraph';
|
|
69
|
+
children: TextBlock[];
|
|
70
|
+
}
|
|
71
|
+
/** A heading (h1-h6) */
|
|
72
|
+
interface HeadingBlock {
|
|
73
|
+
type: 'heading';
|
|
74
|
+
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
75
|
+
children: TextBlock[];
|
|
76
|
+
}
|
|
77
|
+
/** A blockquote containing nested blocks */
|
|
78
|
+
interface BlockquoteBlock {
|
|
79
|
+
type: 'blockquote';
|
|
80
|
+
children: ContentBlock[];
|
|
81
|
+
}
|
|
82
|
+
/** A code block with optional language */
|
|
83
|
+
interface CodeBlock {
|
|
84
|
+
type: 'codeBlock';
|
|
85
|
+
code: string;
|
|
86
|
+
language?: string;
|
|
87
|
+
}
|
|
88
|
+
/** A horizontal rule divider */
|
|
89
|
+
interface HorizontalRuleBlock {
|
|
90
|
+
type: 'horizontalRule';
|
|
91
|
+
}
|
|
92
|
+
/** A hard line break */
|
|
93
|
+
interface HardBreakBlock {
|
|
94
|
+
type: 'hardBreak';
|
|
95
|
+
}
|
|
96
|
+
/** An unordered list */
|
|
97
|
+
interface BulletListBlock {
|
|
98
|
+
type: 'bulletList';
|
|
99
|
+
items: ListItemBlock[];
|
|
100
|
+
}
|
|
101
|
+
/** An ordered list */
|
|
102
|
+
interface OrderedListBlock {
|
|
103
|
+
type: 'orderedList';
|
|
104
|
+
items: ListItemBlock[];
|
|
105
|
+
start?: number;
|
|
106
|
+
}
|
|
107
|
+
/** A list item containing blocks */
|
|
108
|
+
interface ListItemBlock {
|
|
109
|
+
type: 'listItem';
|
|
110
|
+
children: ContentBlock[];
|
|
111
|
+
}
|
|
112
|
+
/** An image */
|
|
113
|
+
interface ImageBlock {
|
|
114
|
+
type: 'image';
|
|
115
|
+
src: string;
|
|
116
|
+
alt: string;
|
|
117
|
+
title?: string;
|
|
118
|
+
width?: number;
|
|
119
|
+
height?: number;
|
|
120
|
+
}
|
|
121
|
+
/** A video embed */
|
|
122
|
+
interface VideoBlock {
|
|
123
|
+
type: 'video';
|
|
124
|
+
src: string;
|
|
125
|
+
poster?: string;
|
|
126
|
+
controls?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** An external embed (YouTube, Vimeo, etc.) */
|
|
129
|
+
interface EmbedBlock {
|
|
130
|
+
type: 'embed';
|
|
131
|
+
url: string;
|
|
132
|
+
embedType: 'youtube' | 'vimeo' | 'twitter' | 'generic';
|
|
133
|
+
}
|
|
134
|
+
/** A container for layout purposes */
|
|
135
|
+
interface ContainerBlock {
|
|
136
|
+
type: 'container';
|
|
137
|
+
children: ContentBlock[];
|
|
138
|
+
layout?: 'stack' | 'row' | 'grid';
|
|
139
|
+
gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
140
|
+
}
|
|
141
|
+
/** A card container */
|
|
142
|
+
interface CardBlock {
|
|
143
|
+
type: 'card';
|
|
144
|
+
children: ContentBlock[];
|
|
145
|
+
variant?: 'default' | 'outlined' | 'elevated';
|
|
146
|
+
}
|
|
147
|
+
/** A page section */
|
|
148
|
+
interface SectionBlock {
|
|
149
|
+
type: 'section';
|
|
150
|
+
children: ContentBlock[];
|
|
151
|
+
id?: string;
|
|
152
|
+
}
|
|
153
|
+
/** An accordion/expandable section */
|
|
154
|
+
interface AccordionBlock {
|
|
155
|
+
type: 'accordion';
|
|
156
|
+
title: string;
|
|
157
|
+
children: ContentBlock[];
|
|
158
|
+
defaultOpen?: boolean;
|
|
159
|
+
}
|
|
160
|
+
/** A tab item for tabbed content */
|
|
161
|
+
interface TabItem {
|
|
162
|
+
label: string;
|
|
163
|
+
content: ContentBlock[];
|
|
164
|
+
}
|
|
165
|
+
/** Tabbed content container */
|
|
166
|
+
interface TabsBlock {
|
|
167
|
+
type: 'tabs';
|
|
168
|
+
items: TabItem[];
|
|
169
|
+
}
|
|
170
|
+
/** A modal dialog */
|
|
171
|
+
interface ModalBlock {
|
|
172
|
+
type: 'modal';
|
|
173
|
+
trigger: string;
|
|
174
|
+
title?: string;
|
|
175
|
+
content: ContentBlock[];
|
|
176
|
+
}
|
|
177
|
+
/** A button */
|
|
178
|
+
interface ButtonBlock {
|
|
179
|
+
type: 'button';
|
|
180
|
+
label: string;
|
|
181
|
+
href?: string;
|
|
182
|
+
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
|
|
183
|
+
action?: string;
|
|
184
|
+
}
|
|
185
|
+
/** A hyperlink */
|
|
186
|
+
interface LinkBlock {
|
|
187
|
+
type: 'link';
|
|
188
|
+
href: string;
|
|
189
|
+
children: TextBlock[];
|
|
190
|
+
target?: '_blank' | '_self';
|
|
191
|
+
}
|
|
192
|
+
/** A data table */
|
|
193
|
+
interface TableBlock {
|
|
194
|
+
type: 'table';
|
|
195
|
+
headers: string[];
|
|
196
|
+
rows: string[][];
|
|
197
|
+
caption?: string;
|
|
198
|
+
}
|
|
199
|
+
/** A status badge */
|
|
200
|
+
interface BadgeBlock {
|
|
201
|
+
type: 'badge';
|
|
202
|
+
text: string;
|
|
203
|
+
variant?: 'default' | 'primary' | 'success' | 'warning' | 'error';
|
|
204
|
+
}
|
|
205
|
+
/** An alert box */
|
|
206
|
+
interface AlertBlock {
|
|
207
|
+
type: 'alert';
|
|
208
|
+
message: string;
|
|
209
|
+
alertType: 'info' | 'warning' | 'error' | 'success';
|
|
210
|
+
}
|
|
211
|
+
/** An icon */
|
|
212
|
+
interface IconBlock {
|
|
213
|
+
type: 'icon';
|
|
214
|
+
name: string;
|
|
215
|
+
size?: 'sm' | 'md' | 'lg';
|
|
216
|
+
}
|
|
217
|
+
/** A form input */
|
|
218
|
+
interface InputBlock {
|
|
219
|
+
type: 'input';
|
|
220
|
+
inputType: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
|
|
221
|
+
label: string;
|
|
222
|
+
name: string;
|
|
223
|
+
placeholder?: string;
|
|
224
|
+
required?: boolean;
|
|
225
|
+
}
|
|
226
|
+
/** A textarea */
|
|
227
|
+
interface TextareaBlock {
|
|
228
|
+
type: 'textarea';
|
|
229
|
+
label: string;
|
|
230
|
+
name: string;
|
|
231
|
+
rows?: number;
|
|
232
|
+
placeholder?: string;
|
|
233
|
+
required?: boolean;
|
|
234
|
+
}
|
|
235
|
+
/** A select dropdown */
|
|
236
|
+
interface SelectBlock {
|
|
237
|
+
type: 'select';
|
|
238
|
+
label: string;
|
|
239
|
+
name: string;
|
|
240
|
+
options: {
|
|
241
|
+
value: string;
|
|
242
|
+
label: string;
|
|
243
|
+
}[];
|
|
244
|
+
required?: boolean;
|
|
245
|
+
}
|
|
246
|
+
/** A checkbox */
|
|
247
|
+
interface CheckboxBlock {
|
|
248
|
+
type: 'checkbox';
|
|
249
|
+
label: string;
|
|
250
|
+
name: string;
|
|
251
|
+
checked?: boolean;
|
|
252
|
+
}
|
|
253
|
+
/** A custom or unknown block type (for plugin extensibility) */
|
|
254
|
+
interface CustomBlock {
|
|
255
|
+
type: 'custom';
|
|
256
|
+
customType: string;
|
|
257
|
+
attrs?: Record<string, unknown>;
|
|
258
|
+
children?: ContentBlock[];
|
|
259
|
+
content?: string;
|
|
260
|
+
}
|
|
261
|
+
/** All content blocks that can appear in the document body */
|
|
262
|
+
type ContentBlock = TextBlock | ParagraphBlock | HeadingBlock | BlockquoteBlock | CodeBlock | HorizontalRuleBlock | HardBreakBlock | BulletListBlock | OrderedListBlock | ListItemBlock | ImageBlock | VideoBlock | EmbedBlock | ContainerBlock | CardBlock | SectionBlock | AccordionBlock | TabsBlock | ModalBlock | ButtonBlock | LinkBlock | TableBlock | BadgeBlock | AlertBlock | IconBlock | InputBlock | TextareaBlock | SelectBlock | CheckboxBlock | CustomBlock;
|
|
263
|
+
/** Building block - alias for ContentBlock for clarity in API */
|
|
264
|
+
type BuildingBlock = ContentBlock;
|
|
265
|
+
/** Helper type to extract block by type */
|
|
266
|
+
type BlockOfType<T extends ContentBlock['type']> = Extract<ContentBlock, {
|
|
267
|
+
type: T;
|
|
268
|
+
}>;
|
|
269
|
+
|
|
270
|
+
/** The type of content being rendered */
|
|
271
|
+
type ContentType = 'page' | 'news-article' | 'news-list';
|
|
272
|
+
/** Base content interface with common fields */
|
|
273
|
+
interface BaseContentDTO {
|
|
274
|
+
/** Page/article title */
|
|
275
|
+
title: string;
|
|
276
|
+
/** Content type discriminator */
|
|
277
|
+
contentType: ContentType;
|
|
278
|
+
}
|
|
279
|
+
/** A regular page's content */
|
|
280
|
+
interface PageContentDTO extends BaseContentDTO {
|
|
281
|
+
contentType: 'page';
|
|
282
|
+
/** Content blocks to render */
|
|
283
|
+
blocks: BuildingBlock[];
|
|
284
|
+
}
|
|
285
|
+
/** A back navigation link */
|
|
286
|
+
interface BackLinkDTO {
|
|
287
|
+
label: string;
|
|
288
|
+
href: string;
|
|
289
|
+
}
|
|
290
|
+
/** A news article's content */
|
|
291
|
+
interface NewsArticleDTO extends BaseContentDTO {
|
|
292
|
+
contentType: 'news-article';
|
|
293
|
+
/** Content blocks to render */
|
|
294
|
+
blocks: BuildingBlock[];
|
|
295
|
+
/** Publication date (ISO string for formatting) */
|
|
296
|
+
publishedAt: string;
|
|
297
|
+
/** Author name */
|
|
298
|
+
author?: string;
|
|
299
|
+
/** Link back to news list */
|
|
300
|
+
backLink: BackLinkDTO;
|
|
301
|
+
}
|
|
302
|
+
/** A news card in the news list */
|
|
303
|
+
interface NewsCardDTO {
|
|
304
|
+
/** Article title */
|
|
305
|
+
title: string;
|
|
306
|
+
/** Article excerpt/preview */
|
|
307
|
+
excerpt?: string;
|
|
308
|
+
/** Publication date (ISO string) */
|
|
309
|
+
publishedAt: string;
|
|
310
|
+
/** Link to full article */
|
|
311
|
+
href: string;
|
|
312
|
+
/** Whether this is a featured article */
|
|
313
|
+
featured?: boolean;
|
|
314
|
+
/** Cover image URL */
|
|
315
|
+
image?: string;
|
|
316
|
+
/** Category label (e.g., "News", "Events") */
|
|
317
|
+
category?: string;
|
|
318
|
+
/** Estimated reading time in minutes */
|
|
319
|
+
readingTime?: number;
|
|
320
|
+
}
|
|
321
|
+
/** A news list page's content */
|
|
322
|
+
interface NewsListDTO extends BaseContentDTO {
|
|
323
|
+
contentType: 'news-list';
|
|
324
|
+
/** The news cards to display */
|
|
325
|
+
items: NewsCardDTO[];
|
|
326
|
+
}
|
|
327
|
+
/** All content types that can be rendered in the main content area */
|
|
328
|
+
type ContentDTO = PageContentDTO | NewsArticleDTO | NewsListDTO;
|
|
329
|
+
/** Check if content is a regular page */
|
|
330
|
+
declare function isPageContent(content: ContentDTO): content is PageContentDTO;
|
|
331
|
+
/** Check if content is a news article */
|
|
332
|
+
declare function isNewsArticle(content: ContentDTO): content is NewsArticleDTO;
|
|
333
|
+
/** Check if content is a news list */
|
|
334
|
+
declare function isNewsList(content: ContentDTO): content is NewsListDTO;
|
|
335
|
+
|
|
336
|
+
/** SEO and social metadata for a page */
|
|
337
|
+
interface MetaDTO {
|
|
338
|
+
description?: string;
|
|
339
|
+
keywords?: string[];
|
|
340
|
+
ogTitle?: string;
|
|
341
|
+
ogDescription?: string;
|
|
342
|
+
ogImage?: string;
|
|
343
|
+
canonical?: string;
|
|
344
|
+
noIndex?: boolean;
|
|
345
|
+
jsonLd: object[];
|
|
346
|
+
}
|
|
347
|
+
/** Logo configuration */
|
|
348
|
+
interface LogoDTO {
|
|
349
|
+
src: string;
|
|
350
|
+
alt: string;
|
|
351
|
+
}
|
|
352
|
+
/** Site header configuration */
|
|
353
|
+
interface HeaderDTO {
|
|
354
|
+
siteName: string;
|
|
355
|
+
tagline?: string;
|
|
356
|
+
logo?: LogoDTO;
|
|
357
|
+
showMenuToggle: boolean;
|
|
358
|
+
}
|
|
359
|
+
/** A navigation item */
|
|
360
|
+
interface NavItemDTO {
|
|
361
|
+
label: string;
|
|
362
|
+
href: string;
|
|
363
|
+
active: boolean;
|
|
364
|
+
children?: NavItemDTO[];
|
|
365
|
+
}
|
|
366
|
+
/** Navigation configuration */
|
|
367
|
+
interface NavigationDTO {
|
|
368
|
+
items: NavItemDTO[];
|
|
369
|
+
}
|
|
370
|
+
/** A single breadcrumb item */
|
|
371
|
+
interface BreadcrumbDTO {
|
|
372
|
+
/** Display label */
|
|
373
|
+
label: string;
|
|
374
|
+
/** Link URL (undefined = current page, no link) */
|
|
375
|
+
href?: string;
|
|
376
|
+
}
|
|
377
|
+
/** Breadcrumb trail configuration */
|
|
378
|
+
interface BreadcrumbsDTO {
|
|
379
|
+
/** Breadcrumb items from root to current */
|
|
380
|
+
items: BreadcrumbDTO[];
|
|
381
|
+
}
|
|
382
|
+
/** A footer link */
|
|
383
|
+
interface FooterLinkDTO {
|
|
384
|
+
label: string;
|
|
385
|
+
href: string;
|
|
386
|
+
}
|
|
387
|
+
/** Site footer configuration */
|
|
388
|
+
interface FooterDTO {
|
|
389
|
+
copyright: string;
|
|
390
|
+
year: number;
|
|
391
|
+
links: FooterLinkDTO[];
|
|
392
|
+
}
|
|
393
|
+
/** A favicon or icon link */
|
|
394
|
+
interface FaviconDTO {
|
|
395
|
+
rel: 'icon' | 'apple-touch-icon';
|
|
396
|
+
type?: string;
|
|
397
|
+
sizes?: string;
|
|
398
|
+
href: string;
|
|
399
|
+
}
|
|
400
|
+
/** Site-level configuration for theming */
|
|
401
|
+
interface SiteConfigDTO {
|
|
402
|
+
siteName: string;
|
|
403
|
+
shortName: string;
|
|
404
|
+
description?: string;
|
|
405
|
+
themeColor?: string;
|
|
406
|
+
backgroundColor?: string;
|
|
407
|
+
language: string;
|
|
408
|
+
}
|
|
409
|
+
/** Full page document DTO */
|
|
410
|
+
interface DocumentDTO {
|
|
411
|
+
/** HTML lang attribute */
|
|
412
|
+
lang: string;
|
|
413
|
+
/** Page title for <title> tag */
|
|
414
|
+
title: string;
|
|
415
|
+
/** Active theme identifier */
|
|
416
|
+
themeId: string;
|
|
417
|
+
/** SEO and social metadata */
|
|
418
|
+
meta: MetaDTO;
|
|
419
|
+
/** Header configuration */
|
|
420
|
+
header: HeaderDTO;
|
|
421
|
+
/** Navigation configuration */
|
|
422
|
+
navigation: NavigationDTO;
|
|
423
|
+
/** Main page content */
|
|
424
|
+
content: ContentDTO;
|
|
425
|
+
/** Footer configuration */
|
|
426
|
+
footer: FooterDTO;
|
|
427
|
+
/** Favicon and icon links */
|
|
428
|
+
favicons: FaviconDTO[];
|
|
429
|
+
/** External stylesheets to include */
|
|
430
|
+
styles: string[];
|
|
431
|
+
/** CSS custom properties to inject */
|
|
432
|
+
cssVariables: Record<string, string>;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
interface ThemeBreakpoints {
|
|
436
|
+
sm?: string;
|
|
437
|
+
md?: string;
|
|
438
|
+
lg?: string;
|
|
439
|
+
xl?: string;
|
|
440
|
+
}
|
|
441
|
+
interface ThemeCustomizableField {
|
|
442
|
+
type: 'color' | 'font' | 'size' | 'select';
|
|
443
|
+
label: string;
|
|
444
|
+
default: string;
|
|
445
|
+
options?: string[];
|
|
446
|
+
}
|
|
447
|
+
interface ThemeManifest {
|
|
448
|
+
id: string;
|
|
449
|
+
name: string;
|
|
450
|
+
version: string;
|
|
451
|
+
description: string;
|
|
452
|
+
author: string;
|
|
453
|
+
homepage?: string;
|
|
454
|
+
breakpoints?: ThemeBreakpoints;
|
|
455
|
+
customizable?: Record<string, ThemeCustomizableField>;
|
|
456
|
+
}
|
|
457
|
+
interface InstalledTheme {
|
|
458
|
+
id: string;
|
|
459
|
+
version: string;
|
|
460
|
+
active: boolean;
|
|
461
|
+
installedAt: string;
|
|
462
|
+
installedBy: string;
|
|
463
|
+
customizations: Record<string, string>;
|
|
464
|
+
manifest: ThemeManifest;
|
|
465
|
+
updatedAt?: string;
|
|
466
|
+
updatedBy?: string;
|
|
467
|
+
releaseUrl?: string;
|
|
468
|
+
}
|
|
469
|
+
interface ThemeRegistryEntry {
|
|
470
|
+
id: string;
|
|
471
|
+
name: string;
|
|
472
|
+
description: string;
|
|
473
|
+
latestVersion: string;
|
|
474
|
+
author: string;
|
|
475
|
+
githubRepo: string;
|
|
476
|
+
releaseUrl: string;
|
|
477
|
+
previewUrl?: string;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Context passed to every render function.
|
|
482
|
+
* Contains everything you need to render content.
|
|
483
|
+
*/
|
|
484
|
+
interface RenderContext {
|
|
485
|
+
/** Render a child block */
|
|
486
|
+
render: (block: ContentBlock | BuildingBlock) => string;
|
|
487
|
+
/** Render multiple blocks */
|
|
488
|
+
renderAll: (blocks: (ContentBlock | BuildingBlock)[]) => string;
|
|
489
|
+
/** Site configuration */
|
|
490
|
+
site: {
|
|
491
|
+
name: string;
|
|
492
|
+
baseUrl: string;
|
|
493
|
+
currentPath?: string;
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* A render function takes data and context, returns HTML.
|
|
498
|
+
*/
|
|
499
|
+
type RenderFn<T> = (data: T, ctx: RenderContext) => string;
|
|
500
|
+
/**
|
|
501
|
+
* A renderer object with optional styles and scripts.
|
|
502
|
+
*/
|
|
503
|
+
interface Renderer<T = unknown> {
|
|
504
|
+
render: RenderFn<T>;
|
|
505
|
+
styles?: () => string;
|
|
506
|
+
scripts?: () => string;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Shorthand type for block renderers.
|
|
510
|
+
*/
|
|
511
|
+
type BlockRenderer<T extends ContentBlock = ContentBlock> = Renderer<T>;
|
|
512
|
+
/**
|
|
513
|
+
* Helper to create a typed renderer.
|
|
514
|
+
*/
|
|
515
|
+
declare function renderer<T>(fn: RenderFn<T>): Renderer<T>;
|
|
516
|
+
declare function renderer<T>(options: Renderer<T>): Renderer<T>;
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* All the components a theme can customize.
|
|
520
|
+
* Every component is optional - defaults are used for missing ones.
|
|
521
|
+
*/
|
|
522
|
+
interface ThemeRenderers {
|
|
523
|
+
document?: Renderer<DocumentDTO>;
|
|
524
|
+
header?: Renderer<HeaderDTO>;
|
|
525
|
+
navigation?: Renderer<NavigationDTO>;
|
|
526
|
+
footer?: Renderer<FooterDTO>;
|
|
527
|
+
article?: Renderer<PageContentDTO>;
|
|
528
|
+
newsArticle?: Renderer<NewsArticleDTO>;
|
|
529
|
+
newsList?: Renderer<NewsListDTO>;
|
|
530
|
+
newsCard?: Renderer<NewsCardDTO>;
|
|
531
|
+
blocks?: Partial<Record<ContentBlock['type'], Renderer<ContentBlock>>>;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Theme configuration.
|
|
535
|
+
*/
|
|
536
|
+
interface ThemeConfig {
|
|
537
|
+
/** Theme ID (must match manifest) */
|
|
538
|
+
id: string;
|
|
539
|
+
/** Theme display name */
|
|
540
|
+
name: string;
|
|
541
|
+
/** Theme version */
|
|
542
|
+
version: string;
|
|
543
|
+
/** CSS variables for customization */
|
|
544
|
+
variables?: Record<string, string>;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Complete theme definition.
|
|
548
|
+
*/
|
|
549
|
+
interface ThemeDefinition {
|
|
550
|
+
config: ThemeConfig;
|
|
551
|
+
renderers: ThemeRenderers;
|
|
552
|
+
/** Global styles for the theme */
|
|
553
|
+
styles?: string;
|
|
554
|
+
/** Global scripts for the theme */
|
|
555
|
+
scripts?: string;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Define a theme with custom renderers.
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```ts
|
|
562
|
+
* import { defineTheme, html } from '@micropress/theme-sdk';
|
|
563
|
+
*
|
|
564
|
+
* export default defineTheme({
|
|
565
|
+
* config: {
|
|
566
|
+
* id: 'my-theme',
|
|
567
|
+
* name: 'My Theme',
|
|
568
|
+
* version: '1.0.0',
|
|
569
|
+
* },
|
|
570
|
+
* renderers: {
|
|
571
|
+
* header: {
|
|
572
|
+
* render: (data, ctx) => html`
|
|
573
|
+
* <header class="my-header">
|
|
574
|
+
* <h1>${data.siteName}</h1>
|
|
575
|
+
* </header>
|
|
576
|
+
* `.html,
|
|
577
|
+
* },
|
|
578
|
+
* },
|
|
579
|
+
* });
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
declare function defineTheme(definition: ThemeDefinition): ThemeDefinition;
|
|
583
|
+
/**
|
|
584
|
+
* Quick helper to define just a render function.
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```ts
|
|
588
|
+
* const header = render<HeaderDTO>((data, ctx) => html`
|
|
589
|
+
* <header>${data.siteName}</header>
|
|
590
|
+
* `.html);
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
declare function render<T>(fn: RenderFn<T>): Renderer<T>;
|
|
594
|
+
/**
|
|
595
|
+
* Quick helper to define a renderer with styles.
|
|
596
|
+
*
|
|
597
|
+
* @example
|
|
598
|
+
* ```ts
|
|
599
|
+
* const card = withStyles<CardDTO>(
|
|
600
|
+
* (data, ctx) => html`<div class="card">${ctx.renderAll(data.children)}</div>`.html,
|
|
601
|
+
* css`.card { padding: 1rem; }`
|
|
602
|
+
* );
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
605
|
+
declare function withStyles<T>(fn: RenderFn<T>, styles: string): Renderer<T>;
|
|
606
|
+
/**
|
|
607
|
+
* Quick helper to define a renderer with scripts.
|
|
608
|
+
*/
|
|
609
|
+
declare function withScripts<T>(fn: RenderFn<T>, scripts: string): Renderer<T>;
|
|
610
|
+
/**
|
|
611
|
+
* Define a renderer with both styles and scripts.
|
|
612
|
+
*/
|
|
613
|
+
declare function withAssets<T>(fn: RenderFn<T>, options: {
|
|
614
|
+
styles?: string;
|
|
615
|
+
scripts?: string;
|
|
616
|
+
}): Renderer<T>;
|
|
617
|
+
|
|
618
|
+
export { type AccordionBlock, type AlertBlock, type BackLinkDTO, type BadgeBlock, type BaseContentDTO, type BlockOfType, type BlockRenderer, type BlockquoteBlock, type BreadcrumbDTO, type BreadcrumbsDTO, type BuildingBlock, type BulletListBlock, type ButtonBlock, type CardBlock, type CheckboxBlock, type CodeBlock, type ContainerBlock, type ContentBlock, type ContentDTO, type ContentType, type CustomBlock, type DocumentDTO, type EmbedBlock, type FaviconDTO, type FooterDTO, type FooterLinkDTO, type HardBreakBlock, type HeaderDTO, type HeadingBlock, type HorizontalRuleBlock, type HtmlResult, type IconBlock, type ImageBlock, type InputBlock, type InstalledTheme, type LinkBlock, type ListItemBlock, type LogoDTO, type MarkType, type MetaDTO, type ModalBlock, type NavItemDTO, type NavigationDTO, type NewsArticleDTO, type NewsCardDTO, type NewsListDTO, type OrderedListBlock, type PageContentDTO, type ParagraphBlock, type RenderContext, type RenderFn, type Renderer, type SectionBlock, type SelectBlock, type SiteConfigDTO, type TabItem, type TableBlock, type TabsBlock, type TextBlock, type TextMark, type TextareaBlock, type ThemeBreakpoints, type ThemeConfig, type ThemeCustomizableField, type ThemeDefinition, type ThemeManifest, type ThemeRegistryEntry, type ThemeRenderers, type VideoBlock, css, defineTheme, escapeHtml, html, isNewsArticle, isNewsList, isPageContent, join, raw, render, renderer, when, withAssets, withScripts, withStyles };
|