Skip to content

Commit

Permalink
Readd mdx-1-to-2 automigration and rename it to mdx-1-to-3
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinpalkovic committed Feb 22, 2024
1 parent 1291b0e commit b481b3f
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 0 deletions.
2 changes: 2 additions & 0 deletions code/lib/cli/src/automigrate/fixes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { removeReactDependency } from './prompt-remove-react';
import { storyshotsMigration } from './storyshots-migration';
import { webpack5CompilerSetup } from './webpack5-compiler-setup';
import { removeJestTestingLibrary } from './remove-jest-testing-library';
import { mdx1to3 } from './mdx-1-to-3';

export * from '../types';

Expand All @@ -44,6 +45,7 @@ export const allFixes: Fix[] = [
storyshotsMigration,
removeReactDependency,
webpack5CompilerSetup,
mdx1to3,
];

export const initFixes: Fix[] = [eslintPlugin];
120 changes: 120 additions & 0 deletions code/lib/cli/src/automigrate/fixes/mdx-1-to-3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { it, expect } from 'vitest';

import { dedent } from 'ts-dedent';
import { fixMdxStyleTags, fixMdxComments } from './mdx-1-to-3';

it('fixMdxStyleTags fixes badly-formatted style blocks', () => {
expect(
fixMdxStyleTags(dedent`
<style>{\`
.foo {}
.bar {}
\`}</style>
`)
).toEqual(dedent`
<style>
{\`
.foo {}
.bar {}
\`}
</style>
`);
});

it('fixMdxStyleTags fixes multiple style blocks', () => {
expect(
fixMdxStyleTags(dedent`
<style>{\`
.foo {}
\`}</style>
<style>{\`
.bar {}
\`}</style>
`)
).toMatchInlineSnapshot(`
"<style>
{\`
.foo {}
\`}
</style>
<style>
{\`
.bar {}
\`}
</style>"
`);
});

it('fixMdxComments fixes all comments', () => {
expect(
fixMdxComments(dedent`
# Hello
<!-- This is a comment -->
and this is not
<!-- This is another comment -->
`)
).toMatchInlineSnapshot(`
"# Hello
{/* This is a comment */}
and this is not
{/* This is another comment */}"
`);
});

it('fixMdxComments keeps html comments in codeblocks', () => {
expect(
fixMdxComments(dedent`
# Hello
~~~html
<!-- This is a comment -->
~~~
~~~html
<!-- This is a comment -->
~~~
\`\`\`html
<!-- This is a comment -->
\`\`\`
\`\`\`html
<!-- This is a comment -->
\`\`\`
and this is not
<!-- This is another comment -->
`)
).toMatchInlineSnapshot(`
"# Hello
~~~html
<!-- This is a comment -->
~~~
~~~html
<!-- This is a comment -->
~~~
\`\`\`html
<!-- This is a comment -->
\`\`\`
\`\`\`html
<!-- This is a comment -->
\`\`\`
and this is not
{/* This is another comment */}"
`);
});
85 changes: 85 additions & 0 deletions code/lib/cli/src/automigrate/fixes/mdx-1-to-3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import chalk from 'chalk';
import { dedent } from 'ts-dedent';
import { basename } from 'path';
import fse from 'fs-extra';
import globby from 'globby';
import type { Fix } from '../types';

const MDX1_STYLE_START = /<style>{`/g;
const MDX1_STYLE_END = /`}<\/style>/g;
const MDX1_COMMENT = /<!--(.+)-->/g;
const MDX1_CODEBLOCK = /(?:\n~~~(?:\n|.)*?\n~~~)|(?:\n```(?:\n|.)*?\n```)/g;

export const fixMdxStyleTags = (mdx: string) => {
return mdx.replace(MDX1_STYLE_START, '<style>\n {`').replace(MDX1_STYLE_END, ' `}\n</style>');
};

export const fixMdxComments = (mdx: string) => {
const codeblocks = mdx.matchAll(MDX1_CODEBLOCK);

// separate the mdx into sections without codeblocks & replace html comments NOT in codeblocks
const sections = mdx
.split(MDX1_CODEBLOCK)
.map((v) => v.replace(MDX1_COMMENT, (original, group) => `{/*${group}*/}`));

// interleave the original codeblocks with the replaced sections
return sections.reduce((acc, item, i) => {
const next = codeblocks.next();
return next.done ? acc + item : acc + item + next.value[0];
}, '');
};

const logger = console;

interface Mdx1to3Options {
storiesMdxFiles: string[];
}

/**
* Does the user have `.stories.mdx` files?
*
* If so:
* - Assume they might be MDX1
* - Offer to help migrate to MDX3
*/
export const mdx1to3: Fix<Mdx1to3Options> = {
id: 'mdx1to3',

versionRange: ['<7.0.0', '>=8.0.0-alpha.0'],

async check() {
const storiesMdxFiles = await globby('./!(node_modules)**/*.(story|stories).mdx');
return storiesMdxFiles.length ? { storiesMdxFiles } : null;
},

prompt({ storiesMdxFiles }) {
return dedent`
We've found ${chalk.yellow(storiesMdxFiles.length)} '.stories.mdx' files in your project.
Storybook has upgraded to MDX3 (https://mdxjs.com/blog/v3/). MDX3 itself doesn't contain disruptive breaking changes, whereas the transition from MDX1 to MDX2 was a significant change.
We can try to automatically upgrade your MDX files to MDX3 format using some common patterns.
After this install completes, and before you start Storybook, we strongly recommend reading the MDX2 section
of the 7.0 migration guide. It contains useful tools for detecting and fixing any remaining issues.
${chalk.cyan('https://storybook.js.org/migration-guides/7.0')}
`;
},

async run({ result: { storiesMdxFiles }, dryRun }) {
await Promise.all([
...storiesMdxFiles.map(async (fname) => {
const contents = await fse.readFile(fname, 'utf-8');
const updated = fixMdxComments(fixMdxStyleTags(contents));
if (updated === contents) {
logger.info(`🆗 Unmodified ${basename(fname)}`);
} else {
logger.info(`✅ Modified ${basename(fname)}`);
if (!dryRun) {
await fse.writeFile(fname, updated);
}
}
}),
]);
},
};

0 comments on commit b481b3f

Please sign in to comment.