@scalar/code-highlight 0.3.0 → 0.3.2

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 (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/code/highlight.js +58 -38
  3. package/dist/code/index.js +1 -5
  4. package/dist/code/line-numbers.js +76 -51
  5. package/dist/constants.js +10 -12
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +5 -14
  9. package/dist/languages/basic.js +28 -31
  10. package/dist/languages/index.js +3 -9
  11. package/dist/languages/json-yaml.js +7 -10
  12. package/dist/languages/standard.js +115 -100
  13. package/dist/markdown/index.d.ts +1 -1
  14. package/dist/markdown/index.d.ts.map +1 -1
  15. package/dist/markdown/index.js +1 -2
  16. package/dist/markdown/markdown.js +148 -100
  17. package/dist/rehype-alert/index.js +1 -5
  18. package/dist/rehype-alert/rehype-alert.js +99 -91
  19. package/dist/rehype-highlight/index.js +1 -5
  20. package/dist/rehype-highlight/rehype-highlight.js +93 -85
  21. package/package.json +11 -17
  22. package/dist/code/highlight.js.map +0 -7
  23. package/dist/code/index.js.map +0 -7
  24. package/dist/code/line-numbers.js.map +0 -7
  25. package/dist/constants.js.map +0 -7
  26. package/dist/index.js.map +0 -7
  27. package/dist/languages/basic.js.map +0 -7
  28. package/dist/languages/index.js.map +0 -7
  29. package/dist/languages/json-yaml.js.map +0 -7
  30. package/dist/languages/standard.js.map +0 -7
  31. package/dist/markdown/index.js.map +0 -7
  32. package/dist/markdown/markdown.js.map +0 -7
  33. package/dist/rehype-alert/index.js.map +0 -7
  34. package/dist/rehype-alert/rehype-alert.js.map +0 -7
  35. package/dist/rehype-highlight/index.js.map +0 -7
  36. package/dist/rehype-highlight/rehype-highlight.js.map +0 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @scalar/code-highlight
2
2
 
3
+ ## 0.3.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#8664](https://github.com/scalar/scalar/pull/8664): refactor: replace wildcard export barrels with explicit named re-exports
8
+
9
+ ## 0.3.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#8466](https://github.com/scalar/scalar/pull/8466): chore: new build pipeline
14
+
3
15
  ## 0.3.0
4
16
 
5
17
  ### Minor Changes
@@ -1,42 +1,62 @@
1
- import rehypeParse from "rehype-parse";
2
- import rehypeStringify from "rehype-stringify";
3
- import { unified } from "unified";
4
- import { visit } from "unist-util-visit";
5
- import { lowlightLanguageMappings } from "../constants.js";
6
- import { rehypeHighlight } from "../rehype-highlight/index.js";
7
- import { codeBlockLinesPlugin } from "./line-numbers.js";
8
- function syntaxHighlight(codeString, options) {
9
- const credentials = (typeof options?.maskCredentials === "string" ? [options.maskCredentials] : options?.maskCredentials ?? []).filter((c) => {
10
- if (c.length < 3) {
11
- return false;
12
- }
13
- return true;
14
- });
15
- const className = `language-${lowlightLanguageMappings[options.lang] ?? options.lang}`;
16
- const nullPlugin = () => {
17
- };
18
- const html = unified().use(rehypeParse, { fragment: true }).use(injectRawCodeStringPlugin(codeString)).use(rehypeHighlight, {
19
- languages: options.languages
20
- }).use(options?.lineNumbers ? codeBlockLinesPlugin : nullPlugin).use(rehypeStringify).processSync(`<pre><code class="${className}"></code></pre>`);
21
- const htmlString = html.toString();
22
- return credentials.length ? credentials.reduce(
23
- (acc, credential) => acc.split(credential).join(`<span class="credential"><span class="credential-value">${credential}</span></span>`),
24
- htmlString
25
- ) : htmlString;
1
+ import rehypeParse from 'rehype-parse';
2
+ import rehypeStringify from 'rehype-stringify';
3
+ import { unified } from 'unified';
4
+ import { visit } from 'unist-util-visit';
5
+ import { lowlightLanguageMappings } from '../constants.js';
6
+ import { rehypeHighlight } from '../rehype-highlight/index.js';
7
+ import { codeBlockLinesPlugin } from './line-numbers.js';
8
+ /**
9
+ * Syntax highlights a code string using the `rehype-highlight` library.
10
+ */
11
+ export function syntaxHighlight(codeString, options) {
12
+ // Simple restriction on credentials to prevent unexpected behavior
13
+ const credentials = (typeof options?.maskCredentials === 'string' ? [options.maskCredentials] : (options?.maskCredentials ?? [])).filter((c) => {
14
+ // Credentials must be at least 3 characters to mask.
15
+ if (c.length < 3) {
16
+ return false;
17
+ }
18
+ return true;
19
+ });
20
+ // Classname is used by lowlight to select the language model
21
+ const className = `language-${lowlightLanguageMappings[options.lang] ?? options.lang}`;
22
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: empty plugin
23
+ const nullPlugin = (() => { });
24
+ const html = unified()
25
+ // Parses markdown
26
+ .use(rehypeParse, { fragment: true })
27
+ // Raw code string must be injected after initial hast parsing
28
+ // so that HTML code is not parsed into the hast tree
29
+ .use(injectRawCodeStringPlugin(codeString))
30
+ // Syntax highlighting
31
+ .use(rehypeHighlight, {
32
+ languages: options.languages,
33
+ })
34
+ .use(options?.lineNumbers ? codeBlockLinesPlugin : nullPlugin)
35
+ // Converts the HTML AST to a string
36
+ .use(rehypeStringify)
37
+ // Run the pipeline
38
+ .processSync(`<pre><code class="${className}"></code></pre>`);
39
+ const htmlString = html.toString();
40
+ // Replace any credentials with a wrapper element
41
+ return credentials.length
42
+ ? credentials.reduce((acc, credential) => acc
43
+ .split(credential)
44
+ .join(`<span class="credential"><span class="credential-value">${credential}</span></span>`), htmlString)
45
+ : htmlString;
26
46
  }
47
+ /**
48
+ * To prevent unified from parsing any content of the code string we inject
49
+ * it as a raw text node into the AST tree as a child of the code element
50
+ */
27
51
  function injectRawCodeStringPlugin(rawCodeString) {
28
- return () => (tree) => {
29
- visit(tree, "element", (node) => {
30
- if (node.tagName === "code") {
31
- node.children.push({
32
- type: "text",
33
- value: rawCodeString
52
+ return () => (tree) => {
53
+ visit(tree, 'element', (node) => {
54
+ if (node.tagName === 'code') {
55
+ node.children.push({
56
+ type: 'text',
57
+ value: rawCodeString,
58
+ });
59
+ }
34
60
  });
35
- }
36
- });
37
- };
61
+ };
38
62
  }
39
- export {
40
- syntaxHighlight
41
- };
42
- //# sourceMappingURL=highlight.js.map
@@ -1,5 +1 @@
1
- import { syntaxHighlight } from "./highlight.js";
2
- export {
3
- syntaxHighlight
4
- };
5
- //# sourceMappingURL=index.js.map
1
+ export { syntaxHighlight } from './highlight.js';
@@ -1,69 +1,94 @@
1
- import { visit } from "unist-util-visit";
1
+ import { visit } from 'unist-util-visit';
2
+ // ---------------------------------------------------------------------------
3
+ // Line Numbering plugin
2
4
  function isText(element) {
3
- return element?.type === "text";
5
+ return element?.type === 'text';
4
6
  }
5
7
  function isElement(node) {
6
- return node?.type === "element";
8
+ return node?.type === 'element';
7
9
  }
8
10
  function textElement(value) {
9
- return { type: "text", value };
11
+ return { type: 'text', value };
10
12
  }
11
13
  function lineBreak() {
12
- return { type: "text", value: "\n" };
14
+ return { type: 'text', value: '\n' };
13
15
  }
14
- function codeBlockLinesPlugin() {
15
- return (tree) => {
16
- visit(tree, "element", (node, _i, parent) => {
17
- if (parent?.type === "element" && parent.tagName === "pre" && node.tagName === "code") {
18
- let numLines = 0;
19
- node.children = addLines(node);
20
- node.children.forEach((child) => {
21
- if (child.type === "element" && child.tagName === "span") {
22
- const lastChild = child.children[child.children.length - 1];
23
- if (lastChild && (!isText(lastChild) || isText(lastChild) && !hasLineBreak(lastChild))) {
24
- child.children.push(lineBreak());
25
- numLines++;
16
+ /**
17
+ * Adds lines to code blocks
18
+ */
19
+ export function codeBlockLinesPlugin() {
20
+ return (tree) => {
21
+ visit(tree, 'element', (node, _i, parent) => {
22
+ if (parent?.type === 'element' && parent.tagName === 'pre' && node.tagName === 'code') {
23
+ let numLines = 0;
24
+ // Wraps each line in a span
25
+ node.children = addLines(node);
26
+ // Adds a line break to the end of each line
27
+ node.children.forEach((child) => {
28
+ if (child.type === 'element' && child.tagName === 'span') {
29
+ const lastChild = child.children[child.children.length - 1];
30
+ if (lastChild && (!isText(lastChild) || (isText(lastChild) && !hasLineBreak(lastChild)))) {
31
+ child.children.push(lineBreak());
32
+ numLines++;
33
+ }
34
+ }
35
+ });
36
+ // We need to maintain a count of the total lines to allow space for the labels
37
+ node.properties.style = [`--line-count: ${numLines};`, `--line-digits: ${numLines.toString().length};`];
26
38
  }
27
- }
28
39
  });
29
- node.properties.style = [`--line-count: ${numLines};`, `--line-digits: ${numLines.toString().length};`];
30
- }
31
- });
32
- };
40
+ // console.log('NUMBER OF LINES IS: ', numLines)
41
+ };
33
42
  }
43
+ /**
44
+ * Adds lines to a node recursively and returns them
45
+ *
46
+ * @param node - The node to add lines to
47
+ * @param lines - The current lines
48
+ * @param copyParent - Whether to copy the parent node to save the original node styles
49
+ */
34
50
  function addLines(node, lines = [], copyParent) {
35
- const line = () => lines[lines.length - 1] ?? (lines.push(createLine()) && lines[lines.length - 1] || void 0);
36
- node.children.forEach((child) => {
37
- if (isText(child) && hasLineBreak(child)) {
38
- const split = child.value.split(/\n/);
39
- split.forEach((content, i) => {
40
- if (copyParent) {
41
- line()?.children.push({ ...node, children: [textElement(content)] });
42
- } else {
43
- line()?.children.push(textElement(content));
51
+ const line = () => lines[lines.length - 1] ?? ((lines.push(createLine()) && lines[lines.length - 1]) || undefined);
52
+ node.children.forEach((child) => {
53
+ if (isText(child) && hasLineBreak(child)) {
54
+ const split = child.value.split(/\n/);
55
+ split.forEach((content, i) => {
56
+ if (copyParent) {
57
+ line()?.children.push({ ...node, children: [textElement(content)] });
58
+ }
59
+ else {
60
+ line()?.children.push(textElement(content));
61
+ }
62
+ i !== split.length - 1 && lines.push(createLine());
63
+ });
64
+ }
65
+ else if (isElement(child) && child.children.some(hasLineBreak)) {
66
+ addLines(child, lines, true);
44
67
  }
45
- i !== split.length - 1 && lines.push(createLine());
46
- });
47
- } else if (isElement(child) && child.children.some(hasLineBreak)) {
48
- addLines(child, lines, true);
49
- } else {
50
- line()?.children.push(child);
51
- }
52
- });
53
- return lines;
68
+ else {
69
+ line()?.children.push(child);
70
+ }
71
+ });
72
+ return lines;
54
73
  }
74
+ /**
75
+ * Creates a new line element
76
+ *
77
+ * @param children - The children the line should have initially
78
+ */
55
79
  function createLine(...children) {
56
- return {
57
- type: "element",
58
- tagName: "span",
59
- properties: { class: ["line"] },
60
- children
61
- };
80
+ return {
81
+ type: 'element',
82
+ tagName: 'span',
83
+ properties: { class: ['line'] },
84
+ children,
85
+ };
62
86
  }
87
+ /**
88
+ * Checks if a node has a line break
89
+ *
90
+ * @param node - The node to check
91
+ */
63
92
  function hasLineBreak(node) {
64
- return isText(node) && /\r?\n/.test(node.value) || isElement(node) && node.children.some(hasLineBreak);
93
+ return (isText(node) && /\r?\n/.test(node.value)) || (isElement(node) && node.children.some(hasLineBreak));
65
94
  }
66
- export {
67
- codeBlockLinesPlugin
68
- };
69
- //# sourceMappingURL=line-numbers.js.map
package/dist/constants.js CHANGED
@@ -1,13 +1,11 @@
1
- const lowlightLanguageMappings = {
2
- "ts": "typescript",
3
- "js": "javascript",
4
- "py": "python",
5
- "py3": "python",
6
- "c#": "csharp",
7
- "c++": "cpp",
8
- "node": "javascript"
1
+ /** Map common markdown language shortcuts to lowlight languages */
2
+ export const lowlightLanguageMappings = {
3
+ 'ts': 'typescript',
4
+ 'js': 'javascript',
5
+ 'py': 'python',
6
+ 'py3': 'python',
7
+ 'c#': 'csharp',
8
+ 'c++': 'cpp',
9
+ 'node': 'javascript',
9
10
  };
10
- export {
11
- lowlightLanguageMappings
12
- };
13
- //# sourceMappingURL=constants.js.map
11
+ //
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { syntaxHighlight } from './code/index.js';
2
2
  export { lowlightLanguageMappings } from './constants.js';
3
- export * from './languages/index.js';
3
+ export { basicLanguages, jsonYamlLanguages, standardLanguages } from './languages/index.js';
4
4
  export { type Node, htmlFromMarkdown, isHeading, textFromNode } from './markdown/index.js';
5
5
  export { rehypeHighlight } from './rehype-highlight/index.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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,KAAK,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
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,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClF,OAAO,EAAE,KAAK,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -1,14 +1,5 @@
1
- import { syntaxHighlight } from "./code/index.js";
2
- import { lowlightLanguageMappings } from "./constants.js";
3
- export * from "./languages/index.js";
4
- import { htmlFromMarkdown, isHeading, textFromNode } from "./markdown/index.js";
5
- import { rehypeHighlight } from "./rehype-highlight/index.js";
6
- export {
7
- htmlFromMarkdown,
8
- isHeading,
9
- lowlightLanguageMappings,
10
- rehypeHighlight,
11
- syntaxHighlight,
12
- textFromNode
13
- };
14
- //# sourceMappingURL=index.js.map
1
+ export { syntaxHighlight } from './code/index.js';
2
+ export { lowlightLanguageMappings } from './constants.js';
3
+ export { basicLanguages, jsonYamlLanguages, standardLanguages } from './languages/index.js';
4
+ export { htmlFromMarkdown, isHeading, textFromNode } from './markdown/index.js';
5
+ export { rehypeHighlight } from './rehype-highlight/index.js';
@@ -1,33 +1,30 @@
1
- import bash from "highlight.js/lib/languages/bash";
2
- import css from "highlight.js/lib/languages/css";
3
- import javascript from "highlight.js/lib/languages/javascript";
4
- import json from "highlight.js/lib/languages/json";
5
- import less from "highlight.js/lib/languages/less";
6
- import markdown from "highlight.js/lib/languages/markdown";
7
- import plaintext from "highlight.js/lib/languages/plaintext";
8
- import python from "highlight.js/lib/languages/python";
9
- import scss from "highlight.js/lib/languages/scss";
10
- import shell from "highlight.js/lib/languages/shell";
11
- import typescript from "highlight.js/lib/languages/typescript";
12
- import xml from "highlight.js/lib/languages/xml";
13
- import yaml from "highlight.js/lib/languages/yaml";
1
+ import bash from 'highlight.js/lib/languages/bash';
2
+ import css from 'highlight.js/lib/languages/css';
3
+ import javascript from 'highlight.js/lib/languages/javascript';
4
+ import json from 'highlight.js/lib/languages/json';
5
+ import less from 'highlight.js/lib/languages/less';
6
+ import markdown from 'highlight.js/lib/languages/markdown';
7
+ import plaintext from 'highlight.js/lib/languages/plaintext';
8
+ import python from 'highlight.js/lib/languages/python';
9
+ import scss from 'highlight.js/lib/languages/scss';
10
+ import shell from 'highlight.js/lib/languages/shell';
11
+ import typescript from 'highlight.js/lib/languages/typescript';
12
+ import xml from 'highlight.js/lib/languages/xml';
13
+ import yaml from 'highlight.js/lib/languages/yaml';
14
14
  const basicLanguages = {
15
- bash,
16
- css,
17
- html: xml,
18
- javascript,
19
- json,
20
- less,
21
- markdown,
22
- plaintext,
23
- python,
24
- scss,
25
- shell,
26
- typescript,
27
- xml,
28
- yaml
15
+ bash,
16
+ css,
17
+ html: xml,
18
+ javascript,
19
+ json,
20
+ less,
21
+ markdown,
22
+ plaintext,
23
+ python,
24
+ scss,
25
+ shell,
26
+ typescript,
27
+ xml,
28
+ yaml,
29
29
  };
30
- export {
31
- basicLanguages
32
- };
33
- //# sourceMappingURL=basic.js.map
30
+ export { basicLanguages };
@@ -1,9 +1,3 @@
1
- import { basicLanguages } from "./basic.js";
2
- import { jsonYamlLanguages } from "./json-yaml.js";
3
- import { standardLanguages } from "./standard.js";
4
- export {
5
- basicLanguages,
6
- jsonYamlLanguages,
7
- standardLanguages
8
- };
9
- //# sourceMappingURL=index.js.map
1
+ export { basicLanguages } from './basic.js';
2
+ export { jsonYamlLanguages } from './json-yaml.js';
3
+ export { standardLanguages } from './standard.js';
@@ -1,12 +1,9 @@
1
- import json from "highlight.js/lib/languages/json";
2
- import plaintext from "highlight.js/lib/languages/plaintext";
3
- import yaml from "highlight.js/lib/languages/yaml";
1
+ import json from 'highlight.js/lib/languages/json';
2
+ import plaintext from 'highlight.js/lib/languages/plaintext';
3
+ import yaml from 'highlight.js/lib/languages/yaml';
4
4
  const jsonYamlLanguages = {
5
- json,
6
- plaintext,
7
- yaml
5
+ json,
6
+ plaintext,
7
+ yaml,
8
8
  };
9
- export {
10
- jsonYamlLanguages
11
- };
12
- //# sourceMappingURL=json-yaml.js.map
9
+ export { jsonYamlLanguages };