@oud-idk/markdown 0.0.0-stage → 0.1.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 +27 -2
- package/dist/components/CopyButton.d.ts +4 -0
- package/dist/components/CopyButton.d.ts.map +1 -0
- package/dist/components/CopyButton.js +21 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/MarkdownLayout.d.ts +16 -0
- package/dist/components/MarkdownLayout.d.ts.map +1 -0
- package/dist/components/MarkdownLayout.js +15 -0
- package/dist/components/MarkdownLayout.js.map +1 -0
- package/dist/components/MarkdownRenderer.d.ts +10 -0
- package/dist/components/MarkdownRenderer.d.ts.map +1 -0
- package/dist/components/MarkdownRenderer.js +113 -0
- package/dist/components/MarkdownRenderer.js.map +1 -0
- package/dist/components/MarkdownWithToC.d.ts +12 -0
- package/dist/components/MarkdownWithToC.d.ts.map +1 -0
- package/dist/components/MarkdownWithToC.js +13 -0
- package/dist/components/MarkdownWithToC.js.map +1 -0
- package/dist/components/ScrollableMarkdownViewer.d.ts +13 -0
- package/dist/components/ScrollableMarkdownViewer.d.ts.map +1 -0
- package/dist/components/ScrollableMarkdownViewer.js +13 -0
- package/dist/components/ScrollableMarkdownViewer.js.map +1 -0
- package/dist/components/TableOfContents.d.ts +10 -0
- package/dist/components/TableOfContents.d.ts.map +1 -0
- package/dist/components/TableOfContents.js +169 -0
- package/dist/components/TableOfContents.js.map +1 -0
- package/dist/components/useMarkdownScroller.d.ts +8 -0
- package/dist/components/useMarkdownScroller.d.ts.map +1 -0
- package/dist/components/useMarkdownScroller.js +32 -0
- package/dist/components/useMarkdownScroller.js.map +1 -0
- package/dist/data/language-map.json +2766 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/linguist.d.ts +2 -0
- package/dist/lib/linguist.d.ts.map +1 -0
- package/dist/lib/linguist.js +14 -0
- package/dist/lib/linguist.js.map +1 -0
- package/dist/lib/markdown-plugins.d.ts +4 -0
- package/dist/lib/markdown-plugins.d.ts.map +1 -0
- package/dist/lib/markdown-plugins.js +75 -0
- package/dist/lib/markdown-plugins.js.map +1 -0
- package/dist/lib/markdown-toc.d.ts +20 -0
- package/dist/lib/markdown-toc.d.ts.map +1 -0
- package/dist/lib/markdown-toc.js +34 -0
- package/dist/lib/markdown-toc.js.map +1 -0
- package/dist/lib/reading-time.d.ts +9 -0
- package/dist/lib/reading-time.d.ts.map +1 -0
- package/dist/lib/reading-time.js +14 -0
- package/dist/lib/reading-time.js.map +1 -0
- package/package.json +58 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./components/CopyButton";
|
|
2
|
+
export * from "./components/MarkdownLayout";
|
|
3
|
+
export * from "./components/MarkdownRenderer";
|
|
4
|
+
export * from "./components/MarkdownWithToC";
|
|
5
|
+
export * from "./components/ScrollableMarkdownViewer";
|
|
6
|
+
export * from "./components/TableOfContents";
|
|
7
|
+
export * from "./components/useMarkdownScroller";
|
|
8
|
+
export * from "./lib/markdown-plugins";
|
|
9
|
+
export * from "./lib/markdown-toc";
|
|
10
|
+
export * from "./lib/reading-time";
|
|
11
|
+
export * from "./lib/linguist";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./components/CopyButton";
|
|
2
|
+
export * from "./components/MarkdownLayout";
|
|
3
|
+
export * from "./components/MarkdownRenderer";
|
|
4
|
+
export * from "./components/MarkdownWithToC";
|
|
5
|
+
export * from "./components/ScrollableMarkdownViewer";
|
|
6
|
+
export * from "./components/TableOfContents";
|
|
7
|
+
export * from "./components/useMarkdownScroller";
|
|
8
|
+
export * from "./lib/markdown-plugins";
|
|
9
|
+
export * from "./lib/markdown-toc";
|
|
10
|
+
export * from "./lib/reading-time";
|
|
11
|
+
export * from "./lib/linguist";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linguist.d.ts","sourceRoot":"","sources":["../../src/lib/linguist.ts"],"names":[],"mappings":"AASA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import languageMap from '../data/language-map.json';
|
|
2
|
+
// The JSON is inferred as an object literal with no index signature, so the
|
|
3
|
+
// Record annotations are required to index it with a runtime string.
|
|
4
|
+
const { names, extensions } = languageMap;
|
|
5
|
+
export function getLinguist(key) {
|
|
6
|
+
const normalized = key.trim().toLowerCase();
|
|
7
|
+
if (normalized === "")
|
|
8
|
+
return undefined;
|
|
9
|
+
// `names` first: the key we hold from a ```rust fence is a language name or
|
|
10
|
+
// alias, not a file extension. `extensions` is the fallback for callers
|
|
11
|
+
// that have an actual file extension.
|
|
12
|
+
return names[normalized] ?? extensions[normalized];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=linguist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linguist.js","sourceRoot":"","sources":["../../src/lib/linguist.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,2BAA2B,CAAC;AAEpD,4EAA4E;AAC5E,qEAAqE;AACrE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAGvB,WAAW,CAAC;AAEhB,MAAM,UAAU,WAAW,CAAC,GAAW;IACnC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,UAAU,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACxC,4EAA4E;IAC5E,wEAAwE;IACxE,sCAAsC;IACtC,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-plugins.d.ts","sourceRoot":"","sources":["../../src/lib/markdown-plugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAmE7C,eAAO,MAAM,aAAa,EAAE,aAAwF,CAAC;AAErH,eAAO,MAAM,aAAa,EAAE,aAiB3B,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import remarkGfm from "remark-gfm";
|
|
3
|
+
import remarkMath from "remark-math";
|
|
4
|
+
import remarkBreaks from "remark-breaks";
|
|
5
|
+
import remarkDirective from "remark-directive";
|
|
6
|
+
/**
|
|
7
|
+
* Turns `:::sidebyside` container directives into a `<div class="sidebyside">`
|
|
8
|
+
* via mdast-util-to-hast's `data.hName`/`data.hProperties` passthrough.
|
|
9
|
+
*/
|
|
10
|
+
const remarkSideBySide = () => (tree) => {
|
|
11
|
+
visit(tree, (node) => {
|
|
12
|
+
if (node.type === "containerDirective" &&
|
|
13
|
+
node.name === "sidebyside") {
|
|
14
|
+
const n = node;
|
|
15
|
+
n.data = n.data ?? {};
|
|
16
|
+
n.data.hName = "div";
|
|
17
|
+
n.data.hProperties = { className: "sidebyside" };
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
import rehypeRaw from "rehype-raw";
|
|
22
|
+
import rehypeKatex from "rehype-katex";
|
|
23
|
+
import rehypeSlug from "rehype-slug";
|
|
24
|
+
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
|
25
|
+
import rehypeExternalLinks from "rehype-external-links";
|
|
26
|
+
import rehypeShiki from "@shikijs/rehype";
|
|
27
|
+
const languageTransformer = {
|
|
28
|
+
name: "language-badge",
|
|
29
|
+
pre(node) {
|
|
30
|
+
node.properties["data-language"] = this.options.lang;
|
|
31
|
+
},
|
|
32
|
+
code(node) {
|
|
33
|
+
node.properties["data-block"] = "";
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* react-markdown funnels *every* `code` element through our `code` component
|
|
38
|
+
* override, so the inline-code pill (background, border, padding, radius) also
|
|
39
|
+
* lands on the `code` nested inside a fenced block. The shiki transformer tags
|
|
40
|
+
* highlighted blocks with `data-block` to opt out, but a block with no language
|
|
41
|
+
* never reaches shiki and so is never tagged — it renders as a bordered pill
|
|
42
|
+
* sitting inside its own `<pre>`. Tag every `pre > code` here instead, running
|
|
43
|
+
* after shiki so highlighted output is covered too.
|
|
44
|
+
*/
|
|
45
|
+
const rehypeMarkBlockCode = () => (tree) => {
|
|
46
|
+
visit(tree, "element", (node) => {
|
|
47
|
+
if (node.tagName !== "pre")
|
|
48
|
+
return;
|
|
49
|
+
for (const child of node.children) {
|
|
50
|
+
if (child.type === "element" && child.tagName === "code") {
|
|
51
|
+
child.properties["data-block"] = "";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export const remarkPlugins = [remarkGfm, remarkMath, remarkBreaks, remarkDirective, remarkSideBySide];
|
|
57
|
+
export const rehypePlugins = [
|
|
58
|
+
rehypeRaw,
|
|
59
|
+
rehypeKatex,
|
|
60
|
+
rehypeSlug,
|
|
61
|
+
[rehypeAutolinkHeadings],
|
|
62
|
+
[rehypeExternalLinks, { target: "_blank", rel: ["noopener", "noreferrer"] }],
|
|
63
|
+
[
|
|
64
|
+
rehypeShiki,
|
|
65
|
+
{
|
|
66
|
+
themes: {
|
|
67
|
+
light: "light-plus",
|
|
68
|
+
dark: "dark-plus",
|
|
69
|
+
},
|
|
70
|
+
transformers: [languageTransformer],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
rehypeMarkBlockCode,
|
|
74
|
+
];
|
|
75
|
+
//# sourceMappingURL=markdown-plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-plugins.js","sourceRoot":"","sources":["../../src/lib/markdown-plugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAG/C;;;GAGG;AACH,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,CAAC,IAAe,EAAE,EAAE;IAC/C,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QACjB,IACI,IAAI,CAAC,IAAI,KAAK,oBAAoB;YACjC,IAA0B,CAAC,IAAI,KAAK,YAAY,EACnD,CAAC;YACC,MAAM,CAAC,GAAG,IAAqD,CAAC;YAChE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;QACrD,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,sBAAsB,MAAM,0BAA0B,CAAC;AAC9D,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAG1C,MAAM,mBAAmB,GAAqB;IAC1C,IAAI,EAAE,gBAAgB;IACtB,GAAG,CAAC,IAAI;QACJ,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,IAAI;QACL,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;IACvC,CAAC;CACJ,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAG,GAAG,EAAE,CAAC,CAAC,IAAU,EAAE,EAAE;IAC7C,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;QAC5B,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;YAAE,OAAO;QAEnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBACvD,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;YACxC,CAAC;QACL,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAkB,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAErH,MAAM,CAAC,MAAM,aAAa,GAAkB;IACxC,SAAS;IACT,WAAW;IACX,UAAU;IACV,CAAC,sBAAsB,CAAC;IACxB,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,CAAC;IAC5E;QACI,WAAW;QACX;YACI,MAAM,EAAE;gBACJ,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,WAAW;aACpB;YACD,YAAY,EAAE,CAAC,mBAAmB,CAAC;SACtC;KACJ;IACD,mBAAmB;CACtB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Root } from "hast";
|
|
2
|
+
export interface TocItem {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
level: number;
|
|
6
|
+
}
|
|
7
|
+
interface CollectHeadingsOptions {
|
|
8
|
+
/** Array the outline is written to, in document order. */
|
|
9
|
+
into: TocItem[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Collects the heading outline while the document is being rendered, so the
|
|
13
|
+
* ToC and the document come out of a single parse of the markdown.
|
|
14
|
+
*
|
|
15
|
+
* Server-side only: wire it in after `rehype-slug` (it reads the ids that
|
|
16
|
+
* plugin mints) via `[rehypeCollectHeadings, { into }]`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function rehypeCollectHeadings({ into }: CollectHeadingsOptions): (tree: Root) => void;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=markdown-toc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-toc.d.ts","sourceRoot":"","sources":["../../src/lib/markdown-toc.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAKD,UAAU,sBAAsB;IAC5B,0DAA0D;IAC1D,IAAI,EAAE,OAAO,EAAE,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,IAAI,EAAE,EAAE,sBAAsB,IAC1D,MAAM,IAAI,KAAG,IAAI,CAsB5B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import { headingRank } from "hast-util-heading-rank";
|
|
3
|
+
import { toString } from "hast-util-to-string";
|
|
4
|
+
/** Deepest heading level the ToC lists; matches the old `h1, h2, h3, h4` query. */
|
|
5
|
+
const MAX_LEVEL = 4;
|
|
6
|
+
/**
|
|
7
|
+
* Collects the heading outline while the document is being rendered, so the
|
|
8
|
+
* ToC and the document come out of a single parse of the markdown.
|
|
9
|
+
*
|
|
10
|
+
* Server-side only: wire it in after `rehype-slug` (it reads the ids that
|
|
11
|
+
* plugin mints) via `[rehypeCollectHeadings, { into }]`.
|
|
12
|
+
*/
|
|
13
|
+
export function rehypeCollectHeadings({ into }) {
|
|
14
|
+
return (tree) => {
|
|
15
|
+
visit(tree, "element", (node) => {
|
|
16
|
+
const level = headingRank(node);
|
|
17
|
+
if (level == null || level > MAX_LEVEL) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// `rehype-slug` only fills in missing ids, so a heading written as
|
|
21
|
+
// raw HTML keeps its own — read it rather than re-slugging the text.
|
|
22
|
+
const id = node.properties.id;
|
|
23
|
+
if (typeof id !== "string" || id.trim() === "") {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const text = toString(node);
|
|
27
|
+
if (text.trim() === "") {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
into.push({ id, text, level });
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=markdown-toc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-toc.js","sourceRoot":"","sources":["../../src/lib/markdown-toc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAS/C,mFAAmF;AACnF,MAAM,SAAS,GAAG,CAAC,CAAC;AAOpB;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAE,IAAI,EAA0B;IAClE,OAAO,CAAC,IAAU,EAAQ,EAAE;QACxB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE;YACrC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;gBACrC,OAAO;YACX,CAAC;YAED,mEAAmE;YACnE,qEAAqE;YACrE,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC7C,OAAO;YACX,CAAC;YAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBACrB,OAAO;YACX,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading time for a markdown document. Code fences and HTML comments are
|
|
3
|
+
* stripped first so a wall of SQL doesn't inflate the estimate.
|
|
4
|
+
*/
|
|
5
|
+
export declare function readingTime(markdown: string): {
|
|
6
|
+
words: number;
|
|
7
|
+
minutes: number;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=reading-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reading-time.d.ts","sourceRoot":"","sources":["../../src/lib/reading-time.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAShF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const WORDS_PER_MINUTE = 225;
|
|
2
|
+
/**
|
|
3
|
+
* Reading time for a markdown document. Code fences and HTML comments are
|
|
4
|
+
* stripped first so a wall of SQL doesn't inflate the estimate.
|
|
5
|
+
*/
|
|
6
|
+
export function readingTime(markdown) {
|
|
7
|
+
const cleaned = markdown
|
|
8
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
9
|
+
.replace(/```[\s\S]*?```/g, "")
|
|
10
|
+
.trim();
|
|
11
|
+
const words = cleaned.split(/\s+/).filter(Boolean).length;
|
|
12
|
+
return { words, minutes: Math.max(1, Math.ceil(words / WORDS_PER_MINUTE)) };
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=reading-time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reading-time.js","sourceRoot":"","sources":["../../src/lib/reading-time.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IACxC,MAAM,OAAO,GAAG,QAAQ;SACnB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;SAC9B,IAAI,EAAE,CAAC;IAEZ,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAE1D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oud-idk/markdown",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Markdown rendering system: React components, remark/rehype plugins, table of contents, reading time.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"sideEffects": [
|
|
18
|
+
"*.css"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"react": "^19.0.0",
|
|
25
|
+
"react-dom": "^19.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@shikijs/rehype": "^4.5.0",
|
|
29
|
+
"cn": "^0.4.0",
|
|
30
|
+
"hast-util-heading-rank": "^3.0.0",
|
|
31
|
+
"hast-util-to-string": "^3.0.1",
|
|
32
|
+
"katex": "^0.17.0",
|
|
33
|
+
"lucide-react": "^1.49.0",
|
|
34
|
+
"react-markdown": "^10.1.0",
|
|
35
|
+
"rehype-autolink-headings": "^7.1.0",
|
|
36
|
+
"rehype-external-links": "^3.0.0",
|
|
37
|
+
"rehype-katex": "^7.0.1",
|
|
38
|
+
"rehype-raw": "^7.0.0",
|
|
39
|
+
"rehype-slug": "^6.0.0",
|
|
40
|
+
"remark-breaks": "^4.0.0",
|
|
41
|
+
"remark-directive": "^4.0.0",
|
|
42
|
+
"remark-gfm": "^4.0.1",
|
|
43
|
+
"remark-math": "^6.0.0",
|
|
44
|
+
"shiki": "^4.5.0",
|
|
45
|
+
"tw-animate-css": "^1.4.0",
|
|
46
|
+
"unified": "^11.0.5",
|
|
47
|
+
"unist-util-visit": "^5.1.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/mdast": "^4.0.4",
|
|
51
|
+
"@types/hast": "^3.0.5",
|
|
52
|
+
"@types/react": "^19",
|
|
53
|
+
"@types/react-dom": "^19",
|
|
54
|
+
"typescript": "^5"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc -p tsconfig.json",
|
|
58
|
+
"clean": "rm -rf dist",
|
|
59
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
60
|
+
}
|
|
6
61
|
}
|