@vxrn/mdx-rust 1.20.3
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 +52 -0
- package/dist/client.mjs +11 -0
- package/dist/client.mjs.map +1 -0
- package/dist/getAllFrontmatter.mjs +26 -0
- package/dist/getAllFrontmatter.mjs.map +1 -0
- package/dist/getHeadings.mjs +12 -0
- package/dist/getHeadings.mjs.map +1 -0
- package/dist/getMDX.mjs +66 -0
- package/dist/getMDX.mjs.map +1 -0
- package/dist/getMDXBySlug.mjs +22 -0
- package/dist/getMDXBySlug.mjs.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/index.mjs.map +1 -0
- package/dist/processImageMeta.mjs +37 -0
- package/dist/processImageMeta.mjs.map +1 -0
- package/dist/slugPlugin.mjs +29 -0
- package/dist/slugPlugin.mjs.map +1 -0
- package/dist/tableWhitespacePlugin.mjs +19 -0
- package/dist/tableWhitespacePlugin.mjs.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/dist/watchFile.mjs +7 -0
- package/dist/watchFile.mjs.map +1 -0
- package/package.json +57 -0
- package/src/client.ts +20 -0
- package/src/getAllFrontmatter.ts +33 -0
- package/src/getHeadings.ts +18 -0
- package/src/getMDX.ts +90 -0
- package/src/getMDXBySlug.ts +34 -0
- package/src/index.ts +9 -0
- package/src/processImageMeta.ts +38 -0
- package/src/slugPlugin.ts +28 -0
- package/src/tableWhitespacePlugin.ts +23 -0
- package/src/types.ts +30 -0
- package/src/watchFile.ts +12 -0
- package/types/client.d.ts +13 -0
- package/types/client.d.ts.map +1 -0
- package/types/getAllFrontmatter.d.ts +3 -0
- package/types/getAllFrontmatter.d.ts.map +1 -0
- package/types/getHeadings.d.ts +3 -0
- package/types/getHeadings.d.ts.map +1 -0
- package/types/getMDX.d.ts +27 -0
- package/types/getMDX.d.ts.map +1 -0
- package/types/getMDXBySlug.d.ts +8 -0
- package/types/getMDXBySlug.d.ts.map +1 -0
- package/types/index.d.ts +10 -0
- package/types/index.d.ts.map +1 -0
- package/types/processImageMeta.d.ts +7 -0
- package/types/processImageMeta.d.ts.map +1 -0
- package/types/slugPlugin.d.ts +8 -0
- package/types/slugPlugin.d.ts.map +1 -0
- package/types/tableWhitespacePlugin.d.ts +8 -0
- package/types/tableWhitespacePlugin.d.ts.map +1 -0
- package/types/types.d.ts +38 -0
- package/types/types.d.ts.map +1 -0
- package/types/watchFile.d.ts +6 -0
- package/types/watchFile.d.ts.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @vxrn/mdx-rust
|
|
2
|
+
|
|
3
|
+
A small, fast MDX pipeline for One, built on [satteri](https://satteri.bruits.org)
|
|
4
|
+
(Markdown/MDX parsed and compiled in Rust) with syntax highlighting from
|
|
5
|
+
[Expressive Code](https://expressive-code.com) (Shiki).
|
|
6
|
+
|
|
7
|
+
It replaces the `mdx-bundler` + remark/rehype stack in `@vxrn/mdx` with far less
|
|
8
|
+
code and a much faster compile. GFM, SmartyPants, frontmatter, and `:::`
|
|
9
|
+
directives are built into the parser; heading slugs and code highlighting are the
|
|
10
|
+
only bundled plugins.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// server (build / loader)
|
|
16
|
+
import { getMDXBySlug } from '@vxrn/mdx-rust'
|
|
17
|
+
|
|
18
|
+
const { frontmatter, code } = await getMDXBySlug('data/docs', slug)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// client
|
|
23
|
+
import { getMDXComponent } from '@vxrn/mdx-rust/client'
|
|
24
|
+
|
|
25
|
+
const Component = useMemo(() => getMDXComponent(code), [code])
|
|
26
|
+
return <Component components={components} />
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
- `getMDX(source, options?)` → `{ frontmatter, code }`
|
|
32
|
+
- `getMDXBySlug(basePath, slug, options?)` → `{ frontmatter, code }`
|
|
33
|
+
- `getAllFrontmatter(fromPath)` → `Frontmatter[]`
|
|
34
|
+
- `getAllVersionsFromPath(fromPath)` → `string[]`
|
|
35
|
+
- `getHeadings(source)` → table-of-contents entries
|
|
36
|
+
- `getMDXComponent(code)` (from `@vxrn/mdx-rust/client`)
|
|
37
|
+
- `slugPlugin` — the bundled heading-id hast plugin, exported for reuse
|
|
38
|
+
|
|
39
|
+
### `GetMDXOptions`
|
|
40
|
+
|
|
41
|
+
- `expressiveCode` — Expressive Code options (themes, frames, styleOverrides,
|
|
42
|
+
plugins), or `false` to skip highlighting. Defaults to `{ themes: ['github-dark'] }`.
|
|
43
|
+
- `mdastPlugins` / `hastPlugins` — extra satteri plugins (e.g. a hero/demo
|
|
44
|
+
source injector). These use satteri's `defineMdastPlugin` / `defineHastPlugin`,
|
|
45
|
+
not remark/rehype.
|
|
46
|
+
- `publicDir` — for resolving `image:` frontmatter paths (default `./public`).
|
|
47
|
+
|
|
48
|
+
## Code fence meta
|
|
49
|
+
|
|
50
|
+
Highlighting, file titles, and line markers use Expressive Code's meta syntax:
|
|
51
|
+
|
|
52
|
+
```tsx title="app/routes/index.tsx" {2-4}
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as runtime from "react/jsx-runtime";
|
|
2
|
+
function getMDXComponent(code, globals = {}) {
|
|
3
|
+
const fn = new Function(String(code));
|
|
4
|
+
const mod = fn({
|
|
5
|
+
...runtime,
|
|
6
|
+
...globals
|
|
7
|
+
});
|
|
8
|
+
return mod.default;
|
|
9
|
+
}
|
|
10
|
+
export { getMDXComponent };
|
|
11
|
+
//# sourceMappingURL=client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["runtime","getMDXComponent","code","globals","fn","Function","String","mod","default"],"sources":["../src/client.ts"],"sourcesContent":[null],"mappings":"AAAA,YAAYA,OAAA,MAAa;AAWlB,SAASC,gBACdC,IAAA,EACAC,OAAA,GAAmC,CAAC,GACsB;EAE1D,MAAMC,EAAA,GAAK,IAAIC,QAAA,CAASC,MAAA,CAAOJ,IAAI,CAAC;EACpC,MAAMK,GAAA,GAAMH,EAAA,CAAG;IAAE,GAAGJ,OAAA;IAAS,GAAGG;EAAQ,CAAC;EACzC,OAAOI,GAAA,CAAIC,OAAA;AACb","ignoreList":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import glob from "fast-glob";
|
|
3
|
+
import matter from "gray-matter";
|
|
4
|
+
import readingTime from "reading-time";
|
|
5
|
+
import { getHeadings } from "./getHeadings.mjs";
|
|
6
|
+
import { notifyFileRead } from "./watchFile.mjs";
|
|
7
|
+
const getAllFrontmatter = fromPath => {
|
|
8
|
+
const paths = glob.sync(`${fromPath}/**/*.mdx`);
|
|
9
|
+
return paths.map(filePath => {
|
|
10
|
+
notifyFileRead(filePath);
|
|
11
|
+
const source = fs.readFileSync(filePath, "utf8");
|
|
12
|
+
const {
|
|
13
|
+
data,
|
|
14
|
+
content
|
|
15
|
+
} = matter(source);
|
|
16
|
+
const slug = filePath.replace(`${fromPath.replaceAll("\\", "/")}/`, "").replace(".mdx", "");
|
|
17
|
+
return {
|
|
18
|
+
...data,
|
|
19
|
+
slug,
|
|
20
|
+
headings: getHeadings(source),
|
|
21
|
+
readingTime: readingTime(content)
|
|
22
|
+
};
|
|
23
|
+
}).sort((a, b) => Number(new Date(b.publishedAt || "")) - Number(new Date(a.publishedAt || "")));
|
|
24
|
+
};
|
|
25
|
+
export { getAllFrontmatter };
|
|
26
|
+
//# sourceMappingURL=getAllFrontmatter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fs","glob","matter","readingTime","getHeadings","notifyFileRead","getAllFrontmatter","fromPath","paths","sync","map","filePath","source","readFileSync","data","content","slug","replace","replaceAll","headings","sort","a","b","Number","Date","publishedAt"],"sources":["../src/getAllFrontmatter.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAOA,EAAA,MAAQ;AAEf,OAAOC,IAAA,MAAU;AACjB,OAAOC,MAAA,MAAY;AACnB,OAAOC,WAAA,MAAiB;AACxB,SAASC,WAAA,QAAmB;AAE5B,SAASC,cAAA,QAAsB;AAIxB,MAAMC,iBAAA,GAAqBC,QAAA,IAAoC;EACpE,MAAMC,KAAA,GAAQP,IAAA,CAAKQ,IAAA,CAAK,GAAGF,QAAQ,WAAW;EAC9C,OAAOC,KAAA,CACJE,GAAA,CAAKC,QAAA,IAAa;IACjBN,cAAA,CAAeM,QAAQ;IACvB,MAAMC,MAAA,GAASZ,EAAA,CAAGa,YAAA,CAAaF,QAAA,EAAU,MAAM;IAC/C,MAAM;MAAEG,IAAA;MAAMC;IAAQ,IAAIb,MAAA,CAAOU,MAAM;IACvC,MAAMI,IAAA,GAAOL,QAAA,CACVM,OAAA,CAAQ,GAAGV,QAAA,CAASW,UAAA,CAAW,MAAM,GAAG,CAAC,KAAK,EAAE,EAChDD,OAAA,CAAQ,QAAQ,EAAE;IACrB,OAAO;MACL,GAAGH,IAAA;MACHE,IAAA;MACAG,QAAA,EAAUf,WAAA,CAAYQ,MAAM;MAC5BT,WAAA,EAAaA,WAAA,CAAYY,OAAO;IAClC;EACF,CAAC,EACAK,IAAA,CACC,CAACC,CAAA,EAAGC,CAAA,KACFC,MAAA,CAAO,IAAIC,IAAA,CAAKF,CAAA,CAAEG,WAAA,IAAe,EAAE,CAAC,IAAIF,MAAA,CAAO,IAAIC,IAAA,CAAKH,CAAA,CAAEI,WAAA,IAAe,EAAE,CAAC,CAChF;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import GithubSlugger from "github-slugger";
|
|
2
|
+
const getTitle = source => source.replace(/^#+\s+/, "").replace(/<.*>/, " ");
|
|
3
|
+
const getHeadings = source => {
|
|
4
|
+
const slugger = new GithubSlugger();
|
|
5
|
+
return source.split("\n").filter(x => x.startsWith("#")).map(x => ({
|
|
6
|
+
title: getTitle(x),
|
|
7
|
+
priority: x.trim().split(" ")[0].length,
|
|
8
|
+
id: slugger.slug(getTitle(x))
|
|
9
|
+
}));
|
|
10
|
+
};
|
|
11
|
+
export { getHeadings };
|
|
12
|
+
//# sourceMappingURL=getHeadings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GithubSlugger","getTitle","source","replace","getHeadings","slugger","split","filter","x","startsWith","map","title","priority","trim","length","id","slug"],"sources":["../src/getHeadings.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAOA,aAAA,MAAmB;AAG1B,MAAMC,QAAA,GAAYC,MAAA,IAAmBA,MAAA,CAAOC,OAAA,CAAQ,UAAU,EAAE,EAAEA,OAAA,CAAQ,QAAQ,GAAG;AAI9E,MAAMC,WAAA,GAAeF,MAAA,IAA8B;EACxD,MAAMG,OAAA,GAAU,IAAIL,aAAA,CAAc;EAClC,OAAOE,MAAA,CACJI,KAAA,CAAM,IAAI,EACVC,MAAA,CAAQC,CAAA,IAAMA,CAAA,CAAEC,UAAA,CAAW,GAAG,CAAC,EAC/BC,GAAA,CAAKF,CAAA,KAAO;IACXG,KAAA,EAAOV,QAAA,CAASO,CAAC;IACjBI,QAAA,EAAUJ,CAAA,CAAEK,IAAA,CAAK,EAAEP,KAAA,CAAM,GAAG,EAAE,CAAC,EAAEQ,MAAA;IACjCC,EAAA,EAAIV,OAAA,CAAQW,IAAA,CAAKf,QAAA,CAASO,CAAC,CAAC;EAC9B,EAAE;AACN","ignoreList":[]}
|
package/dist/getMDX.mjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import matter from "gray-matter";
|
|
2
|
+
import readingTime from "reading-time";
|
|
3
|
+
import { mdxToJs } from "satteri";
|
|
4
|
+
import expressiveCode from "satteri-expressive-code";
|
|
5
|
+
import { getHeadings } from "./getHeadings.mjs";
|
|
6
|
+
import { processImageMeta } from "./processImageMeta.mjs";
|
|
7
|
+
import { slugPlugin } from "./slugPlugin.mjs";
|
|
8
|
+
import { tableWhitespacePlugin } from "./tableWhitespacePlugin.mjs";
|
|
9
|
+
const DEFAULT_EC = {
|
|
10
|
+
themes: ["github-dark"]
|
|
11
|
+
};
|
|
12
|
+
const ecByKey = /* @__PURE__ */new Map();
|
|
13
|
+
function getExpressiveCode(opts) {
|
|
14
|
+
const key = (() => {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.stringify(opts);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
if (key == null) return expressiveCode(opts);
|
|
22
|
+
let plugin = ecByKey.get(key);
|
|
23
|
+
if (!plugin) {
|
|
24
|
+
plugin = expressiveCode(opts);
|
|
25
|
+
ecByKey.set(key, plugin);
|
|
26
|
+
}
|
|
27
|
+
return plugin;
|
|
28
|
+
}
|
|
29
|
+
async function getMDX(source, options = {}) {
|
|
30
|
+
const {
|
|
31
|
+
data,
|
|
32
|
+
content
|
|
33
|
+
} = matter(source);
|
|
34
|
+
const ec = options.expressiveCode === false ? [] : [getExpressiveCode(options.expressiveCode ?? DEFAULT_EC)];
|
|
35
|
+
const {
|
|
36
|
+
code
|
|
37
|
+
} = await mdxToJs(source, {
|
|
38
|
+
outputFormat: "function-body",
|
|
39
|
+
jsxImportSource: "react",
|
|
40
|
+
features: {
|
|
41
|
+
gfm: true,
|
|
42
|
+
smartPunctuation: true,
|
|
43
|
+
frontmatter: true
|
|
44
|
+
},
|
|
45
|
+
mdastPlugins: [...(options.mdastPlugins ?? [])],
|
|
46
|
+
hastPlugins: [slugPlugin, tableWhitespacePlugin, ...ec, ...(options.hastPlugins ?? [])]
|
|
47
|
+
});
|
|
48
|
+
let imageMeta;
|
|
49
|
+
if (data.image && typeof data.image === "string") {
|
|
50
|
+
const meta = await processImageMeta(data.image, {
|
|
51
|
+
publicDir: options.publicDir
|
|
52
|
+
});
|
|
53
|
+
if (meta) imageMeta = meta;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
frontmatter: {
|
|
57
|
+
...data,
|
|
58
|
+
headings: getHeadings(source),
|
|
59
|
+
readingTime: readingTime(content),
|
|
60
|
+
imageMeta
|
|
61
|
+
},
|
|
62
|
+
code
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export { getMDX };
|
|
66
|
+
//# sourceMappingURL=getMDX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["matter","readingTime","mdxToJs","expressiveCode","getHeadings","processImageMeta","slugPlugin","tableWhitespacePlugin","DEFAULT_EC","themes","ecByKey","Map","getExpressiveCode","opts","key","JSON","stringify","plugin","get","set","getMDX","source","options","data","content","ec","code","outputFormat","jsxImportSource","features","gfm","smartPunctuation","frontmatter","mdastPlugins","hastPlugins","imageMeta","image","meta","publicDir","headings"],"sources":["../src/getMDX.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAOA,MAAA,MAAY;AACnB,OAAOC,WAAA,MAAiB;AACxB,SAAsDC,OAAA,QAAe;AACrE,OAAOC,cAAA,MAEA;AACP,SAASC,WAAA,QAAmB;AAC5B,SAASC,gBAAA,QAAwB;AACjC,SAASC,UAAA,QAAkB;AAC3B,SAASC,qBAAA,QAA6B;AAkBtC,MAAMC,UAAA,GAA2C;EAAEC,MAAA,EAAQ,CAAC,aAAa;AAAE;AAK3E,MAAMC,OAAA,GAAU,mBAAIC,GAAA,CAA+C;AACnE,SAASC,kBAAkBC,IAAA,EAAoC;EAC7D,MAAMC,GAAA,IAAO,MAAM;IACjB,IAAI;MACF,OAAOC,IAAA,CAAKC,SAAA,CAAUH,IAAI;IAC5B,QAAQ;MACN,OAAO;IACT;EACF,GAAG;EACH,IAAIC,GAAA,IAAO,MAAM,OAAOX,cAAA,CAAeU,IAAI;EAC3C,IAAII,MAAA,GAASP,OAAA,CAAQQ,GAAA,CAAIJ,GAAG;EAC5B,IAAI,CAACG,MAAA,EAAQ;IACXA,MAAA,GAASd,cAAA,CAAeU,IAAI;IAC5BH,OAAA,CAAQS,GAAA,CAAIL,GAAA,EAAKG,MAAM;EACzB;EACA,OAAOA,MAAA;AACT;AAOA,eAAsBG,OACpBC,MAAA,EACAC,OAAA,GAAyB,CAAC,GAC2B;EACrD,MAAM;IAAEC,IAAA;IAAMC;EAAQ,IAAIxB,MAAA,CAAOqB,MAAM;EAEvC,MAAMI,EAAA,GACJH,OAAA,CAAQnB,cAAA,KAAmB,QACvB,EAAC,GACD,CAACS,iBAAA,CAAkBU,OAAA,CAAQnB,cAAA,IAAkBK,UAAU,CAAC;EAE9D,MAAM;IAAEkB;EAAK,IAAI,MAAMxB,OAAA,CAAQmB,MAAA,EAAQ;IACrCM,YAAA,EAAc;IACdC,eAAA,EAAiB;IACjBC,QAAA,EAAU;MAAEC,GAAA,EAAK;MAAMC,gBAAA,EAAkB;MAAMC,WAAA,EAAa;IAAK;IACjEC,YAAA,EAAc,CAAC,IAAIX,OAAA,CAAQW,YAAA,IAAgB,EAAG;IAC9CC,WAAA,EAAa,CAAC5B,UAAA,EAAYC,qBAAA,EAAuB,GAAGkB,EAAA,EAAI,IAAIH,OAAA,CAAQY,WAAA,IAAe,EAAG;EACxF,CAAC;EAED,IAAIC,SAAA;EACJ,IAAIZ,IAAA,CAAKa,KAAA,IAAS,OAAOb,IAAA,CAAKa,KAAA,KAAU,UAAU;IAChD,MAAMC,IAAA,GAAO,MAAMhC,gBAAA,CAAiBkB,IAAA,CAAKa,KAAA,EAAO;MAAEE,SAAA,EAAWhB,OAAA,CAAQgB;IAAU,CAAC;IAChF,IAAID,IAAA,EAAMF,SAAA,GAAYE,IAAA;EACxB;EAEA,OAAO;IACLL,WAAA,EAAa;MACX,GAAGT,IAAA;MACHgB,QAAA,EAAUnC,WAAA,CAAYiB,MAAM;MAC5BpB,WAAA,EAAaA,WAAA,CAAYuB,OAAO;MAChCW;IACF;IACAT;EACF;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import compareVersions from "compare-versions";
|
|
4
|
+
import { getMDX } from "./getMDX.mjs";
|
|
5
|
+
import { notifyFileRead } from "./watchFile.mjs";
|
|
6
|
+
const getMDXBySlug = async (basePath, slug, options) => {
|
|
7
|
+
let mdxPath = slug;
|
|
8
|
+
if (!slug.includes(".") && basePath.includes("components")) {
|
|
9
|
+
const versions = getAllVersionsFromPath(path.join(basePath, slug));
|
|
10
|
+
mdxPath += `/${versions[0]}`;
|
|
11
|
+
}
|
|
12
|
+
const filePath = path.join(basePath, `${mdxPath}.mdx`);
|
|
13
|
+
notifyFileRead(filePath);
|
|
14
|
+
const source = fs.readFileSync(filePath, "utf8");
|
|
15
|
+
return getMDX(source, options);
|
|
16
|
+
};
|
|
17
|
+
function getAllVersionsFromPath(fromPath) {
|
|
18
|
+
if (!fs.existsSync(fromPath)) return [];
|
|
19
|
+
return fs.readdirSync(fromPath).map(fileName => fileName.replace(".mdx", "")).sort(compareVersions).reverse();
|
|
20
|
+
}
|
|
21
|
+
export { getAllVersionsFromPath, getMDXBySlug };
|
|
22
|
+
//# sourceMappingURL=getMDXBySlug.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fs","path","compareVersions","getMDX","notifyFileRead","getMDXBySlug","basePath","slug","options","mdxPath","includes","versions","getAllVersionsFromPath","join","filePath","source","readFileSync","fromPath","existsSync","readdirSync","map","fileName","replace","sort","reverse"],"sources":["../src/getMDXBySlug.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAOA,EAAA,MAAQ;AACf,OAAOC,IAAA,MAAU;AACjB,OAAOC,eAAA,MAAqB;AAC5B,SAA6BC,MAAA,QAAc;AAE3C,SAASC,cAAA,QAAsB;AAExB,MAAMC,YAAA,GAAe,MAAAA,CAC1BC,QAAA,EACAC,IAAA,EACAC,OAAA,KACwD;EACxD,IAAIC,OAAA,GAAUF,IAAA;EAGd,IAAI,CAACA,IAAA,CAAKG,QAAA,CAAS,GAAG,KAAKJ,QAAA,CAASI,QAAA,CAAS,YAAY,GAAG;IAC1D,MAAMC,QAAA,GAAWC,sBAAA,CAAuBX,IAAA,CAAKY,IAAA,CAAKP,QAAA,EAAUC,IAAI,CAAC;IACjEE,OAAA,IAAW,IAAIE,QAAA,CAAS,CAAC,CAAC;EAC5B;EAEA,MAAMG,QAAA,GAAWb,IAAA,CAAKY,IAAA,CAAKP,QAAA,EAAU,GAAGG,OAAO,MAAM;EACrDL,cAAA,CAAeU,QAAQ;EACvB,MAAMC,MAAA,GAASf,EAAA,CAAGgB,YAAA,CAAaF,QAAA,EAAU,MAAM;EAC/C,OAAOX,MAAA,CAAOY,MAAA,EAAQP,OAAO;AAC/B;AAEO,SAASI,uBAAuBK,QAAA,EAA4B;EACjE,IAAI,CAACjB,EAAA,CAAGkB,UAAA,CAAWD,QAAQ,GAAG,OAAO,EAAC;EACtC,OAAOjB,EAAA,CACJmB,WAAA,CAAYF,QAAQ,EACpBG,GAAA,CAAKC,QAAA,IAAaA,QAAA,CAASC,OAAA,CAAQ,QAAQ,EAAE,CAAC,EAC9CC,IAAA,CAAKrB,eAAe,EACpBsB,OAAA,CAAQ;AACb","ignoreList":[]}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getMDX } from "./getMDX.mjs";
|
|
2
|
+
import { getAllVersionsFromPath, getMDXBySlug } from "./getMDXBySlug.mjs";
|
|
3
|
+
import { getAllFrontmatter } from "./getAllFrontmatter.mjs";
|
|
4
|
+
import { getHeadings } from "./getHeadings.mjs";
|
|
5
|
+
import { slugPlugin } from "./slugPlugin.mjs";
|
|
6
|
+
import { tableWhitespacePlugin } from "./tableWhitespacePlugin.mjs";
|
|
7
|
+
import { processImageMeta } from "./processImageMeta.mjs";
|
|
8
|
+
import { notifyFileRead } from "./watchFile.mjs";
|
|
9
|
+
export { getAllFrontmatter, getAllVersionsFromPath, getHeadings, getMDX, getMDXBySlug, notifyFileRead, processImageMeta, slugPlugin, tableWhitespacePlugin };
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getMDX","getAllVersionsFromPath","getMDXBySlug","getAllFrontmatter","getHeadings","slugPlugin","tableWhitespacePlugin","processImageMeta","notifyFileRead"],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAkC;AAC3C,SAASC,sBAAA,EAAwBC,YAAA,QAAoB;AACrD,SAASC,iBAAA,QAAyB;AAClC,SAASC,WAAA,QAAmB;AAC5B,SAASC,UAAA,QAAkB;AAC3B,SAASC,qBAAA,QAA6B;AACtC,SAASC,gBAAA,QAAwB;AACjC,SAASC,cAAA,QAAsB","ignoreList":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getMDX } from "./getMDX.mjs";
|
|
2
|
+
import { getAllVersionsFromPath, getMDXBySlug } from "./getMDXBySlug.mjs";
|
|
3
|
+
import { getAllFrontmatter } from "./getAllFrontmatter.mjs";
|
|
4
|
+
import { getHeadings } from "./getHeadings.mjs";
|
|
5
|
+
import { slugPlugin } from "./slugPlugin.mjs";
|
|
6
|
+
import { tableWhitespacePlugin } from "./tableWhitespacePlugin.mjs";
|
|
7
|
+
import { processImageMeta } from "./processImageMeta.mjs";
|
|
8
|
+
import { notifyFileRead } from "./watchFile.mjs";
|
|
9
|
+
export { getAllFrontmatter, getAllVersionsFromPath, getHeadings, getMDX, getMDXBySlug, notifyFileRead, processImageMeta, slugPlugin, tableWhitespacePlugin };
|
|
10
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getMDX","getAllVersionsFromPath","getMDXBySlug","getAllFrontmatter","getHeadings","slugPlugin","tableWhitespacePlugin","processImageMeta","notifyFileRead"],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAkC;AAC3C,SAASC,sBAAA,EAAwBC,YAAA,QAAoB;AACrD,SAASC,iBAAA,QAAyB;AAClC,SAASC,WAAA,QAAmB;AAC5B,SAASC,UAAA,QAAkB;AAC3B,SAASC,qBAAA,QAA6B;AACtC,SAASC,gBAAA,QAAwB;AACjC,SAASC,cAAA,QAAsB","ignoreList":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
async function getSharp() {
|
|
4
|
+
try {
|
|
5
|
+
const sharpModule = await import("sharp");
|
|
6
|
+
return sharpModule.default || sharpModule;
|
|
7
|
+
} catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
async function processImageMeta(imagePath, opts) {
|
|
12
|
+
const publicDir = opts?.publicDir ?? "./public";
|
|
13
|
+
const filePath = imagePath.startsWith("/") ? resolve(publicDir, imagePath.slice(1)) : resolve(imagePath);
|
|
14
|
+
if (!existsSync(filePath)) return null;
|
|
15
|
+
const sharp = await getSharp();
|
|
16
|
+
if (!sharp) return null;
|
|
17
|
+
try {
|
|
18
|
+
const image = sharp(filePath);
|
|
19
|
+
const {
|
|
20
|
+
width = 0,
|
|
21
|
+
height = 0
|
|
22
|
+
} = await image.metadata();
|
|
23
|
+
const blurBuffer = await image.resize(10).blur().jpeg({
|
|
24
|
+
quality: 40
|
|
25
|
+
}).toBuffer();
|
|
26
|
+
const blurDataURL = `data:image/jpeg;base64,${blurBuffer.toString("base64")}`;
|
|
27
|
+
return {
|
|
28
|
+
width,
|
|
29
|
+
height,
|
|
30
|
+
blurDataURL
|
|
31
|
+
};
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export { processImageMeta };
|
|
37
|
+
//# sourceMappingURL=processImageMeta.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["existsSync","resolve","getSharp","sharpModule","default","processImageMeta","imagePath","opts","publicDir","filePath","startsWith","slice","sharp","image","width","height","metadata","blurBuffer","resize","blur","jpeg","quality","toBuffer","blurDataURL","toString"],"sources":["../src/processImageMeta.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,UAAA,QAAkB;AAC3B,SAASC,OAAA,QAAe;AAGxB,eAAeC,SAAA,EAAmD;EAChE,IAAI;IACF,MAAMC,WAAA,GAAc,MAAM,OAAO,OAAO;IACxC,OAAQA,WAAA,CAAoBC,OAAA,IAAWD,WAAA;EACzC,QAAQ;IACN,OAAO;EACT;AACF;AAIA,eAAsBE,iBACpBC,SAAA,EACAC,IAAA,EAC2B;EAC3B,MAAMC,SAAA,GAAYD,IAAA,EAAMC,SAAA,IAAa;EACrC,MAAMC,QAAA,GAAWH,SAAA,CAAUI,UAAA,CAAW,GAAG,IACrCT,OAAA,CAAQO,SAAA,EAAWF,SAAA,CAAUK,KAAA,CAAM,CAAC,CAAC,IACrCV,OAAA,CAAQK,SAAS;EAErB,IAAI,CAACN,UAAA,CAAWS,QAAQ,GAAG,OAAO;EAClC,MAAMG,KAAA,GAAQ,MAAMV,QAAA,CAAS;EAC7B,IAAI,CAACU,KAAA,EAAO,OAAO;EAEnB,IAAI;IACF,MAAMC,KAAA,GAAQD,KAAA,CAAMH,QAAQ;IAC5B,MAAM;MAAEK,KAAA,GAAQ;MAAGC,MAAA,GAAS;IAAE,IAAI,MAAMF,KAAA,CAAMG,QAAA,CAAS;IACvD,MAAMC,UAAA,GAAa,MAAMJ,KAAA,CAAMK,MAAA,CAAO,EAAE,EAAEC,IAAA,CAAK,EAAEC,IAAA,CAAK;MAAEC,OAAA,EAAS;IAAG,CAAC,EAAEC,QAAA,CAAS;IAChF,MAAMC,WAAA,GAAc,0BAA0BN,UAAA,CAAWO,QAAA,CAAS,QAAQ,CAAC;IAC3E,OAAO;MAAEV,KAAA;MAAOC,MAAA;MAAQQ;IAAY;EACtC,QAAQ;IACN,OAAO;EACT;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import GithubSlugger from "github-slugger";
|
|
2
|
+
import { defineHastPlugin } from "satteri";
|
|
3
|
+
function textOf(node) {
|
|
4
|
+
if (node.type === "text") return node.value || "";
|
|
5
|
+
if (node.children) return node.children.map(textOf).join("");
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
const slugPlugin = () => {
|
|
9
|
+
const slugger = new GithubSlugger();
|
|
10
|
+
return defineHastPlugin({
|
|
11
|
+
name: "vxrn-heading-slugs",
|
|
12
|
+
element: {
|
|
13
|
+
filter: ["h1", "h2", "h3", "h4", "h5", "h6"],
|
|
14
|
+
visit(node, ctx) {
|
|
15
|
+
if (node.properties?.id) return;
|
|
16
|
+
const id = slugger.slug(textOf(node));
|
|
17
|
+
ctx.replaceNode(node, {
|
|
18
|
+
...node,
|
|
19
|
+
properties: {
|
|
20
|
+
...node.properties,
|
|
21
|
+
id
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export { slugPlugin };
|
|
29
|
+
//# sourceMappingURL=slugPlugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GithubSlugger","defineHastPlugin","textOf","node","type","value","children","map","join","slugPlugin","slugger","name","element","filter","visit","ctx","properties","id","slug","replaceNode"],"sources":["../src/slugPlugin.ts"],"sourcesContent":[null],"mappings":"AAAA,OAAOA,aAAA,MAAmB;AAC1B,SAASC,gBAAA,QAAwB;AAEjC,SAASC,OAAOC,IAAA,EAAmB;EACjC,IAAIA,IAAA,CAAKC,IAAA,KAAS,QAAQ,OAAOD,IAAA,CAAKE,KAAA,IAAS;EAC/C,IAAIF,IAAA,CAAKG,QAAA,EAAU,OAAOH,IAAA,CAAKG,QAAA,CAASC,GAAA,CAAIL,MAAM,EAAEM,IAAA,CAAK,EAAE;EAC3D,OAAO;AACT;AAIO,MAAMC,UAAA,GAAaA,CAAA,KAAM;EAC9B,MAAMC,OAAA,GAAU,IAAIV,aAAA,CAAc;EAClC,OAAOC,gBAAA,CAAiB;IACtBU,IAAA,EAAM;IACNC,OAAA,EAAS;MACPC,MAAA,EAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;MAC3CC,MAAMX,IAAA,EAAWY,GAAA,EAAU;QACzB,IAAIZ,IAAA,CAAKa,UAAA,EAAYC,EAAA,EAAI;QACzB,MAAMA,EAAA,GAAKP,OAAA,CAAQQ,IAAA,CAAKhB,MAAA,CAAOC,IAAI,CAAC;QACpCY,GAAA,CAAII,WAAA,CAAYhB,IAAA,EAAM;UACpB,GAAGA,IAAA;UACHa,UAAA,EAAY;YAAE,GAAGb,IAAA,CAAKa,UAAA;YAAYC;UAAG;QACvC,CAAC;MACH;IACF;EACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineHastPlugin } from "satteri";
|
|
2
|
+
const tableWhitespacePlugin = defineHastPlugin({
|
|
3
|
+
name: "vxrn-strip-table-whitespace",
|
|
4
|
+
element: {
|
|
5
|
+
filter: ["table", "thead", "tbody", "tr"],
|
|
6
|
+
visit(node, ctx) {
|
|
7
|
+
const children = node.children || [];
|
|
8
|
+
const cleaned = children.filter(c => !(c.type === "text" && typeof c.value === "string" && c.value.trim() === ""));
|
|
9
|
+
if (cleaned.length !== children.length) {
|
|
10
|
+
ctx.replaceNode(node, {
|
|
11
|
+
...node,
|
|
12
|
+
children: cleaned
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export { tableWhitespacePlugin };
|
|
19
|
+
//# sourceMappingURL=tableWhitespacePlugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["defineHastPlugin","tableWhitespacePlugin","name","element","filter","visit","node","ctx","children","cleaned","c","type","value","trim","length","replaceNode"],"sources":["../src/tableWhitespacePlugin.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,gBAAA,QAAwB;AAO1B,MAAMC,qBAAA,GAAwBD,gBAAA,CAAiB;EACpDE,IAAA,EAAM;EACNC,OAAA,EAAS;IACPC,MAAA,EAAQ,CAAC,SAAS,SAAS,SAAS,IAAI;IACxCC,MAAMC,IAAA,EAAWC,GAAA,EAAU;MACzB,MAAMC,QAAA,GAAWF,IAAA,CAAKE,QAAA,IAAY,EAAC;MACnC,MAAMC,OAAA,GAAUD,QAAA,CAASJ,MAAA,CACtBM,CAAA,IACC,EAAEA,CAAA,CAAEC,IAAA,KAAS,UAAU,OAAOD,CAAA,CAAEE,KAAA,KAAU,YAAYF,CAAA,CAAEE,KAAA,CAAMC,IAAA,CAAK,MAAM,GAC7E;MACA,IAAIJ,OAAA,CAAQK,MAAA,KAAWN,QAAA,CAASM,MAAA,EAAQ;QACtCP,GAAA,CAAIQ,WAAA,CAAYT,IAAA,EAAM;UAAE,GAAGA,IAAA;UAAME,QAAA,EAAUC;QAAQ,CAAC;MACtD;IACF;EACF;AACF,CAAC","ignoreList":[]}
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":[],"sourcesContent":[],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["WATCH_FILE_KEY","notifyFileRead","filePath","watchFile","globalThis"],"sources":["../src/watchFile.ts"],"sourcesContent":[null],"mappings":"AAAA,MAAMA,cAAA,GAAiB;AAMhB,SAASC,eAAeC,QAAA,EAAwB;EACrD,MAAMC,SAAA,GAAaC,UAAA,CAAmBJ,cAAc;EAGpD,IAAIG,SAAA,EAAWA,SAAA,CAAUD,QAAQ;AACnC","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vxrn/mdx-rust",
|
|
3
|
+
"version": "1.20.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"module": "dist",
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./types/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./client": {
|
|
16
|
+
"types": "./types/client.d.ts",
|
|
17
|
+
"import": "./dist/client.mjs",
|
|
18
|
+
"default": "./dist/client.mjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"types",
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tamagui-build --skip-native",
|
|
28
|
+
"clean": "tamagui-build clean",
|
|
29
|
+
"clean:build": "tamagui-build clean:build",
|
|
30
|
+
"lint": "biome check src",
|
|
31
|
+
"lint:fix": "biome check --write src",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"watch": "bun run build --watch"
|
|
34
|
+
},
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"sharp": "^0.34.5"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"compare-versions": "^4.1.3",
|
|
40
|
+
"fast-glob": "^3.3.3",
|
|
41
|
+
"github-slugger": "^2.0.0",
|
|
42
|
+
"gray-matter": "^4.0.3",
|
|
43
|
+
"reading-time": "1.3.0",
|
|
44
|
+
"satteri": "^0.9.4",
|
|
45
|
+
"satteri-expressive-code": "^0.1.17"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": "*"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@tamagui/build": "2.3.0",
|
|
52
|
+
"react": "^19.0.0"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as runtime from 'react/jsx-runtime'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Evaluate the `code` returned by `getMDX` into a React component.
|
|
5
|
+
*
|
|
6
|
+
* satteri compiles MDX to a `function-body` module that reads its JSX runtime
|
|
7
|
+
* from `arguments[0]` and returns `{ default, ...exports }`. Render the result
|
|
8
|
+
* with a `components` prop: `<Component components={components} />`.
|
|
9
|
+
*
|
|
10
|
+
* Browser-safe: imports only React, never satteri's native binding.
|
|
11
|
+
*/
|
|
12
|
+
export function getMDXComponent(
|
|
13
|
+
code: string,
|
|
14
|
+
globals: Record<string, unknown> = {}
|
|
15
|
+
): (props: { components?: Record<string, unknown> }) => any {
|
|
16
|
+
// eslint-disable-next-line no-new-func
|
|
17
|
+
const fn = new Function(String(code))
|
|
18
|
+
const mod = fn({ ...runtime, ...globals })
|
|
19
|
+
return mod.default
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import glob from 'fast-glob'
|
|
4
|
+
import matter from 'gray-matter'
|
|
5
|
+
import readingTime from 'reading-time'
|
|
6
|
+
import { getHeadings } from './getHeadings'
|
|
7
|
+
import type { Frontmatter } from './types'
|
|
8
|
+
import { notifyFileRead } from './watchFile'
|
|
9
|
+
|
|
10
|
+
// frontmatter for every mdx file under `fromPath`, newest first. reads only the
|
|
11
|
+
// frontmatter, so it stays cheap over hundreds of files.
|
|
12
|
+
export const getAllFrontmatter = (fromPath: string): Frontmatter[] => {
|
|
13
|
+
const paths = glob.sync(`${fromPath}/**/*.mdx`)
|
|
14
|
+
return paths
|
|
15
|
+
.map((filePath) => {
|
|
16
|
+
notifyFileRead(filePath)
|
|
17
|
+
const source = fs.readFileSync(filePath, 'utf8')
|
|
18
|
+
const { data, content } = matter(source)
|
|
19
|
+
const slug = filePath
|
|
20
|
+
.replace(`${fromPath.replaceAll('\\', '/')}/`, '')
|
|
21
|
+
.replace('.mdx', '')
|
|
22
|
+
return {
|
|
23
|
+
...data,
|
|
24
|
+
slug,
|
|
25
|
+
headings: getHeadings(source),
|
|
26
|
+
readingTime: readingTime(content),
|
|
27
|
+
} as Frontmatter
|
|
28
|
+
})
|
|
29
|
+
.sort(
|
|
30
|
+
(a, b) =>
|
|
31
|
+
Number(new Date(b.publishedAt || '')) - Number(new Date(a.publishedAt || ''))
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import GithubSlugger from 'github-slugger'
|
|
2
|
+
import type { Heading } from './types'
|
|
3
|
+
|
|
4
|
+
const getTitle = (source: string) => source.replace(/^#+\s+/, '').replace(/<.*>/, ' ')
|
|
5
|
+
|
|
6
|
+
// extract headings for a table of contents. ids match the slugs added by
|
|
7
|
+
// slugPlugin during compilation, so anchor links resolve.
|
|
8
|
+
export const getHeadings = (source: string): Heading[] => {
|
|
9
|
+
const slugger = new GithubSlugger()
|
|
10
|
+
return source
|
|
11
|
+
.split('\n')
|
|
12
|
+
.filter((x) => x.startsWith('#'))
|
|
13
|
+
.map((x) => ({
|
|
14
|
+
title: getTitle(x),
|
|
15
|
+
priority: x.trim().split(' ')[0].length,
|
|
16
|
+
id: slugger.slug(getTitle(x)),
|
|
17
|
+
}))
|
|
18
|
+
}
|
package/src/getMDX.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import matter from 'gray-matter'
|
|
2
|
+
import readingTime from 'reading-time'
|
|
3
|
+
import { type HastPluginInput, type MdastPluginInput, mdxToJs } from 'satteri'
|
|
4
|
+
import expressiveCode, {
|
|
5
|
+
type SatteriExpressiveCodeOptions,
|
|
6
|
+
} from 'satteri-expressive-code'
|
|
7
|
+
import { getHeadings } from './getHeadings'
|
|
8
|
+
import { processImageMeta } from './processImageMeta'
|
|
9
|
+
import { slugPlugin } from './slugPlugin'
|
|
10
|
+
import { tableWhitespacePlugin } from './tableWhitespacePlugin'
|
|
11
|
+
import type { Frontmatter, ImageMeta } from './types'
|
|
12
|
+
|
|
13
|
+
export type GetMDXOptions = {
|
|
14
|
+
/** public directory for resolving image paths that start with `/` (default: ./public) */
|
|
15
|
+
publicDir?: string
|
|
16
|
+
/**
|
|
17
|
+
* Expressive Code (Shiki) options: themes, frames, styleOverrides, plugins.
|
|
18
|
+
* Pass `false` to skip syntax highlighting entirely. Defaults to the
|
|
19
|
+
* `github-dark` theme.
|
|
20
|
+
*/
|
|
21
|
+
expressiveCode?: SatteriExpressiveCodeOptions | false
|
|
22
|
+
/** extra satteri mdast plugins, e.g. a hero/demo source injector */
|
|
23
|
+
mdastPlugins?: MdastPluginInput[]
|
|
24
|
+
/** extra satteri hast plugins */
|
|
25
|
+
hastPlugins?: HastPluginInput[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_EC: SatteriExpressiveCodeOptions = { themes: ['github-dark'] }
|
|
29
|
+
|
|
30
|
+
// the Expressive Code plugin caches its Shiki renderer (themes + grammars) for
|
|
31
|
+
// its lifetime, so we reuse one instance per config across every getMDX call
|
|
32
|
+
// instead of paying the warmup on every file.
|
|
33
|
+
const ecByKey = new Map<string, ReturnType<typeof expressiveCode>>()
|
|
34
|
+
function getExpressiveCode(opts: SatteriExpressiveCodeOptions) {
|
|
35
|
+
const key = (() => {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.stringify(opts)
|
|
38
|
+
} catch {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
})()
|
|
42
|
+
if (key == null) return expressiveCode(opts)
|
|
43
|
+
let plugin = ecByKey.get(key)
|
|
44
|
+
if (!plugin) {
|
|
45
|
+
plugin = expressiveCode(opts)
|
|
46
|
+
ecByKey.set(key, plugin)
|
|
47
|
+
}
|
|
48
|
+
return plugin
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Compile an MDX string to an evaluatable component module using satteri (Rust)
|
|
53
|
+
* for parsing/compilation and Expressive Code (Shiki) for code highlighting.
|
|
54
|
+
* Evaluate the returned `code` with `getMDXComponent` from `@vxrn/mdx-rust/client`.
|
|
55
|
+
*/
|
|
56
|
+
export async function getMDX(
|
|
57
|
+
source: string,
|
|
58
|
+
options: GetMDXOptions = {}
|
|
59
|
+
): Promise<{ frontmatter: Frontmatter; code: string }> {
|
|
60
|
+
const { data, content } = matter(source)
|
|
61
|
+
|
|
62
|
+
const ec =
|
|
63
|
+
options.expressiveCode === false
|
|
64
|
+
? []
|
|
65
|
+
: [getExpressiveCode(options.expressiveCode ?? DEFAULT_EC)]
|
|
66
|
+
|
|
67
|
+
const { code } = await mdxToJs(source, {
|
|
68
|
+
outputFormat: 'function-body',
|
|
69
|
+
jsxImportSource: 'react',
|
|
70
|
+
features: { gfm: true, smartPunctuation: true, frontmatter: true },
|
|
71
|
+
mdastPlugins: [...(options.mdastPlugins ?? [])],
|
|
72
|
+
hastPlugins: [slugPlugin, tableWhitespacePlugin, ...ec, ...(options.hastPlugins ?? [])],
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
let imageMeta: ImageMeta | undefined
|
|
76
|
+
if (data.image && typeof data.image === 'string') {
|
|
77
|
+
const meta = await processImageMeta(data.image, { publicDir: options.publicDir })
|
|
78
|
+
if (meta) imageMeta = meta
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
frontmatter: {
|
|
83
|
+
...data,
|
|
84
|
+
headings: getHeadings(source),
|
|
85
|
+
readingTime: readingTime(content),
|
|
86
|
+
imageMeta,
|
|
87
|
+
} as Frontmatter,
|
|
88
|
+
code,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import compareVersions from 'compare-versions'
|
|
4
|
+
import { type GetMDXOptions, getMDX } from './getMDX'
|
|
5
|
+
import type { Frontmatter } from './types'
|
|
6
|
+
import { notifyFileRead } from './watchFile'
|
|
7
|
+
|
|
8
|
+
export const getMDXBySlug = async (
|
|
9
|
+
basePath: string,
|
|
10
|
+
slug: string,
|
|
11
|
+
options?: GetMDXOptions
|
|
12
|
+
): Promise<{ frontmatter: Frontmatter; code: string }> => {
|
|
13
|
+
let mdxPath = slug
|
|
14
|
+
|
|
15
|
+
// if no version given, resolve to the latest
|
|
16
|
+
if (!slug.includes('.') && basePath.includes('components')) {
|
|
17
|
+
const versions = getAllVersionsFromPath(path.join(basePath, slug))
|
|
18
|
+
mdxPath += `/${versions[0]}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const filePath = path.join(basePath, `${mdxPath}.mdx`)
|
|
22
|
+
notifyFileRead(filePath)
|
|
23
|
+
const source = fs.readFileSync(filePath, 'utf8')
|
|
24
|
+
return getMDX(source, options)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getAllVersionsFromPath(fromPath: string): string[] {
|
|
28
|
+
if (!fs.existsSync(fromPath)) return []
|
|
29
|
+
return fs
|
|
30
|
+
.readdirSync(fromPath)
|
|
31
|
+
.map((fileName) => fileName.replace('.mdx', ''))
|
|
32
|
+
.sort(compareVersions)
|
|
33
|
+
.reverse()
|
|
34
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { getMDX, type GetMDXOptions } from './getMDX'
|
|
2
|
+
export { getAllVersionsFromPath, getMDXBySlug } from './getMDXBySlug'
|
|
3
|
+
export { getAllFrontmatter } from './getAllFrontmatter'
|
|
4
|
+
export { getHeadings } from './getHeadings'
|
|
5
|
+
export { slugPlugin } from './slugPlugin'
|
|
6
|
+
export { tableWhitespacePlugin } from './tableWhitespacePlugin'
|
|
7
|
+
export { processImageMeta } from './processImageMeta'
|
|
8
|
+
export { notifyFileRead } from './watchFile'
|
|
9
|
+
export type { Frontmatter, Heading, ImageMeta } from './types'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
import type { ImageMeta } from './types'
|
|
4
|
+
|
|
5
|
+
async function getSharp(): Promise<typeof import('sharp') | null> {
|
|
6
|
+
try {
|
|
7
|
+
const sharpModule = await import('sharp')
|
|
8
|
+
return (sharpModule as any).default || sharpModule
|
|
9
|
+
} catch {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Read an image's dimensions and a tiny blur placeholder. Null if sharp is
|
|
15
|
+
* not installed or the file is missing. */
|
|
16
|
+
export async function processImageMeta(
|
|
17
|
+
imagePath: string,
|
|
18
|
+
opts?: { publicDir?: string }
|
|
19
|
+
): Promise<ImageMeta | null> {
|
|
20
|
+
const publicDir = opts?.publicDir ?? './public'
|
|
21
|
+
const filePath = imagePath.startsWith('/')
|
|
22
|
+
? resolve(publicDir, imagePath.slice(1))
|
|
23
|
+
: resolve(imagePath)
|
|
24
|
+
|
|
25
|
+
if (!existsSync(filePath)) return null
|
|
26
|
+
const sharp = await getSharp()
|
|
27
|
+
if (!sharp) return null
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const image = sharp(filePath)
|
|
31
|
+
const { width = 0, height = 0 } = await image.metadata()
|
|
32
|
+
const blurBuffer = await image.resize(10).blur().jpeg({ quality: 40 }).toBuffer()
|
|
33
|
+
const blurDataURL = `data:image/jpeg;base64,${blurBuffer.toString('base64')}`
|
|
34
|
+
return { width, height, blurDataURL }
|
|
35
|
+
} catch {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import GithubSlugger from 'github-slugger'
|
|
2
|
+
import { defineHastPlugin } from 'satteri'
|
|
3
|
+
|
|
4
|
+
function textOf(node: any): string {
|
|
5
|
+
if (node.type === 'text') return node.value || ''
|
|
6
|
+
if (node.children) return node.children.map(textOf).join('')
|
|
7
|
+
return ''
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// adds github-style id slugs to headings so table-of-contents anchors resolve.
|
|
11
|
+
// used as a factory so the slugger's dedupe counter resets per document.
|
|
12
|
+
export const slugPlugin = () => {
|
|
13
|
+
const slugger = new GithubSlugger()
|
|
14
|
+
return defineHastPlugin({
|
|
15
|
+
name: 'vxrn-heading-slugs',
|
|
16
|
+
element: {
|
|
17
|
+
filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
|
|
18
|
+
visit(node: any, ctx: any) {
|
|
19
|
+
if (node.properties?.id) return
|
|
20
|
+
const id = slugger.slug(textOf(node))
|
|
21
|
+
ctx.replaceNode(node, {
|
|
22
|
+
...node,
|
|
23
|
+
properties: { ...node.properties, id },
|
|
24
|
+
})
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineHastPlugin } from 'satteri'
|
|
2
|
+
|
|
3
|
+
// satteri (via pulldown-cmark) keeps the newline text nodes between table
|
|
4
|
+
// elements; they become stray children of the table/row nodes, which trips
|
|
5
|
+
// React's "whitespace text nodes cannot be a child of <table>" hydration
|
|
6
|
+
// warning and can spawn anonymous table cells. strip whitespace-only children
|
|
7
|
+
// from table structural elements, matching remark-rehype's clean output.
|
|
8
|
+
export const tableWhitespacePlugin = defineHastPlugin({
|
|
9
|
+
name: 'vxrn-strip-table-whitespace',
|
|
10
|
+
element: {
|
|
11
|
+
filter: ['table', 'thead', 'tbody', 'tr'],
|
|
12
|
+
visit(node: any, ctx: any) {
|
|
13
|
+
const children = node.children || []
|
|
14
|
+
const cleaned = children.filter(
|
|
15
|
+
(c: any) =>
|
|
16
|
+
!(c.type === 'text' && typeof c.value === 'string' && c.value.trim() === '')
|
|
17
|
+
)
|
|
18
|
+
if (cleaned.length !== children.length) {
|
|
19
|
+
ctx.replaceNode(node, { ...node, children: cleaned })
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
})
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ImageMeta = {
|
|
2
|
+
width: number
|
|
3
|
+
height: number
|
|
4
|
+
blurDataURL: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Heading = { title: string; priority: number; id: string }
|
|
8
|
+
|
|
9
|
+
export type Frontmatter = {
|
|
10
|
+
title: string
|
|
11
|
+
headings?: Heading[]
|
|
12
|
+
description?: string
|
|
13
|
+
name?: string
|
|
14
|
+
versions?: string[]
|
|
15
|
+
version?: string
|
|
16
|
+
by?: string
|
|
17
|
+
publishedAt?: string
|
|
18
|
+
draft?: boolean
|
|
19
|
+
relatedIds?: string[]
|
|
20
|
+
type?: 'changelog' | string
|
|
21
|
+
readingTime?: { text: string; minutes: number; time: number; words: number }
|
|
22
|
+
poster?: string
|
|
23
|
+
slug: string
|
|
24
|
+
image?: string
|
|
25
|
+
/** image dimensions and blur placeholder, populated if `image` exists and sharp is installed */
|
|
26
|
+
imageMeta?: ImageMeta
|
|
27
|
+
component?: string
|
|
28
|
+
package?: string
|
|
29
|
+
demoName?: string
|
|
30
|
+
}
|
package/src/watchFile.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const WATCH_FILE_KEY = '__oneWatchFile'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Notifies One's HMR system about a file dependency so the page hot-reloads
|
|
5
|
+
* when the file changes. No-op when One is not present or in production.
|
|
6
|
+
*/
|
|
7
|
+
export function notifyFileRead(filePath: string): void {
|
|
8
|
+
const watchFile = (globalThis as any)[WATCH_FILE_KEY] as
|
|
9
|
+
| ((path: string) => void)
|
|
10
|
+
| undefined
|
|
11
|
+
if (watchFile) watchFile(filePath)
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate the `code` returned by `getMDX` into a React component.
|
|
3
|
+
*
|
|
4
|
+
* satteri compiles MDX to a `function-body` module that reads its JSX runtime
|
|
5
|
+
* from `arguments[0]` and returns `{ default, ...exports }`. Render the result
|
|
6
|
+
* with a `components` prop: `<Component components={components} />`.
|
|
7
|
+
*
|
|
8
|
+
* Browser-safe: imports only React, never satteri's native binding.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getMDXComponent(code: string, globals?: Record<string, unknown>): (props: {
|
|
11
|
+
components?: Record<string, unknown>;
|
|
12
|
+
}) => any;
|
|
13
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,CAAC,KAAK,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,KAAK,GAAG,CAK1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getAllFrontmatter.d.ts","sourceRoot":"","sources":["../src/getAllFrontmatter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAK1C,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,WAAW,EAqB/D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getHeadings.d.ts","sourceRoot":"","sources":["../src/getHeadings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAMtC,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,OAAO,EAUnD,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type HastPluginInput, type MdastPluginInput } from 'satteri';
|
|
2
|
+
import { type SatteriExpressiveCodeOptions } from 'satteri-expressive-code';
|
|
3
|
+
import type { Frontmatter } from './types';
|
|
4
|
+
export type GetMDXOptions = {
|
|
5
|
+
/** public directory for resolving image paths that start with `/` (default: ./public) */
|
|
6
|
+
publicDir?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Expressive Code (Shiki) options: themes, frames, styleOverrides, plugins.
|
|
9
|
+
* Pass `false` to skip syntax highlighting entirely. Defaults to the
|
|
10
|
+
* `github-dark` theme.
|
|
11
|
+
*/
|
|
12
|
+
expressiveCode?: SatteriExpressiveCodeOptions | false;
|
|
13
|
+
/** extra satteri mdast plugins, e.g. a hero/demo source injector */
|
|
14
|
+
mdastPlugins?: MdastPluginInput[];
|
|
15
|
+
/** extra satteri hast plugins */
|
|
16
|
+
hastPlugins?: HastPluginInput[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Compile an MDX string to an evaluatable component module using satteri (Rust)
|
|
20
|
+
* for parsing/compilation and Expressive Code (Shiki) for code highlighting.
|
|
21
|
+
* Evaluate the returned `code` with `getMDXComponent` from `@vxrn/mdx-rust/client`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getMDX(source: string, options?: GetMDXOptions): Promise<{
|
|
24
|
+
frontmatter: Frontmatter;
|
|
25
|
+
code: string;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=getMDX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMDX.d.ts","sourceRoot":"","sources":["../src/getMDX.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAW,MAAM,SAAS,CAAA;AAC9E,OAAuB,EACrB,KAAK,4BAA4B,EAClC,MAAM,yBAAyB,CAAA;AAKhC,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,SAAS,CAAA;AAErD,MAAM,MAAM,aAAa,GAAG;IAC1B,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,4BAA4B,GAAG,KAAK,CAAA;IACrD,oEAAoE;IACpE,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACjC,iCAAiC;IACjC,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;CAChC,CAAA;AAyBD;;;;GAIG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA+BrD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type GetMDXOptions } from './getMDX';
|
|
2
|
+
import type { Frontmatter } from './types';
|
|
3
|
+
export declare const getMDXBySlug: (basePath: string, slug: string, options?: GetMDXOptions) => Promise<{
|
|
4
|
+
frontmatter: Frontmatter;
|
|
5
|
+
code: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function getAllVersionsFromPath(fromPath: string): string[];
|
|
8
|
+
//# sourceMappingURL=getMDXBySlug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getMDXBySlug.d.ts","sourceRoot":"","sources":["../src/getMDXBySlug.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,UAAU,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,UAAU,aAAa,KACtB,OAAO,CAAC;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAapD,CAAA;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAOjE"}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { getMDX, type GetMDXOptions } from './getMDX';
|
|
2
|
+
export { getAllVersionsFromPath, getMDXBySlug } from './getMDXBySlug';
|
|
3
|
+
export { getAllFrontmatter } from './getAllFrontmatter';
|
|
4
|
+
export { getHeadings } from './getHeadings';
|
|
5
|
+
export { slugPlugin } from './slugPlugin';
|
|
6
|
+
export { tableWhitespacePlugin } from './tableWhitespacePlugin';
|
|
7
|
+
export { processImageMeta } from './processImageMeta';
|
|
8
|
+
export { notifyFileRead } from './watchFile';
|
|
9
|
+
export type { Frontmatter, Heading, ImageMeta } from './types';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ImageMeta } from './types';
|
|
2
|
+
/** Read an image's dimensions and a tiny blur placeholder. Null if sharp is
|
|
3
|
+
* not installed or the file is missing. */
|
|
4
|
+
export declare function processImageMeta(imagePath: string, opts?: {
|
|
5
|
+
publicDir?: string;
|
|
6
|
+
}): Promise<ImageMeta | null>;
|
|
7
|
+
//# sourceMappingURL=processImageMeta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processImageMeta.d.ts","sourceRoot":"","sources":["../src/processImageMeta.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAWxC;4CAC4C;AAC5C,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAmB3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slugPlugin.d.ts","sourceRoot":"","sources":["../src/slugPlugin.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,UAAU;;;;oBAML,GAAG,OAAO,GAAG;;CAU9B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tableWhitespacePlugin.d.ts","sourceRoot":"","sources":["../src/tableWhitespacePlugin.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB;;;;oBAIlB,GAAG,OAAO,GAAG;;CAW3B,CAAA"}
|
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ImageMeta = {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
blurDataURL: string;
|
|
5
|
+
};
|
|
6
|
+
export type Heading = {
|
|
7
|
+
title: string;
|
|
8
|
+
priority: number;
|
|
9
|
+
id: string;
|
|
10
|
+
};
|
|
11
|
+
export type Frontmatter = {
|
|
12
|
+
title: string;
|
|
13
|
+
headings?: Heading[];
|
|
14
|
+
description?: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
versions?: string[];
|
|
17
|
+
version?: string;
|
|
18
|
+
by?: string;
|
|
19
|
+
publishedAt?: string;
|
|
20
|
+
draft?: boolean;
|
|
21
|
+
relatedIds?: string[];
|
|
22
|
+
type?: 'changelog' | string;
|
|
23
|
+
readingTime?: {
|
|
24
|
+
text: string;
|
|
25
|
+
minutes: number;
|
|
26
|
+
time: number;
|
|
27
|
+
words: number;
|
|
28
|
+
};
|
|
29
|
+
poster?: string;
|
|
30
|
+
slug: string;
|
|
31
|
+
image?: string;
|
|
32
|
+
/** image dimensions and blur placeholder, populated if `image` exists and sharp is installed */
|
|
33
|
+
imageMeta?: ImageMeta;
|
|
34
|
+
component?: string;
|
|
35
|
+
package?: string;
|
|
36
|
+
demoName?: string;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAErE,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gGAAgG;IAChG,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watchFile.d.ts","sourceRoot":"","sources":["../src/watchFile.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAKrD"}
|