Skip to content

Commit

Permalink
feat: docusaurus v3
Browse files Browse the repository at this point in the history
  • Loading branch information
Airkro committed Nov 10, 2023
1 parent bc06068 commit 3c31c25
Show file tree
Hide file tree
Showing 16 changed files with 1,599 additions and 232 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module.exports = async () => {
'classic',
{
docs: {
remarkPlugins: [autoTabs, docCardList]
beforeDefaultRemarkPlugins: [autoTabs, docCardList]
}
}
]
Expand All @@ -42,11 +42,12 @@ module.exports = async () => {

### DocCardList

#### Options.placeholder
#### Options.version

- type: `string`
- minLength: 5
- default: `:docusaurus-doc-card-list`
- type: `integer`
- enum: [2, 3]
- default: 2
- description: Docusaurus version

Turn:

Expand Down Expand Up @@ -78,6 +79,13 @@ foo bar
- default: {}
- description: Will merge with default presets

#### Options.version

- type: `integer`
- enum: [2, 3]
- default: 2
- description: Docusaurus version

Turn:

````markdown
Expand Down
92 changes: 62 additions & 30 deletions lib/auto-tabs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,25 @@ function isTab({ type, meta }, _, parent) {
);
}

function needImport(nodes, text) {
function matchStatement(value, target) {
return value === target || value === target.replaceAll("'", '"');
}

function needImport(version, nodes, target) {
return !nodes.some(
({ type, value }) => type === 'import' && value.includes(text),
({ type, value, lang }) =>
(version === 2
? type === 'import'
: type === 'mdxjsEsm' ||
(type === 'code' && lang === 'mdx-code-block')) &&
matchStatement(value, target),
);
}

function importStatement(value) {
return { type: 'import', value };
function importStatement(version, value) {
return version === 2
? { type: 'import', value }
: { type: 'code', lang: 'mdx-code-block', value };
}

const presets = {
Expand Down Expand Up @@ -62,14 +73,21 @@ function isLast(node, index, parent) {
}

/* eslint-disable no-param-reassign */
export function autoTabs({ labels = {} } = {}) {
export function autoTabs({ labels = {}, version = 2 } = {}) {
assert(
labels && typeof labels === 'object' && !Array.isArray(labels),
new TypeError('`labels` should be object'),
);
assert([2, 3].includes(version), new TypeError('`version` should be 2 or 3'));

const allLabels = { ...presets, ...labels };

function jsx(object) {
return version === 2
? { ...object, type: 'jsx' }
: { ...object, type: 'code', lang: 'mdx-code-block' };
}

return (tree) => {
let haveTabs = false;
let haveTabItem = false;
Expand All @@ -93,43 +111,57 @@ export function autoTabs({ labels = {} } = {}) {

node.meta = stringify(meta);

parent.children.splice(index + 1, 0, {
type: 'jsx',
is: 'TabItem-end-tag',
value: '</TabItem>',
});

parent.children.splice(index, 0, {
type: 'jsx',
is: 'TabItem-begin-tag',
value: `<TabItem label="${label}" value="${label}-${lang}">`,
});
parent.children.splice(
index + 1,
0,
jsx({
is: 'TabItem-end-tag',
value: '</TabItem>',
}),
);

parent.children.splice(
index,
0,
jsx({
is: 'TabItem-begin-tag',
value: `<TabItem label="${label}" value="${label}-${lang}">`,
}),
);
});

visit(tree, isFirst, (node, index, parent) => {
haveTabs = true;
parent.children.splice(index, 0, {
type: 'jsx',
is: 'Tabs-begin-tag',
value: '<Tabs>',
});
parent.children.splice(
index,
0,
jsx({
is: 'Tabs-begin-tag',
value: '<Tabs>',
}),
);
});

visit(tree, isLast, (node, index, parent) => {
parent.children.splice(index + 1, 0, {
type: 'jsx',
is: 'Tabs-end-tag',
value: '</Tabs>',
});
parent.children.splice(
index + 1,
0,
jsx({
is: 'Tabs-end-tag',
value: '</Tabs>',
}),
);
});

if (haveTabs && needImport(tree.children, '@theme/Tabs')) {
tree.children.unshift(importStatement("import Tabs from '@theme/Tabs'"));
if (haveTabs && needImport(version, tree.children, '@theme/Tabs')) {
tree.children.unshift(
importStatement(version, "import Tabs from '@theme/Tabs'"),
);
}

if (haveTabItem && needImport(tree.children, '@theme/TabItem')) {
if (haveTabItem && needImport(version, tree.children, '@theme/TabItem')) {
tree.children.unshift(
importStatement("import TabItem from '@theme/TabItem';"),
importStatement(version, "import TabItem from '@theme/TabItem';"),
);
}
};
Expand Down
108 changes: 73 additions & 35 deletions lib/doc-card-list.mjs
Original file line number Diff line number Diff line change
@@ -1,60 +1,98 @@
import { strict as assert } from 'assert';
import { strict as assert } from 'node:assert';

import { visit } from 'unist-util-visit';

function needImport(nodes, text) {
return !nodes.some(
({ type, value }) => type === 'import' && value.includes(text),
const placeholder = 'docusaurus-doc-card-list';

function isDirective({ type, children: [line] = [] }, _, parent) {
return (
parent?.type === 'root' &&
type === 'paragraph' &&
line &&
((line.type === 'textDirective' && line.name === placeholder) ||
(line.type === 'text' && line.value === `:${placeholder}`))
);
}

function importStatement(value) {
return { type: 'import', value };
}
const importStatement = "import DocCardList from '@theme/DocCardList';";

function isDirective(placeholder) {
return ({ type, children: [line] = [] }, _, parent) => {
return (
parent?.type === 'root' &&
type === 'paragraph' &&
line?.type === 'text' &&
line?.value === placeholder
);
};
function matchStatement(value) {
return (
value === importStatement || value === importStatement.replaceAll("'", '"')
);
}

/* eslint-disable no-param-reassign */
export function docCardList({
placeholder = ':docusaurus-doc-card-list',
} = {}) {
assert(
typeof placeholder === 'string',
new TypeError('`placeholder` should be string'),
);

assert(
placeholder.length > 5,
new TypeError('`placeholder` should be longer than 5 characters'),
);
export function docCardList({ version = 2 } = {}) {
assert([2, 3].includes(version), new TypeError('`version` should be 2 or 3'));

return (tree) => {
let haveDirective = false;

visit(tree, isDirective(placeholder), (_, index, parent) => {
visit(tree, isDirective, (_, index, parent) => {
if (!haveDirective) {
haveDirective = true;
}

parent.children[index] = {
type: 'jsx',
value: '<DocCardList />',
...(version === 2
? { type: 'jsx', value: '<DocCardList />' }
: {
type: 'mdxJsxFlowElement',
name: 'DocCardList',
}),
};
});

if (haveDirective && needImport(tree.children, '@theme/DocCardList')) {
tree.children.unshift(
importStatement("import DocCardList from '@theme/DocCardList';"),
);
if (haveDirective) {
if (
version === 2 &&
!tree.children.some(
({ type, value }) => type === 'import' && matchStatement(value),
)
) {
tree.children.unshift({
type: 'import',
value: importStatement,
});
}

if (
version === 3 &&
!tree.children.some(
({ type, value }) => type === 'mdxjsEsm' && matchStatement(value),
)
) {
tree.children.unshift({
type: 'mdxjsEsm',
value: "import DocCardList from '@theme/DocCardList';",
data: {
estree: {
type: 'Program',
body: [
{
type: 'ImportDeclaration',
specifiers: [
{
type: 'ImportDefaultSpecifier',
local: {
type: 'Identifier',
name: 'DocCardList',
},
},
],
source: {
type: 'Literal',
value: '@theme/DocCardList',
raw: "'@theme/DocCardList'",
},
},
],
sourceType: 'module',
},
},
});
}
}
};
}
Loading

0 comments on commit 3c31c25

Please sign in to comment.