@xyd-js/content 0.1.0-xyd.8 → 0.1.0-xyd.97

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.
Files changed (92) hide show
  1. package/CHANGELOG.md +1157 -0
  2. package/ISSUES.md +1 -0
  3. package/LICENSE +21 -0
  4. package/TODO.md +2 -0
  5. package/dist/index.d.ts +24 -5
  6. package/dist/index.js +212 -566
  7. package/dist/index.js.map +1 -1
  8. package/dist/md.d.ts +69 -0
  9. package/dist/md.js +23396 -0
  10. package/dist/md.js.map +1 -0
  11. package/dist/mdToc-NBBxMJ4l.d.ts +12 -0
  12. package/dist/vite.d.ts +103 -9
  13. package/dist/vite.js +19992 -170
  14. package/dist/vite.js.map +1 -1
  15. package/package.json +26 -7
  16. package/packages/md/index.ts +17 -8
  17. package/packages/md/plugins/component-directives/index.ts +3 -0
  18. package/packages/md/plugins/component-directives/mdComponentDirective.ts +524 -0
  19. package/packages/md/plugins/component-directives/types.ts +1 -0
  20. package/packages/md/plugins/component-directives/utils.ts +27 -0
  21. package/packages/md/plugins/composer/__fixtures__/1.single-example/input.md +7 -0
  22. package/packages/md/plugins/composer/__fixtures__/1.single-example/output.json +63 -0
  23. package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/input.md +7 -0
  24. package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/output.json +63 -0
  25. package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/input.md +15 -0
  26. package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/output.json +122 -0
  27. package/packages/md/plugins/composer/__fixtures__/4.example-groups/input.md +23 -0
  28. package/packages/md/plugins/composer/__fixtures__/4.example-groups/output.json +184 -0
  29. package/packages/md/plugins/composer/__tests__/mdComposer.test.ts +41 -0
  30. package/packages/md/plugins/composer/__tests__/testHelpers.ts +48 -0
  31. package/packages/md/plugins/composer/index.ts +1 -0
  32. package/packages/md/plugins/composer/mdComposer.ts +146 -0
  33. package/packages/md/plugins/developer-writing/index.ts +3 -0
  34. package/packages/md/plugins/developer-writing/mdCodeRehype.ts +78 -0
  35. package/packages/md/plugins/functions/__fixtures__/external.ts +4 -0
  36. package/packages/md/plugins/functions/__fixtures__/test.js +11 -0
  37. package/packages/md/plugins/functions/__fixtures__/test.py +9 -0
  38. package/packages/md/plugins/functions/__fixtures__/test.ts +18 -0
  39. package/packages/md/plugins/functions/__tests__/mdFunctionImportCode.test.ts +295 -0
  40. package/packages/md/plugins/functions/__tests__/parseFunctionCall.test.ts +47 -0
  41. package/packages/md/plugins/functions/__tests__/testHelpers.ts +71 -0
  42. package/packages/md/plugins/functions/index.ts +11 -0
  43. package/packages/md/plugins/functions/mdFunctionChangelog.ts +124 -0
  44. package/packages/md/plugins/functions/mdFunctionImportCode.ts +83 -0
  45. package/packages/md/plugins/functions/mdFunctionUniform.ts +79 -0
  46. package/packages/md/plugins/functions/types.ts +6 -0
  47. package/packages/md/plugins/functions/uniformProcessor.ts +349 -0
  48. package/packages/md/plugins/functions/utils.ts +423 -0
  49. package/packages/md/plugins/index.ts +56 -9
  50. package/packages/md/plugins/mdCode.ts +67 -0
  51. package/packages/md/plugins/mdHeadingId.ts +47 -0
  52. package/packages/md/plugins/mdPage.ts +35 -0
  53. package/packages/md/plugins/{md-themeSettings.ts → mdThemeSettings.ts} +8 -0
  54. package/packages/md/plugins/mdToc.ts +224 -0
  55. package/packages/md/plugins/meta/index.ts +1 -0
  56. package/packages/md/plugins/meta/mdMeta.ts +189 -0
  57. package/packages/md/plugins/output-variables/__fixtures__/1.simple/input.md +22 -0
  58. package/packages/md/plugins/output-variables/__fixtures__/1.simple/output.json +191 -0
  59. package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/input.md +21 -0
  60. package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/output.json +127 -0
  61. package/packages/md/plugins/output-variables/__tests__/index.test.ts +28 -0
  62. package/packages/md/plugins/output-variables/__tests__/testHelpers.ts +36 -0
  63. package/packages/md/plugins/output-variables/index.ts +1 -0
  64. package/packages/md/plugins/output-variables/lib/const.ts +4 -0
  65. package/packages/md/plugins/output-variables/lib/factoryAttributes.ts +350 -0
  66. package/packages/md/plugins/output-variables/lib/factoryLabel.ts +135 -0
  67. package/packages/md/plugins/output-variables/lib/factoryName.ts +59 -0
  68. package/packages/md/plugins/output-variables/lib/index.ts +21 -0
  69. package/packages/md/plugins/output-variables/lib/outputVarsContainer.ts +328 -0
  70. package/packages/md/plugins/output-variables/lib/util.ts +494 -0
  71. package/packages/md/plugins/output-variables/remarkOutputVars.ts +22 -0
  72. package/packages/md/plugins/rehypeHeading.ts +50 -0
  73. package/packages/md/plugins/types.ts +15 -0
  74. package/packages/md/plugins/utils/componentLike.ts +72 -0
  75. package/packages/md/plugins/utils/index.ts +2 -0
  76. package/packages/md/plugins/utils/mdParameters.test.ts +114 -0
  77. package/packages/md/plugins/utils/mdParameters.ts +249 -0
  78. package/packages/md/plugins/utils/mdastTypes.ts +42 -0
  79. package/packages/md/search/index.ts +251 -0
  80. package/packages/md/search/types.ts +36 -0
  81. package/packages/vite/index.ts +8 -2
  82. package/src/fs.ts +51 -36
  83. package/src/index.ts +4 -4
  84. package/src/navigation.ts +50 -38
  85. package/src/types.ts +8 -0
  86. package/tsconfig.json +31 -8
  87. package/tsup.config.ts +2 -0
  88. package/vitest.config.ts +17 -0
  89. package/packages/md/plugins/md-code.ts +0 -15
  90. package/packages/md/plugins/md-codegroup.ts +0 -36
  91. package/packages/md/plugins/md-page.ts +0 -22
  92. package/packages/md/plugins/md-toc.ts +0 -133
