Skip to content

Commit

Permalink
[docs] Link to demos and API in IntelliSense (mui#20078)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon authored and EsoterikStare committed Mar 30, 2020
1 parent 7bc847b commit 54ac991
Show file tree
Hide file tree
Showing 133 changed files with 1,903 additions and 30 deletions.
4 changes: 4 additions & 0 deletions docs/pages/api-docs/alert-title.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ You can override the style of the component thanks to one of these customization

If that's not sufficient, you can check the [implementation of the component](https://github.com/mui-org/material-ui/blob/master/packages/material-ui-lab/src/AlertTitle/AlertTitle.js) for more detail.

## Demos

- [Alert](/components/alert/)

2 changes: 1 addition & 1 deletion docs/pages/api-docs/menu-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { MenuList } from '@material-ui/core';

You can learn more about the difference by [reading this guide](/guides/minimizing-bundle-size/).

A permanently displayed menu following https://www.w3.org/TR/wai-aria-practices/#menubutton
A permanently displayed menu following https://www.w3.org/TR/wai-aria-practices/#menubutton.
It's exposed to help customization of the [`Menu`](/api/menu/) component. If you
use it separately you need to move focus into the component manually. Once
the focus is placed inside the component it is fully keyboard accessible.
Expand Down
126 changes: 126 additions & 0 deletions docs/scripts/buildApi.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/* eslint-disable no-console */
import * as babel from '@babel/core';
import traverse from '@babel/traverse';
import { mkdir, readFileSync, writeFileSync } from 'fs';
import { getLineFeed } from './helpers';
import { rewriteUrlForNextExport } from 'next/dist/next-server/lib/router/rewrite-url-for-export';
import path from 'path';
import kebabCase from 'lodash/kebabCase';
import uniqBy from 'lodash/uniqBy';
import { defaultHandlers, parse as docgenParse } from 'react-docgen';
import remark from 'remark';
import remarkVisit from 'unist-util-visit';
import muiDefaultPropsHandler from '../src/modules/utils/defaultPropsHandler';
import generateMarkdown from '../src/modules/utils/generateMarkdown';
import { findPagesMarkdown, findComponents } from '../src/modules/utils/find';
import { getHeaders } from '../src/modules/utils/parseMarkdown';
import parseTest from '../src/modules/utils/parseTest';
import { pageToTitle } from '../src/modules/utils/helpers';
import createMuiTheme from '../../packages/material-ui/src/styles/createMuiTheme';
import getStylesCreator from '../../packages/material-ui-styles/src/getStylesCreator';
import createGenerateClassName from '../../packages/material-ui-styles/src/createGenerateClassName';
Expand Down Expand Up @@ -80,6 +87,123 @@ function getInheritance(testInfo, src) {
};
}

/**
* Produces markdown of the description that can be hosted anywhere.
*
* By default we assume that the markdown is hosted on material-ui.com which is
* why the source includes relative url. We transform them to absolute urls with
* this method.
*
* @param {object} api
* @param {object} options
*/
function computeApiDescription(api, options) {
const { host } = options;
return new Promise((resolve, reject) => {
remark()
.use(function docsLinksAttacher() {
return function transformer(tree) {
remarkVisit(tree, 'link', linkNode => {
if (linkNode.url.startsWith('/')) {
linkNode.url = `${host}${linkNode.url}`;
}
});
};
})
.process(api.description, (error, file) => {
if (error) reject(error);

resolve(file.contents.trim());
});
});
}

