diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json
index 5510268a9e..d0cb4153a9 100644
--- a/packages/docusaurus-mdx-loader/package.json
+++ b/packages/docusaurus-mdx-loader/package.json
@@ -17,6 +17,7 @@
"@docusaurus/utils": "2.0.0-alpha.65",
"@mdx-js/mdx": "^1.5.8",
"@mdx-js/react": "^1.5.8",
+ "npm-to-yarn": "^1.0.0-2",
"escape-html": "^1.0.3",
"file-loader": "^6.0.0",
"fs-extra": "^8.1.0",
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/README.md b/packages/docusaurus-remark-plugin-npm2yarn/README.md
new file mode 100644
index 0000000000..b93d73da21
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/README.md
@@ -0,0 +1,53 @@
+# Remark plugin npm2yarn
+
+## Motivation:
+
+Transforms npm bash command code blocks to Docusaurus tabs:
+
+The following (remove the `//`):
+
+````bash
+// ```bash npm2yarn
+// npm run build
+// ```
+````
+
+Becomes:
+
+
+
+**Note**: it only works when used with Docusaurus themes that have the `Tabs` and `TabItems` components.
+
+## Install
+
+```bash
+npm install @docusaurus/remark-plugin-npm2yarn`
+```
+
+It is a Remark plugin, **not a Docusaurus plugin**, so you have to install it as a Remark plugin in the config of your Docusaurus plugins.
+
+```js
+module.exports = {
+ presets: [
+ [
+ '@docusaurus/preset-classic',
+ {
+ docs: {
+ // ...
+ remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
+ },
+ blog: {
+ // ...
+ remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
+ },
+ pages: {
+ // ...
+ remarkPlugins: [require('@docusaurus/remark-plugin-npm2yarn')],
+ },
+ // ...
+ },
+ ],
+ ],
+ // ...
+};
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/example.png b/packages/docusaurus-remark-plugin-npm2yarn/example.png
new file mode 100644
index 0000000000..a007c1ddd7
Binary files /dev/null and b/packages/docusaurus-remark-plugin-npm2yarn/example.png differ
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/package.json b/packages/docusaurus-remark-plugin-npm2yarn/package.json
new file mode 100644
index 0000000000..65860934dd
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@docusaurus/remark-plugin-npm2yarn",
+ "version": "2.0.0-alpha.65",
+ "description": "Remark plugin for convert npm commands to yarn as tabs",
+ "main": "src/index.js",
+ "publishConfig": {
+ "access": "public"
+ },
+ "license": "MIT",
+ "dependencies": {
+ "npm-to-yarn": "^1.0.1"
+ },
+ "devDependencies": {
+ "remark": "^12.0.0",
+ "remark-mdx": "^1.5.8",
+ "to-vfile": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.4",
+ "react-dom": "^16.8.4"
+ },
+ "engines": {
+ "node": ">=10.15.1"
+ }
+ }
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.js.snap b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.js.snap
new file mode 100644
index 0000000000..735aeb451f
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/__snapshots__/index.test.js.snap
@@ -0,0 +1,74 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`npm2yarn plugin test: installation file 1`] = `
+"import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+
+
+\`\`\`bash
+ $ npm install --global docusaurus
+\`\`\`
+
+
+
+
+\`\`\`bash
+ $ yarn add --global docusaurus
+\`\`\`
+
+
+
+"
+`;
+
+exports[`npm2yarn plugin test: language was not setted 1`] = `
+"\`\`\`npm2yarn
+npm install --save docusaurus-plugin-name
+\`\`\`
+
+\`\`\`bash
+npm install --save docusaurus-plugin-name
+\`\`\`
+
+\`\`\`shell
+npm install --save docusaurus-plugin-name
+\`\`\`
+"
+`;
+
+exports[`npm2yarn plugin test: plugin file 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
+\`\`\`
+
+
+
+"
+`;
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/installation.md b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/installation.md
new file mode 100644
index 0000000000..68ce57629e
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/installation.md
@@ -0,0 +1,3 @@
+```bash npm2yarn
+ $ npm install --global docusaurus
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/plugin.md b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/plugin.md
new file mode 100644
index 0000000000..903c335d29
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/plugin.md
@@ -0,0 +1,7 @@
+## Installing a plugin
+
+A plugin is usually a npm package, so you install them like other npm packages using npm.
+
+```bash npm2yarn
+npm install --save docusaurus-plugin-name
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/syntax-not-properly-set.md b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/syntax-not-properly-set.md
new file mode 100644
index 0000000000..c4bebceed9
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/fixtures/syntax-not-properly-set.md
@@ -0,0 +1,11 @@
+```npm2yarn
+npm install --save docusaurus-plugin-name
+```
+
+```bash
+npm install --save docusaurus-plugin-name
+```
+
+```shell
+npm install --save docusaurus-plugin-name
+```
diff --git a/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.js b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.js
new file mode 100644
index 0000000000..d504331c52
--- /dev/null
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/__tests__/index.test.js
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/* eslint-disable no-param-reassign */
+
+import remark from 'remark';
+import npm2yarn from '../index';
+import vfile from 'to-vfile';
+import {join, relative} from 'path';
+import mdx from 'remark-mdx';
+
+const staticDir = `./${relative(process.cwd(), join(__dirname, 'fixtures'))}`;
+
+const processFixture = async (name, options) => {
+ const path = join(__dirname, 'fixtures', `${name}.md`);
+ const file = await vfile.read(path);
+ const result = await remark()
+ .use(mdx)
+ .use(npm2yarn, {...options, filePath: path})
+ .process(file);
+
+ return result.toString();
+};
+
+describe('npm2yarn plugin', () => {
+ test('test: installation file', async () => {
+ const result = await processFixture('installation', {
+ staticDir,
+ });
+
+ expect(result).toMatchSnapshot();
+ });
+
+ test('test: plugin file', async () => {
+ const result = await processFixture('plugin', {
+ staticDir,
+ });
+
+ expect(result).toMatchSnapshot();
+ });
+
+ test('test: language was not setted', async () => {
+ const result = await processFixture('syntax-not-properly-set', {
+ staticDir,
+ });
+
+ expect(result).toMatchSnapshot();
+ });
+});
diff --git a/website/src/plugins/remark-npm2yarn.js b/packages/docusaurus-remark-plugin-npm2yarn/src/index.js
similarity index 96%
rename from website/src/plugins/remark-npm2yarn.js
rename to packages/docusaurus-remark-plugin-npm2yarn/src/index.js
index 02118ec6d4..3fb7dc6627 100644
--- a/website/src/plugins/remark-npm2yarn.js
+++ b/packages/docusaurus-remark-plugin-npm2yarn/src/index.js
@@ -17,7 +17,7 @@ const transformNode = (node) => {
{
type: 'jsx',
value:
- `