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

remark-custom-container

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

remark-custom-container - npm Package Compare versions

Comparing version 1.1.2 to 1.2.0

LICENSE

5

dist/esm/index.d.ts

@@ -1,3 +0,4 @@

import { Plugin } from "unified";
export declare const REGEX_CUSTOM_CONTAINER: RegExp;
import type { Plugin } from "unified";
export declare const REGEX_BEGIN: RegExp;
export declare const REGEX_END: RegExp;
interface CustomContainerOptions {

@@ -4,0 +5,0 @@ /**

111

dist/esm/index.js
import { visit } from "unist-util-visit";
export const REGEX_CUSTOM_CONTAINER = /^\s*:::\s*(\w+)\s*(.*?)[\n\r]([\s\S]+?)\s*:::\s*?/;
export const REGEX_BEGIN = /^\s*:::\s*(\w+)\s*(.*)?/;
export const REGEX_END = /^\s*:::$/;
const DEFAULT_SETTINGS = {

@@ -10,45 +11,81 @@ className: "remark-container",

};
const isParagraph = (node) => {
return "paragraph" === node.type;
};
export const plugin = (options) => {
const settings = Object.assign({}, DEFAULT_SETTINGS, options);
// Constructs `Parent` node of custom directive which contains given children.
const constructContainer = (children, className) => {
return {
type: "container",
children,
data: {
hName: settings.containerTag,
hProperties: {
className: [settings.className, className.toLowerCase()],
},
},
};
};
const constructTitle = (title) => {
return {
type: "paragraph",
children: [{ type: "text", value: title }],
data: {
hName: "div",
hProperties: { className: [`${settings.className}__title`] },
},
};
};
const transformer = (tree) => {
visit(tree, (node, index, parent) => {
if (index == null)
return;
visit(tree, (_node, _index, parent) => {
if (!parent)
return;
if (!isLiteralNode(node))
return;
if (typeof node.value !== "string" || node.type !== "text")
return;
const match = node.value.match(REGEX_CUSTOM_CONTAINER);
if (!match)
return;
// NOTE title may be null
const [_input, type, title, content] = match;
const children = [];
if (title.length > 0) {
children.push({
type: "container",
children: [{ type: "text", value: title }],
data: {
hName: "div",
hProperties: { className: [`${settings.className}__title`] },
},
});
const len = parent.children.length;
// we walk through each children in `parent` to look for custom directive.
let currentIndex = -1;
while (currentIndex < len - 1) {
currentIndex += 1;
// check if currentIndex of children contains begin node of custom directive
const currentNode = parent.children[currentIndex];
children.push(currentNode);
if (!isParagraph(currentNode))
continue;
// XXX: Consider checking other children in currentNode
const currentElem = currentNode.children[0];
if (!isLiteralNode(currentElem))
continue;
const match = currentElem.value.match(REGEX_BEGIN);
if (!match)
continue;
// Here we're inside of the custom directive. let's find nearest closing directive.
// remove last element, which is custom directive marker.
children.pop();
const beginIndex = currentIndex;
let innerIndex = currentIndex - 1;
while (innerIndex < len - 1) {
innerIndex += 1;
const currentNode = parent.children[innerIndex];
if (!isParagraph(currentNode))
continue;
const currentElem = currentNode.children[0];
if (!isLiteralNode(currentElem) ||
!currentElem.value.match(REGEX_END))
continue;
// here we found the closing directive.
const [_input, type, title] = match;
// remove surrounding `:::` markers and treat rest of them as children of the container
const containerChildren = parent.children.slice(beginIndex + 1, innerIndex);
if (title?.length > 0) {
containerChildren.splice(0, 0, constructTitle(title));
}
const container = constructContainer(containerChildren, type.toLowerCase());
children.push(container);
currentIndex = innerIndex - 1;
break;
}
currentIndex += 1;
}
children.push({
type: "text",
value: content,
});
const container = {
type: "container",
children,
data: {
hName: settings.containerTag,
hProperties: {
className: [settings.className, type.toLowerCase()],
},
},
};
parent.children[index] = container;
parent.children = children;
});

@@ -55,0 +92,0 @@ };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.plugin = exports.REGEX_CUSTOM_CONTAINER = void 0;
exports.plugin = exports.REGEX_END = exports.REGEX_BEGIN = void 0;
const unist_util_visit_1 = require("unist-util-visit");
exports.REGEX_CUSTOM_CONTAINER = /^\s*:::\s*(\w+)\s*(.*?)[\n\r]([\s\S]+?)\s*:::\s*?/;
exports.REGEX_BEGIN = /^\s*:::\s*(\w+)\s*(.*)?/;
exports.REGEX_END = /^\s*:::$/;
const DEFAULT_SETTINGS = {

@@ -13,45 +14,81 @@ className: "remark-container",

};
const isParagraph = (node) => {
return "paragraph" === node.type;
};
const plugin = (options) => {
const settings = Object.assign({}, DEFAULT_SETTINGS, options);
// Constructs `Parent` node of custom directive which contains given children.
const constructContainer = (children, className) => {
return {
type: "container",
children,
data: {
hName: settings.containerTag,
hProperties: {
className: [settings.className, className.toLowerCase()],
},
},
};
};
const constructTitle = (title) => {
return {
type: "paragraph",
children: [{ type: "text", value: title }],
data: {
hName: "div",
hProperties: { className: [`${settings.className}__title`] },
},
};
};
const transformer = (tree) => {
(0, unist_util_visit_1.visit)(tree, (node, index, parent) => {
if (index == null)
return;
(0, unist_util_visit_1.visit)(tree, (_node, _index, parent) => {
if (!parent)
return;
if (!isLiteralNode(node))
return;
if (typeof node.value !== "string" || node.type !== "text")
return;
const match = node.value.match(exports.REGEX_CUSTOM_CONTAINER);
if (!match)
return;
// NOTE title may be null
const [_input, type, title, content] = match;
const children = [];
if (title.length > 0) {
children.push({
type: "container",
children: [{ type: "text", value: title }],
data: {
hName: "div",
hProperties: { className: [`${settings.className}__title`] },
},
});
const len = parent.children.length;
// we walk through each children in `parent` to look for custom directive.
let currentIndex = -1;
while (currentIndex < len - 1) {
currentIndex += 1;
// check if currentIndex of children contains begin node of custom directive
const currentNode = parent.children[currentIndex];
children.push(currentNode);
if (!isParagraph(currentNode))
continue;
// XXX: Consider checking other children in currentNode
const currentElem = currentNode.children[0];
if (!isLiteralNode(currentElem))
continue;
const match = currentElem.value.match(exports.REGEX_BEGIN);
if (!match)
continue;
// Here we're inside of the custom directive. let's find nearest closing directive.
// remove last element, which is custom directive marker.
children.pop();
const beginIndex = currentIndex;
let innerIndex = currentIndex - 1;
while (innerIndex < len - 1) {
innerIndex += 1;
const currentNode = parent.children[innerIndex];
if (!isParagraph(currentNode))
continue;
const currentElem = currentNode.children[0];
if (!isLiteralNode(currentElem) ||
!currentElem.value.match(exports.REGEX_END))
continue;
// here we found the closing directive.
const [_input, type, title] = match;
// remove surrounding `:::` markers and treat rest of them as children of the container
const containerChildren = parent.children.slice(beginIndex + 1, innerIndex);
if (title?.length > 0) {
containerChildren.splice(0, 0, constructTitle(title));
}
const container = constructContainer(containerChildren, type.toLowerCase());
children.push(container);
currentIndex = innerIndex - 1;
break;
}
currentIndex += 1;
}
children.push({
type: "text",
value: content,
});
const container = {
type: "container",
children,
data: {
hName: settings.containerTag,
hProperties: {
className: [settings.className, type.toLowerCase()],
},
},
};
parent.children[index] = container;
parent.children = children;
});

@@ -58,0 +95,0 @@ };

{
"name": "remark-custom-container",
"version": "1.1.2",
"version": "1.2.0",
"description": "remark parser plugin for custom directive in markdown",

@@ -35,15 +35,14 @@ "author": "koka831",

"devDependencies": {
"@jest/types": "^27.0.6",
"@types/jest": "^27.0.3",
"@types/node": "^16.4.2",
"@jest/types": "^29.3.1",
"@types/jest": "^29.2.3",
"@types/node": "^18.11.9",
"@types/unist": "^2.0.3",
"@typescript-eslint/eslint-plugin": "^4.28.4",
"@typescript-eslint/parser": "^4.28.4",
"eslint": "^8.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.0.6",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"jest": "^29.3.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.2",
"rehype-stringify": "^8.0.0",
"prettier": "^2.7.1",
"rehype-stringify": "^9.0.3",
"remark": "^14.0.0",

@@ -53,8 +52,8 @@ "remark-gfm": "^3.0.0",

"rimraf": "^3.0.2",
"ts-jest": "^27.0.4",
"ts-node": "^10.1.0",
"typescript": "^4.3.5",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"typescript": "^4.9.3",
"unified": "^10.1.0",
"vfile": "^5.1.0"
"vfile": "^5.3.6"
}
}
# remark-custom-container
[remarkjs][remarkjs] parser plugin for custom directive (compatible with new parser in remark. see [#536][536])
NOTE: This plugin is highly inspired by [vuepress-plugin-container][vuepress-plugin-container].
> **Note**
> This plugin is highly inspired by [vuepress-plugin-container][vuepress-plugin-container].
This package is ESM only: Node 12+ is needed to use it and it must be `import`ed instead of `require`d.

@@ -16,3 +18,5 @@

::: className Custom Title
Container Body
:::

@@ -62,8 +66,4 @@ ```

### Milestone
- [ ] custom container in container
[remarkjs]: https://github.com/remarkjs/remark
[536]: https://github.com/remarkjs/remark/pull/536
[vuepress-plugin-container]: https://github.com/vuepress/vuepress-community/tree/main/packages/vuepress-plugin-container

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc