diff --git a/packages/docusaurus-remark-plugin-npm2yarn/README.md b/packages/docusaurus-remark-plugin-npm2yarn/README.md
index 5fc6a1705e15..055ca12d30cd 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/README.md
+++ b/packages/docusaurus-remark-plugin-npm2yarn/README.md
@@ -63,3 +63,30 @@ module.exports = {
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `sync` | `boolean` | `false` | Syncing tab choices (Yarn and npm). See https://docusaurus.io/docs/markdown-features/#syncing-tab-choices for details. |
+| `converters` | `array` | `'yarn'`, `'pnpm'` | The list of converters to use. The order of the converters is important, as the first converter will be used as the default choice. |
+
+## Custom converters
+
+In case you want to convert npm commands to something else than `yarn` or `pnpm`, you can use custom converters:
+
+```ts
+type CustomConverter = [name: string, cb: (npmCode: string) => string];
+```
+
+```ts
+{
+ remarkPlugins: [
+ [
+ require('@docusaurus/remark-plugin-npm2yarn'),
+ {
+ sync: true,
+ converters: [
+ 'yarn',
+ 'pnpm',
+ ['Turbo', (code) => code.replace(/npm/g, 'turbo')],
+ ],
+ },
+ ],
+ ];
+}
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json
index cb7b5030a90d..188c5858f174 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/package.json
+++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json
@@ -17,7 +17,7 @@
},
"license": "MIT",
"dependencies": {
- "npm-to-yarn": "^1.2.1",
+ "npm-to-yarn": "^2.0.0",
"tslib": "^2.4.1",
"unist-util-visit": "^2.0.3"
},
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__fixtures__/conversion-test.md b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__fixtures__/conversion-test.md
new file mode 100644
index 000000000000..b0bf7f08a52b
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__fixtures__/conversion-test.md
@@ -0,0 +1,16 @@
+```bash npm2yarn
+npm run xxx -- --arg
+```
+
+```bash npm2yarn
+npm install package
+```
+
+```bash npm2yarn
+npm remove package-name
+```
+
+```bash npm2yarn
+npm init docusaurus
+npm init docusaurus@latest my-website classic
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.ts.snap
index b8e77588d05b..393470b31218 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.ts.snap
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.ts.snap
@@ -6,6 +6,7 @@ exports[`npm2yarn plugin does not re-import tabs components when already importe
import TabItem from '@theme/TabItem';
+
\`\`\`bash
@@ -13,19 +14,30 @@ import TabItem from '@theme/TabItem';
\`\`\`
+
\`\`\`bash
- $ yarn add --global docusaurus
+ $ yarn global add docusaurus
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+ $ pnpm add --global docusaurus
\`\`\`
+
"
`;
exports[`npm2yarn plugin does not re-import tabs components when already imported below 1`] = `
"
+
\`\`\`bash
@@ -33,13 +45,23 @@ exports[`npm2yarn plugin does not re-import tabs components when already importe
\`\`\`
+
\`\`\`bash
- $ yarn add --global docusaurus
+ $ yarn global add docusaurus
\`\`\`
+
+
+
+\`\`\`bash
+ $ pnpm add --global docusaurus
+\`\`\`
+
+
+
import Tabs from '@theme/Tabs';
@@ -63,11 +85,102 @@ npm install --save docusaurus-plugin-name
"
`;
+exports[`npm2yarn plugin work with custom converter 1`] = `
+"import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Installing a plugin
+
+A plugin is usually a npm package, so you install them like other npm packages using npm.
+
+
+
+
+
+\`\`\`bash
+npm install --save docusaurus-plugin-name
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+turbo install --save docusaurus-plugin-name
+\`\`\`
+
+
+
+
+"
+`;
+
+exports[`npm2yarn plugin work with pnpm converter 1`] = `
+"import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Installing a plugin
+
+A plugin is usually a npm package, so you install them like other npm packages using npm.
+
+
+
+
+
+\`\`\`bash
+npm install --save docusaurus-plugin-name
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+pnpm add docusaurus-plugin-name
+\`\`\`
+
+
+
+
+"
+`;
+
+exports[`npm2yarn plugin work with yarn converter 1`] = `
+"import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Installing a plugin
+
+A plugin is usually a npm package, so you install them like other npm packages using npm.
+
+
+
+
+
+\`\`\`bash
+npm install --save docusaurus-plugin-name
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+yarn add docusaurus-plugin-name
+\`\`\`
+
+
+
+
+"
+`;
+
exports[`npm2yarn plugin works on installation file 1`] = `
"import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+
\`\`\`bash
@@ -75,13 +188,23 @@ import TabItem from '@theme/TabItem';
\`\`\`
+
\`\`\`bash
- $ yarn add --global docusaurus
+ $ yarn global add docusaurus
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+ $ pnpm add --global docusaurus
\`\`\`
+
"
`;
@@ -95,6 +218,7 @@ import TabItem from '@theme/TabItem';
A plugin is usually a npm package, so you install them like other npm packages using npm.
+
\`\`\`bash
@@ -102,6 +226,7 @@ npm install --save docusaurus-plugin-name
\`\`\`
+
\`\`\`bash
@@ -109,6 +234,136 @@ yarn add docusaurus-plugin-name
\`\`\`
+
+
+
+\`\`\`bash
+pnpm add docusaurus-plugin-name
+\`\`\`
+
+
+
+
+"
+`;
+
+exports[`npm2yarn plugin works with common commands 1`] = `
+"import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+
+
+
+\`\`\`bash
+npm run xxx -- --arg
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+yarn xxx --arg
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+pnpm run xxx -- --arg
+\`\`\`
+
+
+
+
+
+
+
+
+
+\`\`\`bash
+npm install package
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+yarn add package
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+pnpm add package
+\`\`\`
+
+
+
+
+
+
+
+
+
+\`\`\`bash
+npm remove package-name
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+yarn remove package-name
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+pnpm remove package-name
+\`\`\`
+
+
+
+
+
+
+
+
+
+\`\`\`bash
+npm init docusaurus
+npm init docusaurus@latest my-website classic
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+yarn create docusaurus
+yarn create docusaurus@latest my-website classic
+\`\`\`
+
+
+
+
+
+\`\`\`bash
+pnpm create docusaurus
+pnpm create docusaurus@latest my-website classic
+\`\`\`
+
+
+
"
`;
@@ -122,6 +377,7 @@ import TabItem from '@theme/TabItem';
A plugin is usually a npm package, so you install them like other npm packages using npm.
+
\`\`\`bash
@@ -129,6 +385,7 @@ npm install --save docusaurus-plugin-name
\`\`\`
+
\`\`\`bash
@@ -136,6 +393,15 @@ yarn add docusaurus-plugin-name
\`\`\`
+
+
+
+\`\`\`bash
+pnpm add docusaurus-plugin-name
+\`\`\`
+
+
+
"
`;
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
index 2ed961332463..84afcc23ae29 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.ts
@@ -11,7 +11,10 @@ import mdx from 'remark-mdx';
import remark from 'remark';
import npm2yarn from '../index';
-const processFixture = async (name: string, options?: {sync?: boolean}) => {
+const processFixture = async (
+ name: string,
+ options?: Parameters[0],
+) => {
const filePath = path.join(__dirname, '__fixtures__', `${name}.md`);
const file = await vfile.read(filePath);
const result = await remark().use(mdx).use(npm2yarn, options).process(file);
@@ -32,6 +35,12 @@ describe('npm2yarn plugin', () => {
expect(result).toMatchSnapshot();
});
+ it('works with common commands', async () => {
+ const result = await processFixture('conversion-test', {sync: true});
+
+ expect(result).toMatchSnapshot();
+ });
+
it('works with sync option', async () => {
const result = await processFixture('plugin', {sync: true});
@@ -55,4 +64,24 @@ describe('npm2yarn plugin', () => {
expect(result).toMatchSnapshot();
});
+
+ it('work with yarn converter', async () => {
+ const result = await processFixture('plugin', {converters: ['yarn']});
+
+ expect(result).toMatchSnapshot();
+ });
+
+ it('work with pnpm converter', async () => {
+ const result = await processFixture('plugin', {converters: ['pnpm']});
+
+ expect(result).toMatchSnapshot();
+ });
+
+ it('work with custom converter', async () => {
+ const result = await processFixture('plugin', {
+ converters: [['Turbo', (code) => code.replace(/npm/g, 'turbo')]],
+ });
+
+ expect(result).toMatchSnapshot();
+ });
});
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/index.ts b/packages/docusaurus-remark-plugin-npm2yarn/src/index.ts
index 1da28fb7f243..ee562f491d56 100644
--- a/packages/docusaurus-remark-plugin-npm2yarn/src/index.ts
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/index.ts
@@ -6,45 +6,67 @@
*/
import visit from 'unist-util-visit';
-// @ts-expect-error: this package provides CJS
import npmToYarn from 'npm-to-yarn';
import type {Code, Content, Literal} from 'mdast';
import type {Plugin} from 'unified';
import type {Node, Parent} from 'unist';
+type CustomConverter = [name: string, cb: (npmCode: string) => string];
+
type PluginOptions = {
sync?: boolean;
+ converters?: (CustomConverter | 'yarn' | 'pnpm')[];
};
-// E.g. global install: 'npm i' -> 'yarn'
-const convertNpmToYarn = (npmCode: string) => npmToYarn(npmCode, 'yarn');
-
-const transformNode = (node: Code, isSync: boolean) => {
- const groupIdProp = isSync ? ' groupId="npm2yarn"' : '';
- const npmCode = node.value;
- const yarnCode = convertNpmToYarn(node.value);
+function createTabItem(
+ code: string,
+ node: Code,
+ value: string,
+ label?: string,
+) {
return [
{
type: 'jsx',
- value: `\n`,
+ value: ``,
},
{
type: node.type,
lang: node.lang,
- value: npmCode,
+ value: code,
},
{
type: 'jsx',
- value: '\n',
+ value: '',
},
+ ] as Content[];
+}
+
+const transformNode = (
+ node: Code,
+ isSync: boolean,
+ converters: (CustomConverter | 'yarn' | 'pnpm')[],
+) => {
+ const groupIdProp = isSync ? ' groupId="npm2yarn"' : '';
+ const npmCode = node.value;
+ return [
{
- type: node.type,
- lang: node.lang,
- value: yarnCode,
+ type: 'jsx',
+ value: ``,
},
+ ...createTabItem(npmCode, node, 'npm'),
+ ...converters.flatMap((converter) =>
+ typeof converter === 'string'
+ ? createTabItem(
+ npmToYarn(npmCode, converter),
+ node,
+ converter,
+ converter === 'yarn' ? 'Yarn' : converter,
+ )
+ : createTabItem(converter[1](npmCode), node, converter[0]),
+ ),
{
type: 'jsx',
- value: '\n',
+ value: '',
},
] as Content[];
};
@@ -61,7 +83,7 @@ const nodeForImport: Literal = {
};
const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
- const {sync = false} = options;
+ const {sync = false, converters = ['yarn', 'pnpm']} = options;
return (root) => {
let transformed = false as boolean;
let alreadyImported = false as boolean;
@@ -74,7 +96,7 @@ const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
while (index < node.children.length) {
const child = node.children[index]!;
if (matchNode(child)) {
- const result = transformNode(child, sync);
+ const result = transformNode(child, sync, converters);
node.children.splice(index, 1, ...result);
index += result.length;
transformed = true;
diff --git a/website/docs/guides/markdown-features/markdown-features-code-blocks.mdx b/website/docs/guides/markdown-features/markdown-features-code-blocks.mdx
index a0ac137ca4bb..fd6d65f7e522 100644
--- a/website/docs/guides/markdown-features/markdown-features-code-blocks.mdx
+++ b/website/docs/guides/markdown-features/markdown-features-code-blocks.mdx
@@ -772,6 +772,14 @@ module.exports = {
remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
},
blog: {
+ // highlight-start
+ remarkPlugins: [
+ [
+ require('@docusaurus/remark-plugin-npm2yarn'),
+ {converters: ['pnpm']},
+ ],
+ ],
+ // highlight-end
// ...
},
},
@@ -788,7 +796,12 @@ npm install @docusaurus/remark-plugin-npm2yarn
```
````
-Using the `{sync: true}` option would make all tab choices synced. Because the choice is stored under the same namespace `npm2yarn`, different `npm2yarn` plugin instances would also sync their choices.
+#### Configuration {#npm2yarn-remark-plugin-configuration}
+
+| Option | Type | Default | Description |
+| --- | --- | --- | --- |
+| `sync` | `boolean` | `false` | Whether to sync the selected converter across all code blocks. |
+| `converters` | `array` | `'yarn'`, `'pnpm'` | The list of converters to use. The order of the converters is important, as the first converter will be used as the default choice. |
## Usage in JSX {#usage-in-jsx}
diff --git a/website/docs/installation.mdx b/website/docs/installation.mdx
index 77d6baab05dc..38d53f425d5e 100644
--- a/website/docs/installation.mdx
+++ b/website/docs/installation.mdx
@@ -55,38 +55,10 @@ npx create-docusaurus@latest my-website facebook
You can also initialize a new project using your preferred project manager:
-```mdx-code-block
-
-
-```
-
-```bash
+```bash npm2yarn
npm init docusaurus
```
-```mdx-code-block
-
-
-```
-
-```bash
-yarn create docusaurus
-```
-
-```mdx-code-block
-
-
-```
-
-```bash
-pnpm create docusaurus
-```
-
-```mdx-code-block
-
-
-```
-
Run `npx create-docusaurus@latest --help`, or check out its [API docs](./api/misc/create-docusaurus.mdx) for more information about all available flags.
@@ -193,7 +165,7 @@ npm install
To check that the update occurred successfully, run:
-```bash npm2yarn
+```bash
npx docusaurus --version
```
diff --git a/website/docs/migration/migration-automated.mdx b/website/docs/migration/migration-automated.mdx
index 65f95cfdaf5a..93c41ae8863f 100644
--- a/website/docs/migration/migration-automated.mdx
+++ b/website/docs/migration/migration-automated.mdx
@@ -38,10 +38,10 @@ npx @docusaurus/migrate migrate ./v1-website ./v2-website
3. To view your new website locally, go into your v2 website's directory and start your development server.
-```bash
+```bash npm2yarn
cd ./v2-website
-yarn install
-yarn start
+npm install
+npm start
```
:::danger
diff --git a/website/docs/migration/migration-manual.mdx b/website/docs/migration/migration-manual.mdx
index 95a8c47d0465..49a7cdd1fce4 100644
--- a/website/docs/migration/migration-manual.mdx
+++ b/website/docs/migration/migration-manual.mdx
@@ -622,13 +622,13 @@ my-project
Start the development server and fix any errors:
-```bash
+```bash npm2yarn
cd website
-yarn start
+npm start
```
You can also try to build the site for production:
-```bash
-yarn build
+```bash npm2yarn
+npm run build
```
diff --git a/yarn.lock b/yarn.lock
index ce71ad55cf79..2be620ea79fa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11450,10 +11450,10 @@ npm-run-path@^5.1.0:
dependencies:
path-key "^4.0.0"
-npm-to-yarn@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/npm-to-yarn/-/npm-to-yarn-1.2.1.tgz#ee88854d03ac930510c28a621985d800b51e76e0"
- integrity sha512-ci3GjP40SKgZL2OOVW6B1z/3LdLNBsEtJupkYC/NQ8/Y0grfZZNNsR5DQdoy7zgL+FsKIXtnxMgrDjoMoJ40zQ==
+npm-to-yarn@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/npm-to-yarn/-/npm-to-yarn-2.0.0.tgz#59c9c615eca3ba8920308a0b418007b73ffc7492"
+ integrity sha512-/IbjiJ7vqbxfxJxAZ+QI9CCRjnIbvGxn5KQcSY9xHh0lMKc/Sgqmm7yp7KPmd6TiTZX5/KiSBKlkGHo59ucZbg==
npmlog@^6.0.0, npmlog@^6.0.2:
version "6.0.2"