@@ -1,14 +1,20 @@
1
1
  import type {Plugin} from 'rollup';
2
2
  import mdx from '@mdx-js/rollup';
3
3
 
4
- import {RemarkMdxTocOptions, mdOptions} from "../md";
4
+ import {Settings} from "@xyd-js/core";
5
+
6
+ import {RemarkMdxTocOptions, markdownPlugins} from "../md";
5
7
 
6
8
  export interface VitePluginInterface {
7
9
  toc: RemarkMdxTocOptions
10
+ settings: Settings
8
11
  }
9
12
 
10
13
  export function vitePlugins(options: VitePluginInterface): Plugin[] {
11
14
  return [
12
- mdx(mdOptions(options.toc)),
15
+ mdx(markdownPlugins(
16
+ options.toc,
17
+ options.settings
18
+ )),
13
19
  ];
14
20
  }
package/src/fs.ts CHANGED
@@ -1,43 +1,58 @@
1
- import {promises as fs} from "fs";
2
- import path from "path";
1
+ import fs from "fs/promises"
3
2
 
4
- import {VFile} from "vfile";
5
- import {compile as mdxCompile} from "@mdx-js/mdx";
3
+ import { VFile } from "vfile"
4
+ import { PluggableList } from "unified";
5
+ import { compile as mdxCompile } from "@mdx-js/mdx";
6
6
 
