New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

rehype-highlight-code-lines

Package Overview
Dependencies
Maintainers
0
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rehype-highlight-code-lines - npm Package Compare versions

Comparing version

to
0.0.2

1

dist/esm/index.d.ts

@@ -5,2 +5,3 @@ import type { Plugin } from "unified";

showLineNumbers?: boolean;
lineContainerTagName?: "div" | "span";
};

@@ -7,0 +8,0 @@ export declare function clsx(arr: (string | false | null | undefined | 0)[]): string[];

79

dist/esm/index.js

@@ -5,2 +5,3 @@ import { visit, CONTINUE } from "unist-util-visit";

showLineNumbers: false,
lineContainerTagName: "span",
};

@@ -20,13 +21,42 @@ // a simple util for our use case, like clsx package

*
* flatten deep nodes
*
*/
function flattenCodeTree(children, className = [], newTree = []) {
for (let i = 0; i < children.length; i++) {
const node = children[i];
console.log(node);
if (node.type !== "element") {
newTree = newTree.concat([node]);
}
else if (node.children.length === 1 && node.children[0].type !== "element") {
// @ts-expect-error
node.properties.className = className.concat(node.properties.className);
newTree = newTree.concat([node]);
}
else {
// @ts-expect-error
const classNames = className.concat(node.properties?.className || []);
newTree = newTree.concat(flattenCodeTree(node.children, classNames));
}
}
return newTree;
}
/**
*
* constructs the line element
*
*/
const createLine = (children, lineNumber, classNames) => {
const createLine = (children, lineNumber, showLineNumbers, linesToBeHighlighted) => {
return {
type: "element",
tagName: "div",
tagName: settings.lineContainerTagName,
children,
properties: {
className: classNames,
...(lineNumber && { "data-line-number": lineNumber }),
className: clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
]),
dataLineNumber: showLineNumbers ? lineNumber : undefined,
},

@@ -37,3 +67,3 @@ };

const RE = /\r?\n|\r/g;
function starryNightGutter(tree, showLineNumbers, linesToBeHighlighted) {
function gutter(tree, showLineNumbers, linesToBeHighlighted) {
const replacement = [];

@@ -50,3 +80,3 @@ let index = -1;

while (match) {
// Nodes in this line.
// Nodes in this line. (current child is exclusive)
const line = tree.children.slice(start, index);

@@ -62,17 +92,12 @@ /* v8 ignore start */

if (match.index > textStart) {
line.push({
type: "text",
value: child.value.slice(textStart, match.index),
});
const value = child.value.slice(textStart, match.index);
line.push({ type: "text", value });
}
// Add a line, and the eol.
// Add a line
lineNumber += 1;
replacement.push(createLine(line, showLineNumbers ? lineNumber : undefined, clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
])), {
type: "text",
value: match[0],
});
replacement.push(createLine(line, lineNumber, showLineNumbers, linesToBeHighlighted));
// Add eol if the tag name is "span"
if (settings.lineContainerTagName === "span") {
replacement.push({ type: "text", value: match[0] });
}
start = index + 1;

@@ -97,7 +122,3 @@ textStart = match.index + match[0].length;

lineNumber += 1;
replacement.push(createLine(line, showLineNumbers ? lineNumber : undefined, clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
])));
replacement.push(createLine(line, lineNumber, showLineNumbers, linesToBeHighlighted));
}

@@ -136,5 +157,5 @@ /* v8 ignore end */

meta = meta ? language + meta : language;
const index = code.properties.className.findIndex(testingFunction);
if (index > -1) {
code.properties.className[index] = "language-unknown";
const idx = code.properties.className.findIndex(testingFunction);
if (idx > -1) {
code.properties.className[idx] = "language-unknown";
}

@@ -153,4 +174,6 @@ }

return;
// flatten deeper nodes into first level <span>s an texts
code.children = flattenCodeTree(code.children);
// add wrapper for each line mutating the code element
starryNightGutter(code, showLineNumbers, linesToBeHighlighted);
gutter(code, showLineNumbers, linesToBeHighlighted);
});

@@ -157,0 +180,0 @@ };

