astro-custom-toc 1.0.4 → 1.1.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.
@@ -0,0 +1,4 @@
1
+ import type { AstroIntegration } from "astro";
2
+ import { RemarkCustomTocOptions } from "./remark-custom-toc.js";
3
+ declare const astroCustomToc: (options?: RemarkCustomTocOptions) => AstroIntegration;
4
+ export default astroCustomToc;
@@ -1,9 +1,7 @@
1
- import type { AstroConfig, AstroIntegration } from "astro";
2
- import { remarkCustomToc, RemarkCustomTocOptions } from "./remark-custom-toc";
1
+ import { remarkCustomToc } from "./remark-custom-toc.js";
3
2
  import remarkComment from "remark-comment";
4
-
5
- const astroCustomToc = (options?: RemarkCustomTocOptions) => {
6
- const integration: AstroIntegration = {
3
+ const astroCustomToc = (options) => {
4
+ const integration = {
7
5
  name: "astro-custom-toc",
8
6
  hooks: {
9
7
  "astro:config:setup": ({ config, updateConfig }) => {
@@ -24,21 +22,16 @@ const astroCustomToc = (options?: RemarkCustomTocOptions) => {
24
22
  }
25
23
  }
26
24
  };
27
-
28
25
  return integration;
29
26
  };
30
-
31
- const checkOrder = (config: AstroConfig) => {
27
+ const checkOrder = (config) => {
32
28
  const customTocIndex = config.integrations.findIndex((i) => i.name === "astro-custom-toc");
33
29
  const mdxIndex = config.integrations.findIndex((i) => i.name === "@astrojs/mdx");
34
30
  if (mdxIndex > -1 && customTocIndex > mdxIndex) {
35
- throw new Error(
36
- `
37
- MDX integration configured before astro-custom-toc.
38
- \`astroCustomToc()\` must be loaded before \`mdx()\`.
39
- `.trim()
40
- );
31
+ throw new Error(`
32
+ MDX integration configured before astro-custom-toc.
33
+ \`astroCustomToc()\` must be loaded before \`mdx()\`.
34
+ `.trim());
41
35
  }
42
36
  };
43
-
44
37
  export default astroCustomToc;
@@ -0,0 +1,10 @@
1
+ import type { AstroUserConfig } from "astro";
2
+ export type RemarkCustomTocTemplate = (html: string) => string;
3
+ export interface RemarkCustomTocOptions {
4
+ template?: RemarkCustomTocTemplate;
5
+ maxDepth?: number;
6
+ ordered?: boolean;
7
+ }
8
+ type RemarkPlugin = NonNullable<NonNullable<AstroUserConfig["markdown"]>["remarkPlugins"]>[number];
9
+ export declare const remarkCustomToc: RemarkPlugin;
10
+ export {};
@@ -1,39 +1,7 @@
1
- import type { AstroUserConfig } from "astro";
2
1
  import { visit } from "unist-util-visit";
3
2
  import Slugger from "github-slugger";
4
3
  import { JSDOM } from "jsdom";
5
-
6
- interface Heading {
7
- slug: string;
8
- text: string;
9
- depth: number;
10
- }
11
-
12
- export type RemarkCustomTocTemplate = (html: string) => string;
13
-
14
- export interface RemarkCustomTocOptions {
15
- template?: RemarkCustomTocTemplate;
16
- maxDepth?: number;
17
- ordered?: boolean;
18
- }
19
-
20
- type RemarkPlugin = NonNullable<NonNullable<AstroUserConfig["markdown"]>["remarkPlugins"]>[number];
21
-
22
- interface VFile {
23
- data: {
24
- astro?: {
25
- frontmatter: Record<string, any>;
26
- };
27
- };
28
- }
29
-
30
- interface CommentNode {
31
- type: "comment";
32
- value: "";
33
- commentValue: string;
34
- }
35
-
36
- const defaultTemplate = (html: string) => {
4
+ const defaultTemplate = (html) => {
37
5
  return `
38
6
  <aside class="toc">
39
7
  <h2>Contents</h2>
@@ -42,63 +10,51 @@ const defaultTemplate = (html: string) => {
42
10
  </nav>
43
11
  </aside>`.trim();
44
12
  };
45
-
46
- export const remarkCustomToc: RemarkPlugin = ({
47
- template = defaultTemplate,
48
- maxDepth = 3,
49
- ordered = false
50
- }: RemarkCustomTocOptions = {}) => {
51
- return (tree, { data }: VFile) => {
52
- if (data.astro && data.astro.frontmatter.showToc !== true) return;
53
-
13
+ export const remarkCustomToc = ({ template = defaultTemplate, maxDepth = 3, ordered = false } = {}) => {
14
+ return (tree, { data }) => {
15
+ if (data.astro && data.astro.frontmatter.showToc !== true)
16
+ return;
54
17
  const slugs = new Slugger();
55
18
  slugs.reset();
56
-
57
- const headings: Heading[] = [];
19
+ const headings = [];
58
20
  visit(tree, "heading", (node) => {
59
21
  const { depth } = node;
60
- const textNode = node.children[0];
61
- // @ts-ignore
62
- const text = textNode ? textNode.value : "";
22
+ const text = node.children.map((n) => ("value" in n ? n.value : "")).join("");
63
23
  const slug = slugs.slug(text);
64
24
  // @ts-ignore
65
25
  node.data = { id: slug };
66
26
  headings.push({ slug, text, depth });
67
27
  });
68
-
69
28
  let tocIndex = 0;
70
- visit(tree, "comment", (node: CommentNode, index) => {
29
+ visit(tree, "comment", (node, index) => {
71
30
  if (node.commentValue.trim().toLowerCase() === "toc" && index !== undefined) {
72
31
  tocIndex = index;
73
32
  }
74
33
  });
75
-
76
34
  visit(tree, "html", (node, index) => {
77
35
  if (node.value.trim().toLowerCase() === "<!-- toc -->" && index !== undefined) {
78
36
  tocIndex = index;
79
37
  }
80
38
  });
81
-
82
39
  const toc = generateToc(template, maxDepth, ordered, headings);
83
40
  if (tocIndex === 0) {
84
41
  // @ts-ignore
85
42
  tree.children.unshift(toc);
86
- } else {
43
+ }
44
+ else {
87
45
  // @ts-ignore
88
46
  tree.children.splice(tocIndex, 1, toc);
89
47
  }
90
48
  };
91
49
  };
92
-
93
- const generateToc = (template: RemarkCustomTocTemplate, maxDepth: number, ordered: boolean, headings: Heading[]) => {
50
+ const generateToc = (template, maxDepth, ordered, headings) => {
94
51
  const { document } = new JSDOM().window;
95
-
96
- const toc: HTMLElement = document.createElement(ordered ? "ol" : "ul");
52
+ const toc = document.createElement(ordered ? "ol" : "ul");
97
53
  let currentDepth = headings[0].depth;
98
54
  let currentParent = toc;
99
55
  for (const heading of headings) {
100
- if (heading.depth > maxDepth) continue;
101
-
56
+ if (heading.depth > maxDepth)
57
+ continue;
102
58
  if (heading.depth === currentDepth) {
103
59
  const li = document.createElement("li");
104
60
  const a = document.createElement("a");
@@ -107,7 +63,8 @@ const generateToc = (template: RemarkCustomTocTemplate, maxDepth: number, ordere
107
63
  li.appendChild(a);
108
64
  currentParent.appendChild(li);
109
65
  currentDepth = heading.depth;
110
- } else if (heading.depth > currentDepth) {
66
+ }
67
+ else if (heading.depth > currentDepth) {
111
68
  const ul = document.createElement(ordered ? "ol" : "ul");
112
69
  const li = document.createElement("li");
113
70
  const a = document.createElement("a");
@@ -118,9 +75,10 @@ const generateToc = (template: RemarkCustomTocTemplate, maxDepth: number, ordere
118
75
  currentParent.appendChild(ul);
119
76
  currentParent = ul;
120
77
  currentDepth = heading.depth;
121
- } else {
78
+ }
79
+ else {
122
80
  for (let i = 0; i < currentDepth - heading.depth; i++) {
123
- currentParent = currentParent.parentElement!;
81
+ currentParent = currentParent.parentElement;
124
82
  }
125
83
  const li = document.createElement("li");
126
84
  const a = document.createElement("a");
@@ -131,7 +89,6 @@ const generateToc = (template: RemarkCustomTocTemplate, maxDepth: number, ordere
131
89
  currentDepth = heading.depth;
132
90
  }
133
91
  }
134
-
135
92
  return {
136
93
  type: "html",
137
94
  value: template(toc.outerHTML)
package/package.json CHANGED
@@ -1,44 +1,49 @@
1
- {
2
- "name": "astro-custom-toc",
3
- "version": "1.0.4",
4
- "description": "Astro Integration to generate a customizable table of contents",
5
- "type": "module",
6
- "exports": {
7
- ".": "./index.ts"
8
- },
9
- "files": [
10
- "index.ts",
11
- "remark-custom-toc.ts"
12
- ],
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/Robot-Inventor/astro-custom-toc.git"
16
- },
17
- "keywords": [
18
- "astro",
19
- "withastro",
20
- "ui",
21
- "remark",
22
- "markdown",
23
- "astro-integration"
24
- ],
25
- "author": "Robot-Inventor",
26
- "license": "MIT",
27
- "bugs": {
28
- "url": "https://github.com/Robot-Inventor/astro-custom-toc/issues"
29
- },
30
- "homepage": "https://github.com/Robot-Inventor/astro-custom-toc#readme",
31
- "dependencies": {
32
- "github-slugger": "^2.0.0",
33
- "jsdom": "^24.0.0",
34
- "remark-comment": "^1.0.0",
35
- "typescript": "^5.3.3",
36
- "unist-util-visit": "^5.0.0"
37
- },
38
- "peerDependencies": {
39
- "astro": "^4.0.0"
40
- },
41
- "devDependencies": {
42
- "@types/jsdom": "^21.1.6"
43
- }
44
- }
1
+ {
2
+ "name": "astro-custom-toc",
3
+ "version": "1.1.1",
4
+ "description": "Astro Integration to generate a customizable table of contents",
5
+ "scripts": {
6
+ "build": "tsc",
7
+ "format": "prettier ./src/ --write",
8
+ "format:check": "prettier ./src/ --check",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "type": "module",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "files": [
15
+ "./dist/"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/Robot-Inventor/astro-custom-toc.git"
20
+ },
21
+ "keywords": [
22
+ "astro",
23
+ "withastro",
24
+ "ui",
25
+ "remark",
26
+ "markdown",
27
+ "astro-integration"
28
+ ],
29
+ "author": "Robot-Inventor",
30
+ "license": "MIT",
31
+ "bugs": {
32
+ "url": "https://github.com/Robot-Inventor/astro-custom-toc/issues"
33
+ },
34
+ "homepage": "https://github.com/Robot-Inventor/astro-custom-toc#readme",
35
+ "dependencies": {
36
+ "github-slugger": "^2.0.0",
37
+ "jsdom": "^24.0.0",
38
+ "remark-comment": "^1.0.0",
39
+ "typescript": "^5.3.3",
40
+ "unist-util-visit": "^5.0.0"
41
+ },
42
+ "peerDependencies": {
43
+ "astro": "^4.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/jsdom": "^21.1.6",
47
+ "prettier": "^3.2.5"
48
+ }
49
+ }