async function annotateComponentDefinition(component, api) {
const HOST = 'https://material-ui.com';

const typesFilename = component.filename.replace(/\.js$/, '.d.ts');
const typesSource = readFileSync(typesFilename, { encoding: 'utf8' });
const typesAST = await babel.parseAsync(typesSource, {
configFile: false,
filename: typesFilename,
presets: [require.resolve('@babel/preset-typescript')],
});

let start = null;
let end = null;
traverse(typesAST, {
ExportDefaultDeclaration(babelPath) {
// export default function Menu() {}
let node = babelPath.node;
if (node.declaration.type === 'Identifier') {
// declare const Menu: {};
// export default Menu;
const bindingId = babelPath.node.declaration.name;
const binding = babelPath.scope.bindings[bindingId];
node = binding.path.parentPath.node;
}

const { leadingComments = [] } = node;
const [jsdocBlock, ...rest] = leadingComments;
if (rest.length > 0) {
throw new Error('Should only have a single leading jsdoc block');
}
if (jsdocBlock !== undefined) {
start = jsdocBlock.start;
end = jsdocBlock.end;
} else {
start = node.start - 1;
end = start;
}
},
});

if (end === null || start === 0) {
throw new TypeError(
"Don't know where to insert the jsdoc block. Probably no `default export` found",
);
}

const demos = uniqBy(
api.pagesMarkdown.filter(page => {
return page.components.includes(api.name);
}, []),
page => page.pathname,
);

let inheritanceAPILink = null;
if (api.inheritance !== null) {
const url = api.inheritance.pathname.startsWith('/')
? `${HOST}${rewriteUrlForNextExport(api.inheritance.pathname)}`
: api.inheritance.pathname;

inheritanceAPILink = `[${api.inheritance.component} API](${url})`;
}

const markdownLines = (await computeApiDescription(api, { host: HOST })).split('\n');
if (demos.length > 0) {
markdownLines.push(
'Demos:',
'',
...demos.map(
page => `- [${pageToTitle(page)}](${HOST}${rewriteUrlForNextExport(page.pathname)})`,
),
'',
);
}

markdownLines.push('API:', '', `- [${api.name} API](${HOST}/api/${kebabCase(api.name)}/)`);
if (api.inheritance !== null) {
markdownLines.push(`- inherits ${inheritanceAPILink}`);
}

const jsdoc = `/**\n${markdownLines
.map(line => (line.length > 0 ? ` * ${line}` : ` *`))
.join('\n')}\n */`;
const typesSourceNew = typesSource.slice(0, start) + jsdoc + typesSource.slice(end);
writeFileSync(typesFilename, typesSourceNew, { encoding: 'utf8' });
}

async function buildDocs(options) {
const { component: componentObject, pagesMarkdown } = options;
const src = readFileSync(componentObject.filename, 'utf8');
Expand Down Expand Up @@ -209,6 +333,8 @@ export default function Page() {

console.log('Built markdown docs for', reactAPI.name);
});

await annotateComponentDefinition(componentObject, reactAPI);
}

function run() {
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/components/alert/alert.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Alert React component
components: Alert
components: Alert, AlertTitle
---

# Alert
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-test-renderer": "^16.13.0",
"remark": "^11.0.2",
"rimraf": "^3.0.0",
"rollup": "^1.21.4",
"rollup-plugin-babel": "^4.3.3",
Expand All @@ -141,6 +142,7 @@
"tslint": "5.14.0",
"typescript": "^3.8.2",
"typescript-to-proptypes": "^1.4.0",
"unist-util-visit": "^2.0.2",
"vrtest-mui": "^0.3.3",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
Expand Down
11 changes: 11 additions & 0 deletions packages/material-ui-lab/src/Alert/Alert.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,15 @@ export type AlertClassKey =
| 'message'
| 'action';

/**
*
* Demos:
*
* - [Alert](https://material-ui.com/components/alert/)
*
* API:
*
* - [Alert API](https://material-ui.com/api/alert/)
* - inherits [Paper API](https://material-ui.com/api/paper/)
*/
export default function Alert(props: AlertProps): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/AlertTitle/AlertTitle.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,14 @@ export interface AlertTitleProps

export type AlertTitleClassKey = 'root';

/**
*
* Demos:
*
* - [Alert](https://material-ui.com/components/alert/)
*
* API:
*
* - [AlertTitle API](https://material-ui.com/api/alert-title/)
*/
export default function AlertTitle(props: AlertTitleProps): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/Autocomplete/Autocomplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ export type AutocompleteClassKey =
| 'groupLabel'
| 'groupUl';

/**
*
* Demos:
*
* - [Autocomplete](https://material-ui.com/components/autocomplete/)
*
* API:
*
* - [Autocomplete API](https://material-ui.com/api/autocomplete/)
*/
export default function Autocomplete<T>(
props: AutocompleteProps<T> & UseAutocompleteProps<T>,
): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/AvatarGroup/AvatarGroup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ export interface AvatarGroupProps

export type AvatarGroupClassKey = 'root' | 'avatar';

/**
*
* Demos:
*
* - [Avatars](https://material-ui.com/components/avatars/)
*
* API:
*
* - [AvatarGroup API](https://material-ui.com/api/avatar-group/)
*/
export default function AvatarGroup(props: AvatarGroupProps): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/Pagination/Pagination.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,14 @@ export interface PaginationProps

export type PaginationClassKey = 'root' | 'ul';

/**
*
* Demos:
*
* - [Pagination](https://material-ui.com/components/pagination/)
*
* API:
*
* - [Pagination API](https://material-ui.com/api/pagination/)
*/
export default function Pagination(props: PaginationProps): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/PaginationItem/PaginationItem.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ export interface PaginationItemTypeMap<P = {}, D extends React.ElementType = 'di
classKey: PaginationItemClassKey;
}

