🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@scalar/code-highlight

Package Overview
Dependencies
Maintainers
8
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@scalar/code-highlight - npm Package Compare versions

Comparing version
0.2.3
to
0.2.4
+6
-0
CHANGELOG.md
# @scalar/code-highlight
## 0.2.4
### Patch Changes
- [#8248](https://github.com/scalar/scalar/pull/8248): feat: slugs for headings with nested content
## 0.2.3

@@ -4,0 +10,0 @@

+1
-1
export { syntaxHighlight } from './code/index.js';
export { lowlightLanguageMappings } from './constants.js';
export * from './languages/index.js';
export { htmlFromMarkdown } from './markdown/index.js';
export { type Node, htmlFromMarkdown, isHeading, textFromNode } from './markdown/index.js';
export { rehypeHighlight } from './rehype-highlight/index.js';
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtD,cAAc,aAAa,CAAA;AAC3B,OAAO,EAAE,KAAK,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
import { syntaxHighlight } from "./code/index.js";
import { lowlightLanguageMappings } from "./constants.js";
export * from "./languages/index.js";
import { htmlFromMarkdown } from "./markdown/index.js";
import { htmlFromMarkdown, isHeading, textFromNode } from "./markdown/index.js";
import { rehypeHighlight } from "./rehype-highlight/index.js";
export {
htmlFromMarkdown,
isHeading,
lowlightLanguageMappings,
rehypeHighlight,
syntaxHighlight
syntaxHighlight,
textFromNode
};
//# sourceMappingURL=index.js.map
{
"version": 3,
"sources": ["../src/index.ts"],
"sourcesContent": ["export { syntaxHighlight } from './code'\nexport { lowlightLanguageMappings } from './constants'\nexport * from './languages'\nexport { htmlFromMarkdown } from './markdown'\nexport { rehypeHighlight } from './rehype-highlight'\n"],
"mappings": "AAAA,SAAS,uBAAuB;AAChC,SAAS,gCAAgC;AACzC,cAAc;AACd,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;",
"sourcesContent": ["export { syntaxHighlight } from './code'\nexport { lowlightLanguageMappings } from './constants'\nexport * from './languages'\nexport { type Node, htmlFromMarkdown, isHeading, textFromNode } from './markdown'\nexport { rehypeHighlight } from './rehype-highlight'\n"],
"mappings": "AAAA,SAAS,uBAAuB;AAChC,SAAS,gCAAgC;AACzC,cAAc;AACd,SAAoB,kBAAkB,WAAW,oBAAoB;AACrE,SAAS,uBAAuB;",
"names": []
}

@@ -0,2 +1,8 @@

import type { Heading, Node, PhrasingContent } from 'mdast';
export type { Node } from 'mdast';
/**
* Type-guard to check if a node is a heading.
*/
export declare const isHeading: (node: Node) => node is Heading;
/**
* Take a Markdown string and generate HTML from it

@@ -7,3 +13,3 @@ */

allowTags?: string[];
transform?: (node: Record<string, any>) => Record<string, any>;
transform?: (node: Node) => Node;
transformType?: string;

@@ -19,2 +25,8 @@ }): string;

/**
* Extract plain text from a Markdown AST node (recursively).
*
* Handles headings with nested phrasing content such as links.
*/
export declare function textFromNode(node: Heading | PhrasingContent): string;
/**
* Return multiple Markdown documents. Every heading should be its own document.

@@ -21,0 +33,0 @@ */

@@ -1,1 +0,1 @@

