mirror of
https://github.com/jlengrand/open-wc.git
synced 2026-03-10 08:31:19 +00:00
feat: allow to set plugins for mdjs processing
This commit is contained in:
@@ -7,6 +7,8 @@ module.exports = {
|
||||
'storybook-prebuilt/addon-docs/register.js',
|
||||
'storybook-prebuilt/addon-knobs/register.js',
|
||||
],
|
||||
// this would disable the ids of headlines - you can also use it to add your own unified/remark plugins
|
||||
// setupMdjsPlugins: plugins => plugins.filter(plugin => plugin.name !== 'mdSlug'),
|
||||
rollup: config => {
|
||||
config.plugins.push({
|
||||
generateBundle() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/** @typedef {import('es-dev-server').Config} ServerConfig */
|
||||
/** @typedef {import('@mdjs/core').MdjsProcessPlugin} MdjsProcessPlugin */
|
||||
|
||||
/* eslint-disable no-console, no-param-reassign */
|
||||
const { createConfig, startServer } = require('es-dev-server');
|
||||
@@ -8,14 +9,14 @@ const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const readCommandLineArgs = require('./readCommandLineArgs');
|
||||
const mdjsToCsfTransformer = require('./transformers/mdjsToCsfTransformer');
|
||||
const createMdjsToCsfTransformer = require('./transformers/createMdjsToCsfTransformer');
|
||||
const createServeStorybookTransformer = require('./transformers/createServeStorybookTransformer');
|
||||
const { mdxToCsfTransformer } = require('./transformers/mdxToCsfTransformer');
|
||||
const toBrowserPath = require('../shared/toBrowserPath');
|
||||
const getAssets = require('../shared/getAssets');
|
||||
|
||||
async function run() {
|
||||
const config = /** @type {ServerConfig & { stories: string[], addons: string[], configDir: string}} */ (readCommandLineArgs());
|
||||
const config = /** @type {ServerConfig & { stories: string[], addons: string[], configDir: string, setupMdjsPlugins: MdjsProcessPlugin[] }} */ (readCommandLineArgs());
|
||||
const rootDir = config.rootDir ? path.resolve(process.cwd(), config.rootDir) : process.cwd();
|
||||
|
||||
const storybookConfigDir = config.configDir;
|
||||
@@ -45,7 +46,9 @@ async function run() {
|
||||
|
||||
config.responseTransformers = [
|
||||
...(config.responseTransformers || []),
|
||||
mdjsToCsfTransformer,
|
||||
createMdjsToCsfTransformer({
|
||||
setupMdjsPlugins: config.setupMdjsPlugins,
|
||||
}),
|
||||
mdxToCsfTransformer,
|
||||
createServeStorybookTransformer({
|
||||
assets,
|
||||
|
||||
@@ -87,6 +87,7 @@ module.exports = function readCommandLineArgs() {
|
||||
configDir: storybookArgs['config-dir'],
|
||||
stories: storybookArgs.stories,
|
||||
addons: mainJs.addons || [],
|
||||
setupMdjsPlugins: mainJs.setupMdjsPlugins,
|
||||
|
||||
// TODO: we should separate es dev server config and storybook config
|
||||
// command line args read from regular es-dev-server
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
const { mdjsToCsf } = require('storybook-addon-markdown-docs');
|
||||
|
||||
function createMdjsToCsfTransformer(options) {
|
||||
/**
|
||||
* @param {object} params
|
||||
* @param {string} params.body
|
||||
* @param {string} params.url
|
||||
* @param {number} params.status
|
||||
*/
|
||||
return async function mdjsToCsfTransformer({ url, body, status }) {
|
||||
if (status < 200 || status >= 300) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const split = url.split('?');
|
||||
const path = split[0].split('#')[0];
|
||||
|
||||
if (!path.endsWith('.md')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const searchParams = split[1];
|
||||
if (!searchParams || !searchParams.startsWith('storybook-story')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const markdownStory = await mdjsToCsf(body, path, options);
|
||||
|
||||
return { body: markdownStory };
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = createMdjsToCsfTransformer;
|
||||
@@ -1,31 +0,0 @@
|
||||
const { mdjsToCsf } = require('storybook-addon-markdown-docs');
|
||||
|
||||
/**
|
||||
* @param {object} params
|
||||
* @param {string} params.body
|
||||
* @param {string} params.url
|
||||
* @param {number} params.status
|
||||
*/
|
||||
async function mdjsToCsfTransformer({ url, body, status }) {
|
||||
if (status < 200 || status >= 300) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const split = url.split('?');
|
||||
const path = split[0].split('#')[0];
|
||||
|
||||
if (!path.endsWith('.md')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const searchParams = split[1];
|
||||
if (!searchParams || !searchParams.startsWith('storybook-story')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const markdownStory = await mdjsToCsf(body, path);
|
||||
|
||||
return { body: markdownStory };
|
||||
}
|
||||
|
||||
module.exports = mdjsToCsfTransformer;
|
||||
@@ -1,21 +1,10 @@
|
||||
const { mdjsToCsf } = require('../../index');
|
||||
|
||||
module.exports = {
|
||||
stories: ['../stories/*.stories.{js,md}'],
|
||||
// this would disable the ids of headlines - you can also use it to add your own unified/remark plugins
|
||||
// setupMdjsPlugins: plugins => plugins.filter(plugin => plugin.name !== 'mdSlug'),
|
||||
esDevServer: {
|
||||
open: true,
|
||||
watch: true,
|
||||
nodeResolve: true,
|
||||
fileExtensions: ['.js', '.mjs', '.md'],
|
||||
responseTransformers: [
|
||||
async function mdToStory({ url, body }) {
|
||||
const cleanURL = url.split('?')[0].split('#')[0];
|
||||
|
||||
if (cleanURL.endsWith('md')) {
|
||||
const markdownStory = await mdjsToCsf(body, cleanURL);
|
||||
return { body: markdownStory };
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -7,10 +7,11 @@ const { jsxToJs } = require('./jsxToJs');
|
||||
/**
|
||||
* @param {string} markdown
|
||||
* @param {string} filePath
|
||||
* @param {object} options
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function mdjsToCsf(markdown, filePath) {
|
||||
const markdownResult = await mdjsToMd(markdown);
|
||||
async function mdjsToCsf(markdown, filePath, options = {}) {
|
||||
const markdownResult = await mdjsToMd(markdown, { ...options, filePath });
|
||||
|
||||
const jsCode = renameDefaultExport(markdownResult.jsCode, filePath);
|
||||
const storiesCode = createStoriesCode(markdownResult.stories);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @typedef {import('@mdjs/core').Story} Story */
|
||||
/** @typedef {import('@mdjs/core').MarkdownResult} MarkdownResult */
|
||||
/** @typedef {import('@mdjs/core').ParseResult} ParseResult */
|
||||
/** @typedef {import('@mdjs/core').MdjsProcessPlugin} MdjsProcessPlugin */
|
||||
|
||||
const unified = require('unified');
|
||||
const markdown = require('remark-parse');
|
||||
@@ -91,27 +92,69 @@ function transformPropsHook() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} markdownText
|
||||
* @returns {Promise<MarkdownResult>}
|
||||
* @param {string} name
|
||||
*/
|
||||
async function mdjsToMd(markdownText) {
|
||||
const parser = unified()
|
||||
.use(markdown)
|
||||
.use(mdjsParse)
|
||||
.use(mdjsStoryParse, {
|
||||
storyTag: name => `<Story name="${name}"></Story>`,
|
||||
previewStoryTag: name => `<Preview><Story name="${name}"></Story></Preview>`,
|
||||
})
|
||||
.use(transformPropsHook)
|
||||
.use(mdSlug)
|
||||
.use(mdStringify, {
|
||||
function storyTag(name) {
|
||||
return `<Story name="${name}"></Story>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function previewStoryTag(name) {
|
||||
return `<Preview><Story name="${name}"></Story></Preview>`;
|
||||
}
|
||||
|
||||
/** @type {MdjsProcessPlugin[]} */
|
||||
const mdjsToMdPlugins = [
|
||||
{ name: 'markdown', plugin: markdown },
|
||||
{ name: 'mdjsParse', plugin: mdjsParse },
|
||||
{
|
||||
name: 'mdjsStoryParse',
|
||||
plugin: mdjsStoryParse,
|
||||
options: {
|
||||
storyTag,
|
||||
previewStoryTag,
|
||||
},
|
||||
},
|
||||
{ name: 'transformPropsHook', plugin: transformPropsHook },
|
||||
{ name: 'mdSlug', plugin: mdSlug },
|
||||
{
|
||||
name: 'mdStringify',
|
||||
plugin: mdStringify,
|
||||
options: {
|
||||
handlers: {
|
||||
code,
|
||||
image,
|
||||
break: hardBreak,
|
||||
thematicBreak,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {MdjsProcessPlugin[]} plugins
|
||||
* @param {string=} filePath
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function defaultSetupMdjsPlugins(plugins, filePath = '') {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} markdownText
|
||||
* @returns {Promise<MarkdownResult>}
|
||||
*/
|
||||
async function mdjsToMd(
|
||||
markdownText,
|
||||
{ filePath = '', setupMdjsPlugins = defaultSetupMdjsPlugins } = {},
|
||||
) {
|
||||
const plugins = setupMdjsPlugins(mdjsToMdPlugins, filePath);
|
||||
const parser = unified();
|
||||
for (const pluginObj of plugins) {
|
||||
parser.use(pluginObj.plugin, pluginObj.options);
|
||||
}
|
||||
/** @type {unknown} */
|
||||
const parseResult = await parser.process(markdownText);
|
||||
const result = /** @type {ParseResult} */ (parseResult);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/** @typedef {import('@mdjs/core').MdjsProcessPlugin} MdjsProcessPlugin */
|
||||
|
||||
const chai = require('chai');
|
||||
// @ts-ignore
|
||||
const chaiSnapshot = require('mocha-chai-snapshot');
|
||||
@@ -41,4 +43,30 @@ describe('mdjsToCsf', () => {
|
||||
// @ts-ignore
|
||||
expect(output).to.matchSnapshot(this);
|
||||
});
|
||||
|
||||
it('passes on filePath and options to mdjsToMd', async () => {
|
||||
let resultPlugins = [];
|
||||
let resultFilePath;
|
||||
const input = [
|
||||
'```js script',
|
||||
'export default { title: "My docs" }',
|
||||
'```',
|
||||
'',
|
||||
'# Title',
|
||||
].join('\n');
|
||||
/**
|
||||
* @param {MdjsProcessPlugin[]} plugins
|
||||
* @param {string} filePath
|
||||
*/
|
||||
function setupMdjsPlugins(plugins, filePath) {
|
||||
resultPlugins = plugins;
|
||||
resultFilePath = filePath;
|
||||
return plugins;
|
||||
}
|
||||
await mdjsToCsf(input, '/foo.js', {
|
||||
setupMdjsPlugins,
|
||||
});
|
||||
expect(resultPlugins.length).to.equal(6);
|
||||
expect(resultFilePath).to.equal('/foo.js');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -142,4 +142,14 @@ describe('mdjsToMd', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows to configure unified plugins via setupMdjsPlugins(plugins, filePath)', async () => {
|
||||
const outputWithSlug = await mdjsToMd('# Title');
|
||||
expect(outputWithSlug.html).to.equal('<h1 id="title">Title</h1>\n');
|
||||
|
||||
const outputWithoutSlug = await mdjsToMd('# Title', {
|
||||
setupMdjsPlugins: plugins => plugins.filter(plugin => plugin.name !== 'mdSlug'),
|
||||
});
|
||||
expect(outputWithoutSlug.html).to.equal('<h1>Title</h1>\n');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user