/**
*
* Demos:
*
* - [Pagination](https://material-ui.com/components/pagination/)
*
* API:
*
* - [PaginationItem API](https://material-ui.com/api/pagination-item/)
*/
declare const PaginationItem: OverridableComponent<PaginationItemTypeMap>;

export type PaginationItemClassKey =
Expand Down
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/Rating/Rating.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ export type RatingClassKey =
| 'iconActive'
| 'decimal';

/**
*
* Demos:
*
* - [Rating](https://material-ui.com/components/rating/)
*
* API:
*
* - [Rating API](https://material-ui.com/api/rating/)
*/
declare const Rating: React.ComponentType<RatingProps>;

export default Rating;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/Skeleton/Skeleton.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ export interface SkeletonTypeMap<P = {}, D extends React.ElementType = 'span'> {
classKey: SkeletonClassKey;
}

/**
*
* Demos:
*
* - [Skeleton](https://material-ui.com/components/skeleton/)
*
* API:
*
* - [Skeleton API](https://material-ui.com/api/skeleton/)
*/
declare const Skeleton: OverridableComponent<SkeletonTypeMap>;

export type SkeletonClassKey = 'root' | 'text' | 'rect' | 'circle' | 'pulse' | 'wave';
Expand Down
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/SpeedDial/SpeedDial.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,14 @@ export type SpeedDialClassKey =
| 'actions'
| 'actionsClosed';

/**
*
* Demos:
*
* - [Speed Dial](https://material-ui.com/components/speed-dial/)
*
* API:
*
* - [SpeedDial API](https://material-ui.com/api/speed-dial/)
*/
export default function SpeedDial(props: SpeedDialProps): JSX.Element;
11 changes: 11 additions & 0 deletions packages/material-ui-lab/src/SpeedDialAction/SpeedDialAction.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,15 @@ export type SpeedDialActionClassKey =
| 'staticTooltipLabel'
| 'tooltipPlacementLeft';

/**
*
* Demos:
*
* - [Speed Dial](https://material-ui.com/components/speed-dial/)
*
* API:
*
* - [SpeedDialAction API](https://material-ui.com/api/speed-dial-action/)
* - inherits [Tooltip API](https://material-ui.com/api/tooltip/)
*/
export default function SpeedDialAction(props: SpeedDialActionProps): JSX.Element;
10 changes: 10 additions & 0 deletions packages/material-ui-lab/src/SpeedDialIcon/SpeedDialIcon.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,14 @@ export type SpeedDialIconClassKey =
| 'openIcon'
| 'openIconOpen';

/**
*
* Demos:
*
* - [Speed Dial](https://material-ui.com/components/speed-dial/)
*
* API:
*
* - [SpeedDialIcon API](https://material-ui.com/api/speed-dial-icon/)
*/
export default function SpeedDialIcon(props: SpeedDialIconProps): JSX.Element;
11 changes: 11 additions & 0 deletions packages/material-ui-lab/src/ToggleButton/ToggleButton.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ export type ToggleButtonTypeMap<
classKey: ToggleButtonClassKey;
}>;

/**
*
* Demos:
*
* - [Toggle Button](https://material-ui.com/components/toggle-button/)
*
* API:
*
* - [ToggleButton API](https://material-ui.com/api/toggle-button/)
* - inherits [ButtonBase API](https://material-ui.com/api/button-base/)
*/
declare const ToggleButton: ExtendButtonBase<ToggleButtonTypeMap>;

export type ToggleButtonProps<
Expand Down
Loading

0 comments on commit 54ac991

Please sign in to comment.