@amamo/mdx 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -39
- package/dist/config.d.ts +9 -7
- package/dist/config.js +26 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/native.d.ts +4 -4
- package/package.json +19 -16
package/README.md
CHANGED
|
@@ -1,50 +1,75 @@
|
|
|
1
1
|
# @amamo/mdx
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
highlighted HAST back into the same compile pipeline.
|
|
3
|
+
Build MDX collections for Vite 8, Next 16, or a custom Node.js build. Define each collection with
|
|
4
|
+
the package's `z` schema builder, then import MDX as application modules or consume the generated
|
|
5
|
+
collection registry and JSON manifests.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
`@amamo/mdx` provides:
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
- frontmatter validation and defaults;
|
|
10
|
+
- JavaScript modules for a configurable JSX runtime, with React as the default;
|
|
11
|
+
- fenced-code highlighting and Markdown media imports;
|
|
12
|
+
- collection metadata with companion TypeScript declarations;
|
|
13
|
+
- configurable JSON manifests and a persistent build cache.
|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Node.js 20.19 or newer.
|
|
18
|
+
- A [supported native target](https://jikkai.github.io/mdx/native-targets/). There is no JavaScript
|
|
19
|
+
or WASI fallback for MDX compilation.
|
|
20
|
+
- React 19 when using the default JSX runtime.
|
|
21
|
+
|
|
22
|
+
MDX can contain imports, expressions, and JSX. Compile content from authors who are allowed to add
|
|
23
|
+
application code.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
17
26
|
|
|
18
27
|
```sh
|
|
19
28
|
pnpm add @amamo/mdx
|
|
20
29
|
```
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
The package manager installs the platform package for the current operating system and CPU. Install
|
|
32
|
+
dependencies again after moving the project to a different platform instead of copying
|
|
33
|
+
`node_modules`.
|
|
34
|
+
|
|
35
|
+
## Define a collection
|
|
24
36
|
|
|
25
|
-
Create
|
|
37
|
+
Create `amamo.config.mjs`:
|
|
26
38
|
|
|
27
39
|
```js
|
|
28
|
-
|
|
29
|
-
import { defineConfig } from '@amamo/mdx'
|
|
40
|
+
import { defineConfig, z } from '@amamo/mdx'
|
|
30
41
|
|
|
31
42
|
export default defineConfig({
|
|
32
43
|
root: import.meta.dirname,
|
|
33
44
|
collections: {
|
|
34
45
|
posts: {
|
|
35
46
|
directory: 'content/posts',
|
|
36
|
-
schema: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
required: ['title'],
|
|
41
|
-
},
|
|
47
|
+
schema: z.object({
|
|
48
|
+
title: z.string(),
|
|
49
|
+
publishedAt: z.string().optional(),
|
|
50
|
+
}),
|
|
42
51
|
},
|
|
43
52
|
},
|
|
44
53
|
})
|
|
45
54
|
```
|
|
46
55
|
|
|
47
|
-
Then
|
|
56
|
+
Then add `content/posts/hello.mdx`:
|
|
57
|
+
|
|
58
|
+
```mdx
|
|
59
|
+
---
|
|
60
|
+
title: Hello
|
|
61
|
+
publishedAt: 2026-08-15
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
# Hello
|
|
65
|
+
|
|
66
|
+
This document is compiled by @amamo/mdx.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The collection directory must exist before the first full build. Relative collection, cache,
|
|
70
|
+
generated, and manifest paths are resolved from `root`.
|
|
71
|
+
|
|
72
|
+
## Choose an integration
|
|
48
73
|
|
|
49
74
|
### Vite
|
|
50
75
|
|
|
@@ -55,7 +80,9 @@ import { defineConfig } from 'vite'
|
|
|
55
80
|
|
|
56
81
|
import amamo from './amamo.config.mjs'
|
|
57
82
|
|
|
58
|
-
export default defineConfig({
|
|
83
|
+
export default defineConfig({
|
|
84
|
+
plugins: [amamoMdx(amamo)],
|
|
85
|
+
})
|
|
59
86
|
```
|
|
60
87
|
|
|
61
88
|
### Next
|
|
@@ -66,17 +93,21 @@ import { withAmamoMdx } from '@amamo/mdx/next'
|
|
|
66
93
|
|
|
67
94
|
import amamo from './amamo.config.mjs'
|
|
68
95
|
|
|
69
|
-
export default withAmamoMdx(amamo)({
|
|
96
|
+
export default withAmamoMdx(amamo)({
|
|
97
|
+
reactStrictMode: true,
|
|
98
|
+
})
|
|
70
99
|
```
|
|
71
100
|
|
|
72
101
|
### Direct compiler API
|
|
73
102
|
|
|
74
|
-
```
|
|
103
|
+
```js
|
|
104
|
+
// build-content.mjs
|
|
75
105
|
import { createCompiler } from '@amamo/mdx'
|
|
76
106
|
|
|
77
107
|
import amamo from './amamo.config.mjs'
|
|
78
108
|
|
|
79
109
|
const compiler = await createCompiler(amamo)
|
|
110
|
+
|
|
80
111
|
try {
|
|
81
112
|
const result = await compiler.build()
|
|
82
113
|
console.log(result)
|
|
@@ -85,25 +116,57 @@ try {
|
|
|
85
116
|
}
|
|
86
117
|
```
|
|
87
118
|
|
|
88
|
-
|
|
89
|
-
`.amamo-mdx`):
|
|
119
|
+
Run the script with `node build-content.mjs`.
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
- `collections.d.ts` — a companion declaration output for the collection registry.
|
|
93
|
-
- `index.json` — the private index used by the Next loader.
|
|
121
|
+
## Use compiled content
|
|
94
122
|
|
|
95
|
-
|
|
123
|
+
With the Vite plugin or Next wrapper configured, import an MDX file like an application module:
|
|
96
124
|
|
|
97
|
-
|
|
125
|
+
```tsx
|
|
126
|
+
import Post, { frontmatter } from './content/posts/hello.mdx'
|
|
98
127
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
128
|
+
export function Page() {
|
|
129
|
+
return (
|
|
130
|
+
<main>
|
|
131
|
+
<h1>{frontmatter.title}</h1>
|
|
132
|
+
<Post />
|
|
133
|
+
</main>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
103
137
|
|
|
104
|
-
|
|
138
|
+
Or load a document from the generated registry:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { collections } from './.amamo-mdx/collections.mjs'
|
|
142
|
+
|
|
143
|
+
const hello = collections.posts.find((document) => document.slug === 'hello')
|
|
144
|
+
const module = await hello?.load()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Registry `load()` functions import the source MDX file, so they must run through the configured Vite
|
|
148
|
+
plugin or Next loader.
|
|
105
149
|
|
|
106
|
-
|
|
150
|
+
## Generated files
|
|
151
|
+
|
|
152
|
+
The first build writes these files under `generatedDirectory`, which defaults to `.amamo-mdx`:
|
|
153
|
+
|
|
154
|
+
- `collections.mjs` — sorted collection metadata and lazy source imports;
|
|
155
|
+
- `collections.d.ts` — TypeScript declarations for the registry;
|
|
156
|
+
- `index.json` — the source-to-cache index used by the Next loader.
|
|
157
|
+
|
|
158
|
+
Cache and manifest paths are configured separately from `generatedDirectory`. Add `.amamo-mdx/` to
|
|
159
|
+
the host repository's ignore file unless the application deliberately tracks generated output.
|
|
160
|
+
|
|
161
|
+
## Package entry points
|
|
162
|
+
|
|
163
|
+
| Import | Use it for |
|
|
164
|
+
| ----------------- | ------------------------------------------ |
|
|
165
|
+
| `@amamo/mdx` | Configuration and the direct compiler API. |
|
|
166
|
+
| `@amamo/mdx/vite` | Vite 8 development and production builds. |
|
|
167
|
+
| `@amamo/mdx/next` | Next 16 development and production builds. |
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
107
170
|
|
|
108
171
|
- [Getting started](https://jikkai.github.io/mdx/getting-started/)
|
|
109
172
|
- [Configuration reference](https://jikkai.github.io/mdx/configuration/)
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
export { z };
|
|
1
3
|
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
2
4
|
[key: string]: JsonValue;
|
|
3
5
|
};
|
|
@@ -13,14 +15,15 @@ export interface ILocaleConfig {
|
|
|
13
15
|
export interface ISlugConfig {
|
|
14
16
|
indexNames?: string[];
|
|
15
17
|
}
|
|
18
|
+
export interface IFrontmatterSchema {
|
|
19
|
+
readonly shape: Readonly<Record<string, unknown>>;
|
|
20
|
+
toJSONSchema(): unknown;
|
|
21
|
+
}
|
|
16
22
|
export interface ICollectionConfig {
|
|
17
23
|
directory: string;
|
|
18
24
|
extensions?: string[];
|
|
19
25
|
locales?: ILocaleConfig;
|
|
20
|
-
schema:
|
|
21
|
-
[key: string]: JsonValue;
|
|
22
|
-
};
|
|
23
|
-
sensitive?: string[];
|
|
26
|
+
schema: IFrontmatterSchema;
|
|
24
27
|
slug?: ISlugConfig;
|
|
25
28
|
}
|
|
26
29
|
export interface IMathConfig {
|
|
@@ -90,7 +93,6 @@ export interface INormalizedCollectionConfig {
|
|
|
90
93
|
schema: {
|
|
91
94
|
[key: string]: JsonValue;
|
|
92
95
|
};
|
|
93
|
-
sensitive: string[];
|
|
94
96
|
slug: {
|
|
95
97
|
indexNames: string[];
|
|
96
98
|
};
|
|
@@ -116,7 +118,7 @@ export interface INormalizedManifestConfig extends Omit<IManifestConfig, 'collec
|
|
|
116
118
|
collections: string[];
|
|
117
119
|
output: string;
|
|
118
120
|
}
|
|
119
|
-
export interface
|
|
121
|
+
export interface IAmamoMDXConfig {
|
|
120
122
|
cache: {
|
|
121
123
|
directory: string;
|
|
122
124
|
enabled: boolean;
|
|
@@ -142,4 +144,4 @@ export interface INormalizedConfig {
|
|
|
142
144
|
root: string;
|
|
143
145
|
}
|
|
144
146
|
export declare function defineConfig<T extends IAmamoMdxConfig>(config: T): T;
|
|
145
|
-
export declare function normalizeConfig(config: IAmamoMdxConfig):
|
|
147
|
+
export declare function normalizeConfig(config: IAmamoMdxConfig): IAmamoMDXConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
import { existsSync, realpathSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import * as z from 'zod';
|
|
5
|
+
export { z };
|
|
4
6
|
const DEFAULT_MEDIA_ATTRIBUTES = {
|
|
5
7
|
audio: ['src'],
|
|
6
8
|
embed: ['src'],
|
|
@@ -16,7 +18,9 @@ const MAX_MATH_MACROS_BYTES = 16 * 1024;
|
|
|
16
18
|
function notSerializable(location, reason) {
|
|
17
19
|
throw new TypeError(`AMAMO_CONFIG_NOT_SERIALIZABLE: ${location} ${reason}`);
|
|
18
20
|
}
|
|
19
|
-
function assertPlainData(value, location, active) {
|
|
21
|
+
function assertPlainData(value, location, active, segments = []) {
|
|
22
|
+
if (segments.length === 3 && segments[0] === 'collections' && segments[2] === 'schema')
|
|
23
|
+
return;
|
|
20
24
|
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
21
25
|
return;
|
|
22
26
|
if (typeof value === 'number') {
|
|
@@ -39,7 +43,7 @@ function assertPlainData(value, location, active) {
|
|
|
39
43
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
40
44
|
if (!descriptor || !('value' in descriptor))
|
|
41
45
|
notSerializable(`${location}.${key}`, 'contains an accessor');
|
|
42
|
-
assertPlainData(descriptor.value, `${location}.${key}`, active);
|
|
46
|
+
assertPlainData(descriptor.value, `${location}.${key}`, active, [...segments, key]);
|
|
43
47
|
}
|
|
44
48
|
active.delete(value);
|
|
45
49
|
}
|
|
@@ -57,14 +61,32 @@ function normalizeCollection(root, name, config) {
|
|
|
57
61
|
throw new TypeError(`AMAMO_CONFIG_INVALID: collections.${name}.locales.default must be listed in names`);
|
|
58
62
|
}
|
|
59
63
|
const directory = path.resolve(root, requireNonEmpty(config.directory, `collections.${name}.directory`));
|
|
64
|
+
if (typeof config.schema?.shape !== 'object' ||
|
|
65
|
+
config.schema.shape === null ||
|
|
66
|
+
typeof config.schema.toJSONSchema !== 'function') {
|
|
67
|
+
throw new TypeError(`AMAMO_CONFIG_INVALID: collections.${name}.schema must be a compatible object schema`);
|
|
68
|
+
}
|
|
69
|
+
let schema;
|
|
70
|
+
try {
|
|
71
|
+
schema = JSON.parse(JSON.stringify(config.schema.toJSONSchema()));
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const reason = error instanceof Error ? error.message : 'could not be converted to JSON Schema';
|
|
75
|
+
throw new TypeError(`AMAMO_CONFIG_INVALID: collections.${name}.schema ${reason}`, {
|
|
76
|
+
cause: error,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (schema.type !== 'object') {
|
|
80
|
+
throw new TypeError(`AMAMO_CONFIG_INVALID: collections.${name}.schema must convert to an object schema`);
|
|
81
|
+
}
|
|
82
|
+
assertPlainData(schema, `collections.${name}.schema`, new WeakSet());
|
|
60
83
|
return {
|
|
61
84
|
directory: existsSync(directory) ? realpathSync.native(directory) : directory,
|
|
62
85
|
extensions: [...extensions],
|
|
63
86
|
locales: config.locales
|
|
64
87
|
? { default: config.locales.default, names: [...config.locales.names] }
|
|
65
88
|
: undefined,
|
|
66
|
-
schema
|
|
67
|
-
sensitive: [...(config.sensitive ?? [])],
|
|
89
|
+
schema,
|
|
68
90
|
slug: { indexNames: [...(config.slug?.indexNames ?? ['index', 'page'])] },
|
|
69
91
|
};
|
|
70
92
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export type { IAmamoMdxConfig, ICacheConfig, ICollectionConfig, IDerivedConfig, IHighlightConfig, ILocaleConfig, IManifestConfig, IMathConfig, IMdxConfig, IMdxExtensionsConfig, IMediaConfig,
|
|
2
|
-
export { defineConfig, normalizeConfig } from './config.js';
|
|
1
|
+
export type { IAmamoMDXConfig, IAmamoMdxConfig, ICacheConfig, ICollectionConfig, IDerivedConfig, IFrontmatterSchema, IHighlightConfig, ILocaleConfig, IManifestConfig, IMathConfig, IMdxConfig, IMdxExtensionsConfig, IMediaConfig, JsonValue, ManifestField, } from './config.js';
|
|
2
|
+
export { defineConfig, normalizeConfig, z } from './config.js';
|
|
3
3
|
export type { IBuildResult, ICompiler, ITransformResult } from './compiler.js';
|
|
4
4
|
export { createCompiler } from './compiler.js';
|
|
5
5
|
export type { IDiagnostic } from './native.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { defineConfig, normalizeConfig } from './config.js';
|
|
1
|
+
export { defineConfig, normalizeConfig, z } from './config.js';
|
|
2
2
|
export { createCompiler } from './compiler.js';
|
package/dist/native.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IAmamoMDXConfig, JsonValue } from './config.js';
|
|
2
2
|
export interface ISourcePoint {
|
|
3
3
|
column: number;
|
|
4
4
|
line: number;
|
|
@@ -65,7 +65,7 @@ export declare class AmamoMdxError extends Error {
|
|
|
65
65
|
readonly diagnostics: IDiagnostic[];
|
|
66
66
|
constructor(diagnostics: IDiagnostic[]);
|
|
67
67
|
}
|
|
68
|
-
export declare function configurationFingerprint(config:
|
|
69
|
-
export declare function prepareNativeBatch(config:
|
|
68
|
+
export declare function configurationFingerprint(config: IAmamoMDXConfig): string;
|
|
69
|
+
export declare function prepareNativeBatch(config: IAmamoMDXConfig, inputs: INativeDocumentInput[]): IPreparedNativeBatch;
|
|
70
70
|
export declare function pruneNativeCache(cacheDirectory: string, keepKeys: string[]): number;
|
|
71
|
-
export declare function renderNativeManifests(config:
|
|
71
|
+
export declare function renderNativeManifests(config: IAmamoMDXConfig, records: IDocumentRecord[]): IRenderedManifest[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amamo/mdx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A native MDX content compiler with Vite and Next adapters",
|
|
5
5
|
"homepage": "https://jikkai.github.io/mdx/",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,24 +48,27 @@
|
|
|
48
48
|
"test": "pnpm run build && vitest run src/__tests__",
|
|
49
49
|
"test:rust": "cargo test",
|
|
50
50
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
51
|
-
"check": "pnpm run format:check && pnpm run lint &&
|
|
51
|
+
"check": "pnpm run format:check && pnpm run lint && pnpm run check:rust && pnpm run check:npm && pnpm run check:docs",
|
|
52
52
|
"check:docs": "pnpm --filter @amamo/mdx-docs types:check && pnpm --filter @amamo/mdx-docs build",
|
|
53
|
+
"check:npm": "pnpm run typecheck && pnpm run test",
|
|
54
|
+
"check:rust": "cargo clippy --all-targets -- -D warnings && pnpm run test:rust",
|
|
53
55
|
"release": "verso"
|
|
54
56
|
},
|
|
55
57
|
"dependencies": {
|
|
56
|
-
"shiki": "4.4.
|
|
58
|
+
"shiki": "4.4.3",
|
|
59
|
+
"zod": "4.4.3"
|
|
57
60
|
},
|
|
58
61
|
"devDependencies": {
|
|
59
|
-
"@amamo/oxlint-config": "1.
|
|
60
|
-
"@amamo/verso": "1.0
|
|
61
|
-
"@napi-rs/cli": "3.8.
|
|
62
|
+
"@amamo/oxlint-config": "1.1.0",
|
|
63
|
+
"@amamo/verso": "1.1.0",
|
|
64
|
+
"@napi-rs/cli": "3.8.6",
|
|
62
65
|
"@types/node": "26.2.0",
|
|
63
66
|
"@types/react": "19.2.18",
|
|
64
67
|
"@types/react-dom": "19.2.4",
|
|
65
68
|
"lint-staged": "17.3.0",
|
|
66
|
-
"next": "16.3.
|
|
67
|
-
"oxfmt": "0.
|
|
68
|
-
"oxlint": "1.
|
|
69
|
+
"next": "16.3.1",
|
|
70
|
+
"oxfmt": "0.63.0",
|
|
71
|
+
"oxlint": "1.78.0",
|
|
69
72
|
"react": "19.2.8",
|
|
70
73
|
"react-dom": "19.2.8",
|
|
71
74
|
"simple-git-hooks": "2.13.1",
|
|
@@ -116,12 +119,12 @@
|
|
|
116
119
|
},
|
|
117
120
|
"packageManager": "pnpm@11.20.0",
|
|
118
121
|
"optionalDependencies": {
|
|
119
|
-
"@amamo/mdx-darwin-arm64": "0.
|
|
120
|
-
"@amamo/mdx-darwin-x64": "0.
|
|
121
|
-
"@amamo/mdx-linux-arm64-gnu": "0.
|
|
122
|
-
"@amamo/mdx-linux-x64-gnu": "0.
|
|
123
|
-
"@amamo/mdx-linux-arm64-musl": "0.
|
|
124
|
-
"@amamo/mdx-linux-x64-musl": "0.
|
|
125
|
-
"@amamo/mdx-win32-x64-msvc": "0.
|
|
122
|
+
"@amamo/mdx-darwin-arm64": "0.3.0",
|
|
123
|
+
"@amamo/mdx-darwin-x64": "0.3.0",
|
|
124
|
+
"@amamo/mdx-linux-arm64-gnu": "0.3.0",
|
|
125
|
+
"@amamo/mdx-linux-x64-gnu": "0.3.0",
|
|
126
|
+
"@amamo/mdx-linux-arm64-musl": "0.3.0",
|
|
127
|
+
"@amamo/mdx-linux-x64-musl": "0.3.0",
|
|
128
|
+
"@amamo/mdx-win32-x64-msvc": "0.3.0"
|
|
126
129
|
}
|
|
127
130
|
}
|