mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-01 18:32:52 +02:00
refactor(remark-plugin-npm2yarn): migrate package to TS (#5931)
* refactor(remark-plugin-npm2yarn): migrate package to TS * fix(remark-plugin-npm2yarn): type as unified Plugin * refactor(remark-plugin-npm2yarn): standardize code style with remark plugins in mdx-loader * Use unist-util-visit * Use export = * Remove unneeded includes option * Fix tests * Migrate test to TS * Make output look better Co-authored-by: Josh-Cena <sidachen2003@gmail.com>
This commit is contained in:
parent
c914da3a0c
commit
1e725a158e
7 changed files with 128 additions and 116 deletions
|
@ -2,10 +2,14 @@
|
|||
"name": "@docusaurus/remark-plugin-npm2yarn",
|
||||
"version": "2.0.0-beta.9",
|
||||
"description": "Remark plugin for converting npm commands to Yarn commands as tabs.",
|
||||
"main": "src/index.js",
|
||||
"main": "lib/index.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facebook/docusaurus.git",
|
||||
|
@ -13,9 +17,11 @@
|
|||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"npm-to-yarn": "^1.0.1"
|
||||
"npm-to-yarn": "^1.0.1",
|
||||
"unist-util-visit": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mdast": "^3.0.10",
|
||||
"remark": "^12.0.0",
|
||||
"remark-mdx": "^1.6.21",
|
||||
"to-vfile": "^6.0.0"
|
||||
|
|
|
@ -5,11 +5,7 @@ exports[`npm2yarn plugin test: already imported tabs components above are not re
|
|||
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs defaultValue=\\"npm\\" values={[
|
||||
{ label: 'npm', value: 'npm', },
|
||||
{ label: 'Yarn', value: 'yarn', },
|
||||
]}
|
||||
>
|
||||
<Tabs>
|
||||
<TabItem value=\\"npm\\">
|
||||
|
||||
\`\`\`bash
|
||||
|
@ -17,7 +13,7 @@ import TabItem from '@theme/TabItem';
|
|||
\`\`\`
|
||||
|
||||
</TabItem>
|
||||
<TabItem value=\\"yarn\\">
|
||||
<TabItem value=\\"yarn\\" label=\\"Yarn\\">
|
||||
|
||||
\`\`\`bash
|
||||
$ yarn add --global docusaurus
|
||||
|
@ -29,11 +25,7 @@ import TabItem from '@theme/TabItem';
|
|||
`;
|
||||
|
||||
exports[`npm2yarn plugin test: already imported tabs components below are not re-imported 1`] = `
|
||||
"<Tabs defaultValue=\\"npm\\" values={[
|
||||
{ label: 'npm', value: 'npm', },
|
||||
{ label: 'Yarn', value: 'yarn', },
|
||||
]}
|
||||
>
|
||||
"<Tabs>
|
||||
<TabItem value=\\"npm\\">
|
||||
|
||||
\`\`\`bash
|
||||
|
@ -41,7 +33,7 @@ exports[`npm2yarn plugin test: already imported tabs components below are not re
|
|||
\`\`\`
|
||||
|
||||
</TabItem>
|
||||
<TabItem value=\\"yarn\\">
|
||||
<TabItem value=\\"yarn\\" label=\\"Yarn\\">
|
||||
|
||||
\`\`\`bash
|
||||
$ yarn add --global docusaurus
|
||||
|
@ -60,11 +52,7 @@ exports[`npm2yarn plugin test: installation file 1`] = `
|
|||
"import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<Tabs defaultValue=\\"npm\\" values={[
|
||||
{ label: 'npm', value: 'npm', },
|
||||
{ label: 'Yarn', value: 'yarn', },
|
||||
]}
|
||||
>
|
||||
<Tabs>
|
||||
<TabItem value=\\"npm\\">
|
||||
|
||||
\`\`\`bash
|
||||
|
@ -72,7 +60,7 @@ import TabItem from '@theme/TabItem';
|
|||
\`\`\`
|
||||
|
||||
</TabItem>
|
||||
<TabItem value=\\"yarn\\">
|
||||
<TabItem value=\\"yarn\\" label=\\"Yarn\\">
|
||||
|
||||
\`\`\`bash
|
||||
$ yarn add --global docusaurus
|
||||
|
@ -106,11 +94,7 @@ import TabItem from '@theme/TabItem';
|
|||
|
||||
A plugin is usually a npm package, so you install them like other npm packages using npm.
|
||||
|
||||
<Tabs defaultValue=\\"npm\\" values={[
|
||||
{ label: 'npm', value: 'npm', },
|
||||
{ label: 'Yarn', value: 'yarn', },
|
||||
]}
|
||||
>
|
||||
<Tabs>
|
||||
<TabItem value=\\"npm\\">
|
||||
|
||||
\`\`\`bash
|
||||
|
@ -118,7 +102,7 @@ npm install --save docusaurus-plugin-name
|
|||
\`\`\`
|
||||
|
||||
</TabItem>
|
||||
<TabItem value=\\"yarn\\">
|
||||
<TabItem value=\\"yarn\\" label=\\"Yarn\\">
|
||||
|
||||
\`\`\`bash
|
||||
yarn add docusaurus-plugin-name
|
|
@ -6,14 +6,19 @@
|
|||
*/
|
||||
|
||||
import remark from 'remark';
|
||||
import npm2yarn from '../index';
|
||||
// import from the transpiled lib because Babel can't transpile `export =` syntax
|
||||
// TODO change to `../index` after migrating to ESM
|
||||
import npm2yarn from '../../lib/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 processFixture = async (
|
||||
name: string,
|
||||
options: {sync?: boolean; staticDir: string},
|
||||
) => {
|
||||
const path = join(__dirname, 'fixtures', `${name}.md`);
|
||||
const file = await vfile.read(path);
|
||||
const result = await remark()
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const npmToYarn = require('npm-to-yarn');
|
||||
|
||||
// E.g. global install: 'npm i' -> 'yarn'
|
||||
const convertNpmToYarn = (npmCode) => npmToYarn(npmCode, 'yarn');
|
||||
|
||||
const transformNode = (node, isSync) => {
|
||||
const groupIdProp = isSync ? 'groupId="npm2yarn" ' : '';
|
||||
const npmCode = node.value;
|
||||
const yarnCode = convertNpmToYarn(node.value);
|
||||
return [
|
||||
{
|
||||
type: 'jsx',
|
||||
value:
|
||||
`<Tabs defaultValue="npm" ${groupIdProp}` +
|
||||
`values={[
|
||||
{ label: 'npm', value: 'npm', },
|
||||
{ label: 'Yarn', value: 'yarn', },
|
||||
]}
|
||||
>
|
||||
<TabItem value="npm">`,
|
||||
},
|
||||
{
|
||||
type: node.type,
|
||||
lang: node.lang,
|
||||
value: npmCode,
|
||||
},
|
||||
{
|
||||
type: 'jsx',
|
||||
value: '</TabItem>\n<TabItem value="yarn">',
|
||||
},
|
||||
{
|
||||
type: node.type,
|
||||
lang: node.lang,
|
||||
value: yarnCode,
|
||||
},
|
||||
{
|
||||
type: 'jsx',
|
||||
value: '</TabItem>\n</Tabs>',
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const matchNode = (node) => node.type === 'code' && node.meta === 'npm2yarn';
|
||||
const nodeForImport = {
|
||||
type: 'import',
|
||||
value:
|
||||
"import Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';",
|
||||
};
|
||||
|
||||
module.exports = (options = {}) => {
|
||||
const {sync = false} = options;
|
||||
let transformed = false;
|
||||
let alreadyImported = false;
|
||||
const transformer = (node) => {
|
||||
if (node.type === 'import' && node.value.includes('@theme/Tabs')) {
|
||||
alreadyImported = true;
|
||||
}
|
||||
if (matchNode(node)) {
|
||||
transformed = true;
|
||||
return transformNode(node, sync);
|
||||
}
|
||||
if (Array.isArray(node.children)) {
|
||||
let index = 0;
|
||||
while (index < node.children.length) {
|
||||
const result = transformer(node.children[index]);
|
||||
if (result) {
|
||||
node.children.splice(index, 1, ...result);
|
||||
index += result.length;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type === 'root' && transformed && !alreadyImported) {
|
||||
node.children.unshift(nodeForImport);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return transformer;
|
||||
};
|
95
packages/docusaurus-remark-plugin-npm2yarn/src/index.ts
Normal file
95
packages/docusaurus-remark-plugin-npm2yarn/src/index.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import type {Code, Content, Literal} from 'mdast';
|
||||
import type {Plugin, Transformer} from 'unified';
|
||||
import type {Node, Parent} from 'unist';
|
||||
import visit from 'unist-util-visit';
|
||||
import npmToYarn from 'npm-to-yarn';
|
||||
|
||||
interface PluginOptions {
|
||||
sync?: boolean;
|
||||
}
|
||||
|
||||
// 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);
|
||||
return [
|
||||
{
|
||||
type: 'jsx',
|
||||
value: `<Tabs${groupIdProp}>\n<TabItem value="npm">`,
|
||||
},
|
||||
{
|
||||
type: node.type,
|
||||
lang: node.lang,
|
||||
value: npmCode,
|
||||
},
|
||||
{
|
||||
type: 'jsx',
|
||||
value: '</TabItem>\n<TabItem value="yarn" label="Yarn">',
|
||||
},
|
||||
{
|
||||
type: node.type,
|
||||
lang: node.lang,
|
||||
value: yarnCode,
|
||||
},
|
||||
{
|
||||
type: 'jsx',
|
||||
value: '</TabItem>\n</Tabs>',
|
||||
},
|
||||
] as Content[];
|
||||
};
|
||||
|
||||
const isImport = (node: Node): node is Literal => node.type === 'import';
|
||||
const isParent = (node: Node): node is Parent =>
|
||||
Array.isArray((node as Parent).children);
|
||||
const matchNode = (node: Node): node is Code =>
|
||||
node.type === 'code' && (node as Code).meta === 'npm2yarn';
|
||||
const nodeForImport: Literal = {
|
||||
type: 'import',
|
||||
value:
|
||||
"import Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';",
|
||||
};
|
||||
|
||||
const plugin: Plugin<[PluginOptions?]> = (options = {}) => {
|
||||
const {sync = false} = options;
|
||||
let transformed = false;
|
||||
let alreadyImported = false;
|
||||
const transformer: Transformer = (root) => {
|
||||
visit(root, (node: Node) => {
|
||||
if (isImport(node) && node.value.includes('@theme/Tabs')) {
|
||||
alreadyImported = true;
|
||||
}
|
||||
if (isParent(node)) {
|
||||
let index = 0;
|
||||
while (index < node.children.length) {
|
||||
const child = node.children[index];
|
||||
if (matchNode(child)) {
|
||||
const result = transformNode(child, sync);
|
||||
node.children.splice(index, 1, ...result);
|
||||
index += result.length;
|
||||
transformed = true;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (transformed && !alreadyImported) {
|
||||
(root as Parent).children.unshift(nodeForImport);
|
||||
}
|
||||
};
|
||||
return transformer;
|
||||
};
|
||||
|
||||
// To continue supporting `require('npm2yarn')` without the `.default` ㄟ(▔,▔)ㄏ
|
||||
// TODO change to export default after migrating to ESM
|
||||
export = plugin;
|
9
packages/docusaurus-remark-plugin-npm2yarn/tsconfig.json
Normal file
9
packages/docusaurus-remark-plugin-npm2yarn/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "./lib/.tsbuildinfo",
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
}
|
||||
}
|
|
@ -4262,7 +4262,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.174.tgz#b4b06b6eced9850eed6b6a8f1abdd0f5192803c1"
|
||||
integrity sha512-KMBLT6+g9qrGXpDt7ohjWPUD34WA/jasrtjTEHStF0NPdEwJ1N9SZ+4GaMVDeuk/y0+X5j9xFm6mNiXS7UoaLQ==
|
||||
|
||||
"@types/mdast@^3.0.0", "@types/mdast@^3.0.7":
|
||||
"@types/mdast@^3.0.0", "@types/mdast@^3.0.10", "@types/mdast@^3.0.7":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af"
|
||||
integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue