@analogjs/content 3.0.0-alpha.4 → 3.0.0-alpha.41
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/devtools/package.json +4 -0
- package/fesm2022/analogjs-content-devtools.mjs +162 -0
- package/fesm2022/analogjs-content-devtools.mjs.map +1 -0
- package/fesm2022/analogjs-content-md4x.mjs +291 -0
- package/fesm2022/analogjs-content-md4x.mjs.map +1 -0
- package/fesm2022/analogjs-content-mdc.mjs +170 -0
- package/fesm2022/analogjs-content-mdc.mjs.map +1 -0
- package/fesm2022/analogjs-content-og.mjs.map +1 -0
- package/fesm2022/analogjs-content-prism-highlighter.mjs +5 -4
- package/fesm2022/analogjs-content-prism-highlighter.mjs.map +1 -0
- package/fesm2022/analogjs-content-resources.mjs +39 -25
- package/fesm2022/analogjs-content-resources.mjs.map +1 -0
- package/fesm2022/analogjs-content-shiki-highlighter.mjs +1 -1
- package/fesm2022/analogjs-content-shiki-highlighter.mjs.map +1 -0
- package/fesm2022/analogjs-content.mjs +29 -353
- package/fesm2022/analogjs-content.mjs.map +1 -0
- package/fesm2022/content-list-loader.mjs +248 -0
- package/fesm2022/content-list-loader.mjs.map +1 -0
- package/fesm2022/content-renderer.mjs +128 -0
- package/fesm2022/content-renderer.mjs.map +1 -0
- package/fesm2022/marked-content-highlighter.mjs +40 -0
- package/fesm2022/marked-content-highlighter.mjs.map +1 -0
- package/fesm2022/parse-raw-content-file.mjs +45 -0
- package/fesm2022/parse-raw-content-file.mjs.map +1 -0
- package/md4x/package.json +4 -0
- package/mdc/package.json +4 -0
- package/package.json +71 -36
- package/plugin/migrations.json +1 -1
- package/plugin/package.json +2 -21
- package/plugin/src/index.d.ts +3 -1
- package/plugin/src/index.d.ts.map +1 -0
- package/plugin/src/index.js +5 -4
- package/plugin/src/index.js.map +1 -0
- package/plugin/src/migrations/update-markdown-version/compat.d.ts +5 -2
- package/plugin/src/migrations/update-markdown-version/compat.d.ts.map +1 -0
- package/plugin/src/migrations/update-markdown-version/compat.js +8 -7
- package/plugin/src/migrations/update-markdown-version/compat.js.map +1 -0
- package/plugin/src/migrations/update-markdown-version/update-markdown-version.d.ts +6 -2
- package/plugin/src/migrations/update-markdown-version/update-markdown-version.d.ts.map +1 -0
- package/plugin/src/migrations/update-markdown-version/update-markdown-version.js +18 -20
- package/plugin/src/migrations/update-markdown-version/update-markdown-version.js.map +1 -0
- package/src/lib/devtools/content-devtools-client.ts +215 -0
- package/src/lib/devtools/content-devtools.styles.css +194 -0
- package/types/devtools/src/index.d.ts +1 -0
- package/types/md4x/src/index.d.ts +5 -0
- package/types/md4x/src/lib/md4x-content-renderer.service.d.ts +33 -0
- package/types/md4x/src/lib/md4x-wasm-content-renderer.service.d.ts +16 -0
- package/types/md4x/src/lib/provide-md4x.d.ts +26 -0
- package/types/md4x/src/lib/streaming-markdown-renderer.d.ts +21 -0
- package/types/mdc/src/index.d.ts +2 -0
- package/types/mdc/src/lib/mdc-component-registry.d.ts +25 -0
- package/types/mdc/src/lib/mdc-renderer.directive.d.ts +33 -0
- package/types/prism-highlighter/src/lib/prism-highlighter.d.ts +1 -1
- package/types/resources/src/content-file-resource.d.ts +32 -7
- package/types/resources/src/content-files-resource.d.ts +2 -1
- package/types/src/index.d.ts +6 -3
- package/types/src/lib/content-locale.d.ts +68 -0
- package/types/src/lib/devtools/content-devtools-plugin.d.ts +23 -0
- package/types/src/lib/devtools/content-devtools-renderer.d.ts +23 -0
- package/types/src/lib/devtools/index.d.ts +23 -0
- package/types/src/lib/parse-raw-content-file.d.ts +15 -1
- package/plugin/README.md +0 -11
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#analog-content-devtools {
|
|
2
|
+
position: fixed;
|
|
3
|
+
bottom: 0;
|
|
4
|
+
right: 0;
|
|
5
|
+
z-index: 99999;
|
|
6
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
7
|
+
font-size: 12px;
|
|
8
|
+
color: #e4e4e7;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#analog-content-devtools * {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#analog-content-devtools .acd-toggle {
|
|
17
|
+
position: fixed;
|
|
18
|
+
bottom: 12px;
|
|
19
|
+
right: 12px;
|
|
20
|
+
width: 36px;
|
|
21
|
+
height: 36px;
|
|
22
|
+
border-radius: 8px;
|
|
23
|
+
background: #18181b;
|
|
24
|
+
border: 1px solid #3f3f46;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
pointer-events: auto;
|
|
30
|
+
opacity: 0.7;
|
|
31
|
+
transition: opacity 0.15s;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#analog-content-devtools .acd-toggle:hover {
|
|
35
|
+
opacity: 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#analog-content-devtools .acd-toggle svg {
|
|
39
|
+
width: 20px;
|
|
40
|
+
height: 20px;
|
|
41
|
+
fill: #a1a1aa;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#analog-content-devtools .acd-panel {
|
|
45
|
+
position: fixed;
|
|
46
|
+
bottom: 56px;
|
|
47
|
+
right: 12px;
|
|
48
|
+
width: 420px;
|
|
49
|
+
max-height: 70vh;
|
|
50
|
+
background: #18181b;
|
|
51
|
+
border: 1px solid #3f3f46;
|
|
52
|
+
border-radius: 10px;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: column;
|
|
56
|
+
pointer-events: auto;
|
|
57
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#analog-content-devtools .acd-header {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
justify-content: space-between;
|
|
64
|
+
padding: 8px 12px;
|
|
65
|
+
background: #27272a;
|
|
66
|
+
border-bottom: 1px solid #3f3f46;
|
|
67
|
+
font-weight: 600;
|
|
68
|
+
font-size: 11px;
|
|
69
|
+
text-transform: uppercase;
|
|
70
|
+
letter-spacing: 0.05em;
|
|
71
|
+
color: #a1a1aa;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#analog-content-devtools .acd-tabs {
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: 2px;
|
|
77
|
+
padding: 4px 8px;
|
|
78
|
+
background: #27272a;
|
|
79
|
+
border-bottom: 1px solid #3f3f46;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#analog-content-devtools .acd-tab {
|
|
83
|
+
padding: 4px 10px;
|
|
84
|
+
border-radius: 4px;
|
|
85
|
+
background: transparent;
|
|
86
|
+
border: none;
|
|
87
|
+
color: #71717a;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
font-size: 11px;
|
|
90
|
+
font-family: inherit;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#analog-content-devtools .acd-tab:hover {
|
|
94
|
+
color: #a1a1aa;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#analog-content-devtools .acd-tab[data-active='true'] {
|
|
98
|
+
background: #3f3f46;
|
|
99
|
+
color: #e4e4e7;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#analog-content-devtools .acd-body {
|
|
103
|
+
overflow-y: auto;
|
|
104
|
+
padding: 12px;
|
|
105
|
+
flex: 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#analog-content-devtools .acd-section {
|
|
109
|
+
margin-bottom: 12px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#analog-content-devtools .acd-section-title {
|
|
113
|
+
font-size: 10px;
|
|
114
|
+
font-weight: 600;
|
|
115
|
+
text-transform: uppercase;
|
|
116
|
+
letter-spacing: 0.05em;
|
|
117
|
+
color: #71717a;
|
|
118
|
+
margin-bottom: 6px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#analog-content-devtools .acd-kv {
|
|
122
|
+
display: flex;
|
|
123
|
+
justify-content: space-between;
|
|
124
|
+
padding: 2px 0;
|
|
125
|
+
border-bottom: 1px solid #27272a;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#analog-content-devtools .acd-key {
|
|
129
|
+
color: #a1a1aa;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#analog-content-devtools .acd-value {
|
|
133
|
+
color: #22d3ee;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#analog-content-devtools .acd-value.acd-fast {
|
|
137
|
+
color: #4ade80;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#analog-content-devtools .acd-value.acd-slow {
|
|
141
|
+
color: #fb923c;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
#analog-content-devtools .acd-toc-item {
|
|
145
|
+
padding: 2px 0;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
color: #a1a1aa;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
#analog-content-devtools .acd-toc-item:hover {
|
|
151
|
+
color: #e4e4e7;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#analog-content-devtools .acd-toc-item a {
|
|
155
|
+
color: inherit;
|
|
156
|
+
text-decoration: none;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#analog-content-devtools .acd-pre {
|
|
160
|
+
background: #09090b;
|
|
161
|
+
border: 1px solid #27272a;
|
|
162
|
+
border-radius: 6px;
|
|
163
|
+
padding: 8px;
|
|
164
|
+
overflow-x: auto;
|
|
165
|
+
white-space: pre-wrap;
|
|
166
|
+
overflow-wrap: anywhere;
|
|
167
|
+
font-size: 11px;
|
|
168
|
+
line-height: 1.5;
|
|
169
|
+
max-height: 300px;
|
|
170
|
+
overflow-y: auto;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#analog-content-devtools .acd-empty {
|
|
174
|
+
color: #52525b;
|
|
175
|
+
font-style: italic;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#analog-content-devtools .acd-badge {
|
|
179
|
+
display: inline-block;
|
|
180
|
+
padding: 1px 6px;
|
|
181
|
+
border-radius: 4px;
|
|
182
|
+
font-size: 10px;
|
|
183
|
+
font-weight: 600;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#analog-content-devtools .acd-badge-experimental {
|
|
187
|
+
background: #422006;
|
|
188
|
+
color: #fb923c;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
#analog-content-devtools .acd-badge-renderer {
|
|
192
|
+
background: #042f2e;
|
|
193
|
+
color: #2dd4bf;
|
|
194
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { contentDevToolsPlugin, DevToolsContentRenderer, withContentDevTools, } from '../../src/lib/devtools/index';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { withMd4xRenderer, withMd4xWasmRenderer } from './lib/provide-md4x';
|
|
2
|
+
export { Md4xContentRendererService, MD4X_RENDERER_OPTIONS, } from './lib/md4x-content-renderer.service';
|
|
3
|
+
export type { Md4xRendererOptions } from './lib/md4x-content-renderer.service';
|
|
4
|
+
export { Md4xWasmContentRendererService } from './lib/md4x-wasm-content-renderer.service';
|
|
5
|
+
export { streamMarkdown } from './lib/streaming-markdown-renderer';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { ContentRenderer, RenderedContent, TableOfContentItem } from '../../../src/lib/content-renderer';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Options for the experimental md4x-based content renderer.
|
|
6
|
+
*
|
|
7
|
+
* @experimental md4x integration is experimental and may change in future releases.
|
|
8
|
+
*/
|
|
9
|
+
export interface Md4xRendererOptions {
|
|
10
|
+
/** Heal incomplete markdown (useful for streaming/LLM content). */
|
|
11
|
+
heal?: boolean;
|
|
12
|
+
/** Custom code block highlighter. Receives raw code and block metadata,
|
|
13
|
+
* returns highlighted HTML or undefined to keep default rendering. */
|
|
14
|
+
highlighter?: (code: string, block: {
|
|
15
|
+
lang: string;
|
|
16
|
+
filename?: string;
|
|
17
|
+
highlights?: number[];
|
|
18
|
+
}) => string | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare const MD4X_RENDERER_OPTIONS: InjectionToken<Md4xRendererOptions>;
|
|
21
|
+
/**
|
|
22
|
+
* Content renderer backed by md4x (C-based CommonMark parser compiled with Zig).
|
|
23
|
+
* 50-70x faster than marked for complex documents.
|
|
24
|
+
*
|
|
25
|
+
* @experimental md4x integration is experimental and may change in future releases.
|
|
26
|
+
*/
|
|
27
|
+
export declare class Md4xContentRendererService extends ContentRenderer {
|
|
28
|
+
private options;
|
|
29
|
+
render(content: string): Promise<RenderedContent>;
|
|
30
|
+
getContentHeadings(content: string): TableOfContentItem[];
|
|
31
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<Md4xContentRendererService, never>;
|
|
32
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<Md4xContentRendererService>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ContentRenderer, RenderedContent, TableOfContentItem } from '../../../src/lib/content-renderer';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Content renderer backed by md4x/wasm for client-side (browser) rendering.
|
|
5
|
+
* ~100KB gzip, 3-6x faster than marked in the browser.
|
|
6
|
+
*
|
|
7
|
+
* @experimental md4x integration is experimental and may change in future releases.
|
|
8
|
+
*/
|
|
9
|
+
export declare class Md4xWasmContentRendererService extends ContentRenderer {
|
|
10
|
+
private options;
|
|
11
|
+
private initPromise;
|
|
12
|
+
render(content: string): Promise<RenderedContent>;
|
|
13
|
+
getContentHeadings(content: string): TableOfContentItem[];
|
|
14
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<Md4xWasmContentRendererService, never>;
|
|
15
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<Md4xWasmContentRendererService>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Provider } from '@angular/core';
|
|
2
|
+
import type { Md4xRendererOptions } from './md4x-content-renderer.service';
|
|
3
|
+
/**
|
|
4
|
+
* Provides the experimental md4x-based content renderer (NAPI, server/build-time).
|
|
5
|
+
*
|
|
6
|
+
* @experimental md4x integration is experimental and may change in future releases.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* provideContent(withMd4xRenderer());
|
|
11
|
+
* provideContent(withMd4xRenderer({ heal: true }));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function withMd4xRenderer(options?: Md4xRendererOptions): Provider;
|
|
15
|
+
/**
|
|
16
|
+
* Provides the experimental md4x WASM content renderer (browser/CSR).
|
|
17
|
+
* ~100KB gzip, 3-6x faster than marked in the browser.
|
|
18
|
+
*
|
|
19
|
+
* @experimental md4x integration is experimental and may change in future releases.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* provideContent(withMd4xWasmRenderer());
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function withMd4xWasmRenderer(options?: Md4xRendererOptions): Provider;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transforms a stream of markdown chunks into a stream of rendered HTML.
|
|
3
|
+
* Uses md4x's `heal()` to fix incomplete markdown from streaming sources
|
|
4
|
+
* (LLMs, collaborative editing) so each emitted HTML chunk is valid.
|
|
5
|
+
*
|
|
6
|
+
* @experimental Streaming markdown support is experimental and may change in future releases.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // In a Nitro API route
|
|
11
|
+
* import { streamMarkdown } from '@analogjs/content';
|
|
12
|
+
*
|
|
13
|
+
* export default defineEventHandler(async (event) => {
|
|
14
|
+
* const llmStream = getAIStream(prompt);
|
|
15
|
+
* return streamMarkdown(llmStream, { heal: true });
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function streamMarkdown(input: ReadableStream<string>, options?: {
|
|
20
|
+
heal?: boolean;
|
|
21
|
+
}): Promise<ReadableStream<string>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InjectionToken, Type, Provider } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Registry mapping MDC component names to lazy-loaded Angular components.
|
|
4
|
+
*
|
|
5
|
+
* @experimental MDC component support is experimental and may change in future releases.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MDC_COMPONENTS: InjectionToken<Map<string, () => Promise<Type<unknown>>>>;
|
|
8
|
+
/**
|
|
9
|
+
* Provides a registry of Angular components that can be used in MDC
|
|
10
|
+
* (Markdown Components) syntax within markdown content.
|
|
11
|
+
*
|
|
12
|
+
* @experimental MDC component support is experimental and may change in future releases.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* provideContent(
|
|
17
|
+
* withMd4xRenderer(),
|
|
18
|
+
* withMdcComponents({
|
|
19
|
+
* alert: () => import('./components/alert.component').then(m => m.AlertComponent),
|
|
20
|
+
* card: () => import('./components/card.component').then(m => m.CardComponent),
|
|
21
|
+
* }),
|
|
22
|
+
* );
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function withMdcComponents(components: Record<string, () => Promise<Type<unknown>>>): Provider;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InputSignal } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
type ComarkNode = string | [string | null, Record<string, unknown>, ...ComarkNode[]];
|
|
4
|
+
/**
|
|
5
|
+
* Directive that renders MDC (Markdown Components) AST nodes as Angular components.
|
|
6
|
+
*
|
|
7
|
+
* Walks the ComarkTree AST from md4x's `parseAST()`, matches component nodes
|
|
8
|
+
* to the registered MDC_COMPONENTS map, and instantiates them via
|
|
9
|
+
* `ViewContainerRef.createComponent()` with MDC attributes bound as inputs.
|
|
10
|
+
*
|
|
11
|
+
* @experimental MDC component support is experimental and may change in future releases.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <div [mdcAst]="parsedAst"></div>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class MdcRendererDirective {
|
|
19
|
+
readonly ast: InputSignal<{
|
|
20
|
+
nodes: ComarkNode[];
|
|
21
|
+
} | null>;
|
|
22
|
+
private readonly viewContainer;
|
|
23
|
+
private readonly renderer;
|
|
24
|
+
private readonly el;
|
|
25
|
+
private readonly components;
|
|
26
|
+
private renderId;
|
|
27
|
+
constructor();
|
|
28
|
+
private renderNodes;
|
|
29
|
+
private renderNode;
|
|
30
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MdcRendererDirective, never>;
|
|
31
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<MdcRendererDirective, "[mdcAst]", never, { "ast": { "alias": "mdcAst"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MarkedContentHighlighter } from '
|
|
1
|
+
import { MarkedContentHighlighter } from '../../../src/lib/marked-content-highlighter';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
export declare class PrismHighlighter extends MarkedContentHighlighter {
|
|
4
4
|
augmentCodeBlock(code: string, lang: string): string;
|
|
@@ -1,14 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import { Signal, type ResourceRef } from '@angular/core';
|
|
3
|
+
import type { ContentFile } from '../../src/lib/content-file';
|
|
4
|
+
export interface ContentFileResourceResult<Attributes extends Record<string, any> = Record<string, any>> extends ContentFile<Attributes | Record<string, never>> {
|
|
5
|
+
toc: Array<{
|
|
6
|
+
id: string;
|
|
7
|
+
level: number;
|
|
8
|
+
text: string;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
3
11
|
type ContentFileParams = Signal<string | {
|
|
4
12
|
customFilename: string;
|
|
13
|
+
}> | Signal<string> | Signal<{
|
|
14
|
+
customFilename: string;
|
|
5
15
|
}>;
|
|
6
16
|
/**
|
|
7
|
-
* Resource for requesting an individual content file
|
|
17
|
+
* Resource for requesting an individual content file.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Without schema (existing behavior)
|
|
22
|
+
* const post = contentFileResource<BlogAttributes>();
|
|
8
23
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
24
|
+
* // With schema validation
|
|
25
|
+
* import * as v from 'valibot';
|
|
26
|
+
* const BlogSchema = v.object({
|
|
27
|
+
* title: v.string(),
|
|
28
|
+
* date: v.pipe(v.string(), v.isoDate()),
|
|
29
|
+
* });
|
|
30
|
+
* const post = contentFileResource({ schema: BlogSchema });
|
|
31
|
+
* ```
|
|
12
32
|
*/
|
|
13
|
-
export declare function contentFileResource<Attributes extends Record<string, any> = Record<string, any>>(params?: ContentFileParams, fallback?: string): ResourceRef<
|
|
33
|
+
export declare function contentFileResource<Attributes extends Record<string, any> = Record<string, any>>(params?: ContentFileParams, fallback?: string): ResourceRef<ContentFileResourceResult<Attributes> | undefined>;
|
|
34
|
+
export declare function contentFileResource<TSchema extends StandardSchemaV1>(options: {
|
|
35
|
+
params?: ContentFileParams;
|
|
36
|
+
fallback?: string;
|
|
37
|
+
schema: TSchema;
|
|
38
|
+
}): ResourceRef<ContentFileResourceResult<StandardSchemaV1.InferOutput<TSchema> & Record<string, any>> | undefined>;
|
|
14
39
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ResourceRef } from '@angular/core';
|
|
2
|
-
import { ContentFile
|
|
2
|
+
import type { ContentFile } from '../../src/lib/content-file';
|
|
3
|
+
import type { InjectContentFilesFilterFunction } from '../../src/lib/inject-content-files';
|
|
3
4
|
export declare function contentFilesResource<Attributes extends Record<string, any>>(filterFn?: InjectContentFilesFilterFunction<Attributes> | undefined): ResourceRef<ContentFile<Attributes>[] | undefined>;
|
package/types/src/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
export { AnchorNavigationDirective } from './lib/anchor-navigation.directive';
|
|
2
2
|
export { injectContent } from './lib/content';
|
|
3
|
-
export { ContentFile } from './lib/content-file';
|
|
3
|
+
export type { ContentFile } from './lib/content-file';
|
|
4
4
|
export { ContentRenderer, NoopContentRenderer } from './lib/content-renderer';
|
|
5
|
-
export {
|
|
5
|
+
export type { RenderedContent, TableOfContentItem, } from './lib/content-renderer';
|
|
6
|
+
export { injectContentFiles } from './lib/inject-content-files';
|
|
7
|
+
export type { InjectContentFilesFilterFunction } from './lib/inject-content-files';
|
|
6
8
|
export { MarkdownContentRendererService } from './lib/markdown-content-renderer.service';
|
|
7
9
|
export { provideContent, withMarkdownRenderer, MERMAID_IMPORT_TOKEN, } from './lib/provide-content';
|
|
8
10
|
export { default as MarkdownRouteComponent } from './lib/markdown-route.component';
|
|
9
11
|
export { default as MarkdownComponent } from './lib/markdown.component';
|
|
10
|
-
export { parseRawContentFile } from './lib/parse-raw-content-file';
|
|
12
|
+
export { parseRawContentFile, parseRawContentFileAsync, FrontmatterValidationError, } from './lib/parse-raw-content-file';
|
|
11
13
|
export { MarkedSetupService } from './lib/marked-setup.service';
|
|
12
14
|
export { MarkedContentHighlighter, withHighlighter, } from './lib/marked-content-highlighter';
|
|
13
15
|
export { injectContentFilesMap } from './lib/inject-content-files';
|
|
14
16
|
export { injectContentListLoader, withContentListLoader, CONTENT_LIST_LOADER, } from './lib/content-list-loader';
|
|
15
17
|
export { injectContentFileLoader, withContentFileLoader, CONTENT_FILE_LOADER, } from './lib/content-file-loader';
|
|
18
|
+
export { CONTENT_LOCALE, injectContentLocale, withLocale, filterByLocale, withLocaleCandidates, } from './lib/content-locale';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { InjectionToken, Provider } from '@angular/core';
|
|
2
|
+
import { ContentFile } from './content-file';
|
|
3
|
+
/**
|
|
4
|
+
* Token for the active content locale.
|
|
5
|
+
* Provided via `withLocale()` in `provideContent()`.
|
|
6
|
+
*
|
|
7
|
+
* When set, `injectContentFiles()` filters to content matching this locale,
|
|
8
|
+
* and `injectContent()` resolves locale-prefixed content paths first.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CONTENT_LOCALE: InjectionToken<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Injects the content locale, returning null if not configured.
|
|
13
|
+
*/
|
|
14
|
+
export declare function injectContentLocale(): string | null;
|
|
15
|
+
export interface ContentLocaleOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Function that returns the active locale.
|
|
18
|
+
* Runs in injection context so `inject()` can be used to read
|
|
19
|
+
* from other tokens (e.g., a LOCALE token from a router package).
|
|
20
|
+
*
|
|
21
|
+
* ```typescript
|
|
22
|
+
* withLocale({ loadLocale: injectLocale })
|
|
23
|
+
* withLocale({ loadLocale: () => navigator.language.split('-')[0] })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
loadLocale: () => string | null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Content feature that sets the active locale for content resolution.
|
|
30
|
+
*
|
|
31
|
+
* When provided, content APIs become locale-aware:
|
|
32
|
+
* - `injectContentFiles()` filters to files in the locale subdirectory
|
|
33
|
+
* or with a matching `locale` frontmatter attribute.
|
|
34
|
+
* - `injectContent()` tries locale-prefixed paths first
|
|
35
|
+
* (e.g., `content/fr/blog/post.md` before `content/blog/post.md`).
|
|
36
|
+
*
|
|
37
|
+
* Usage:
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // With loader — runs in injection context
|
|
40
|
+
* provideContent(
|
|
41
|
+
* withMarkdownRenderer(),
|
|
42
|
+
* withLocale({ loadLocale: injectLocale }),
|
|
43
|
+
* )
|
|
44
|
+
*
|
|
45
|
+
* // Static locale
|
|
46
|
+
* provideContent(
|
|
47
|
+
* withMarkdownRenderer(),
|
|
48
|
+
* withLocale('fr'),
|
|
49
|
+
* )
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function withLocale(locale: string | ContentLocaleOptions): Provider;
|
|
53
|
+
/**
|
|
54
|
+
* Filters content files by locale using map-based key lookup.
|
|
55
|
+
*
|
|
56
|
+
* Matching rules:
|
|
57
|
+
* 1. Frontmatter `locale` attribute matches the active locale.
|
|
58
|
+
* 2. File is in the active locale subdirectory (e.g., `/content/fr/blog/post`).
|
|
59
|
+
* 3. File has no locale marker and no localized variant exists — included as universal content.
|
|
60
|
+
*
|
|
61
|
+
* Files in a different locale's subdirectory are always excluded.
|
|
62
|
+
*/
|
|
63
|
+
export declare function filterByLocale<T extends Record<string, any>>(files: ContentFile<T>[], locale: string): ContentFile<T>[];
|
|
64
|
+
/**
|
|
65
|
+
* Prepends locale-prefixed candidates before the standard candidates
|
|
66
|
+
* for content file map key lookup.
|
|
67
|
+
*/
|
|
68
|
+
export declare function withLocaleCandidates(candidates: string[], locale: string | null | undefined): string[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Vite plugin that injects the Analog Content DevTools panel in dev mode.
|
|
4
|
+
*
|
|
5
|
+
* Shows render time, frontmatter data, TOC, and content stats in a floating
|
|
6
|
+
* panel. Dev-only — completely stripped from production builds.
|
|
7
|
+
*
|
|
8
|
+
* @experimental Content DevTools is experimental and may change in future releases.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // vite.config.ts
|
|
13
|
+
* import { contentDevToolsPlugin } from '@analogjs/content/devtools';
|
|
14
|
+
*
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* plugins: [
|
|
17
|
+
* analog({ ... }),
|
|
18
|
+
* contentDevToolsPlugin(),
|
|
19
|
+
* ],
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function contentDevToolsPlugin(): Plugin;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { ContentRenderer, RenderedContent, TableOfContentItem } from '../content-renderer';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Token for the wrapped renderer that DevTools delegates to.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEVTOOLS_INNER_RENDERER: InjectionToken<ContentRenderer>;
|
|
9
|
+
/**
|
|
10
|
+
* Wraps an existing ContentRenderer to collect timing and metadata for the
|
|
11
|
+
* Content DevTools panel. Dispatches a custom event on the window after
|
|
12
|
+
* each render so the devtools client can update.
|
|
13
|
+
*
|
|
14
|
+
* @experimental Content DevTools is experimental and may change in future releases.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DevToolsContentRenderer extends ContentRenderer {
|
|
17
|
+
private readonly inner;
|
|
18
|
+
render(content: string): Promise<RenderedContent>;
|
|
19
|
+
getContentHeadings(content: string): TableOfContentItem[];
|
|
20
|
+
enhance(): void;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DevToolsContentRenderer, never>;
|
|
22
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<DevToolsContentRenderer>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Provider, Type } from '@angular/core';
|
|
2
|
+
import { ContentRenderer } from '../content-renderer';
|
|
3
|
+
export { contentDevToolsPlugin } from './content-devtools-plugin';
|
|
4
|
+
export { DevToolsContentRenderer, DEVTOOLS_INNER_RENDERER, } from './content-devtools-renderer';
|
|
5
|
+
/**
|
|
6
|
+
* Wraps the given ContentRenderer with DevTools instrumentation.
|
|
7
|
+
*
|
|
8
|
+
* The supplied renderer class is provided under DEVTOOLS_INNER_RENDERER and
|
|
9
|
+
* DevToolsContentRenderer becomes the new ContentRenderer, delegating
|
|
10
|
+
* all calls and collecting timing data.
|
|
11
|
+
*
|
|
12
|
+
* @param innerRenderer The renderer class to wrap with devtools instrumentation.
|
|
13
|
+
*
|
|
14
|
+
* @experimental Content DevTools is experimental and may change in future releases.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* provideContent(
|
|
19
|
+
* withContentDevTools(NoopContentRenderer),
|
|
20
|
+
* );
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function withContentDevTools(innerRenderer: Type<ContentRenderer>): Provider;
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
export declare class FrontmatterValidationError extends Error {
|
|
3
|
+
readonly issues: ReadonlyArray<StandardSchemaV1.Issue>;
|
|
4
|
+
readonly filename?: string | undefined;
|
|
5
|
+
constructor(issues: ReadonlyArray<StandardSchemaV1.Issue>, filename?: string | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare function parseRawContentFile<Attributes extends Record<string, any> = Record<string, any>>(rawContentFile: string): {
|
|
2
8
|
content: string;
|
|
3
9
|
attributes: Attributes;
|
|
4
10
|
};
|
|
11
|
+
export declare function parseRawContentFile<TSchema extends StandardSchemaV1>(rawContentFile: string, schema: TSchema, filename?: string): {
|
|
12
|
+
content: string;
|
|
13
|
+
attributes: StandardSchemaV1.InferOutput<TSchema>;
|
|
14
|
+
};
|
|
15
|
+
export declare function parseRawContentFileAsync<TSchema extends StandardSchemaV1>(rawContentFile: string, schema: TSchema, filename?: string): Promise<{
|
|
16
|
+
content: string;
|
|
17
|
+
attributes: StandardSchemaV1.InferOutput<TSchema>;
|
|
18
|
+
}>;
|
package/plugin/README.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# content-plugin
|
|
2
|
-
|
|
3
|
-
This library was generated with [Nx](https://nx.dev).
|
|
4
|
-
|
|
5
|
-
## Building
|
|
6
|
-
|
|
7
|
-
Run `nx build content-plugin` to build the library.
|
|
8
|
-
|
|
9
|
-
## Running unit tests
|
|
10
|
-
|
|
11
|
-
Run `nx test content-plugin` to execute the unit tests via [Vitest](https://vitest.dev).
|