lion/packages-node/rocket-preset-extend-lion-docs/src/remarkExtendLionDocsTransformJs.js
2021-07-21 11:04:55 +02:00

97 lines
2.3 KiB
JavaScript

/* eslint-disable no-param-reassign */
import babelPkg from '@babel/core';
import visit from 'unist-util-visit';
const { transformSync } = babelPkg;
/** @typedef {import('vfile').VFileOptions} VFileOptions */
/** @typedef {import('unist').Node} Node */
/**
* @typedef {Object} CodeProperties
* @property {string} [value]
* @property {string} [lang]
* @property {string} [meta]
*/
/** @typedef {Node & CodeProperties} CodeNode */
/**
* @param {string} value
* @param {string} from
* @param {string} to
*/
function replaceTag(value, from, to) {
return value
.replace(new RegExp(`<${from}(?=\\s|>)`, 'g'), `<${to}`) // positive lookahead for '>' or ' ' after the tagName
.replace(new RegExp(`/${from}>`, 'g'), `/${to}>`);
}
/**
* @param {string} value
* @param {{changes: Array<{ tag: { from: string, to: string }}> }} config
* @returns {string} value with replaced tags
*/
function replaceTags(value, config) {
let newValue = value;
if (config && config.changes) {
for (const change of config.changes) {
if (change.tag) {
const { from, to } = change.tag;
newValue = replaceTag(newValue, from, to);
}
}
}
return newValue;
}
/**
* @param {object} opts
* @param {{changes: Array<{ tag: { from: string, to: string }}> }} opts.extendDocsConfig
* @returns
*/
export function remarkExtendLionDocsTransformJs({ extendDocsConfig }) {
/**
* @param {CodeNode} node
*/
const visitor = node => {
if (
node.type === 'code' &&
node.lang === 'js' &&
(node.meta === 'story' || node.meta === 'preview-story' || node.meta === 'script') &&
node.value
) {
const processed = transformSync(node.value, {
plugins: [
['babel-plugin-extend-docs', extendDocsConfig],
'@babel/plugin-syntax-import-assertions',
],
});
if (processed && processed.code) {
node.value = processed.code;
}
}
if (
node.type === 'code' &&
node.lang === 'html' &&
(node.meta === 'story' || node.meta === 'preview-story' || node.meta === 'script') &&
node.value
) {
node.value = replaceTags(node.value, extendDocsConfig);
}
return node;
};
/**
* @param {Node} tree
*/
function transformer(tree) {
// @ts-ignore
visit(tree, visitor);
return tree;
}
return transformer;
}