UNPKG

@synstack/markdown

Version:
1 lines 13.9 kB
{"version":3,"sources":["../src/markdown.index.ts","../src/markdown.bundle.ts","../src/markdown.lib.ts"],"sourcesContent":["export * from \"./markdown.bundle.ts\";\nexport * as md from \"./markdown.bundle.ts\";\nexport { MdDoc } from \"./markdown.lib.ts\";\n","export {\n beautify,\n fromHtml,\n getBody,\n getHeaderData,\n minify,\n setBody,\n setHeaderData,\n} from \"./markdown.lib.ts\";\n","import { yaml } from \"@synstack/yaml\";\nimport type { Options as StringifyOptions } from \"mdast-util-to-markdown\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeRemark from \"rehype-remark\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkGfm, { type Options as GfmOptions } from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport remarkStringify from \"remark-stringify\";\nimport { unified } from \"unified\";\nimport type { ZodTypeDef as ZodTypeDefV3, ZodType as ZodTypeV3 } from \"zod/v3\";\nimport type { ZodType as ZodTypeV4 } from \"zod/v4\";\nimport { type Stringable } from \"../../shared/src/ts.utils.ts\";\n\n// Union type to support both Zod v3 and v4 schemas\ntype ZodSchema<OUT = any, IN = any> =\n | ZodTypeV3<OUT, ZodTypeDefV3, IN>\n | ZodTypeV4<OUT, IN>;\n\nconst beautifiedConfig = {\n gfm: {\n firstLineBlank: true,\n singleTilde: false,\n tableCellPadding: true,\n tablePipeAlign: true,\n } satisfies GfmOptions,\n stringify: {\n bullet: \"*\",\n bulletOther: \"-\",\n bulletOrdered: \".\",\n listItemIndent: \"one\",\n fence: \"`\",\n fences: true,\n rule: \"-\",\n ruleRepetition: 3,\n ruleSpaces: false,\n closeAtx: false,\n emphasis: \"_\",\n strong: \"_\",\n setext: false,\n quote: '\"',\n resourceLink: true,\n tightDefinitions: false,\n } satisfies StringifyOptions,\n};\n\nconst minifiedConfig = {\n gfm: {\n firstLineBlank: false,\n singleTilde: false,\n tableCellPadding: false,\n tablePipeAlign: false,\n } satisfies GfmOptions,\n stringify: {\n bullet: \"*\",\n bulletOther: \"-\",\n bulletOrdered: \".\",\n listItemIndent: \"one\",\n fence: \"`\",\n fences: true,\n rule: \"-\",\n ruleRepetition: 3,\n ruleSpaces: false,\n closeAtx: false,\n emphasis: \"_\",\n strong: \"_\",\n setext: false,\n quote: '\"',\n resourceLink: false,\n tightDefinitions: true,\n } satisfies StringifyOptions,\n};\n\n/**\n * Convert HTML to markdown\n * @param html - The HTML to convert\n * @returns The markdown (minified for LLM processing)\n */\nexport const fromHtml = (html: Stringable) => {\n return unified()\n .use(rehypeParse)\n .use(rehypeRemark)\n .use(remarkGfm, minifiedConfig.gfm)\n .use(remarkStringify, minifiedConfig.stringify)\n .processSync(html.toString())\n .toString()\n .trim();\n};\n\nconst HEADER_REGEX = /^--- *\\r?\\n([\\s\\S]*?)\\r?\\n--- *\\r?\\n?/;\n\n/**\n * Get the header data from a markdown document\n * @param text - The markdown document\n * @param options - The options (optional)\n * @param options.schema - The schema to use for deserialization (optional)\n * @returns The header data\n */\nexport const getHeaderData = <SHAPE = unknown>(\n text: Stringable,\n { schema }: { schema?: ZodSchema<SHAPE> } = {},\n): SHAPE | undefined => {\n const header = text.toString().match(HEADER_REGEX)?.[1];\n if (!header && !schema) return undefined;\n if (!header && schema) return schema.parse(undefined);\n return yaml.deserialize(header ?? \"\", { schema });\n};\n\n/**\n * Set the header data in a markdown document while preserving the body\n * @param text - The markdown document\n * @param data - The data to set\n * @param options - The options (optional)\n * @param options.schema - The schema to use for serialization (optional)\n * @returns The markdown document with the header data set\n */\nexport const setHeaderData = <SHAPE = any>(\n text: Stringable,\n data: SHAPE,\n options: { schema?: ZodSchema<any, SHAPE> } = {},\n) => {\n return `---\\n${yaml.serialize(data, { schema: options.schema })}---\\n${getBody(text.toString())}`;\n};\n\n/**\n * Get the body of a markdown document\n * @param text - The markdown document\n * @returns The body as a string\n */\nexport const getBody = (text: string) => {\n return text.replace(HEADER_REGEX, \"\");\n};\n\n/**\n * Set the body of a markdown document while preserving the header\n * @param text - The markdown document\n * @param body - The body to set\n * @returns The markdown document with the body set\n */\nexport const setBody = (text: string, body: string) => {\n const header = text.match(HEADER_REGEX)?.[0];\n return `${header ?? \"\"}${body}`;\n};\n\n/**\n * Minify a markdown document for better LLM processing\n * @param text - The markdown document\n * @returns The minified markdown document\n */\nexport const minify = (md: string) => {\n return unified()\n .use(remarkParse)\n .use(remarkGfm, minifiedConfig.gfm)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkStringify, minifiedConfig.stringify)\n .processSync(md)\n .toString()\n .trim();\n};\n\n/**\n * Beautify a markdown document for better human readability\n * @param md - The markdown document\n * @returns The beautified markdown document\n */\nexport const beautify = (md: string) => {\n return unified()\n .use(remarkParse)\n .use(remarkGfm, beautifiedConfig.gfm)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkStringify, beautifiedConfig.stringify)\n .processSync(md)\n .toString();\n};\n\n/**\n * Markdown document instance\n */\nexport class MdDoc<SHAPE = never, DATA extends SHAPE | undefined = never> {\n private readonly _body: string;\n private readonly _data: DATA;\n private readonly _options: { schema?: ZodSchema<SHAPE> };\n\n protected constructor(\n data: DATA,\n body: string,\n options: { schema?: ZodSchema<SHAPE, SHAPE> } = {},\n ) {\n this._body = body;\n this._data = data;\n this._options = options ?? {};\n }\n\n /**\n * Create a new markdown document with options\n * @param options\n * @param options.schema - The zod schema to use for serialization/deserialization (optional)\n * @returns A new markdown document instance\n */\n public static withOptions<SHAPE = unknown>(\n this: void,\n options: { schema?: ZodSchema<SHAPE, SHAPE> },\n ) {\n return new MdDoc<SHAPE, undefined>(undefined, \"\", options);\n }\n\n /**\n * Create a new markdown document from a string\n * @param text - The markdown document\n * @returns The markdown document\n */\n public static fromString<SHAPE = unknown>(this: void, text: string) {\n return new MdDoc<SHAPE, SHAPE>(getHeaderData(text) as SHAPE, getBody(text));\n }\n\n /**\n * Create a new markdown document from HTML\n * @param html - The HTML to convert\n * @returns The markdown document\n */\n public static fromHtml<SHAPE = unknown>(this: void, html: string) {\n return new MdDoc<SHAPE, undefined>(undefined, fromHtml(html));\n }\n\n /**\n * Get the body of the markdown document\n * @returns The body of the markdown document\n */\n public get body(): string {\n return this._body;\n }\n\n /**\n * Get the data of the markdown document\n * @returns The data of the markdown document\n */\n public get data(): DATA {\n return this._data;\n }\n\n /**\n * Get the header of the markdown document\n * @returns The header of the markdown document\n */\n public get header(): string {\n return this._data ? `---\\n${yaml.serialize(this._data)}---\\n` : \"\";\n }\n\n /**\n * Get the options of the markdown document\n * @returns The options of the markdown document\n */\n public get options(): { schema?: ZodSchema<SHAPE, SHAPE> } {\n return this._options;\n }\n\n /**\n * Create a new markdown document from a string\n * @param text - The markdown document\n * @returns A new markdown document\n */\n public fromString(text: string) {\n const validatedData = getHeaderData<SHAPE>(text, {\n schema: this._options.schema,\n })!;\n return new MdDoc<SHAPE, SHAPE>(validatedData, getBody(text), this._options);\n }\n\n /**\n * Create a new markdown document from HTML\n * @param html - The HTML to convert\n * @returns A new markdown document\n */\n public fromHtml(html: string) {\n return new MdDoc(this._data, fromHtml(html), this._options);\n }\n\n /**\n * Set the data of the markdown document\n * @param data - The data to set\n * @returns A new markdown document\n */\n public setData(data: SHAPE) {\n const validatedData = this._options.schema\n ? this._options.schema.parse(data)\n : data;\n return new MdDoc(validatedData, this._body, this._options);\n }\n\n /**\n * Set the body of the markdown document\n * @param text - The body to set\n * @returns A new markdown document\n */\n public setBody(text: string) {\n return new MdDoc(this._data, text, this._options);\n }\n\n /**\n * Minify the markdown document for better LLM processing\n * @returns A new markdown document\n */\n public minify() {\n return new MdDoc(this._data, minify(this.body), this._options);\n }\n\n /**\n * Beautify the markdown document for better human readability\n * @returns A new markdown document\n */\n public beautify() {\n return new MdDoc(this._data, beautify(this.body), this._options);\n }\n\n /**\n * Get the markdown document as a string\n *\n * @alias {@link toString}\n * @returns The markdown document as a string\n */\n public toMd() {\n return this.toString();\n }\n\n /**\n * Get the markdown document as a string\n * @returns The markdown document as a string\n */\n public toString() {\n return `${this.header}${this.body}`;\n }\n}\n"],"mappings":"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","names":["rehypeParse","rehypeRemark","remarkGfm","remarkStringify","remarkParse","remarkFrontmatter"]}