{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/markdown.ts"],"names":[],"mappings":"AA0CA;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,UAuDF;AASD;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,EAAE,CAiBF;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,YAgC5C"}
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/markdown/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAqB,MAAM,OAAO,CAAA;AAsB9E,YAAY,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,KAAG,IAAI,IAAI,OAE9C,CAAA;AAqBD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,UAuDF;AASD;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB;IACD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,EAAE,CAiBF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,MAAM,CAUpE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,YAgC5C"}

@@ -15,2 +15,5 @@ import rehypeExternalLinks from "rehype-external-links";

import { rehypeHighlight } from "../rehype-highlight/index.js";
const isHeading = (node) => {
return node.type === "heading" && "depth" in node && "children" in node;
};
const transformNodes = (options, ..._ignored) => (tree) => {

@@ -62,5 +65,5 @@ if (!options?.transform || !options?.type) {

visit(tree, "heading", (node) => {
const text = findTextInHeading(node);
const text = textFromNode(node);
if (text) {
nodes.push({ depth: node.depth ?? depth, value: text.value });
nodes.push({ depth: node.depth ?? depth, value: text });
}

@@ -70,15 +73,10 @@ });

}
function findTextInHeading(node) {
function textFromNode(node) {
if (node.type === "text") {
return node;
return node.value ?? "";
}
if ("children" in node && node.children) {
for (const child of node.children) {
const text = findTextInHeading(child);
if (text) {
return text;
}
}
if ("children" in node && Array.isArray(node.children)) {
return node.children.map((child) => textFromNode(child)).join("");
}
return null;
return "";
}

@@ -115,4 +113,6 @@ function splitContent(markdown) {

htmlFromMarkdown,
splitContent
isHeading,
splitContent,
textFromNode
};
//# sourceMappingURL=markdown.js.map
{
"version": 3,
"sources": ["../../src/markdown/markdown.ts"],
"sourcesContent": ["import type { Heading, PhrasingContent, Root, RootContent, Text } from 'mdast'\nimport rehypeExternalLinks from 'rehype-external-links'\nimport rehypeFormat from 'rehype-format'\nimport rehypeRaw from 'rehype-raw'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport rehypeStringify from 'rehype-stringify'\nimport remarkGfm from 'remark-gfm'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport remarkStringify from 'remark-stringify'\nimport { unified } from 'unified'\nimport type { Node } from 'unist'\nimport { SKIP, visit } from 'unist-util-visit'\n\nimport { standardLanguages } from '@/languages'\nimport { rehypeAlert } from '@/rehype-alert'\nimport { rehypeHighlight } from '@/rehype-highlight'\n\ntype Options = {\n transform?: (node: Record<string, any>) => Record<string, any>\n type?: string\n}\n\n/**\n * Plugin to transform nodes in a Markdown AST\n */\nconst transformNodes =\n (options?: Readonly<Options> | null | undefined, ..._ignored: any[]) =>\n (tree: Node) => {\n if (!options?.transform || !options?.type) {\n return\n }\n\n visit(tree, options?.type, (node) => {\n options?.transform ? options?.transform(node) : node\n\n return SKIP\n })\n\n return\n }\n\n/**\n * Take a Markdown string and generate HTML from it\n */\nexport function htmlFromMarkdown(\n markdown: string,\n options?: {\n removeTags?: string[]\n allowTags?: string[]\n transform?: (node: Record<string, any>) => Record<string, any>\n transformType?: string\n },\n) {\n // Add permitted tags and remove stripped ones\n const removeTags = options?.removeTags ?? []\n const tagNames = [...(defaultSchema.tagNames ?? []), ...(options?.allowTags ?? [])].filter(\n (t) => !removeTags.includes(t),\n )\n\n const html = unified()\n // Parses markdown\n .use(remarkParse)\n // Support autolink literals, footnotes, strikethrough, tables and tasklists\n .use(remarkGfm)\n .use(transformNodes, {\n transform: options?.transform,\n type: options?.transformType,\n })\n // Allows any HTML tags\n .use(remarkRehype, { allowDangerousHtml: true })\n // Adds GitHub alerts\n .use(rehypeAlert)\n // Creates a HTML AST\n .use(rehypeRaw)\n // Removes disallowed tags\n .use(rehypeSanitize, {\n ...defaultSchema,\n // Don't prefix the heading ids\n clobberPrefix: '',\n // Makes it even more strict\n tagNames,\n attributes: {\n ...defaultSchema.attributes,\n abbr: ['title'],\n // Allow all class names while preserving the existing default attributes\n '*': [...(defaultSchema.attributes?.['*'] ?? []), 'className'],\n },\n // Strip content of dangerous elements, not just the tags\n strip: ['script', 'style', 'object', 'embed', 'form'],\n })\n // Syntax highlighting\n .use(rehypeHighlight, {\n languages: standardLanguages,\n // Enable auto detection\n detect: true,\n })\n // Adds target=\"_blank\" to external links\n .use(rehypeExternalLinks, { target: '_blank' })\n // Formats the HTML\n .use(rehypeFormat)\n // Converts the HTML AST to a string\n .use(rehypeStringify)\n // Run the pipeline\n .processSync(markdown)\n\n return html.toString()\n}\n\n/**\n * Create a Markdown AST from a string.\n */\nfunction getMarkdownAst(markdown: string): Root {\n return unified().use(remarkParse).use(remarkGfm).parse(markdown)\n}\n\n/**\n * Find all headings of a specific type in a Markdown AST.\n */\nexport function getHeadings(\n markdown: string,\n depth: number = 1,\n): {\n depth: number\n value: string\n}[] {\n const tree = getMarkdownAst(markdown)\n\n const nodes: {\n depth: number\n value: string\n }[] = []\n\n visit(tree, 'heading', (node) => {\n const text = findTextInHeading(node)\n\n if (text) {\n nodes.push({ depth: node.depth ?? depth, value: text.value })\n }\n })\n\n return nodes\n}\n\n/**\n * Find the text in a Markdown node (recursively).\n */\nfunction findTextInHeading(node: Heading | PhrasingContent): Text | null {\n if (node.type === 'text') {\n return node as Text\n }\n\n if ('children' in node && node.children) {\n for (const child of node.children) {\n const text = findTextInHeading(child)\n\n if (text) {\n return text\n }\n }\n }\n\n return null\n}\n\n/**\n * Return multiple Markdown documents. Every heading should be its own document.\n */\nexport function splitContent(markdown: string) {\n const tree = getMarkdownAst(markdown)\n\n /** Sections */\n const sections: RootContent[][] = []\n\n /** Nodes inside a section */\n let nodes: RootContent[] = []\n\n tree.children?.forEach((node) => {\n // If the node is a heading, start a new section\n if (node.type === 'heading') {\n if (nodes.length) {\n sections.push(nodes)\n }\n\n sections.push([node])\n\n nodes = []\n }\n // Otherwise, add the node to the current section\n else {\n nodes.push(node)\n }\n })\n\n // Add any remaining nodes\n if (nodes.length) {\n sections.push(nodes)\n }\n\n return sections.map((section) => createDocument(section))\n}\n\n/**\n * Use remark to create a Markdown document from a list of nodes.\n */\nfunction createDocument(nodes: RootContent[]) {\n // Create the Markdown string\n const markdown = unified().use(remarkStringify).use(remarkGfm).stringify({\n type: 'root',\n children: nodes,\n })\n\n // Remove the whitespace\n return markdown.trim()\n}\n"],
"mappings": "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",
"sourcesContent": ["import type { Heading, Node, PhrasingContent, Root, RootContent } from 'mdast'\nimport rehypeExternalLinks from 'rehype-external-links'\nimport rehypeFormat from 'rehype-format'\nimport rehypeRaw from 'rehype-raw'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport rehypeStringify from 'rehype-stringify'\nimport remarkGfm from 'remark-gfm'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport remarkStringify from 'remark-stringify'\nimport { unified } from 'unified'\nimport { SKIP, visit } from 'unist-util-visit'\n\nimport { standardLanguages } from '@/languages'\nimport { rehypeAlert } from '@/rehype-alert'\nimport { rehypeHighlight } from '@/rehype-highlight'\n\ntype Options = {\n transform?: (node: Node) => Node\n type?: string\n}\n\nexport type { Node } from 'mdast'\n\n/**\n * Type-guard to check if a node is a heading.\n */\nexport const isHeading = (node: Node): node is Heading => {\n return node.type === 'heading' && 'depth' in node && 'children' in node\n}\n\n/**\n * Plugin to transform nodes in a Markdown AST\n */\nconst transformNodes =\n (options?: Readonly<Options> | null | undefined, ..._ignored: any[]) =>\n (tree: Node) => {\n if (!options?.transform || !options?.type) {\n return\n }\n\n visit(tree, options?.type, (node) => {\n options?.transform ? options?.transform(node) : node\n\n return SKIP\n })\n\n return\n }\n\n/**\n * Take a Markdown string and generate HTML from it\n */\nexport function htmlFromMarkdown(\n markdown: string,\n options?: {\n removeTags?: string[]\n allowTags?: string[]\n transform?: (node: Node) => Node\n transformType?: string\n },\n) {\n // Add permitted tags and remove stripped ones\n const removeTags = options?.removeTags ?? []\n const tagNames = [...(defaultSchema.tagNames ?? []), ...(options?.allowTags ?? [])].filter(\n (t) => !removeTags.includes(t),\n )\n\n const html = unified()\n // Parses markdown\n .use(remarkParse)\n // Support autolink literals, footnotes, strikethrough, tables and tasklists\n .use(remarkGfm)\n .use(transformNodes, {\n transform: options?.transform,\n type: options?.transformType,\n })\n // Allows any HTML tags\n .use(remarkRehype, { allowDangerousHtml: true })\n // Adds GitHub alerts\n .use(rehypeAlert)\n // Creates a HTML AST\n .use(rehypeRaw)\n // Removes disallowed tags\n .use(rehypeSanitize, {\n ...defaultSchema,\n // Don't prefix the heading ids\n clobberPrefix: '',\n // Makes it even more strict\n tagNames,\n attributes: {\n ...defaultSchema.attributes,\n abbr: ['title'],\n // Allow all class names while preserving the existing default attributes\n '*': [...(defaultSchema.attributes?.['*'] ?? []), 'className'],\n },\n // Strip content of dangerous elements, not just the tags\n strip: ['script', 'style', 'object', 'embed', 'form'],\n })\n // Syntax highlighting\n .use(rehypeHighlight, {\n languages: standardLanguages,\n // Enable auto detection\n detect: true,\n })\n // Adds target=\"_blank\" to external links\n .use(rehypeExternalLinks, { target: '_blank' })\n // Formats the HTML\n .use(rehypeFormat)\n // Converts the HTML AST to a string\n .use(rehypeStringify)\n // Run the pipeline\n .processSync(markdown)\n\n return html.toString()\n}\n\n/**\n * Create a Markdown AST from a string.\n */\nfunction getMarkdownAst(markdown: string): Root {\n return unified().use(remarkParse).use(remarkGfm).parse(markdown)\n}\n\n/**\n * Find all headings of a specific type in a Markdown AST.\n */\nexport function getHeadings(\n markdown: string,\n depth: number = 1,\n): {\n depth: number\n value: string\n}[] {\n const tree = getMarkdownAst(markdown)\n\n const nodes: {\n depth: number\n value: string\n }[] = []\n\n visit(tree, 'heading', (node) => {\n const text = textFromNode(node)\n\n if (text) {\n nodes.push({ depth: node.depth ?? depth, value: text })\n }\n })\n\n return nodes\n}\n\n/**\n * Extract plain text from a Markdown AST node (recursively).\n *\n * Handles headings with nested phrasing content such as links.\n */\nexport function textFromNode(node: Heading | PhrasingContent): string {\n if (node.type === 'text') {\n return node.value ?? ''\n }\n\n if ('children' in node && Array.isArray(node.children)) {\n return node.children.map((child) => textFromNode(child)).join('')\n }\n\n return ''\n}\n\n/**\n * Return multiple Markdown documents. Every heading should be its own document.\n */\nexport function splitContent(markdown: string) {\n const tree = getMarkdownAst(markdown)\n\n /** Sections */\n const sections: RootContent[][] = []\n\n /** Nodes inside a section */\n let nodes: RootContent[] = []\n\n tree.children?.forEach((node) => {\n // If the node is a heading, start a new section\n if (node.type === 'heading') {\n if (nodes.length) {\n sections.push(nodes)\n }\n\n sections.push([node])\n\n nodes = []\n }\n // Otherwise, add the node to the current section\n else {\n nodes.push(node)\n }\n })\n\n // Add any remaining nodes\n if (nodes.length) {\n sections.push(nodes)\n }\n\n return sections.map((section) => createDocument(section))\n}\n\n/**\n * Use remark to create a Markdown document from a list of nodes.\n */\nfunction createDocument(nodes: RootContent[]) {\n // Create the Markdown string\n const markdown = unified().use(remarkStringify).use(remarkGfm).stringify({\n type: 'root',\n children: nodes,\n })\n\n // Remove the whitespace\n return markdown.trim()\n}\n"],
"mappings": "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",
"names": []
}

@@ -19,3 +19,3 @@ {

],
"version": "0.2.3",
"version": "0.2.4",
"engines": {

@@ -95,3 +95,2 @@ "node": ">=20"

"@types/mdast": "^4.0.4",
"@types/unist": "^3.0.3",
"vfile": "^6.0.1",

@@ -98,0 +97,0 @@ "vite": "^7.3.1",