Skip to content

Commit

Permalink
feat: Improved sidebar structure
Browse files Browse the repository at this point in the history
  • Loading branch information
tgreyuk committed May 10, 2021
1 parent d5760a3 commit c32ed2c
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 50 deletions.
26 changes: 16 additions & 10 deletions packages/vuepress-plugin-typedoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ This guide assumes that a VuePress project has been setup. See [getting started
npm install typedoc typedoc-plugin-markdown vuepress-plugin-typedoc --save-dev
```

## Usage

### Config

Add the plugin to `.vuepress/config.js` and specify the required options (see [options](#options)).


```js
plugins: [
[
Expand Down Expand Up @@ -78,15 +79,22 @@ Additional TypeDoc plugins will need to be explicitly set:
plugin:['typedoc-plugin-xyz']
```

TypeDoc options can also be declared:

- Using a `typedoc.json` file.
- Under the `typedocOptions` key in `tsconfig.json`.

Note: Options declared in this manner will take priority and overwrite options declared in `docusaurus.config.js`.


### Plugin options

| Name | Default | Description |
| :------------------------------ | :------- | :--------------------------------------------------------------------------------- |
| `out` | `"api"` | Output directory relative to docs directory. |
| `allReflectionsHaveOwnDocument` | `false` | Output all reflections into seperate output files. |
| `hideInPageTOC` | `false` | Do not render in-page table of contents items. |
| `sidebar.fullNames` | `false` | Display full names with module path if applicable. |
| `sidebar.parentCategory` | `"none"` | The parent category label for sidebar - (defaults to `none` - no parent category). |
| Name | Default | Description |
| :----------------------- | :------ | :--------------------------------------------------------------------------- |
| `out` | `"api"` | Output directory relative to docs directory. |
| `hideInPageTOC` | `false` | Do not render in-page table of contents items. |
| `sidebar.fullNames` | `false` | Display full names with module path if applicable. |
| `sidebar.parentCategory` | `"API"` | The parent category label for sidebar. Pass `"none"` for no parent category. |


### Example config
Expand All @@ -113,8 +121,6 @@ plugin:['typedoc-plugin-xyz']

```

Once built the docs will be available at `/api` or equivalent out directory.

## License

[MIT](https://github.com/tgreyuk/typedoc-plugin-markdown/blob/master/packages/vuepress-plugin-typedoc/LICENSE)
4 changes: 2 additions & 2 deletions packages/vuepress-plugin-typedoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"prepublishOnly": "yarn run lint && yarn run build && yarn run test",
"build": "rm -rf ./dist && tsc",
"test:init": "rm -rf test/site && yarn create vuepress-site test/site",
"test:demo:start": "rm -rf ./test/site/docs/api && yarn run build && cd test/site/docs && yarn run dev",
"test:demo:build": "rm -rf ./test/site/docs/api && yarn run build && cd test/site/docs && yarn run build && npx http-server ./src/.vuepress/dist -o",
"test:demo:start": "yarn run build && cd test/site/docs && yarn run dev",
"test:demo:build": "yarn run build && cd test/site/docs && yarn run build && npx http-server ./src/.vuepress/dist -o",
"test": "jest --colors",
"build-and-test": "npm run build && npm run test"
},
Expand Down
10 changes: 8 additions & 2 deletions packages/vuepress-plugin-typedoc/src/front-matter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,27 @@ import { Component } from 'typedoc/dist/lib/converter/components';
import { RendererComponent } from 'typedoc/dist/lib/output/components';
import { PageEvent } from 'typedoc/dist/lib/output/events';

import { FrontMatter } from './types';

@Component({ name: 'front-matter' })
export class FrontMatterComponent extends RendererComponent {
@BindOption('entryDocument')
entryDocument!: string;
@BindOption('entryPoints')
entryPoints!: string[];
initialize() {
super.initialize();
this.listenTo(this.application.renderer, {
[PageEvent.END]: this.onPageEnd,
});
}

onPageEnd(page: PageEvent) {
if (page.contents) {
page.contents = prependYAML(page.contents, {
const items: FrontMatter = {
title: this.getTitle(page),
});
};
page.contents = prependYAML(page.contents, items as any);
}
}

Expand Down
3 changes: 1 addition & 2 deletions packages/vuepress-plugin-typedoc/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import { PluginOptions, SidebarOptions } from './types';

const DEFAULT_PLUGIN_OPTIONS: PluginOptions = {
out: 'api',
hideBreadcrumbs: true,
sidebar: {
parentCategory: 'none',
parentCategory: 'API',
fullNames: false,
sidebarFile: 'typedoc-sidebar.js',
sidebarPath: '',
Expand Down
17 changes: 7 additions & 10 deletions packages/vuepress-plugin-typedoc/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as path from 'path';

import { Application, ProjectReflection } from 'typedoc';
import MarkdownPlugin from 'typedoc-plugin-markdown';

Expand All @@ -21,7 +23,7 @@ export const typedocPlugin = (opts: PluginOptions, ctx: any) => {

addOptions(app);

app.bootstrap(options);
app.bootstrap({ ...options, theme: path.resolve(__dirname) });

app.renderer.addComponent('fm', new FrontMatterComponent(app.renderer));

Expand Down Expand Up @@ -50,19 +52,14 @@ export const typedocPlugin = (opts: PluginOptions, ctx: any) => {
}
const theme = app.renderer.theme as any;
const navigation = theme.getNavigation(project);
const sidebarJson = JSON.stringify({
[`/${options.out}/`]: getSidebarJson(navigation, options),
});
return {
name: 'typedoc-sidebar',
content: `export default ({ siteData, options }) => {
siteData.themeConfig.sidebarDepth = 0;
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,${JSON.stringify(
{
[`/${options.out}/`]: getSidebarJson(
navigation,
options.out,
options.sidebar,
),
},
)});
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,${sidebarJson});
}`,
};
},
Expand Down
50 changes: 32 additions & 18 deletions packages/vuepress-plugin-typedoc/src/sidebar.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,57 @@
import { NavigationItem } from 'typedoc';

import { SidebarOptions } from './types';
import { PluginOptions } from './types';

export const getSidebarJson = (
navigation: NavigationItem,
out: string,
sidebar: SidebarOptions,
options: PluginOptions,
) => {
const navJson: any = [];

const getShortName = (title: string) => {
const longTitle = title.split('.');
return longTitle[longTitle.length - 1];
};

navigation.children?.forEach((navigationItem) => {
if (navigationItem.url && navigationItem.children?.length === 0) {
const urlKey = navigationItem.url.replace('.md', '');
navJson.push([
urlKey === 'README' ? `/${out}/` : 'modules',
navigationItem.title,
]);
} else {
if (navigationItem.isLabel) {
navJson.push({
title: navigationItem.title,
children: navigationItem.children?.map((navItem) => {
return [
getUrlKey(navItem.url),
sidebar.fullNames ? navItem.title : getShortName(navItem.title),
options.sidebar?.fullNames
? navItem.title
: getShortName(navItem.title),
];
}),
});
} else {
navJson.push([
getUrlKey(navigationItem.url) === 'README'
? `/${options.out}/`
: `/${options.out}/modules`,
navigationItem.title,
]);
}
});
if (sidebar.parentCategory && sidebar.parentCategory !== 'none') {
return [{ title: sidebar.parentCategory, children: navJson }];
if (
options.sidebar?.parentCategory &&
options.sidebar.parentCategory !== 'none'
) {
return [
{
title: options.sidebar.parentCategory,
children: navJson,
initialOpenGroupIndex: -1,
collapsable: false,
},
];
}

return navJson;
};

const getShortName = (title: string) => {
const longTitle = title.split('.');
return longTitle[longTitle.length - 1];
};

const getUrlKey = (url: string) => {
return url.replace('.md', '');
};
9 changes: 9 additions & 0 deletions packages/vuepress-plugin-typedoc/src/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import MarkdownTheme from 'typedoc-plugin-markdown/dist/theme';
import { Renderer } from 'typedoc/dist/lib/output/renderer';

export default class VuePressTheme extends MarkdownTheme {
constructor(renderer: Renderer, basePath: string) {
super(renderer, basePath);
renderer.application.options.setValue('hideBreadcrumbs', true);
}
}
7 changes: 6 additions & 1 deletion packages/vuepress-plugin-typedoc/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Application, ProjectReflection } from 'typedoc';

export interface PluginOptions {
hideBreadcrumbs: boolean;
out: string;
readme?: string;
sidebar?: SidebarOptions | null;
plugin: string[];
watch: boolean;
Expand All @@ -19,3 +19,8 @@ export interface LoadedContent {
app: Application;
project: ProjectReflection;
}

export interface FrontMatter {
title: string;
sidebarDepth?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ module.exports = {
editLinkText: '',
lastUpdated: false,
nav: [
{
text: 'API',
link: '/api/',
},
{
text: 'Guide',
link: '/guide/',
Expand Down Expand Up @@ -68,8 +72,9 @@ module.exports = {
[
path.resolve(__dirname, '..', '..', '..', '..', '..', 'dist'),
{
entryPoints:
entryPoints: [
'../../../../typedoc-plugin-markdown/test/stubs/src/index.ts',
],
tsconfig:
'../../../../typedoc-plugin-markdown/test/stubs/tsconfig.json',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ exports[`(sidebars) should generate default 1`] = `
Object {
"content": "export default ({ siteData, options }) => {
siteData.themeConfig.sidebarDepth = 0;
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,{\\"/api/\\":[[\\"/api/\\",\\"Readme\\"],[\\"modules\\",\\"Exports\\"],{\\"title\\":\\"Namespaces\\",\\"children\\":[[\\"modules/namespacea\\",\\"namespaceA\\"],[\\"modules/namespaceb\\",\\"namespaceB\\"]]},{\\"title\\":\\"Enumerations\\",\\"children\\":[[\\"enums/enumitema\\",\\"enumItemA\\"],[\\"enums/enumitemb\\",\\"enumItemB\\"]]},{\\"title\\":\\"Classes\\",\\"children\\":[[\\"classes/namespacea.somenestedclass\\",\\"SomeNestedClass\\"],[\\"classes/classitema\\",\\"ClassItemA\\"],[\\"classes/classitemb\\",\\"ClassItemB\\"]]},{\\"title\\":\\"Interfaces\\",\\"children\\":[[\\"interfaces/interfaceitema\\",\\"InterfaceItemA\\"],[\\"interfaces/interfaceitemb\\",\\"InterfaceItemB\\"]]}]});
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,{\\"/api/\\":[[\\"/api/\\",\\"Readme\\"],[\\"/api/modules\\",\\"Exports\\"],{\\"title\\":\\"Namespaces\\",\\"children\\":[[\\"modules/namespacea\\",\\"namespaceA\\"],[\\"modules/namespaceb\\",\\"namespaceB\\"]]},{\\"title\\":\\"Enumerations\\",\\"children\\":[[\\"enums/enumitema\\",\\"enumItemA\\"],[\\"enums/enumitemb\\",\\"enumItemB\\"]]},{\\"title\\":\\"Classes\\",\\"children\\":[[\\"classes/classitema\\",\\"ClassItemA\\"],[\\"classes/classitemb\\",\\"ClassItemB\\"],[\\"classes/namespacea.somenestedclass\\",\\"SomeNestedClass\\"]]},{\\"title\\":\\"Interfaces\\",\\"children\\":[[\\"interfaces/interfaceitema\\",\\"InterfaceItemA\\"],[\\"interfaces/interfaceitemb\\",\\"InterfaceItemB\\"]]}]});
}",
"name": "typedoc-sidebar",
}
Expand All @@ -40,7 +40,7 @@ exports[`(sidebars) should generate with parent category and fullNames 1`] = `
Object {
"content": "export default ({ siteData, options }) => {
siteData.themeConfig.sidebarDepth = 0;
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,{\\"/api/\\":[{\\"title\\":\\"Parent Category\\",\\"children\\":[[\\"/api/\\",\\"Readme\\"],[\\"modules\\",\\"Exports\\"],{\\"title\\":\\"Namespaces\\",\\"children\\":[[\\"modules/namespacea\\",\\"namespaceA\\"],[\\"modules/namespaceb\\",\\"namespaceB\\"]]},{\\"title\\":\\"Enumerations\\",\\"children\\":[[\\"enums/enumitema\\",\\"enumItemA\\"],[\\"enums/enumitemb\\",\\"enumItemB\\"]]},{\\"title\\":\\"Classes\\",\\"children\\":[[\\"classes/namespacea.somenestedclass\\",\\"namespaceA.SomeNestedClass\\"],[\\"classes/classitema\\",\\"ClassItemA\\"],[\\"classes/classitemb\\",\\"ClassItemB\\"]]},{\\"title\\":\\"Interfaces\\",\\"children\\":[[\\"interfaces/interfaceitema\\",\\"InterfaceItemA\\"],[\\"interfaces/interfaceitemb\\",\\"InterfaceItemB\\"]]}]}]});
siteData.themeConfig.sidebar = Object.assign({},siteData.themeConfig.sidebar,{\\"/api/\\":[{\\"title\\":\\"API\\",\\"children\\":[[\\"/api/\\",\\"Readme\\"],[\\"/api/modules\\",\\"Exports\\"],{\\"title\\":\\"Namespaces\\",\\"children\\":[[\\"modules/namespacea\\",\\"namespaceA\\"],[\\"modules/namespaceb\\",\\"namespaceB\\"]]},{\\"title\\":\\"Enumerations\\",\\"children\\":[[\\"enums/enumitema\\",\\"enumItemA\\"],[\\"enums/enumitemb\\",\\"enumItemB\\"]]},{\\"title\\":\\"Classes\\",\\"children\\":[[\\"classes/classitema\\",\\"ClassItemA\\"],[\\"classes/classitemb\\",\\"ClassItemB\\"],[\\"classes/namespacea.somenestedclass\\",\\"namespaceA.SomeNestedClass\\"]]},{\\"title\\":\\"Interfaces\\",\\"children\\":[[\\"interfaces/interfaceitema\\",\\"InterfaceItemA\\"],[\\"interfaces/interfaceitemb\\",\\"InterfaceItemB\\"]]}],\\"initialOpenGroupIndex\\":-1,\\"collapsable\\":false}]});
}",
"name": "typedoc-sidebar",
}
Expand Down
4 changes: 2 additions & 2 deletions packages/vuepress-plugin-typedoc/test/specs/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ describe(`(sidebars)`, () => {
bootstrap(tmpobj);
});
test(`should generate default`, async () => {
const plugin = bootstrap(tmpobj);
const plugin = bootstrap(tmpobj, { sidebar: { parentCategory: 'none' } });
const enhancedFiles = await plugin.enhanceAppFiles();
expect(enhancedFiles).toMatchSnapshot();
});

test(`should generate with parent category and fullNames`, async () => {
const plugin = bootstrap(tmpobj, {
sidebar: { parentCategory: 'Parent Category', fullNames: true },
sidebar: { fullNames: true },
});
const enhancedFiles = await plugin.enhanceAppFiles();
expect(enhancedFiles).toMatchSnapshot();
Expand Down

0 comments on commit c32ed2c

Please sign in to comment.