Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@atomiks/mdx-pretty-code

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@atomiks/mdx-pretty-code - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

374

dist/mdx-pretty-code.js

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

import visit from 'unist-util-visit';
import { JSDOM } from 'jsdom';

@@ -7,2 +6,365 @@ import rangeParser from 'parse-numeric-range';

/**
* @typedef {import('unist').Node} Node
* @typedef {import('unist').Parent} Parent
*
* @typedef {string} Type
* @typedef {Object<string, unknown>} Props
*
* @typedef {null|undefined|Type|Props|TestFunctionAnything|Array.<Type|Props|TestFunctionAnything>} Test
*/
const convert =
/**
* @type {(
* (<T extends Node>(test: T['type']|Partial<T>|TestFunctionPredicate<T>) => AssertPredicate<T>) &
* ((test?: Test) => AssertAnything)
* )}
*/
(
/**
* Generate an assertion from a check.
* @param {Test} [test]
* When nullish, checks if `node` is a `Node`.
* When `string`, works like passing `function (node) {return node.type === test}`.
* When `function` checks if function passed the node is true.
* When `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
* When `array`, checks any one of the subtests pass.
* @returns {AssertAnything}
*/
function (test) {
if (test === undefined || test === null) {
return ok
}
if (typeof test === 'string') {
return typeFactory(test)
}
if (typeof test === 'object') {
return Array.isArray(test) ? anyFactory(test) : propsFactory(test)
}
if (typeof test === 'function') {
return castFactory(test)
}
throw new Error('Expected function, string, or object as test')
}
);
/**
* @param {Array.<Type|Props|TestFunctionAnything>} tests
* @returns {AssertAnything}
*/
function anyFactory(tests) {
/** @type {Array.<AssertAnything>} */
const checks = [];
let index = -1;
while (++index < tests.length) {
checks[index] = convert(tests[index]);
}
return castFactory(any)
/**
* @this {unknown}
* @param {unknown[]} parameters
* @returns {boolean}
*/
function any(...parameters) {
let index = -1;
while (++index < checks.length) {
if (checks[index].call(this, ...parameters)) return true
}
return false
}
}
/**
* Utility to assert each property in `test` is represented in `node`, and each
* values are strictly equal.
*
* @param {Props} check
* @returns {AssertAnything}
*/
function propsFactory(check) {
return castFactory(all)
/**
* @param {Node} node
* @returns {boolean}
*/
function all(node) {
/** @type {string} */
let key;
for (key in check) {
// @ts-expect-error: hush, it sure works as an index.
if (node[key] !== check[key]) return false
}
return true
}
}
/**
* Utility to convert a string into a function which checks a given node’s type
* for said string.
*
* @param {Type} check
* @returns {AssertAnything}
*/
function typeFactory(check) {
return castFactory(type)
/**
* @param {Node} node
*/
function type(node) {
return node && node.type === check
}
}
/**
* Utility to convert a string into a function which checks a given node’s type
* for said string.
* @param {TestFunctionAnything} check
* @returns {AssertAnything}
*/
function castFactory(check) {
return assertion
/**
* @this {unknown}
* @param {Array.<unknown>} parameters
* @returns {boolean}
*/
function assertion(...parameters) {
// @ts-expect-error: spreading is fine.
return Boolean(check.call(this, ...parameters))
}
}
// Utility to return true.
function ok() {
return true
}
/**
* @param {string} d
* @returns {string}
*/
function color(d) {
return '\u001B[33m' + d + '\u001B[39m'
}
/**
* @typedef {import('unist').Node} Node
* @typedef {import('unist').Parent} Parent
* @typedef {import('unist-util-is').Test} Test
* @typedef {import('./complex-types').Action} Action
* @typedef {import('./complex-types').Index} Index
* @typedef {import('./complex-types').ActionTuple} ActionTuple
* @typedef {import('./complex-types').VisitorResult} VisitorResult
* @typedef {import('./complex-types').Visitor} Visitor
*/
/**
* Continue traversing as normal
*/
const CONTINUE = true;
/**
* Do not traverse this node’s children
*/
const SKIP = 'skip';
/**
* Stop traversing immediately
*/
const EXIT = false;
/**
* Visit children of tree which pass a test
*
* @param tree Abstract syntax tree to walk
* @param test Test node, optional
* @param visitor Function to run for each node
* @param reverse Visit the tree in reverse order, defaults to false
*/
const visitParents =
/**
* @type {(
* (<Tree extends Node, Check extends Test>(tree: Tree, test: Check, visitor: import('./complex-types').BuildVisitor<Tree, Check>, reverse?: boolean) => void) &
* (<Tree extends Node>(tree: Tree, visitor: import('./complex-types').BuildVisitor<Tree>, reverse?: boolean) => void)
* )}
*/
(
/**
* @param {Node} tree
* @param {Test} test
* @param {import('./complex-types').Visitor<Node>} visitor
* @param {boolean} [reverse]
*/
function (tree, test, visitor, reverse) {
if (typeof test === 'function' && typeof visitor !== 'function') {
reverse = visitor;
// @ts-expect-error no visitor given, so `visitor` is test.
visitor = test;
test = null;
}
const is = convert(test);
const step = reverse ? -1 : 1;
factory(tree, null, [])();
/**
* @param {Node} node
* @param {number?} index
* @param {Array.<Parent>} parents
*/
function factory(node, index, parents) {
/** @type {Object.<string, unknown>} */
// @ts-expect-error: hush
const value = typeof node === 'object' && node !== null ? node : {};
/** @type {string|undefined} */
let name;
if (typeof value.type === 'string') {
name =
typeof value.tagName === 'string'
? value.tagName
: typeof value.name === 'string'
? value.name
: undefined;
Object.defineProperty(visit, 'name', {
value:
'node (' +
color(value.type + (name ? '<' + name + '>' : '')) +
')'
});
}
return visit
function visit() {
/** @type {ActionTuple} */
let result = [];
/** @type {ActionTuple} */
let subresult;
/** @type {number} */
let offset;
/** @type {Array.<Parent>} */
let grandparents;
if (!test || is(node, index, parents[parents.length - 1] || null)) {
result = toResult(visitor(node, parents));
if (result[0] === EXIT) {
return result
}
}
// @ts-expect-error looks like a parent.
if (node.children && result[0] !== SKIP) {
// @ts-expect-error looks like a parent.
offset = (reverse ? node.children.length : -1) + step;
// @ts-expect-error looks like a parent.
grandparents = parents.concat(node);
// @ts-expect-error looks like a parent.
while (offset > -1 && offset < node.children.length) {
// @ts-expect-error looks like a parent.
subresult = factory(node.children[offset], offset, grandparents)();
if (subresult[0] === EXIT) {
return subresult
}
offset =
typeof subresult[1] === 'number' ? subresult[1] : offset + step;
}
}
return result
}
}
}
);
/**
* @param {VisitorResult} value
* @returns {ActionTuple}
*/
function toResult(value) {
if (Array.isArray(value)) {
return value
}
if (typeof value === 'number') {
return [CONTINUE, value]
}
return [value]
}
/**
* @typedef {import('unist').Node} Node
* @typedef {import('unist').Parent} Parent
* @typedef {import('unist-util-is').Test} Test
* @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult
* @typedef {import('./complex-types').Visitor} Visitor
*/
/**
* Visit children of tree which pass a test
*
* @param tree Abstract syntax tree to walk
* @param test Test, optional
* @param visitor Function to run for each node
* @param reverse Fisit the tree in reverse, defaults to false
*/
const visit =
/**
* @type {(
* (<Tree extends Node, Check extends Test>(tree: Tree, test: Check, visitor: import('./complex-types').BuildVisitor<Tree, Check>, reverse?: boolean) => void) &
* (<Tree extends Node>(tree: Tree, visitor: import('./complex-types').BuildVisitor<Tree>, reverse?: boolean) => void)
* )}
*/
(
/**
* @param {Node} tree
* @param {Test} test
* @param {import('./complex-types').Visitor} visitor
* @param {boolean} [reverse]
*/
function (tree, test, visitor, reverse) {
if (typeof test === 'function' && typeof visitor !== 'function') {
reverse = visitor;
visitor = test;
test = null;
}
visitParents(tree, test, overload, reverse);
/**
* @param {Node} node
* @param {Array.<Parent>} parents
*/
function overload(node, parents) {
const parent = parents[parents.length - 1];
return visitor(
node,
parent ? parent.children.indexOf(node) : null,
parent
)
}
}
);
let highlighter = null;
function createRemarkPlugin(options = {}) {

@@ -25,3 +387,6 @@ return () => async (tree) => {

const highlighter = await shiki.getHighlighter(shikiOptions);
if (!highlighter) {
highlighter = await shiki.getHighlighter(shikiOptions);
}
const loadedLanguages = highlighter.getLoadedLanguages();

@@ -126,3 +491,2 @@

)
.flat()
.join('');

@@ -140,2 +504,6 @@

dom.window.document
.querySelector('code')
.setAttribute('data-language', lang);
node.value = sanitizeHtml(

@@ -142,0 +510,0 @@ dom.window.document.body.innerHTML,

9

package.json
{
"name": "@atomiks/mdx-pretty-code",
"version": "0.0.2",
"version": "0.0.3",
"description": "A Remark plugin to make the code in your MDX docs simply beautiful. Powered by [Shiki](https://github.com/shikijs/shiki).",
"main": "./dist/mdx-pretty-code.cjs",
"module": "./dist/mdx-pretty-code.js",
"type": "module",

@@ -26,6 +27,6 @@ "exports": {

"peerDependencies": {
"shiki": "*",
"unist-util-visit": "*"
"shiki": "*"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^13.1.1",
"prettier": "^2.5.1",

@@ -35,3 +36,3 @@ "rollup": "^2.60.2",

"typescript": "^4.5.2",
"unist-util-visit": "^4.1.0"
"unist-util-visit": "^4.0.0"
},

@@ -38,0 +39,0 @@ "dependencies": {

# MDX Pretty Code
<p align="center">
<img src="./preview.jpg" height="761">
<img src="https://github.com/atomiks/mdx-pretty-code/raw/master//preview.jpg">
</p>

@@ -13,17 +13,11 @@

- ✅ Context-adjustable inline code highlighting
- ✅ Line numbers
- ✅ No runtime or bundle size cost
## Installation
ESM contexts:
```shell
npm install @atomiks/mdx-pretty-code shiki unist-util-visit
npm install @atomiks/mdx-pretty-code shiki
```
CJS contexts:
```shell
npm install @atomiks/mdx-pretty-code shiki unist-util-visit@2
```
## Usage

@@ -185,2 +179,29 @@

## Line numbers
CSS counters can be used to add line numbers.
```css
code {
counter-reset: line;
}
code > .line::before {
counter-increment: line;
content: counter(line);
/* Other styling */
display: inline-block;
width: 1rem;
margin-right: 2rem;
text-align: right;
color: gray;
}
```
## Language meta
The `code` tag has a `data-language` attribute, so you can add the language
information to the code block.
## Sanitizing

@@ -187,0 +208,0 @@

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