@quartz-community/types 0.2.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/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/index.d.ts +307 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/globals.d.ts +32 -0
- package/package.json +74 -0
- package/src/index.ts +423 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Quartz Community
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @quartz-community/types
|
|
2
|
+
|
|
3
|
+
Type definitions for Quartz community plugins. This package provides TypeScript interfaces and types that mirror the internal Quartz types, enabling external plugins to have full type safety without depending on the core Quartz package.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @quartz-community/types
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import {
|
|
15
|
+
QuartzComponent,
|
|
16
|
+
QuartzComponentProps,
|
|
17
|
+
ExplorerOptions,
|
|
18
|
+
} from "@quartz-community/types";
|
|
19
|
+
|
|
20
|
+
const MyComponent: QuartzComponent = (props: QuartzComponentProps) => {
|
|
21
|
+
// Component implementation
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
MyComponent.css = `
|
|
25
|
+
.my-component { /* styles */ }
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
MyComponent.afterDOMLoaded = `
|
|
29
|
+
// Client-side script
|
|
30
|
+
`;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Included Types
|
|
34
|
+
|
|
35
|
+
- **Component Types**: `QuartzComponent`, `QuartzComponentProps`, `StringResource`
|
|
36
|
+
- **Plugin Types**: `QuartzTransformerPlugin`, `QuartzFilterPlugin`, `QuartzEmitterPlugin`
|
|
37
|
+
- **Data Types**: `FileTrieNode`, `ContentIndex`, `ContentIndexEntry`
|
|
38
|
+
- **Component Options**: `ExplorerOptions`, `GraphOptions`, `SearchOptions`, `D3Config`
|
|
39
|
+
- **Utility Types**: `HTMLAttributes`, `EventHandler`, `CleanupFunction`, `ClassValue`
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import * as hast from 'hast';
|
|
2
|
+
import { Root as Root$1 } from 'hast';
|
|
3
|
+
import { Root } from 'mdast';
|
|
4
|
+
import { VFile, Data } from 'vfile';
|
|
5
|
+
import { PluggableList } from 'unified';
|
|
6
|
+
|
|
7
|
+
type FilePath = string & {
|
|
8
|
+
_brand: "FilePath";
|
|
9
|
+
};
|
|
10
|
+
type FullSlug = string & {
|
|
11
|
+
_brand: "FullSlug";
|
|
12
|
+
};
|
|
13
|
+
type SimpleSlug = string & {
|
|
14
|
+
_brand: "SimpleSlug";
|
|
15
|
+
};
|
|
16
|
+
declare function joinSegments(...segments: string[]): FilePath;
|
|
17
|
+
type JSResource = {
|
|
18
|
+
loadTime: "beforeDOMReady" | "afterDOMReady";
|
|
19
|
+
moduleType?: "module";
|
|
20
|
+
spaPreserve?: boolean;
|
|
21
|
+
src: string;
|
|
22
|
+
contentType: "external";
|
|
23
|
+
} | {
|
|
24
|
+
loadTime: "beforeDOMReady" | "afterDOMReady";
|
|
25
|
+
moduleType?: "module";
|
|
26
|
+
spaPreserve?: boolean;
|
|
27
|
+
script: string;
|
|
28
|
+
contentType: "inline";
|
|
29
|
+
};
|
|
30
|
+
type CSSResource = {
|
|
31
|
+
content: string;
|
|
32
|
+
inline?: boolean;
|
|
33
|
+
spaPreserve?: boolean;
|
|
34
|
+
};
|
|
35
|
+
interface StaticResources {
|
|
36
|
+
css: CSSResource[];
|
|
37
|
+
js: JSResource[];
|
|
38
|
+
additionalHead: any[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Flat configuration object that components receive as `cfg` prop.
|
|
42
|
+
* This matches Quartz's `GlobalConfiguration` — the resolved config
|
|
43
|
+
* passed to components at render time (i.e. `ctx.cfg.configuration`).
|
|
44
|
+
*/
|
|
45
|
+
interface GlobalConfiguration {
|
|
46
|
+
pageTitle?: string;
|
|
47
|
+
pageTitleSuffix?: string;
|
|
48
|
+
enableSPA?: boolean;
|
|
49
|
+
enablePopovers?: boolean;
|
|
50
|
+
analytics?: unknown;
|
|
51
|
+
ignorePatterns?: string[];
|
|
52
|
+
defaultDateType?: string;
|
|
53
|
+
baseUrl?: string;
|
|
54
|
+
theme?: unknown;
|
|
55
|
+
locale?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Full Quartz config with nested `configuration` property.
|
|
59
|
+
* This is what `BuildCtx.cfg` holds — used in plugin hooks
|
|
60
|
+
* (transformers, filters, emitters), NOT in component props.
|
|
61
|
+
*/
|
|
62
|
+
interface QuartzConfig {
|
|
63
|
+
configuration: GlobalConfiguration;
|
|
64
|
+
plugins?: unknown;
|
|
65
|
+
externalPlugins?: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface Argv {
|
|
68
|
+
directory: string;
|
|
69
|
+
verbose: boolean;
|
|
70
|
+
output: string;
|
|
71
|
+
serve: boolean;
|
|
72
|
+
watch: boolean;
|
|
73
|
+
port: number;
|
|
74
|
+
wsPort: number;
|
|
75
|
+
remoteDevHost?: string;
|
|
76
|
+
concurrency?: number;
|
|
77
|
+
}
|
|
78
|
+
interface BuildCtx {
|
|
79
|
+
buildId: string;
|
|
80
|
+
argv: Argv;
|
|
81
|
+
cfg: QuartzConfig;
|
|
82
|
+
allSlugs: FullSlug[];
|
|
83
|
+
allFiles: FilePath[];
|
|
84
|
+
incremental: boolean;
|
|
85
|
+
}
|
|
86
|
+
type QuartzPluginData = Data;
|
|
87
|
+
type MarkdownContent = [Root, VFile];
|
|
88
|
+
type ProcessedContent = [Root$1, VFile];
|
|
89
|
+
type QuartzComponentProps = {
|
|
90
|
+
ctx: unknown;
|
|
91
|
+
externalResources: StaticResources;
|
|
92
|
+
fileData: QuartzPluginData & Record<string, unknown>;
|
|
93
|
+
cfg: GlobalConfiguration;
|
|
94
|
+
children: unknown;
|
|
95
|
+
tree: unknown;
|
|
96
|
+
allFiles: (QuartzPluginData & Record<string, unknown>)[];
|
|
97
|
+
displayClass?: "mobile-only" | "desktop-only";
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
};
|
|
100
|
+
type QuartzComponent = ((props: QuartzComponentProps) => unknown) & {
|
|
101
|
+
css?: string | string[] | undefined;
|
|
102
|
+
beforeDOMLoaded?: string | string[] | undefined;
|
|
103
|
+
afterDOMLoaded?: string | string[] | undefined;
|
|
104
|
+
};
|
|
105
|
+
type QuartzComponentConstructor<Options extends object | undefined = undefined> = (opts?: Options) => QuartzComponent;
|
|
106
|
+
type StringResource = string | string[];
|
|
107
|
+
type OptionType = object | undefined;
|
|
108
|
+
type ExternalResourcesFn = (ctx: BuildCtx) => Partial<StaticResources> | undefined;
|
|
109
|
+
|
|
110
|
+
interface PluginTypes {
|
|
111
|
+
transformers: QuartzTransformerPluginInstance[];
|
|
112
|
+
filters: QuartzFilterPluginInstance[];
|
|
113
|
+
emitters: QuartzEmitterPluginInstance[];
|
|
114
|
+
pageTypes: QuartzPageTypePluginInstance[];
|
|
115
|
+
}
|
|
116
|
+
type QuartzTransformerPlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzTransformerPluginInstance;
|
|
117
|
+
type QuartzTransformerPluginInstance = {
|
|
118
|
+
name: string;
|
|
119
|
+
textTransform?: (ctx: BuildCtx, src: string) => string;
|
|
120
|
+
markdownPlugins?: (ctx: BuildCtx) => PluggableList;
|
|
121
|
+
htmlPlugins?: (ctx: BuildCtx) => PluggableList;
|
|
122
|
+
externalResources?: ExternalResourcesFn;
|
|
123
|
+
};
|
|
124
|
+
type QuartzFilterPlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzFilterPluginInstance;
|
|
125
|
+
type QuartzFilterPluginInstance = {
|
|
126
|
+
name: string;
|
|
127
|
+
shouldPublish(ctx: BuildCtx, content: ProcessedContent): boolean;
|
|
128
|
+
};
|
|
129
|
+
type ChangeEvent = {
|
|
130
|
+
type: "add" | "change" | "delete";
|
|
131
|
+
path: FilePath;
|
|
132
|
+
file?: VFile;
|
|
133
|
+
};
|
|
134
|
+
type QuartzEmitterPlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzEmitterPluginInstance;
|
|
135
|
+
type QuartzEmitterPluginInstance = {
|
|
136
|
+
name: string;
|
|
137
|
+
emit: (ctx: BuildCtx, content: ProcessedContent[], resources: StaticResources) => Promise<FilePath[]> | AsyncGenerator<FilePath>;
|
|
138
|
+
partialEmit?: (ctx: BuildCtx, content: ProcessedContent[], resources: StaticResources, changeEvents: ChangeEvent[]) => Promise<FilePath[]> | AsyncGenerator<FilePath> | null;
|
|
139
|
+
getQuartzComponents?: (ctx: BuildCtx) => QuartzComponent[];
|
|
140
|
+
externalResources?: ExternalResourcesFn;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Matcher function: determines if a source file belongs to a page type.
|
|
144
|
+
* Returns true if the page type should own this file.
|
|
145
|
+
*/
|
|
146
|
+
type PageMatcher = (args: {
|
|
147
|
+
slug: FullSlug;
|
|
148
|
+
fileData: QuartzPluginData & Record<string, unknown>;
|
|
149
|
+
cfg: GlobalConfiguration;
|
|
150
|
+
}) => boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Virtual page descriptor for page types that generate pages
|
|
153
|
+
* from aggregated data (e.g., tag indexes, folder listings).
|
|
154
|
+
*/
|
|
155
|
+
interface VirtualPage {
|
|
156
|
+
slug: FullSlug;
|
|
157
|
+
title: string;
|
|
158
|
+
data: Partial<QuartzPluginData> & Record<string, unknown>;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generator function: produces virtual pages from all processed content.
|
|
162
|
+
* Used by page types that don't match source files but instead create
|
|
163
|
+
* synthetic pages (e.g., one page per tag, one page per folder).
|
|
164
|
+
*/
|
|
165
|
+
type PageGenerator = (args: {
|
|
166
|
+
content: ProcessedContent[];
|
|
167
|
+
cfg: GlobalConfiguration;
|
|
168
|
+
ctx: BuildCtx;
|
|
169
|
+
}) => VirtualPage[];
|
|
170
|
+
/** A function that mutates a HAST tree at render time, when allFiles is available. */
|
|
171
|
+
type TreeTransform = (root: Root$1, slug: FullSlug, componentData: QuartzComponentProps) => void;
|
|
172
|
+
/**
|
|
173
|
+
* A PageType plugin definition.
|
|
174
|
+
*
|
|
175
|
+
* PageTypes are a declarative abstraction over page-rendering emitters.
|
|
176
|
+
* Each PageType declares which files it owns (via `match`), optionally
|
|
177
|
+
* generates virtual pages (via `generate`), and provides a body component
|
|
178
|
+
* and layout reference for rendering.
|
|
179
|
+
*/
|
|
180
|
+
type QuartzPageTypePlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzPageTypePluginInstance;
|
|
181
|
+
type QuartzPageTypePluginInstance = {
|
|
182
|
+
name: string;
|
|
183
|
+
/** Higher priority wins when multiple page types match the same file. Default: 0. */
|
|
184
|
+
priority?: number;
|
|
185
|
+
/** File extensions this page type handles (e.g. [".canvas"]). Files with these extensions are excluded from the default asset emitter and processed by generate() instead. */
|
|
186
|
+
fileExtensions?: string[];
|
|
187
|
+
/** Determines which source files this page type owns. */
|
|
188
|
+
match: PageMatcher;
|
|
189
|
+
/** Produces virtual pages from aggregated content data. */
|
|
190
|
+
generate?: PageGenerator;
|
|
191
|
+
/** Layout key — references a key in `layout.byPageType`. */
|
|
192
|
+
layout: string;
|
|
193
|
+
/** Optional page frame name (e.g. "default", "full-width", "canvas"). Defaults to "default". */
|
|
194
|
+
frame?: string;
|
|
195
|
+
/** The body component constructor for this page type. */
|
|
196
|
+
body: QuartzComponentConstructor;
|
|
197
|
+
/** Optional render-time HAST tree transforms (e.g. resolving inline codeblocks). */
|
|
198
|
+
treeTransforms?: (ctx: BuildCtx) => TreeTransform[];
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Props passed to a PageFrame's render function.
|
|
202
|
+
* Contains the resolved layout components and the shared component data.
|
|
203
|
+
*/
|
|
204
|
+
interface PageFrameProps {
|
|
205
|
+
/** Component data shared across all components on the page */
|
|
206
|
+
componentData: QuartzComponentProps;
|
|
207
|
+
/** The Head component (rendered in <head>) — NOT used by frames, included for completeness */
|
|
208
|
+
head: QuartzComponent;
|
|
209
|
+
/** Header slot components (rendered inside <header>) */
|
|
210
|
+
header: QuartzComponent[];
|
|
211
|
+
/** Components rendered before the page body */
|
|
212
|
+
beforeBody: QuartzComponent[];
|
|
213
|
+
/** The page body component (Content) */
|
|
214
|
+
pageBody: QuartzComponent;
|
|
215
|
+
/** Components rendered after the page body */
|
|
216
|
+
afterBody: QuartzComponent[];
|
|
217
|
+
/** Left sidebar components */
|
|
218
|
+
left: QuartzComponent[];
|
|
219
|
+
/** Right sidebar components */
|
|
220
|
+
right: QuartzComponent[];
|
|
221
|
+
/** Footer component */
|
|
222
|
+
footer: QuartzComponent;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* A PageFrame defines the inner HTML structure of a page inside the
|
|
226
|
+
* `<div id="quartz-root">` shell. Different frames can produce completely
|
|
227
|
+
* different layouts (e.g. with/without sidebars, horizontal scroll, etc.)
|
|
228
|
+
* while the outer shell (html, head, body, quartz-root) remains stable
|
|
229
|
+
* for SPA navigation.
|
|
230
|
+
*
|
|
231
|
+
* The `render` function returns `unknown` to avoid coupling to a specific
|
|
232
|
+
* JSX runtime (Preact, React, etc.). Quartz core casts this to JSX.Element.
|
|
233
|
+
*/
|
|
234
|
+
interface PageFrame {
|
|
235
|
+
/** Unique name for this frame (e.g. "default", "full-width", "canvas") */
|
|
236
|
+
name: string;
|
|
237
|
+
/** Render the inner page structure. Returns a JSX tree to be placed inside Body > #quartz-body. */
|
|
238
|
+
render: (props: PageFrameProps) => unknown;
|
|
239
|
+
/** Optional CSS string to include when this frame is active */
|
|
240
|
+
css?: string;
|
|
241
|
+
}
|
|
242
|
+
type HTMLAttributes = Record<string, string | number | boolean | undefined>;
|
|
243
|
+
type EventHandler = (event: Event) => void;
|
|
244
|
+
type CleanupFunction = () => void;
|
|
245
|
+
type ClassValue = string | number | boolean | undefined | null | ClassValue[];
|
|
246
|
+
type ContentDetails = {
|
|
247
|
+
slug: FullSlug;
|
|
248
|
+
filePath: FilePath;
|
|
249
|
+
title: string;
|
|
250
|
+
links: string[];
|
|
251
|
+
tags: string[];
|
|
252
|
+
content: string;
|
|
253
|
+
richContent?: string;
|
|
254
|
+
date?: Date;
|
|
255
|
+
description?: string;
|
|
256
|
+
};
|
|
257
|
+
type ContentIndex = Record<FullSlug, ContentDetails>;
|
|
258
|
+
type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number;
|
|
259
|
+
type ThemeKey = "lightMode" | "darkMode";
|
|
260
|
+
type ValidDateType = "created" | "modified" | "published";
|
|
261
|
+
declare module "vfile" {
|
|
262
|
+
interface DataMap {
|
|
263
|
+
slug: FullSlug;
|
|
264
|
+
filePath: FilePath;
|
|
265
|
+
relativePath: FilePath;
|
|
266
|
+
description: string;
|
|
267
|
+
text: string;
|
|
268
|
+
links: SimpleSlug[];
|
|
269
|
+
toc: {
|
|
270
|
+
depth: number;
|
|
271
|
+
text: string;
|
|
272
|
+
slug: string;
|
|
273
|
+
}[];
|
|
274
|
+
collapseToc: boolean;
|
|
275
|
+
blocks: Record<string, hast.Element>;
|
|
276
|
+
htmlAst: hast.Root;
|
|
277
|
+
hasMermaidDiagram: boolean | undefined;
|
|
278
|
+
frontmatter: {
|
|
279
|
+
[key: string]: unknown;
|
|
280
|
+
} & {
|
|
281
|
+
title: string;
|
|
282
|
+
} & Partial<{
|
|
283
|
+
tags: string[];
|
|
284
|
+
aliases: string[];
|
|
285
|
+
modified: string;
|
|
286
|
+
created: string;
|
|
287
|
+
published: string;
|
|
288
|
+
description: string;
|
|
289
|
+
socialDescription: string;
|
|
290
|
+
publish: boolean | string;
|
|
291
|
+
draft: boolean | string;
|
|
292
|
+
lang: string;
|
|
293
|
+
enableToc: string;
|
|
294
|
+
cssclasses: string[];
|
|
295
|
+
socialImage: string;
|
|
296
|
+
comments: boolean | string;
|
|
297
|
+
}>;
|
|
298
|
+
dates: {
|
|
299
|
+
created: Date;
|
|
300
|
+
modified: Date;
|
|
301
|
+
published: Date;
|
|
302
|
+
};
|
|
303
|
+
defaultDateType?: ValidDateType;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export { type Argv, type BuildCtx, type CSSResource, type ChangeEvent, type ClassValue, type CleanupFunction, type ContentDetails, type ContentIndex, type EventHandler, type ExternalResourcesFn, type FilePath, type FullSlug, type GlobalConfiguration, type HTMLAttributes, type JSResource, type MarkdownContent, type PageFrame, type PageFrameProps, type PageGenerator, type PageMatcher, type PluginTypes, type ProcessedContent, type QuartzComponent, type QuartzComponentConstructor, type QuartzComponentProps, type QuartzConfig, type QuartzEmitterPlugin, type QuartzEmitterPluginInstance, type QuartzFilterPlugin, type QuartzFilterPluginInstance, type QuartzPageTypePlugin, type QuartzPageTypePluginInstance, type QuartzPluginData, type QuartzTransformerPlugin, type QuartzTransformerPluginInstance, type SimpleSlug, type SortFn, type StaticResources, type StringResource, type ThemeKey, type TreeTransform, type ValidDateType, type VirtualPage, joinSegments };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Root as HtmlRoot } from \"hast\";\nimport type { Root as MdRoot } from \"mdast\";\nimport type { Data, VFile } from \"vfile\";\nimport type { PluggableList } from \"unified\";\n\n// ============================================================================\n// Path Types - Branded string types for type-safe file paths\n// ============================================================================\n\nexport type FilePath = string & { _brand: \"FilePath\" };\nexport type FullSlug = string & { _brand: \"FullSlug\" };\nexport type SimpleSlug = string & { _brand: \"SimpleSlug\" };\n\nexport function joinSegments(...segments: string[]): FilePath {\n return segments\n .filter((segment) => segment.length > 0)\n .join(\"/\")\n .replace(/\\/+/g, \"/\") as FilePath;\n}\n\n// ============================================================================\n// Resource Types - CSS/JS resources that plugins can inject\n// ============================================================================\n\nexport type JSResource =\n | {\n loadTime: \"beforeDOMReady\" | \"afterDOMReady\";\n moduleType?: \"module\";\n spaPreserve?: boolean;\n src: string;\n contentType: \"external\";\n }\n | {\n loadTime: \"beforeDOMReady\" | \"afterDOMReady\";\n moduleType?: \"module\";\n spaPreserve?: boolean;\n script: string;\n contentType: \"inline\";\n };\n\nexport type CSSResource = {\n content: string;\n inline?: boolean;\n spaPreserve?: boolean;\n};\n\nexport interface StaticResources {\n css: CSSResource[];\n js: JSResource[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n additionalHead: any[];\n}\n\n// ============================================================================\n// Config Types - Quartz configuration\n// ============================================================================\n\n/**\n * Flat configuration object that components receive as `cfg` prop.\n * This matches Quartz's `GlobalConfiguration` — the resolved config\n * passed to components at render time (i.e. `ctx.cfg.configuration`).\n */\nexport interface GlobalConfiguration {\n pageTitle?: string;\n pageTitleSuffix?: string;\n enableSPA?: boolean;\n enablePopovers?: boolean;\n analytics?: unknown;\n ignorePatterns?: string[];\n defaultDateType?: string;\n baseUrl?: string;\n theme?: unknown;\n locale?: string;\n}\n\n/**\n * Full Quartz config with nested `configuration` property.\n * This is what `BuildCtx.cfg` holds — used in plugin hooks\n * (transformers, filters, emitters), NOT in component props.\n */\nexport interface QuartzConfig {\n configuration: GlobalConfiguration;\n plugins?: unknown;\n externalPlugins?: unknown;\n}\n\n// ============================================================================\n// Context Types - Build context passed to plugin hooks\n// ============================================================================\n\nexport interface Argv {\n directory: string;\n verbose: boolean;\n output: string;\n serve: boolean;\n watch: boolean;\n port: number;\n wsPort: number;\n remoteDevHost?: string;\n concurrency?: number;\n}\n\nexport interface BuildCtx {\n buildId: string;\n argv: Argv;\n cfg: QuartzConfig;\n allSlugs: FullSlug[];\n allFiles: FilePath[];\n incremental: boolean;\n}\n\n// ============================================================================\n// VFile Types - Content data types\n// ============================================================================\n\nexport type QuartzPluginData = Data;\nexport type MarkdownContent = [MdRoot, VFile];\nexport type ProcessedContent = [HtmlRoot, VFile];\n\n// ============================================================================\n// Core Component Types - The contract between Quartz and plugins\n// ============================================================================\n\nexport type QuartzComponentProps = {\n ctx: unknown;\n externalResources: StaticResources;\n fileData: QuartzPluginData & Record<string, unknown>;\n cfg: GlobalConfiguration;\n children: unknown;\n tree: unknown;\n allFiles: (QuartzPluginData & Record<string, unknown>)[];\n displayClass?: \"mobile-only\" | \"desktop-only\";\n [key: string]: unknown;\n};\n\nexport type QuartzComponent = ((props: QuartzComponentProps) => unknown) & {\n css?: string | string[] | undefined;\n beforeDOMLoaded?: string | string[] | undefined;\n afterDOMLoaded?: string | string[] | undefined;\n};\n\nexport type QuartzComponentConstructor<\n Options extends object | undefined = undefined,\n> = (opts?: Options) => QuartzComponent;\n\nexport type StringResource = string | string[];\n\n// ============================================================================\n// Plugin Types - What Quartz expects from plugins\n// ============================================================================\n\ntype OptionType = object | undefined;\ntype ExternalResourcesFn = (\n ctx: BuildCtx,\n) => Partial<StaticResources> | undefined;\n\nexport type { ExternalResourcesFn };\n\nexport interface PluginTypes {\n transformers: QuartzTransformerPluginInstance[];\n filters: QuartzFilterPluginInstance[];\n emitters: QuartzEmitterPluginInstance[];\n pageTypes: QuartzPageTypePluginInstance[];\n}\n\nexport type QuartzTransformerPlugin<Options extends OptionType = undefined> = (\n opts?: Options,\n) => QuartzTransformerPluginInstance;\n\nexport type QuartzTransformerPluginInstance = {\n name: string;\n textTransform?: (ctx: BuildCtx, src: string) => string;\n markdownPlugins?: (ctx: BuildCtx) => PluggableList;\n htmlPlugins?: (ctx: BuildCtx) => PluggableList;\n externalResources?: ExternalResourcesFn;\n};\n\nexport type QuartzFilterPlugin<Options extends OptionType = undefined> = (\n opts?: Options,\n) => QuartzFilterPluginInstance;\n\nexport type QuartzFilterPluginInstance = {\n name: string;\n shouldPublish(ctx: BuildCtx, content: ProcessedContent): boolean;\n};\n\nexport type ChangeEvent = {\n type: \"add\" | \"change\" | \"delete\";\n path: FilePath;\n file?: VFile;\n};\n\nexport type QuartzEmitterPlugin<Options extends OptionType = undefined> = (\n opts?: Options,\n) => QuartzEmitterPluginInstance;\n\nexport type QuartzEmitterPluginInstance = {\n name: string;\n emit: (\n ctx: BuildCtx,\n content: ProcessedContent[],\n resources: StaticResources,\n ) => Promise<FilePath[]> | AsyncGenerator<FilePath>;\n partialEmit?: (\n ctx: BuildCtx,\n content: ProcessedContent[],\n resources: StaticResources,\n changeEvents: ChangeEvent[],\n ) => Promise<FilePath[]> | AsyncGenerator<FilePath> | null;\n getQuartzComponents?: (ctx: BuildCtx) => QuartzComponent[];\n externalResources?: ExternalResourcesFn;\n};\n\n// ============================================================================\n// PageType Plugin Types - Declarative page rendering plugins\n// ============================================================================\n\n/**\n * Matcher function: determines if a source file belongs to a page type.\n * Returns true if the page type should own this file.\n */\nexport type PageMatcher = (args: {\n slug: FullSlug;\n fileData: QuartzPluginData & Record<string, unknown>;\n cfg: GlobalConfiguration;\n}) => boolean;\n\n/**\n * Virtual page descriptor for page types that generate pages\n * from aggregated data (e.g., tag indexes, folder listings).\n */\nexport interface VirtualPage {\n slug: FullSlug;\n title: string;\n data: Partial<QuartzPluginData> & Record<string, unknown>;\n}\n\n/**\n * Generator function: produces virtual pages from all processed content.\n * Used by page types that don't match source files but instead create\n * synthetic pages (e.g., one page per tag, one page per folder).\n */\nexport type PageGenerator = (args: {\n content: ProcessedContent[];\n cfg: GlobalConfiguration;\n ctx: BuildCtx;\n}) => VirtualPage[];\n\n/** A function that mutates a HAST tree at render time, when allFiles is available. */\nexport type TreeTransform = (\n root: HtmlRoot,\n slug: FullSlug,\n componentData: QuartzComponentProps,\n) => void;\n\n/**\n * A PageType plugin definition.\n *\n * PageTypes are a declarative abstraction over page-rendering emitters.\n * Each PageType declares which files it owns (via `match`), optionally\n * generates virtual pages (via `generate`), and provides a body component\n * and layout reference for rendering.\n */\nexport type QuartzPageTypePlugin<Options extends OptionType = undefined> = (\n opts?: Options,\n) => QuartzPageTypePluginInstance;\n\nexport type QuartzPageTypePluginInstance = {\n name: string;\n /** Higher priority wins when multiple page types match the same file. Default: 0. */\n priority?: number;\n /** File extensions this page type handles (e.g. [\".canvas\"]). Files with these extensions are excluded from the default asset emitter and processed by generate() instead. */\n fileExtensions?: string[];\n /** Determines which source files this page type owns. */\n match: PageMatcher;\n /** Produces virtual pages from aggregated content data. */\n generate?: PageGenerator;\n /** Layout key — references a key in `layout.byPageType`. */\n layout: string;\n /** Optional page frame name (e.g. \"default\", \"full-width\", \"canvas\"). Defaults to \"default\". */\n frame?: string;\n /** The body component constructor for this page type. */\n body: QuartzComponentConstructor;\n /** Optional render-time HAST tree transforms (e.g. resolving inline codeblocks). */\n treeTransforms?: (ctx: BuildCtx) => TreeTransform[];\n};\n\n// ============================================================================\n// PageFrame Types — Custom page layout frames\n// ============================================================================\n\n/**\n * Props passed to a PageFrame's render function.\n * Contains the resolved layout components and the shared component data.\n */\nexport interface PageFrameProps {\n /** Component data shared across all components on the page */\n componentData: QuartzComponentProps;\n /** The Head component (rendered in <head>) — NOT used by frames, included for completeness */\n head: QuartzComponent;\n /** Header slot components (rendered inside <header>) */\n header: QuartzComponent[];\n /** Components rendered before the page body */\n beforeBody: QuartzComponent[];\n /** The page body component (Content) */\n pageBody: QuartzComponent;\n /** Components rendered after the page body */\n afterBody: QuartzComponent[];\n /** Left sidebar components */\n left: QuartzComponent[];\n /** Right sidebar components */\n right: QuartzComponent[];\n /** Footer component */\n footer: QuartzComponent;\n}\n\n/**\n * A PageFrame defines the inner HTML structure of a page inside the\n * `<div id=\"quartz-root\">` shell. Different frames can produce completely\n * different layouts (e.g. with/without sidebars, horizontal scroll, etc.)\n * while the outer shell (html, head, body, quartz-root) remains stable\n * for SPA navigation.\n *\n * The `render` function returns `unknown` to avoid coupling to a specific\n * JSX runtime (Preact, React, etc.). Quartz core casts this to JSX.Element.\n */\nexport interface PageFrame {\n /** Unique name for this frame (e.g. \"default\", \"full-width\", \"canvas\") */\n name: string;\n /** Render the inner page structure. Returns a JSX tree to be placed inside Body > #quartz-body. */\n render: (props: PageFrameProps) => unknown;\n /** Optional CSS string to include when this frame is active */\n css?: string;\n}\n\nexport type HTMLAttributes = Record<\n string,\n string | number | boolean | undefined\n>;\n\nexport type EventHandler = (event: Event) => void;\n\nexport type CleanupFunction = () => void;\n\nexport type ClassValue =\n | string\n | number\n | boolean\n | undefined\n | null\n | ClassValue[];\n\n// ============================================================================\n// Content Index Types - Data shape for contentIndex.json\n// ============================================================================\n\nexport type ContentDetails = {\n slug: FullSlug;\n filePath: FilePath;\n title: string;\n links: string[];\n tags: string[];\n content: string;\n richContent?: string;\n date?: Date;\n description?: string;\n};\n\nexport type ContentIndex = Record<FullSlug, ContentDetails>;\n\n// ============================================================================\n// Sort & Theme Types\n// ============================================================================\n\nexport type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number;\n\nexport type ThemeKey = \"lightMode\" | \"darkMode\";\n\nexport type ValidDateType = \"created\" | \"modified\" | \"published\";\n\n// ============================================================================\n// VFile DataMap Augmentation — canonical vfile shape for Quartz\n// ============================================================================\n\ndeclare module \"vfile\" {\n interface DataMap {\n slug: FullSlug;\n filePath: FilePath;\n relativePath: FilePath;\n description: string;\n text: string;\n links: SimpleSlug[];\n toc: { depth: number; text: string; slug: string }[];\n collapseToc: boolean;\n blocks: Record<string, import(\"hast\").Element>;\n htmlAst: import(\"hast\").Root;\n hasMermaidDiagram: boolean | undefined;\n frontmatter: { [key: string]: unknown } & {\n title: string;\n } & Partial<{\n tags: string[];\n aliases: string[];\n modified: string;\n created: string;\n published: string;\n description: string;\n socialDescription: string;\n publish: boolean | string;\n draft: boolean | string;\n lang: string;\n enableToc: string;\n cssclasses: string[];\n socialImage: string;\n comments: boolean | string;\n }>;\n dates: {\n created: Date;\n modified: Date;\n published: Date;\n };\n defaultDateType?: ValidDateType;\n }\n}\n"],"mappings":";AAaO,SAAS,gBAAgB,UAA8B;AAC5D,SAAO,SACJ,OAAO,CAAC,YAAY,QAAQ,SAAS,CAAC,EACtC,KAAK,GAAG,EACR,QAAQ,QAAQ,GAAG;AACxB;","names":[]}
|
package/globals.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ContentIndex, FullSlug } from "./dist/index.js";
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface CustomEventMap {
|
|
5
|
+
nav: CustomEvent<{ url: FullSlug }>;
|
|
6
|
+
prenav: CustomEvent<undefined>;
|
|
7
|
+
themechange: CustomEvent<{ theme: "light" | "dark" }>;
|
|
8
|
+
readermodechange: CustomEvent<{ mode: "on" | "off" }>;
|
|
9
|
+
render: CustomEvent<object>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Document {
|
|
13
|
+
addEventListener<K extends keyof CustomEventMap>(
|
|
14
|
+
type: K,
|
|
15
|
+
listener: (this: Document, ev: CustomEventMap[K]) => void,
|
|
16
|
+
): void;
|
|
17
|
+
removeEventListener<K extends keyof CustomEventMap>(
|
|
18
|
+
type: K,
|
|
19
|
+
listener: (this: Document, ev: CustomEventMap[K]) => void,
|
|
20
|
+
): void;
|
|
21
|
+
dispatchEvent<K extends keyof CustomEventMap>(
|
|
22
|
+
ev: CustomEventMap[K] | UIEvent,
|
|
23
|
+
): void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Window {
|
|
27
|
+
addCleanup(fn: (...args: unknown[]) => void): void;
|
|
28
|
+
spaNavigate?(url: URL, isBack: boolean): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const fetchData: Promise<ContentIndex>;
|
|
32
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quartz-community/types",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Type definitions for Quartz community plugins",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Quartz Community",
|
|
8
|
+
"homepage": "https://quartz.jzhao.xyz",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/quartz-community/types"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"quartz",
|
|
15
|
+
"quartz-plugin",
|
|
16
|
+
"types",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
19
|
+
"files": [
|
|
20
|
+
"src",
|
|
21
|
+
"dist",
|
|
22
|
+
"globals.d.ts",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./globals": {
|
|
32
|
+
"types": "./globals.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
|
+
"typecheck": "tsc --noEmit",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"unified": "^11.0.5",
|
|
47
|
+
"vfile": "^6.0.3"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22",
|
|
51
|
+
"npm": ">=10.9.2"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/hast": "^3.0.4",
|
|
55
|
+
"@types/mdast": "^4.0.4",
|
|
56
|
+
"tsup": "^8.5.0",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"unified": "^11.0.5",
|
|
61
|
+
"vfile": "^6.0.3"
|
|
62
|
+
},
|
|
63
|
+
"peerDependenciesMeta": {
|
|
64
|
+
"unified": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"vfile": {
|
|
68
|
+
"optional": true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"publishConfig": {
|
|
72
|
+
"access": "public"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import type { Root as HtmlRoot } from "hast";
|
|
2
|
+
import type { Root as MdRoot } from "mdast";
|
|
3
|
+
import type { Data, VFile } from "vfile";
|
|
4
|
+
import type { PluggableList } from "unified";
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Path Types - Branded string types for type-safe file paths
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
export type FilePath = string & { _brand: "FilePath" };
|
|
11
|
+
export type FullSlug = string & { _brand: "FullSlug" };
|
|
12
|
+
export type SimpleSlug = string & { _brand: "SimpleSlug" };
|
|
13
|
+
|
|
14
|
+
export function joinSegments(...segments: string[]): FilePath {
|
|
15
|
+
return segments
|
|
16
|
+
.filter((segment) => segment.length > 0)
|
|
17
|
+
.join("/")
|
|
18
|
+
.replace(/\/+/g, "/") as FilePath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Resource Types - CSS/JS resources that plugins can inject
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
export type JSResource =
|
|
26
|
+
| {
|
|
27
|
+
loadTime: "beforeDOMReady" | "afterDOMReady";
|
|
28
|
+
moduleType?: "module";
|
|
29
|
+
spaPreserve?: boolean;
|
|
30
|
+
src: string;
|
|
31
|
+
contentType: "external";
|
|
32
|
+
}
|
|
33
|
+
| {
|
|
34
|
+
loadTime: "beforeDOMReady" | "afterDOMReady";
|
|
35
|
+
moduleType?: "module";
|
|
36
|
+
spaPreserve?: boolean;
|
|
37
|
+
script: string;
|
|
38
|
+
contentType: "inline";
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type CSSResource = {
|
|
42
|
+
content: string;
|
|
43
|
+
inline?: boolean;
|
|
44
|
+
spaPreserve?: boolean;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export interface StaticResources {
|
|
48
|
+
css: CSSResource[];
|
|
49
|
+
js: JSResource[];
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
additionalHead: any[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Config Types - Quartz configuration
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Flat configuration object that components receive as `cfg` prop.
|
|
60
|
+
* This matches Quartz's `GlobalConfiguration` — the resolved config
|
|
61
|
+
* passed to components at render time (i.e. `ctx.cfg.configuration`).
|
|
62
|
+
*/
|
|
63
|
+
export interface GlobalConfiguration {
|
|
64
|
+
pageTitle?: string;
|
|
65
|
+
pageTitleSuffix?: string;
|
|
66
|
+
enableSPA?: boolean;
|
|
67
|
+
enablePopovers?: boolean;
|
|
68
|
+
analytics?: unknown;
|
|
69
|
+
ignorePatterns?: string[];
|
|
70
|
+
defaultDateType?: string;
|
|
71
|
+
baseUrl?: string;
|
|
72
|
+
theme?: unknown;
|
|
73
|
+
locale?: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Full Quartz config with nested `configuration` property.
|
|
78
|
+
* This is what `BuildCtx.cfg` holds — used in plugin hooks
|
|
79
|
+
* (transformers, filters, emitters), NOT in component props.
|
|
80
|
+
*/
|
|
81
|
+
export interface QuartzConfig {
|
|
82
|
+
configuration: GlobalConfiguration;
|
|
83
|
+
plugins?: unknown;
|
|
84
|
+
externalPlugins?: unknown;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ============================================================================
|
|
88
|
+
// Context Types - Build context passed to plugin hooks
|
|
89
|
+
// ============================================================================
|
|
90
|
+
|
|
91
|
+
export interface Argv {
|
|
92
|
+
directory: string;
|
|
93
|
+
verbose: boolean;
|
|
94
|
+
output: string;
|
|
95
|
+
serve: boolean;
|
|
96
|
+
watch: boolean;
|
|
97
|
+
port: number;
|
|
98
|
+
wsPort: number;
|
|
99
|
+
remoteDevHost?: string;
|
|
100
|
+
concurrency?: number;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface BuildCtx {
|
|
104
|
+
buildId: string;
|
|
105
|
+
argv: Argv;
|
|
106
|
+
cfg: QuartzConfig;
|
|
107
|
+
allSlugs: FullSlug[];
|
|
108
|
+
allFiles: FilePath[];
|
|
109
|
+
incremental: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// VFile Types - Content data types
|
|
114
|
+
// ============================================================================
|
|
115
|
+
|
|
116
|
+
export type QuartzPluginData = Data;
|
|
117
|
+
export type MarkdownContent = [MdRoot, VFile];
|
|
118
|
+
export type ProcessedContent = [HtmlRoot, VFile];
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Core Component Types - The contract between Quartz and plugins
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
export type QuartzComponentProps = {
|
|
125
|
+
ctx: unknown;
|
|
126
|
+
externalResources: StaticResources;
|
|
127
|
+
fileData: QuartzPluginData & Record<string, unknown>;
|
|
128
|
+
cfg: GlobalConfiguration;
|
|
129
|
+
children: unknown;
|
|
130
|
+
tree: unknown;
|
|
131
|
+
allFiles: (QuartzPluginData & Record<string, unknown>)[];
|
|
132
|
+
displayClass?: "mobile-only" | "desktop-only";
|
|
133
|
+
[key: string]: unknown;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type QuartzComponent = ((props: QuartzComponentProps) => unknown) & {
|
|
137
|
+
css?: string | string[] | undefined;
|
|
138
|
+
beforeDOMLoaded?: string | string[] | undefined;
|
|
139
|
+
afterDOMLoaded?: string | string[] | undefined;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export type QuartzComponentConstructor<
|
|
143
|
+
Options extends object | undefined = undefined,
|
|
144
|
+
> = (opts?: Options) => QuartzComponent;
|
|
145
|
+
|
|
146
|
+
export type StringResource = string | string[];
|
|
147
|
+
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// Plugin Types - What Quartz expects from plugins
|
|
150
|
+
// ============================================================================
|
|
151
|
+
|
|
152
|
+
type OptionType = object | undefined;
|
|
153
|
+
type ExternalResourcesFn = (
|
|
154
|
+
ctx: BuildCtx,
|
|
155
|
+
) => Partial<StaticResources> | undefined;
|
|
156
|
+
|
|
157
|
+
export type { ExternalResourcesFn };
|
|
158
|
+
|
|
159
|
+
export interface PluginTypes {
|
|
160
|
+
transformers: QuartzTransformerPluginInstance[];
|
|
161
|
+
filters: QuartzFilterPluginInstance[];
|
|
162
|
+
emitters: QuartzEmitterPluginInstance[];
|
|
163
|
+
pageTypes: QuartzPageTypePluginInstance[];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type QuartzTransformerPlugin<Options extends OptionType = undefined> = (
|
|
167
|
+
opts?: Options,
|
|
168
|
+
) => QuartzTransformerPluginInstance;
|
|
169
|
+
|
|
170
|
+
export type QuartzTransformerPluginInstance = {
|
|
171
|
+
name: string;
|
|
172
|
+
textTransform?: (ctx: BuildCtx, src: string) => string;
|
|
173
|
+
markdownPlugins?: (ctx: BuildCtx) => PluggableList;
|
|
174
|
+
htmlPlugins?: (ctx: BuildCtx) => PluggableList;
|
|
175
|
+
externalResources?: ExternalResourcesFn;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
export type QuartzFilterPlugin<Options extends OptionType = undefined> = (
|
|
179
|
+
opts?: Options,
|
|
180
|
+
) => QuartzFilterPluginInstance;
|
|
181
|
+
|
|
182
|
+
export type QuartzFilterPluginInstance = {
|
|
183
|
+
name: string;
|
|
184
|
+
shouldPublish(ctx: BuildCtx, content: ProcessedContent): boolean;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export type ChangeEvent = {
|
|
188
|
+
type: "add" | "change" | "delete";
|
|
189
|
+
path: FilePath;
|
|
190
|
+
file?: VFile;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export type QuartzEmitterPlugin<Options extends OptionType = undefined> = (
|
|
194
|
+
opts?: Options,
|
|
195
|
+
) => QuartzEmitterPluginInstance;
|
|
196
|
+
|
|
197
|
+
export type QuartzEmitterPluginInstance = {
|
|
198
|
+
name: string;
|
|
199
|
+
emit: (
|
|
200
|
+
ctx: BuildCtx,
|
|
201
|
+
content: ProcessedContent[],
|
|
202
|
+
resources: StaticResources,
|
|
203
|
+
) => Promise<FilePath[]> | AsyncGenerator<FilePath>;
|
|
204
|
+
partialEmit?: (
|
|
205
|
+
ctx: BuildCtx,
|
|
206
|
+
content: ProcessedContent[],
|
|
207
|
+
resources: StaticResources,
|
|
208
|
+
changeEvents: ChangeEvent[],
|
|
209
|
+
) => Promise<FilePath[]> | AsyncGenerator<FilePath> | null;
|
|
210
|
+
getQuartzComponents?: (ctx: BuildCtx) => QuartzComponent[];
|
|
211
|
+
externalResources?: ExternalResourcesFn;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// PageType Plugin Types - Declarative page rendering plugins
|
|
216
|
+
// ============================================================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Matcher function: determines if a source file belongs to a page type.
|
|
220
|
+
* Returns true if the page type should own this file.
|
|
221
|
+
*/
|
|
222
|
+
export type PageMatcher = (args: {
|
|
223
|
+
slug: FullSlug;
|
|
224
|
+
fileData: QuartzPluginData & Record<string, unknown>;
|
|
225
|
+
cfg: GlobalConfiguration;
|
|
226
|
+
}) => boolean;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Virtual page descriptor for page types that generate pages
|
|
230
|
+
* from aggregated data (e.g., tag indexes, folder listings).
|
|
231
|
+
*/
|
|
232
|
+
export interface VirtualPage {
|
|
233
|
+
slug: FullSlug;
|
|
234
|
+
title: string;
|
|
235
|
+
data: Partial<QuartzPluginData> & Record<string, unknown>;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Generator function: produces virtual pages from all processed content.
|
|
240
|
+
* Used by page types that don't match source files but instead create
|
|
241
|
+
* synthetic pages (e.g., one page per tag, one page per folder).
|
|
242
|
+
*/
|
|
243
|
+
export type PageGenerator = (args: {
|
|
244
|
+
content: ProcessedContent[];
|
|
245
|
+
cfg: GlobalConfiguration;
|
|
246
|
+
ctx: BuildCtx;
|
|
247
|
+
}) => VirtualPage[];
|
|
248
|
+
|
|
249
|
+
/** A function that mutates a HAST tree at render time, when allFiles is available. */
|
|
250
|
+
export type TreeTransform = (
|
|
251
|
+
root: HtmlRoot,
|
|
252
|
+
slug: FullSlug,
|
|
253
|
+
componentData: QuartzComponentProps,
|
|
254
|
+
) => void;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* A PageType plugin definition.
|
|
258
|
+
*
|
|
259
|
+
* PageTypes are a declarative abstraction over page-rendering emitters.
|
|
260
|
+
* Each PageType declares which files it owns (via `match`), optionally
|
|
261
|
+
* generates virtual pages (via `generate`), and provides a body component
|
|
262
|
+
* and layout reference for rendering.
|
|
263
|
+
*/
|
|
264
|
+
export type QuartzPageTypePlugin<Options extends OptionType = undefined> = (
|
|
265
|
+
opts?: Options,
|
|
266
|
+
) => QuartzPageTypePluginInstance;
|
|
267
|
+
|
|
268
|
+
export type QuartzPageTypePluginInstance = {
|
|
269
|
+
name: string;
|
|
270
|
+
/** Higher priority wins when multiple page types match the same file. Default: 0. */
|
|
271
|
+
priority?: number;
|
|
272
|
+
/** File extensions this page type handles (e.g. [".canvas"]). Files with these extensions are excluded from the default asset emitter and processed by generate() instead. */
|
|
273
|
+
fileExtensions?: string[];
|
|
274
|
+
/** Determines which source files this page type owns. */
|
|
275
|
+
match: PageMatcher;
|
|
276
|
+
/** Produces virtual pages from aggregated content data. */
|
|
277
|
+
generate?: PageGenerator;
|
|
278
|
+
/** Layout key — references a key in `layout.byPageType`. */
|
|
279
|
+
layout: string;
|
|
280
|
+
/** Optional page frame name (e.g. "default", "full-width", "canvas"). Defaults to "default". */
|
|
281
|
+
frame?: string;
|
|
282
|
+
/** The body component constructor for this page type. */
|
|
283
|
+
body: QuartzComponentConstructor;
|
|
284
|
+
/** Optional render-time HAST tree transforms (e.g. resolving inline codeblocks). */
|
|
285
|
+
treeTransforms?: (ctx: BuildCtx) => TreeTransform[];
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// ============================================================================
|
|
289
|
+
// PageFrame Types — Custom page layout frames
|
|
290
|
+
// ============================================================================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Props passed to a PageFrame's render function.
|
|
294
|
+
* Contains the resolved layout components and the shared component data.
|
|
295
|
+
*/
|
|
296
|
+
export interface PageFrameProps {
|
|
297
|
+
/** Component data shared across all components on the page */
|
|
298
|
+
componentData: QuartzComponentProps;
|
|
299
|
+
/** The Head component (rendered in <head>) — NOT used by frames, included for completeness */
|
|
300
|
+
head: QuartzComponent;
|
|
301
|
+
/** Header slot components (rendered inside <header>) */
|
|
302
|
+
header: QuartzComponent[];
|
|
303
|
+
/** Components rendered before the page body */
|
|
304
|
+
beforeBody: QuartzComponent[];
|
|
305
|
+
/** The page body component (Content) */
|
|
306
|
+
pageBody: QuartzComponent;
|
|
307
|
+
/** Components rendered after the page body */
|
|
308
|
+
afterBody: QuartzComponent[];
|
|
309
|
+
/** Left sidebar components */
|
|
310
|
+
left: QuartzComponent[];
|
|
311
|
+
/** Right sidebar components */
|
|
312
|
+
right: QuartzComponent[];
|
|
313
|
+
/** Footer component */
|
|
314
|
+
footer: QuartzComponent;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* A PageFrame defines the inner HTML structure of a page inside the
|
|
319
|
+
* `<div id="quartz-root">` shell. Different frames can produce completely
|
|
320
|
+
* different layouts (e.g. with/without sidebars, horizontal scroll, etc.)
|
|
321
|
+
* while the outer shell (html, head, body, quartz-root) remains stable
|
|
322
|
+
* for SPA navigation.
|
|
323
|
+
*
|
|
324
|
+
* The `render` function returns `unknown` to avoid coupling to a specific
|
|
325
|
+
* JSX runtime (Preact, React, etc.). Quartz core casts this to JSX.Element.
|
|
326
|
+
*/
|
|
327
|
+
export interface PageFrame {
|
|
328
|
+
/** Unique name for this frame (e.g. "default", "full-width", "canvas") */
|
|
329
|
+
name: string;
|
|
330
|
+
/** Render the inner page structure. Returns a JSX tree to be placed inside Body > #quartz-body. */
|
|
331
|
+
render: (props: PageFrameProps) => unknown;
|
|
332
|
+
/** Optional CSS string to include when this frame is active */
|
|
333
|
+
css?: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export type HTMLAttributes = Record<
|
|
337
|
+
string,
|
|
338
|
+
string | number | boolean | undefined
|
|
339
|
+
>;
|
|
340
|
+
|
|
341
|
+
export type EventHandler = (event: Event) => void;
|
|
342
|
+
|
|
343
|
+
export type CleanupFunction = () => void;
|
|
344
|
+
|
|
345
|
+
export type ClassValue =
|
|
346
|
+
| string
|
|
347
|
+
| number
|
|
348
|
+
| boolean
|
|
349
|
+
| undefined
|
|
350
|
+
| null
|
|
351
|
+
| ClassValue[];
|
|
352
|
+
|
|
353
|
+
// ============================================================================
|
|
354
|
+
// Content Index Types - Data shape for contentIndex.json
|
|
355
|
+
// ============================================================================
|
|
356
|
+
|
|
357
|
+
export type ContentDetails = {
|
|
358
|
+
slug: FullSlug;
|
|
359
|
+
filePath: FilePath;
|
|
360
|
+
title: string;
|
|
361
|
+
links: string[];
|
|
362
|
+
tags: string[];
|
|
363
|
+
content: string;
|
|
364
|
+
richContent?: string;
|
|
365
|
+
date?: Date;
|
|
366
|
+
description?: string;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export type ContentIndex = Record<FullSlug, ContentDetails>;
|
|
370
|
+
|
|
371
|
+
// ============================================================================
|
|
372
|
+
// Sort & Theme Types
|
|
373
|
+
// ============================================================================
|
|
374
|
+
|
|
375
|
+
export type SortFn = (f1: QuartzPluginData, f2: QuartzPluginData) => number;
|
|
376
|
+
|
|
377
|
+
export type ThemeKey = "lightMode" | "darkMode";
|
|
378
|
+
|
|
379
|
+
export type ValidDateType = "created" | "modified" | "published";
|
|
380
|
+
|
|
381
|
+
// ============================================================================
|
|
382
|
+
// VFile DataMap Augmentation — canonical vfile shape for Quartz
|
|
383
|
+
// ============================================================================
|
|
384
|
+
|
|
385
|
+
declare module "vfile" {
|
|
386
|
+
interface DataMap {
|
|
387
|
+
slug: FullSlug;
|
|
388
|
+
filePath: FilePath;
|
|
389
|
+
relativePath: FilePath;
|
|
390
|
+
description: string;
|
|
391
|
+
text: string;
|
|
392
|
+
links: SimpleSlug[];
|
|
393
|
+
toc: { depth: number; text: string; slug: string }[];
|
|
394
|
+
collapseToc: boolean;
|
|
395
|
+
blocks: Record<string, import("hast").Element>;
|
|
396
|
+
htmlAst: import("hast").Root;
|
|
397
|
+
hasMermaidDiagram: boolean | undefined;
|
|
398
|
+
frontmatter: { [key: string]: unknown } & {
|
|
399
|
+
title: string;
|
|
400
|
+
} & Partial<{
|
|
401
|
+
tags: string[];
|
|
402
|
+
aliases: string[];
|
|
403
|
+
modified: string;
|
|
404
|
+
created: string;
|
|
405
|
+
published: string;
|
|
406
|
+
description: string;
|
|
407
|
+
socialDescription: string;
|
|
408
|
+
publish: boolean | string;
|
|
409
|
+
draft: boolean | string;
|
|
410
|
+
lang: string;
|
|
411
|
+
enableToc: string;
|
|
412
|
+
cssclasses: string[];
|
|
413
|
+
socialImage: string;
|
|
414
|
+
comments: boolean | string;
|
|
415
|
+
}>;
|
|
416
|
+
dates: {
|
|
417
|
+
created: Date;
|
|
418
|
+
modified: Date;
|
|
419
|
+
published: Date;
|
|
420
|
+
};
|
|
421
|
+
defaultDateType?: ValidDateType;
|
|
422
|
+
}
|
|
423
|
+
}
|