{
"name": "rehype-highlight-code-lines",
"version": "0.0.1",
"version": "0.0.2",
"description": "Rehype plugin to add line numbers to code blocks and allow highlighting of desired code lines",

@@ -5,0 +5,0 @@ "type": "module",

@@ -11,3 +11,3 @@ # rehype-highlight-code-lines

This package is a [unified][unified] ([rehype][rehype]) plugin **to add wrapper to each line in a code block, allowing numbering of the code block and highlighting desired lines of code**.
This package is a [unified][unified] ([rehype][rehype]) plugin **to add container to each line in a code block, allowing numbering of the code block and highlighting desired lines of code**.

@@ -135,9 +135,12 @@ **[unified][unified]** is a project that transforms content with abstract syntax trees (ASTs) using the new parser **[micromark][micromark]**. **[remark][remark]** adds support for markdown to unified. **[mdast][mdast]** is the Markdown Abstract Syntax Tree (AST) which is a specification for representing markdown in a syntax tree. "**[rehype][rehype]**" is a tool that transforms HTML with plugins. "**[hast][hast]**" stands for HTML Abstract Syntax Tree (HAST) that rehype uses.

***Note:** `hljs` prefix comes from `rehype-highlight`*.
## Options
There is one **boolean** option.
All options are **optional** and have **default values**.
```typescript
type HighlightLinesOptions = {
showLineNumbers?: boolean; // the default is "false"
showLineNumbers?: boolean; // default is "false"
lineContainerTagName?: "div" | "span"; // default is "span"
};

@@ -148,2 +151,30 @@

#### `showLineNumbers`
It is a **boolean** option which is for all code blocks will be numbered.
By default, it is `false`.
```javascript
use(rehypeHighlightLines, {
showLineNumbers: true,
});
```
Now, all code blocks will become numbered by line.
#### `lineContainerTagName`
It is a **union** type option which is **"div" | "span"** for providing custom HTML tag name for code lines.
By default, it is `span` which is **inline** level container. If you set it as `div`, the container will be **block** level, in perspective of CSS.
```javascript
use(rehypeHighlightLines, {
lineContainerTagName: "div",
});
```
Now, the code line container's tag name will be `div`.
### Examples:

@@ -150,0 +181,0 @@

@@ -6,4 +6,11 @@ import type { Plugin } from "unified";

// eslint-disable-next-line @typescript-eslint/ban-types
type Prettify<T> = { [K in keyof T]: T[K] } & {};
// eslint-disable-next-line @typescript-eslint/ban-types
type PartiallyRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
export type HighlightLinesOptions = {
showLineNumbers?: boolean;
lineContainerTagName?: "div" | "span";
};

@@ -13,4 +20,9 @@

showLineNumbers: false,
lineContainerTagName: "span",
};
type PartiallyRequiredHighlightLinesOptions = Prettify<
PartiallyRequired<HighlightLinesOptions, "showLineNumbers" | "lineContainerTagName">
>;
type CodeData = ElementData & {

@@ -31,6 +43,38 @@ meta?: string;

const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
const settings = Object.assign({}, DEFAULT_SETTINGS, options);
const settings = Object.assign(
{},
DEFAULT_SETTINGS,
options,
) as PartiallyRequiredHighlightLinesOptions;
/**
*
* flatten deep nodes
*
*/
function flattenCodeTree(
children: ElementContent[],
className: string[] = [],
newTree: ElementContent[] = [],
): ElementContent[] {
for (let i = 0; i < children.length; i++) {
const node = children[i];
console.log(node);
if (node.type !== "element") {
newTree = newTree.concat([node]);
} else if (node.children.length === 1 && node.children[0].type !== "element") {
// @ts-expect-error
node.properties.className = className.concat(node.properties.className);
newTree = newTree.concat([node]);
} else {
// @ts-expect-error
const classNames = className.concat(node.properties?.className || []);
newTree = newTree.concat(flattenCodeTree(node.children, classNames));
}
}
return newTree;
}
/**
*
* constructs the line element

@@ -41,12 +85,17 @@ *

children: ElementContent[],
lineNumber: number | undefined,
classNames: string[],
lineNumber: number,
showLineNumbers: boolean,
linesToBeHighlighted: number[],
): Element => {
return {
type: "element",
tagName: "div",
tagName: settings.lineContainerTagName,
children,
properties: {
className: classNames,
...(lineNumber && { "data-line-number": lineNumber }),
className: clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
]),
dataLineNumber: showLineNumbers ? lineNumber : undefined,
},

@@ -59,8 +108,5 @@ };

function starryNightGutter(
tree: Element,
showLineNumbers: boolean,
linesToBeHighlighted: number[],
) {
function gutter(tree: Element, showLineNumbers: boolean, linesToBeHighlighted: number[]) {
const replacement: Array<ElementContent> = [];
let index = -1;

@@ -79,3 +125,3 @@ let start = 0;

while (match) {
// Nodes in this line.
// Nodes in this line. (current child is exclusive)
const line = tree.children.slice(start, index);

@@ -95,26 +141,15 @@

if (match.index > textStart) {
line.push({
type: "text",
value: child.value.slice(textStart, match.index),
});
const value = child.value.slice(textStart, match.index);
line.push({ type: "text", value });
}
// Add a line, and the eol.
// Add a line
lineNumber += 1;
replacement.push(
createLine(
line,
showLineNumbers ? lineNumber : undefined,
clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
]),
),
{
type: "text",
value: match[0],
},
);
replacement.push(createLine(line, lineNumber, showLineNumbers, linesToBeHighlighted));
// Add eol if the tag name is "span"
if (settings.lineContainerTagName === "span") {
replacement.push({ type: "text", value: match[0] });
}
start = index + 1;

@@ -144,13 +179,3 @@ textStart = match.index + match[0].length;

lineNumber += 1;
replacement.push(
createLine(
line,
showLineNumbers ? lineNumber : undefined,
clsx([
"code-line",
showLineNumbers && "numbered-code-line",
linesToBeHighlighted.includes(lineNumber) && "highlighted-code-line",
]),
),
);
replacement.push(createLine(line, lineNumber, showLineNumbers, linesToBeHighlighted));
}

@@ -199,6 +224,6 @@

const index = code.properties.className.findIndex(testingFunction);
const idx = code.properties.className.findIndex(testingFunction);
if (index > -1) {
code.properties.className[index] = "language-unknown";
if (idx > -1) {
code.properties.className[idx] = "language-unknown";
}

@@ -220,4 +245,7 @@ }

// flatten deeper nodes into first level <span>s an texts
code.children = flattenCodeTree(code.children);
// add wrapper for each line mutating the code element
starryNightGutter(code, showLineNumbers, linesToBeHighlighted);
gutter(code, showLineNumbers, linesToBeHighlighted);
});

@@ -224,0 +252,0 @@ };

Sorry, the diff of this file is not supported yet