7
- import {mdOptions} from "../packages/md";
7
+ import { Settings } from "@xyd-js/core"
8
8
 
9
- export async function compileBySlug(
10
- slug: string,
11
- mdx: boolean
12
- ): Promise<string> {
13
- // TODO: cwd ?
14
- const filePath = path.join(process.cwd(), `${slug}.${mdx ? "mdx" : "md"}`)
9
+ export {
10
+ pageFrontMatters,
11
+ filterNavigationByLevels
12
+ } from "./navigation"
15
13
 
16
- await fs.access(filePath)
14
+ export type { VarCode } from "./types"
17
15
 
18
- const content = await fs.readFile(filePath, "utf-8");
16
+ export class ContentFS {
17
+ constructor(
18
+ private readonly settings: Settings,
19
+ private readonly remarkPlugins: PluggableList,
20
+ private readonly rehypePlugins: PluggableList,
21
+ ) { }
19
22
 
20
- return await compile(content, filePath)
21
- }
23
+ public async compile(filePath: string): Promise<string> {
24
+ await fs.access(filePath)
25
+
26
+ const content = await fs.readFile(filePath, "utf-8");
27
+
28
+ return await this.compileContent(content, filePath)
29
+ }
30
+
31
+
32
+ public async compileContent(content: string, filePath?: string): Promise<string> {
33
+ const vfile = new VFile({
34
+ path: filePath,
35
+ value: content,
36
+ contents: content
37
+ });
22
38
 
23
- async function compile(content: string, filePath: string): Promise<string> {
24
- const vfile = new VFile({
25
- path: filePath,
26
- value: content,
27
- contents: content
28
- });
29
-
30
- const opt = mdOptions({
31
- minDepth: 2 // TODO: configurable?
32
- })
33
-
34
- const compiled = await mdxCompile(vfile, {
35
- remarkPlugins: opt.remarkPlugins,
36
- rehypePlugins: opt.rehypePlugins,
37
- recmaPlugins: [],
38
- outputFormat: 'function-body',
39
- development: false,
40
- });
41
-
42
- return String(compiled)
43
- }
39
+ const compiled = await mdxCompile(vfile, {
40
+ remarkPlugins: this.remarkPlugins,
41
+ rehypePlugins: this.rehypePlugins,
42
+ recmaPlugins: [],
43
+ outputFormat: 'function-body',
44
+ development: false,
45
+ jsx: false
46
+ });
47
+
48
+ return String(compiled)
49
+ }
50
+
51
+ public async readRaw(filePath: string) {
52
+ await fs.access(filePath)
53
+
54
+ const content = await fs.readFile(filePath, "utf-8");
55
+
56
+ return content
57
+ }
58
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
- export {
2
- compileBySlug
3
- } from "./fs"
1
+ export { ContentFS } from "./fs"
4
2
 
5
3
  export {
6
4
  pageFrontMatters,
7
5
  filterNavigationByLevels
8
- } from "./navigation"
6
+ } from "./navigation"
7
+
8
+ export type { VarCode } from "./types"
package/src/navigation.ts CHANGED
@@ -1,31 +1,33 @@
1
- import {promises as fs} from 'fs';
2
- import fs2, {open} from 'fs';
1
+ import { promises as fs } from 'fs';
3
2
  import path from 'path';
4
3
 
5
4
  import React from "react";
6
5
  import remarkFrontmatter from "remark-frontmatter";
7
6
  import remarkMdxFrontmatter from "remark-mdx-frontmatter";
8
- import matter from 'gray-matter';
9
- import {VFile} from "vfile";
10
- import {compile as mdxCompile} from "@mdx-js/mdx";
7
+ import { VFile } from "vfile";
8
+ import { compile as mdxCompile } from "@mdx-js/mdx";
11
9
 
12
- import {FrontMatter, Sidebar, PageFrontMatter, Header} from "@xyd-js/core";
10
+ import { Metadata, Sidebar, MetadataMap, Header, PageURL, VirtualPage } from "@xyd-js/core";
13
11
 
