Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Link to demos and API in IntelliSense #20078

Merged
merged 15 commits into from
Mar 18, 2020
Merged
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