14
12
  // TODO: better algorithm + data structures - since it's on build time it's not a big deal nevertheless it should be changed in the future
15
13
 
16
14
  // pageFrontMatters gets frontmatters for given navigation
17
- export async function pageFrontMatters(navigation: Sidebar[]): Promise<PageFrontMatter> {
18
- const frontmatters: PageFrontMatter = {}
15
+ export async function pageFrontMatters(navigation: Sidebar[], pagePathMapping: { [key: string]: string }): Promise<MetadataMap> {
16
+ const frontmatters: MetadataMap = {}
19
17
 
20
18
  const promises: Promise<any>[] = []
21
19
 
22
- function mapPages(page: string | Sidebar) {
20
+ function mapPages(page: PageURL) {
23
21
  if (typeof page !== "string") {
24
- page.pages?.forEach(mapPages)
22
+ if ("virtual" in page) {
23
+ promises.push(job(page, frontmatters, pagePathMapping))
24
+ } else if ("pages" in page) {
25
+ page.pages?.forEach(mapPages)
26
+ }
25
27
  return
26
28
  }
27
29
 
28
- promises.push(job(page, frontmatters))
30
+ promises.push(job(page, frontmatters, pagePathMapping))
29
31
  }
30
32
 
31
33
  navigation.map(async (nav: Sidebar) => {
@@ -43,7 +45,7 @@ export function filterNavigationByLevels(
43
45
  slug: string
44
46
  ) {
45
47
  const topLevelTabMatcher = headers?.reduce((acc: any, header) => {
46
- const tabLevel = header?.url?.split("/")?.length
48
+ const tabLevel = header?.page?.split("/")?.length
47
49
 
48
50
  if (!tabLevel) {
49
51
  return {
@@ -54,13 +56,13 @@ export function filterNavigationByLevels(
54
56
  if (!acc[tabLevel]) {
55
57
  return {
56
58
  ...acc,
57
- [tabLevel]: new Set().add(header?.url)
59
+ [tabLevel]: new Set().add(header?.page)
58
60
  }
59
61
  }
60
62
 
61
63
  return {
62
64
  ...acc,
63
- [tabLevel]: acc[tabLevel].add(header?.url)
65
+ [tabLevel]: acc[tabLevel].add(header?.page)
64
66
  }
65
67
  }, {}) as { [level: number]: Set<string> }
66
68
 
@@ -74,11 +76,20 @@ export function filterNavigationByLevels(
74
76
  const level = parseInt(levelStr)
75
77
  const findThisSlug = slug.split("/").filter(s => !!s).slice(0, level).join("/")
76
78
 
77
- function findMatchedPage(page: string | Sidebar) {
79
+ function findMatchedPage(page: PageURL) {
78
80
  if (typeof page !== "string") {
79
- page.pages?.forEach(findMatchedPage)
81
+ if ("virtual" in page && page.virtual) {
82
+ return matchPage(page.virtual)
83
+ } else if ("pages" in page) {
84
+ page.pages?.forEach(findMatchedPage)
85
+ }
80
86
  return
81
87
  }
88
+
89
+ return matchPage(page)
90
+ }
91
+
92
+ function matchPage(page: string) {
82
93
  const findThisPage = page.split("/").filter(p => !!p).slice(0, level).join("/")
83
94
 
84
95
  const set = topLevelTabMatcher[level]
@@ -107,7 +118,7 @@ function mdxExport(code: string) {
107
118
  return fn(scope)
108
119
  }
109
120
 
110
- async function getFrontmatter(filePath: string): Promise<FrontMatter> {
121
+ async function getFrontmatter(filePath: string): Promise<Metadata> {
111
122
  const body = await fs.readFile(filePath, "utf-8");
112
123
 
113
124
  const vfile = new VFile({
@@ -134,39 +145,40 @@ async function getFrontmatter(filePath: string): Promise<FrontMatter> {
134
145
  frontmatter
135
146
  } = mdxExport(code)
136
147
 
137
- const matter: FrontMatter = frontmatter
148
+ const matter: Metadata = frontmatter
149
+
150
+ if (!matter) {
151
+ throw new Error(`Frontmatter not found in ${filePath}`)
152
+ }
138
153
 
139
154
  let title = ""
140
- if (typeof matter.title === "string" ) {
155
+ if (typeof matter.title === "string") {
141
156
  title = matter.title
142
157
  }
143
158
  if (reactFrontmatter) {
144
- if (typeof reactFrontmatter?.title === "function") {
145
- matter.title = {
146
- title,
147
- code: reactFrontmatter.title.toString()
148
- }
149
- }
159
+ console.error("currently react frontmatter is not supported")
150
160
  }
151
161
 
152
162
  return matter
153
163
  }
154
164
 
155
- async function job(page: string, frontmatters: PageFrontMatter) {
156
- // TODO: it can be cwd because on build time it has entire path?
157
- let filePath = path.join(process.cwd(), `${page}.mdx`) // TODO: support md toos
158
- try {
159
- await fs.access(filePath)
160
- } catch (e) {
161
- try {
162
- const mdPath = filePath.replace(".mdx", ".md")
163
- await fs.access(mdPath)
164
- filePath = mdPath
165
- } catch (e) {
166
- }
165
+ // TODO: indices map to not do like this - search for mdx if not then md
166
+ async function job(page: string | VirtualPage, frontmatters: MetadataMap, pagePathMapping: { [key: string]: string }) {
167
+ let pageName = ""
168
+ if (typeof page === "string") {
169
+ pageName = page
170
+ } else if (page.page) {
171
+ pageName = page.page
172
+ }
173
+
174
+ if (!pageName || !pagePathMapping[pageName]) {
175
+ console.log(`⚠️ "${pageName}" is defined in the docs.json navigation but the file does not exist.`)
176
+ return
167
177
  }
168
178
 
179
+ const filePath = path.join(process.cwd(), pagePathMapping[pageName])
180
+
169
181
  const matter = await getFrontmatter(filePath)
170
182
 
171
- frontmatters[page] = matter
183
+ frontmatters[pageName] = matter
172
184
  }
package/src/types.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { HighlightedCode } from "codehike/code"
2
+
3
+ export type VarCode = [
4
+ [
5
+ string,
6
+ ...(HighlightedCode)[]
7
+ ] | HighlightedCode
8
+ ]
package/tsconfig.json CHANGED
@@ -2,10 +2,24 @@
2
2
  "compilerOptions": {
3
3
  "baseUrl": ".",
4
4
  "paths": {
5
- "@/mdx/*": ["src/mdx/*"],
6
- "@/navigation/*": ["src/navigation/*"],
7
- "@/utils/*": ["src/utils/*"],
8
- "@/vite-plugins/*": ["src/vite-plugins/*"]
5
+ "@/mdx/*": [
6
+ "src/mdx/*"
7
+ ],
8
+ "@/navigation/*": [
9
+ "src/navigation/*"
10
+ ],
11
+ "@/utils/*": [
12
+ "src/utils/*"
13
+ ],
14
+ "@/vite-plugins/*": [
15
+ "src/vite-plugins/*"
16
+ ],
17
+ "@xyd-js/core": [
18
+ "../xyd-core"
19
+ ],
20
+ "@xyd-js/context": [
21
+ "../xyd-context/src/index.ts"
22
+ ]
9
23
  },
10
24
  "target": "ES2020",
11
25
  "module": "ESNext",
@@ -15,12 +29,21 @@
15
29
  "skipLibCheck": true,
16
30
  "forceConsistentCasingInFileNames": true,
17
31
  "outDir": "./dist",
18
- "types": ["node", "estree", "vite"],
32
+ "types": [
33
+ "node",
34
+ "estree",
35
+ "vite"
36
+ ],
19
37
  "declaration": true,
20
38
  "declarationMap": true,
21
39
  "incremental": true,
22
- "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
40
+ "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo",
23
41
  },
24
- "include": ["src/**/*.ts"],
25
- "exclude": ["node_modules", "dist"]
42
+ "include": [
43
+ "src/**/*.ts"
44
+ ],
45
+ "exclude": [
46
+ "node_modules",
47
+ "dist"
48
+ ]
26
49
  }
package/tsup.config.ts CHANGED
@@ -4,11 +4,13 @@ const config: Options = {
4
4
  entry: {
5
5
  index: 'src/index.ts',
6
6
  vite: 'packages/vite/index.ts',
7
+ md: 'packages/md/index.ts',
7
8
  },
8
9
  dts: {
9
10
  entry: {
10
11
  index: 'src/index.ts',
11
12
  vite: 'packages/vite/index.ts',
13
+ md: 'packages/md/index.ts'
12
14
  },
13
15
  resolve: true, // Resolve external types
14
16
  },
@@ -0,0 +1,17 @@
1
+ import {defineConfig} from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: [
8
+ 'src/**/*.test.ts',
9
+ 'packages/**/*.test.ts',
10
+ '**/__tests__/**/*.test.ts'
11
+ ],
12
+ coverage: {
13
+ provider: 'v8',
14
+ reporter: ['text', 'json', 'html'],
15
+ },
16
+ },
17
+ })
@@ -1,15 +0,0 @@
1
- import {visit} from "unist-util-visit";
2
-
3
- export function remarkInjectCodeMeta() {
4
- return (tree: any) => {
5
- visit(tree, 'code', (node) => {
6
- if (node.meta) {
7
- node.data = node.data || {};
8
- node.data.hProperties = {
9
- ...(node.data.hProperties || {}),
10
- meta: node.meta,
11
- };
12
- }
13
- });
14
- };
15
- }
@@ -1,36 +0,0 @@
1
- import {visit} from 'unist-util-visit';
2
-
3
- // This plugin transforms a custom container directive into a JSX node
4
- // https://github.com/remarkjs/remark-directive is needed to parse the container directive
5
-
6
- export function mdCodeGroup() {
7
- return (tree: any) => {
8
- visit(tree, 'containerDirective', (node) => {
9
- if (node.name !== 'code-group') return;
10
-
11
- const description = node.attributes?.title || '';
12
- const codeblocks = [];
13
-
14
- for (const child of node.children) {
15
- if (child.type === 'code') {
16
- const meta = child.meta || '';
17
- const value = child.value || '';
18
- const lang = child.lang || '';
19
-
20
- codeblocks.push({value, lang, meta});
21
- }
22
- }
23
-
24
- // Add metadata to the node
25
- node.data = {
26
- hName: 'DirectiveCodeSample',
27
- hProperties: {
28
- description,
29
- codeblocks: JSON.stringify(codeblocks),
30
- },
31
- };
32
-
33
- node.children = [];
34
- });
35
- };
36
- }
@@ -1,22 +0,0 @@
1
- import {Plugin} from 'unified';
2
- import {Node as UnistNode} from 'unist';
3
- import {visit} from 'unist-util-visit';
4
-
5
- declare global {
6
- var page: boolean | null | undefined
7
- }
8
-
9
- export const extractPage: Plugin = () => {
10
- return (tree: UnistNode) => {
11
- visit(tree, 'exportNamedDeclaration', (node: any) => {
12
- const declaration = node.declaration;
13
- if (declaration && declaration.declarations) {
14
- declaration.declarations.forEach((decl: any) => {
15
- if (decl.id.name === 'page') {
16
- global.page = decl.init as boolean;
17
- }
18
- });
19
- }
20
- });
21
- };
22
- };
@@ -1,133 +0,0 @@
1
- import {Root, Heading} from "mdast";
2
- import {MdxjsEsm} from "mdast-util-mdx";
3
- import {Plugin} from "unified"; // TODO: use Plugin type
4
- import {MdxJsxFlowElement, MdxJsxAttribute} from "mdast-util-mdx-jsx";
5
-
6
- export type TocEntry = {
7
- depth: number,
8
- value: string,
9
- attributes: { [key: string]: string },
10
- children: TocEntry[]
11
- };
12
-
13
- export type CustomTag = {
14
- name: RegExp,
15
- depth: (name: string) => number
16
- };
17
-
18
- export interface RemarkMdxTocOptions {
19
- name?: string,
20
- customTags?: CustomTag[],
21
- minDepth?: number
22
- }
23
-
24
- // TODO: fix any
25
- export const remarkMdxToc = (options: RemarkMdxTocOptions): Plugin => () => async (ast: any) => {
26
- const {visit} = await import("unist-util-visit");
27
- const {toString} = await import("mdast-util-to-string");
28
- const {valueToEstree} = await import('estree-util-value-to-estree')
29
- const {name: isIdentifierName} = await import('estree-util-is-identifier-name');
30
-
31
- const mdast = ast as Root;
32
- const name = options.name ?? "toc";
33
- if (!isIdentifierName(name)) {
34
- throw new Error(`Invalid name for an identifier: ${name}`);
35
- }
36
-
37
- const toc: TocEntry[] = [];
38
- const flatToc: TocEntry[] = [];
39
- const createEntry = (node: Heading | MdxJsxFlowElement, depth: number): TocEntry => {
40
- let attributes = (node.data || {}) as TocEntry['attributes'];
41
- if (node.type === "mdxJsxFlowElement") {
42
- attributes = Object.fromEntries(
43
- node.attributes
44
- .filter(attribute => attribute.type === 'mdxJsxAttribute' && typeof attribute.value === 'string')
45
- .map(attribute => [(attribute as MdxJsxAttribute).name, attribute.value])
46
- ) as TocEntry['attributes'];
47
- }
48
- return {
49
- depth,
50
- value: toString(node, {includeImageAlt: false}),
51
- attributes,
52
- children: []
53
- }
54
- };
55
-
56
- visit(mdast, ["heading", "mdxJsxFlowElement"], node => {
57
- let depth = 0;
58
- if (node.type === "mdxJsxFlowElement") {
59
- let valid = false;
60
- if (/^h[1-6]$/.test(node.name || "")) {
61
- valid = true;
62
- depth = parseInt(node.name!.substring(1));
63
- } else if (options.customTags) {
64
- for (const tag of options.customTags) {
65
- if (tag.name.test(node.name || "")) {
66
- valid = true;
67
- depth = tag.depth(node.name || "");
68
- break;
69
- }
70
- }
71
- }
72
-
73
- if (!valid) {
74
- return;
75
- }
76
- } else if (node.type === "heading") {
77
- depth = node.depth;
78
- } else {
79
- return;
80
- }
81
-
82
- if (depth && (options?.minDepth && options.minDepth > depth)) {
83
- return
84
- }
85
-
86
- const entry = createEntry(node, depth);
87
- flatToc.push(entry);
88
-
89
- let parent: TocEntry[] = toc;
90
- for (let i = flatToc.length - 1; i >= 0; --i) {
91
- const current = flatToc[i];
92
- if (current.depth < entry.depth) {
93
- parent = current.children;
94
- break;
95
- }
96
- }
97
- parent.push(entry);
98
- });
99
-
100
- const tocExport: MdxjsEsm = {
101
- type: "mdxjsEsm",
102
- value: "",
103
- data: {
104
- estree: {
105
- type: "Program",
106
- sourceType: "module",
107
- body: [
108
- {
109
- type: "ExportNamedDeclaration",
110
- specifiers: [],
111
- attributes: [],
112
- source: null,
113
- declaration: {
114
- type: "VariableDeclaration",
115
- kind: "const",
116
- declarations: [
117
- {
118
- type: "VariableDeclarator",
119
- id: {
120
- type: "Identifier",
121
- name
122
- },
123
- init: valueToEstree(toc)
124
- }
125
- ]
126
- }
127
- }
128
- ]
129
- }
130
- }
131
- };
132
- mdast.children.unshift(tocExport);
133
- };