From d7bcf637920e08830def11112b02c5d14130711d Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:11:32 -0800 Subject: [PATCH 01/19] tag renderers are just SFCs! remove page arg from renderBlock --- packages/docs-theme/src/components/block.tsx | 10 +++++----- packages/docs-theme/src/components/page.tsx | 2 +- packages/docs-theme/src/tags/index.ts | 8 ++------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/docs-theme/src/components/block.tsx b/packages/docs-theme/src/components/block.tsx index aee6ffb370..767061cac2 100644 --- a/packages/docs-theme/src/components/block.tsx +++ b/packages/docs-theme/src/components/block.tsx @@ -4,12 +4,12 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { IBlock, IPageData } from "documentalist/dist/client"; +import { IBlock } from "documentalist/dist/client"; import * as React from "react"; -import { ITagRendererMap, TagElement } from "../tags"; +import { ITagRendererMap } from "../tags"; -export function renderBlock(block: IBlock | undefined, tagRenderers: ITagRendererMap, page?: IPageData): TagElement[] { +export function renderBlock(block: IBlock | undefined, tagRenderers: ITagRendererMap): JSX.Element[] { if (block === undefined) { return []; } @@ -22,11 +22,11 @@ export function renderBlock(block: IBlock | undefined, tagRenderers: ITagRendere if (renderer === undefined) { throw new Error(`Unknown @tag: ${node.tag}`); } - return renderer(node, i, tagRenderers, page); + return React.createElement(renderer, { ...node, key: i }); } catch (ex) { console.error(ex.message); return ( -

+

{ex.message}

); diff --git a/packages/docs-theme/src/components/page.tsx b/packages/docs-theme/src/components/page.tsx index 1ef8c9334a..8b41574fcf 100644 --- a/packages/docs-theme/src/components/page.tsx +++ b/packages/docs-theme/src/components/page.tsx @@ -16,7 +16,7 @@ export interface IPageProps { } export const Page: React.SFC = ({ tagRenderers, page }) => { - const pageContents = renderBlock(page, tagRenderers, page); + const pageContents = renderBlock(page, tagRenderers); return (
{pageContents} diff --git a/packages/docs-theme/src/tags/index.ts b/packages/docs-theme/src/tags/index.ts index 75a691b3f8..b5544ec595 100644 --- a/packages/docs-theme/src/tags/index.ts +++ b/packages/docs-theme/src/tags/index.ts @@ -4,16 +4,12 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { IPageData, ITag } from "documentalist/dist/client"; +import { ITag } from "documentalist/dist/client"; export interface ITagRendererMap { - [tagName: string]: TagRenderer; + [tagName: string]: React.SFC | undefined; } -export type TagElement = JSX.Element | undefined; - -export type TagRenderer = (tag: ITag, key: React.Key, tagRenderers: ITagRendererMap, page?: IPageData) => TagElement; - export * from "./css"; export * from "./defaults"; export * from "./heading"; From fd09617c2cf9ab25f75b8818a8ef1021afbc95e0 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:14:18 -0800 Subject: [PATCH 02/19] add context to Documentation component to expose renderers and docs data to children --- packages/docs-theme/src/common/context.ts | 37 +++++++++++++++++++ .../src/components/documentation.tsx | 18 +++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 packages/docs-theme/src/common/context.ts diff --git a/packages/docs-theme/src/common/context.ts b/packages/docs-theme/src/common/context.ts new file mode 100644 index 0000000000..7ffed95e0f --- /dev/null +++ b/packages/docs-theme/src/common/context.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { Utils } from "@blueprintjs/core"; +import { IBlock, IKssPluginData, IMarkdownPluginData, ITypescriptPluginData } from "documentalist/dist/client"; + +/** + * Gonna use React context to pass some helpful functions around. + * This is basically the pauper's Redux store connector: some central state from the root + * `Documentation` component is exposed to its children so those in the know can speak + * directly to their parent. + */ +export interface IDocumentationContext { + getDocsData(): IMarkdownPluginData & (ITypescriptPluginData | {}) & (IKssPluginData | {}); + + /** Render a block of Documentalist documentation to a React node. */ + renderBlock(block: IBlock): React.ReactNode; + + /** Render a Documentalist type string to a React node. */ + renderType(type: string): React.ReactNode; +} + +export const DocumentationContextTypes: React.ValidationMap = { + getDocsData: assertFunctionProp, + renderBlock: assertFunctionProp, + renderType: assertFunctionProp, +}; + +function assertFunctionProp(obj: T, key: keyof T) { + if (obj[key] != null && Utils.isFunction(obj[key])) { + return undefined; + } + return new Error(`[Blueprint] Documentation context ${key} must be function.`); +} diff --git a/packages/docs-theme/src/components/documentation.tsx b/packages/docs-theme/src/components/documentation.tsx index af440c0261..392807f745 100644 --- a/packages/docs-theme/src/components/documentation.tsx +++ b/packages/docs-theme/src/components/documentation.tsx @@ -5,13 +5,15 @@ */ import * as classNames from "classnames"; -import { IMarkdownPluginData, isPageNode } from "documentalist/dist/client"; +import { IMarkdownPluginData, isPageNode, ITypescriptPluginData, linkify } from "documentalist/dist/client"; import * as React from "react"; import { FocusStyleManager, Hotkey, Hotkeys, HotkeysTarget, IProps, Utils } from "@blueprintjs/core"; +import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; import { eachLayoutNode } from "../common/utils"; -import { TagRenderer } from "../tags"; +import { ITagRendererMap } from "../tags"; +import { renderBlock } from "./block"; import { Navigator } from "./navigator"; import { NavMenu } from "./navMenu"; import { Page } from "./page"; @@ -36,7 +38,7 @@ export interface IDocumentationProps extends IProps { onComponentUpdate?: (pageId: string) => void; /** Tag renderer functions. Unknown tags will log console errors. */ - tagRenderers: { [tag: string]: TagRenderer }; + tagRenderers: ITagRendererMap; /** * Elements to render on the left side of the navbar, typically logo and title. @@ -59,6 +61,8 @@ export interface IDocumentationState { @HotkeysTarget export class Documentation extends React.PureComponent { + public static childContextTypes = DocumentationContextTypes; + public static defaultProps = { navbarLeft: "Documentation", }; @@ -88,6 +92,14 @@ export class Documentation extends React.PureComponent this.props.docs, + renderBlock: block => renderBlock(block, this.props.tagRenderers), + renderType: type => linkify(type, this.props.docs.typescript, name => ), + }; + } + public render() { const { activePageId, activeSectionId } = this.state; const { nav, pages } = this.props.docs; From 1f190f624f8e65cd6f2d86070c237b26276274c4 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:14:40 -0800 Subject: [PATCH 03/19] rewrite all tag renderers to be simple SFCs and use context for rendering --- packages/docs-theme/src/tags/css.tsx | 60 +++++++++---------- packages/docs-theme/src/tags/defaults.ts | 19 +++--- packages/docs-theme/src/tags/heading.tsx | 7 +-- packages/docs-theme/src/tags/index.ts | 3 +- packages/docs-theme/src/tags/interface.tsx | 25 -------- packages/docs-theme/src/tags/page.tsx | 11 ---- packages/docs-theme/src/tags/reactDocs.tsx | 8 +-- packages/docs-theme/src/tags/reactExample.tsx | 8 +-- packages/docs-theme/src/tags/typescript.tsx | 27 +++++++++ 9 files changed, 73 insertions(+), 95 deletions(-) delete mode 100644 packages/docs-theme/src/tags/interface.tsx delete mode 100644 packages/docs-theme/src/tags/page.tsx create mode 100644 packages/docs-theme/src/tags/typescript.tsx diff --git a/packages/docs-theme/src/tags/css.tsx b/packages/docs-theme/src/tags/css.tsx index 06f6637cca..adc3cb1d8e 100644 --- a/packages/docs-theme/src/tags/css.tsx +++ b/packages/docs-theme/src/tags/css.tsx @@ -4,30 +4,32 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { IKssExample, IKssModifier, IKssPluginData } from "documentalist/dist/client"; +import { IKssModifier, IKssPluginData, ITag } from "documentalist/dist/client"; import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; import { ModifierTable } from "../components/modifierTable"; -import { TagRenderer } from "./"; -const MODIFIER_PLACEHOLDER = /\{\{([\.\:]?)modifier\}\}/g; -const DEFAULT_MODIFIER: IKssModifier = { - documentation: "Default", - name: "default", -}; - -const CssExample: React.SFC = ({ markup, markupHtml, modifiers, reference }) => ( -
- {modifiers.length > 0 ? : undefined} -
- {renderMarkupForModifier(markup, DEFAULT_MODIFIER)} - {modifiers.map(mod => renderMarkupForModifier(markup, mod))} +export const CssExample: React.SFC = ({ value }, { getDocsData }: IDocumentationContext) => { + const { css } = getDocsData() as IKssPluginData; + if (css == null || css[value] == null) { + return null; + } + const { markup, markupHtml, modifiers, reference } = css[value]; + return ( +
+ {modifiers.length > 0 ? : undefined} +
+ {renderMarkupForModifier(markup, DEFAULT_MODIFIER)} + {modifiers.map(mod => renderMarkupForModifier(markup, mod))} +
+
-
-
-); + ); +}; +CssExample.contextTypes = DocumentationContextTypes; +CssExample.displayName = "Docs.CssExample"; -function renderMarkupForModifier(markup: string, modifier: IKssModifier) { - const { name } = modifier; +function renderMarkupForModifier(markup: string, { name }: IKssModifier) { const html = markup.replace(MODIFIER_PLACEHOLDER, (_, prefix) => { if (prefix && name.charAt(0) === prefix) { return name.slice(1); @@ -38,21 +40,15 @@ function renderMarkupForModifier(markup: string, modifier: IKssModifier) { } }); return ( -
- {modifier.name} +
+ {name}
); } -export class CssTagRenderer { - constructor(private docs: IKssPluginData) {} - - public render: TagRenderer = ({ value: reference }, key) => { - const example = this.docs.css[reference]; - if (example === undefined || example.reference === undefined) { - throw new Error(`Unknown @css reference: ${reference}`); - } - return ; - }; -} +const MODIFIER_PLACEHOLDER = /\{\{([.:]?)modifier\}\}/g; +const DEFAULT_MODIFIER: IKssModifier = { + documentation: "Default", + name: "default", +}; diff --git a/packages/docs-theme/src/tags/defaults.ts b/packages/docs-theme/src/tags/defaults.ts index 1fede92c5e..48256e9b71 100644 --- a/packages/docs-theme/src/tags/defaults.ts +++ b/packages/docs-theme/src/tags/defaults.ts @@ -4,22 +4,19 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ +import * as React from "react"; import * as tags from "./"; -import { IKssPluginData, IMarkdownPluginData, ITypescriptPluginData } from "documentalist/dist/client"; +import { IKssPluginData, IMarkdownPluginData, ITag, ITypescriptPluginData } from "documentalist/dist/client"; export interface IDocsData extends IKssPluginData, IMarkdownPluginData, ITypescriptPluginData {} -export function createDefaultRenderers(docs: IDocsData) { - const css = new tags.CssTagRenderer(docs); - const heading = new tags.HeadingTagRenderer(); - const iface = new tags.InterfaceTagRenderer(docs); - const page = new tags.PageTagRenderer(); - +export function createDefaultRenderers(): Record> { return { - css: css.render, - heading: heading.render, - interface: iface.render, - page: page.render, + css: tags.CssExample, + heading: tags.Heading, + interface: tags.TypescriptExample, + page: () => null, + // TODO: @see }; } diff --git a/packages/docs-theme/src/tags/heading.tsx b/packages/docs-theme/src/tags/heading.tsx index d26e6007a8..d3cce3b98b 100644 --- a/packages/docs-theme/src/tags/heading.tsx +++ b/packages/docs-theme/src/tags/heading.tsx @@ -6,9 +6,8 @@ import { IHeadingTag } from "documentalist/dist/client"; import * as React from "react"; -import { TagRenderer } from "./"; -const Heading: React.SFC = ({ level, route, value }) => +export const Heading: React.SFC = ({ level, route, value }) => // use createElement so we can dynamically choose tag based on depth React.createElement( `h${level}`, @@ -20,7 +19,3 @@ const Heading: React.SFC = ({ level, route, value }) => value, ); Heading.displayName = "Docs.Heading"; - -export class HeadingTagRenderer { - public render: TagRenderer = (heading: IHeadingTag, key) => ; -} diff --git a/packages/docs-theme/src/tags/index.ts b/packages/docs-theme/src/tags/index.ts index b5544ec595..be3b6a8e55 100644 --- a/packages/docs-theme/src/tags/index.ts +++ b/packages/docs-theme/src/tags/index.ts @@ -13,7 +13,6 @@ export interface ITagRendererMap { export * from "./css"; export * from "./defaults"; export * from "./heading"; -export * from "./interface"; -export * from "./page"; export * from "./reactDocs"; export * from "./reactExample"; +export * from "./typescript"; diff --git a/packages/docs-theme/src/tags/interface.tsx b/packages/docs-theme/src/tags/interface.tsx deleted file mode 100644 index 2735d0d194..0000000000 --- a/packages/docs-theme/src/tags/interface.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2017 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the terms of the LICENSE file distributed with this project. - */ - -import { isTsClass, isTsInterface, ITypescriptPluginData } from "documentalist/dist/client"; -import * as React from "react"; -import { InterfaceTable } from "../components/interfaceTable"; -import { TagRenderer } from "./"; - -export class InterfaceTagRenderer { - constructor(private docs: ITypescriptPluginData) {} - - public render: TagRenderer = ({ value: name }, key, tagRenderers) => { - const iface = this.docs.typescript[name]; - if (iface === undefined) { - throw new Error(`Unknown @interface ${name}`); - } - if (isTsClass(iface) || isTsInterface(iface)) { - return ; - } - throw new Error(`@interface cannot render ${iface.kind}`); - }; -} diff --git a/packages/docs-theme/src/tags/page.tsx b/packages/docs-theme/src/tags/page.tsx deleted file mode 100644 index 0e2c4d1ed6..0000000000 --- a/packages/docs-theme/src/tags/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2017 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the terms of the LICENSE file distributed with this project. - */ - -import { TagRenderer } from "./"; - -export class PageTagRenderer { - public render: TagRenderer = () => undefined; -} diff --git a/packages/docs-theme/src/tags/reactDocs.tsx b/packages/docs-theme/src/tags/reactDocs.tsx index 4e169d219d..2ad603950b 100644 --- a/packages/docs-theme/src/tags/reactDocs.tsx +++ b/packages/docs-theme/src/tags/reactDocs.tsx @@ -4,8 +4,8 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ +import { ITag } from "documentalist/dist/client"; import * as React from "react"; -import { TagRenderer } from "./"; export interface IDocsMap { [name: string]: React.ComponentClass<{}>; @@ -19,15 +19,15 @@ export class ReactDocsTagRenderer { * it to an actual component class in the given map, or in the default map which contains * valid docs components from this package. Provide a custom map to inject your own components. */ - public render: TagRenderer = ({ value: componentName }, key) => { + public render: React.SFC = ({ value: componentName }) => { if (componentName == null) { - return undefined; + return null; } const docsComponent = this.docs[componentName]; if (docsComponent == null) { throw new Error(`Unknown @reactDocs component: ${componentName}`); } - return React.createElement(docsComponent, { key }); + return React.createElement(docsComponent); }; } diff --git a/packages/docs-theme/src/tags/reactExample.tsx b/packages/docs-theme/src/tags/reactExample.tsx index edbbcc7e78..7d0628b43a 100644 --- a/packages/docs-theme/src/tags/reactExample.tsx +++ b/packages/docs-theme/src/tags/reactExample.tsx @@ -4,8 +4,8 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ +import { ITag } from "documentalist/dist/client"; import * as React from "react"; -import { TagRenderer } from "./"; export interface IExample { sourceUrl: string; @@ -41,15 +41,15 @@ export class ReactExampleTagRenderer { * it to an actual example component exported by one of the packages. Also returns * the URL of the source code on GitHub. */ - public render: TagRenderer = ({ value: exampleName }, key) => { + public render: React.SFC = ({ value: exampleName }) => { if (exampleName == null) { - return undefined; + return null; } const example = this.examples[exampleName]; if (example == null) { throw new Error(`Unknown @example component: ${exampleName}`); } - return ; + return ; }; } diff --git a/packages/docs-theme/src/tags/typescript.tsx b/packages/docs-theme/src/tags/typescript.tsx new file mode 100644 index 0000000000..e6f3858899 --- /dev/null +++ b/packages/docs-theme/src/tags/typescript.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { isTsClass, isTsInterface, ITag, ITypescriptPluginData } from "documentalist/dist/client"; +import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; +import { InterfaceTable } from "../components/typescript/interfaceTable"; + +export const TypescriptExample: React.SFC = ({ value }, { getDocsData }: IDocumentationContext) => { + const { typescript } = getDocsData() as ITypescriptPluginData; + if (typescript == null || typescript[value] == null) { + return null; + } + const iface = typescript[value]; + if (iface === undefined) { + throw new Error(`Unknown @interface ${name}`); + } + if (isTsClass(iface) || isTsInterface(iface)) { + return ; + } + throw new Error(`@interface cannot render ${iface.kind}`); +}; +TypescriptExample.contextTypes = DocumentationContextTypes; +TypescriptExample.displayName = "Docs.TypescriptExample"; From 47bf9b63ac4c196748c0e88f51911c7fbf5cb9ca Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:26:14 -0800 Subject: [PATCH 04/19] typescript tag supports enums and type aliases too!! --- .../src/components/interfaceTable.tsx | 122 ------------------ .../src/components/typescript/enumTable.tsx | 105 +++++++++++++++ .../components/typescript/interfaceTable.tsx | 119 +++++++++++++++++ .../components/typescript/typeAliasTable.tsx | 33 +++++ packages/docs-theme/src/tags/typescript.tsx | 27 +++- 5 files changed, 277 insertions(+), 129 deletions(-) delete mode 100644 packages/docs-theme/src/components/interfaceTable.tsx create mode 100644 packages/docs-theme/src/components/typescript/enumTable.tsx create mode 100644 packages/docs-theme/src/components/typescript/interfaceTable.tsx create mode 100644 packages/docs-theme/src/components/typescript/typeAliasTable.tsx diff --git a/packages/docs-theme/src/components/interfaceTable.tsx b/packages/docs-theme/src/components/interfaceTable.tsx deleted file mode 100644 index c5a29decc8..0000000000 --- a/packages/docs-theme/src/components/interfaceTable.tsx +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2017 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the terms of the LICENSE file distributed with this project. - */ - -import { Classes, Intent, Tag } from "@blueprintjs/core"; -import * as classNames from "classnames"; -import { isTsProperty, ITsClass, ITsInterface, ITsMethod, ITsProperty } from "documentalist/dist/client"; -import * as React from "react"; -import { ITagRendererMap } from "../tags"; -import { renderBlock } from "./block"; - -// HACKHACK support `code` blocks until we get real markdown parsing in ts-quick-docs -function dirtyMarkdown(text: string) { - return { - __html: text - .replace("<", "<") - .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) - .replace(/`([^`]+)`/g, (_, code) => `${code}`), - }; -} - -function propTag(intent: Intent, title: string, ...children: React.ReactNode[]) { - return ( - - {title} - {children} - - ); -} - -function renderPropType(prop: ITsProperty | ITsMethod) { - if (isTsProperty(prop)) { - const formattedType = prop.type.replace(/\b(JSX\.)?Element\b/, "JSX.Element"); - return ( - - {formattedType} - {prop.defaultValue} - - ); - } else { - return ( - - {prop.signatures[0].type} - - ); - } -} - -function renderPropRow(prop: ITsProperty | ITsMethod) { - const { flags: { isDeprecated, isExternal, isOptional }, inheritedFrom, name } = prop; - const isDeprecatedBoolean = isDeprecated === true || typeof isDeprecated === "string"; - const classes = classNames("docs-prop-name", { - "docs-prop-is-deprecated": isDeprecatedBoolean, - "docs-prop-is-internal": !isExternal, - "docs-prop-is-required": !isOptional, - }); - - const tags: JSX.Element[] = []; - if (!isOptional) { - tags.push(propTag(Intent.SUCCESS, "Required")); - } - if (isDeprecatedBoolean) { - const maybeMessage = - typeof isDeprecated === "string" ? ( - - ) : ( - "" - ); - tags.push(propTag(Intent.DANGER, "Deprecated", maybeMessage)); - } - if (inheritedFrom != null) { - tags.push(propTag(Intent.NONE, "Inherited from ", {inheritedFrom})); - } - - const documentation = isTsProperty(prop) ? prop.documentation : prop.signatures[0].documentation; - // TODO: this ignores tags in prop docs, but that's kind of OK cuz they all get processed - // into prop.tags by the TS compiler. - const html = - documentation && documentation.contents.reduce((a, b) => (typeof b === "string" ? a + b : a), ""); - - return ( - - - {name} - - - {renderPropType(prop)} -
-

{tags}

- - - ); -} - -export interface IInterfaceTableProps { - iface: ITsClass | ITsInterface; - tagRenderers: ITagRendererMap; -} - -export const InterfaceTable: React.SFC = ({ iface, tagRenderers }) => { - const propRows = [...iface.properties, ...iface.methods] - .sort((a, b) => a.name.localeCompare(b.name)) - .map(renderPropRow); - return ( -
-
{iface.name}
- {renderBlock(iface.documentation, tagRenderers)} - - - - - - - - {propRows} -
PropDescription
-
- ); -}; -InterfaceTable.displayName = "Docs.InterfaceTable"; diff --git a/packages/docs-theme/src/components/typescript/enumTable.tsx b/packages/docs-theme/src/components/typescript/enumTable.tsx new file mode 100644 index 0000000000..2fd28fa5b8 --- /dev/null +++ b/packages/docs-theme/src/components/typescript/enumTable.tsx @@ -0,0 +1,105 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { Classes, Intent, Tag } from "@blueprintjs/core"; +import * as classNames from "classnames"; +import { isTsMethod, ITsEnum, ITsEnumMember } from "documentalist/dist/client"; +import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; +import { ApiHeader } from "./apiHeader"; + +export type Renderer = (props: T) => React.ReactNode; + +export interface IEnumTableProps { + data: ITsEnum; +} + +export class EnumTable extends React.PureComponent { + public static contextTypes = DocumentationContextTypes; + public static displayName = "Docs.EnumTable"; + + public context: IDocumentationContext; + + public render() { + const { data } = this.props; + const { renderBlock } = this.context; + return ( +
+ + {renderBlock(data.documentation)} + + + + + + + + {data.members.map(this.renderPropRow)} +
MembersDescription
+
+ ); + } + + private renderPropRow = (entry: ITsEnumMember) => { + const { renderBlock, renderType } = this.context; + const { flags: { isDeprecated, isExternal, isOptional }, name } = entry; + + const classes = classNames("docs-prop-name", { + "docs-prop-is-deprecated": !!isDeprecated, + "docs-prop-is-internal": !isExternal, + "docs-prop-is-required": !isOptional, + }); + + const typeInfo = isTsMethod(entry) ? ( + <> + {renderType(entry.signatures[0].type)} + + ) : ( + <> + {entry.name} + {entry.defaultValue && {entry.defaultValue}} + + ); + + return ( + + + {name} + + + {typeInfo} +
{renderBlock(entry.documentation)}
+

{this.renderTags(entry)}

+ + + ); + }; + + private renderTags(entry: ITsEnumMember) { + const { flags: { isDeprecated } } = entry; + return ( + (isDeprecated === true || typeof isDeprecated === "string") && ( + + {typeof isDeprecated === "string" ? ( + + ) : ( + "Deprecated" + )} + + ) + ); + } +} + +// HACKHACK support `code` blocks until we get real markdown parsing in ts-quick-docs +function dirtyMarkdown(text: string) { + return { + __html: text + .replace("<", "<") + .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) + .replace(/`([^`]+)`/g, (_, code) => `${code}`), + }; +} diff --git a/packages/docs-theme/src/components/typescript/interfaceTable.tsx b/packages/docs-theme/src/components/typescript/interfaceTable.tsx new file mode 100644 index 0000000000..110600ec8e --- /dev/null +++ b/packages/docs-theme/src/components/typescript/interfaceTable.tsx @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { Classes, Intent, Tag } from "@blueprintjs/core"; +import * as classNames from "classnames"; +import { isTsProperty, ITsClass, ITsInterface, ITsMethod, ITsProperty } from "documentalist/dist/client"; +import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; +import { ApiHeader } from "./apiHeader"; + +export type Renderer = (props: T) => React.ReactNode; + +export interface IInterfaceTableProps { + data: ITsClass | ITsInterface; + title: string; +} + +export class InterfaceTable extends React.PureComponent { + public static contextTypes = DocumentationContextTypes; + public static displayName = "Docs.InterfaceTable"; + + public context: IDocumentationContext; + + public render() { + const { data, title } = this.props; + const { renderBlock } = this.context; + const propRows = [...data.properties, ...data.methods] + .sort((a, b) => a.name.localeCompare(b.name)) + .map(this.renderPropRow); + return ( +
+ + {renderBlock(data.documentation)} + + + + + + + + {propRows} +
{title}Description
+
+ ); + } + + private renderPropRow = (entry: ITsProperty | ITsMethod) => { + const { renderBlock, renderType } = this.context; + const { flags: { isDeprecated, isExternal, isOptional }, name } = entry; + const { documentation } = isTsProperty(entry) ? entry : entry.signatures[0]; + + const classes = classNames("docs-prop-name", { + "docs-prop-is-deprecated": isDeprecated === true || typeof isDeprecated === "string", + "docs-prop-is-internal": !isExternal, + "docs-prop-is-required": !isOptional, + }); + + const typeInfo = isTsProperty(entry) ? ( + <> + {renderType(entry.type)} + {entry.defaultValue} + + ) : ( + <> + {renderType(entry.signatures[0].type)} + + ); + + return ( + + + {name} + + + {typeInfo} +
{renderBlock(documentation)}
+

{this.renderTags(entry)}

+ + + ); + }; + + private renderTags(entry: ITsProperty | ITsMethod) { + const { renderType } = this.context; + const { flags: { isDeprecated, isOptional }, inheritedFrom } = entry; + return ( + <> + {!isOptional && } + {(isDeprecated === true || typeof isDeprecated === "string") && ( + + {typeof isDeprecated === "string" ? ( + + ) : ( + "Deprecated" + )} + + )} + {inheritedFrom && ( + + Inherited from {renderType(inheritedFrom)} + + )} + + ); + } +} + +// HACKHACK support `code` blocks until we get real markdown parsing in ts-quick-docs +function dirtyMarkdown(text: string) { + return { + __html: text + .replace("<", "<") + .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) + .replace(/`([^`]+)`/g, (_, code) => `${code}`), + }; +} diff --git a/packages/docs-theme/src/components/typescript/typeAliasTable.tsx b/packages/docs-theme/src/components/typescript/typeAliasTable.tsx new file mode 100644 index 0000000000..25f12a9755 --- /dev/null +++ b/packages/docs-theme/src/components/typescript/typeAliasTable.tsx @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { ITsTypeAlias } from "documentalist/dist/client"; +import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; +import { ApiHeader } from "./apiHeader"; + +export interface ITypeAliasTableProps { + data: ITsTypeAlias; +} + +export class TypeAliasTable extends React.PureComponent { + public static contextTypes = DocumentationContextTypes; + public static displayName = "Docs.TypeAliasTable"; + + public context: IDocumentationContext; + + public render() { + const { data } = this.props; + const { renderBlock, renderType } = this.context; + return ( +
+ +

= {renderType(data.type)}

+ {renderBlock(data.documentation)} +
+ ); + } +} diff --git a/packages/docs-theme/src/tags/typescript.tsx b/packages/docs-theme/src/tags/typescript.tsx index e6f3858899..995d1a951e 100644 --- a/packages/docs-theme/src/tags/typescript.tsx +++ b/packages/docs-theme/src/tags/typescript.tsx @@ -4,24 +4,37 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { isTsClass, isTsInterface, ITag, ITypescriptPluginData } from "documentalist/dist/client"; +import { + isTsClass, + isTsEnum, + isTsInterface, + isTsTypeAlias, + ITag, + ITypescriptPluginData, +} from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; +import { EnumTable } from "../components/typescript/enumTable"; import { InterfaceTable } from "../components/typescript/interfaceTable"; +import { TypeAliasTable } from "../components/typescript/typeAliasTable"; export const TypescriptExample: React.SFC = ({ value }, { getDocsData }: IDocumentationContext) => { const { typescript } = getDocsData() as ITypescriptPluginData; if (typescript == null || typescript[value] == null) { return null; } - const iface = typescript[value]; - if (iface === undefined) { + const member = typescript[value]; + if (member === undefined) { throw new Error(`Unknown @interface ${name}`); + } else if (isTsClass(member) || isTsInterface(member)) { + return ; + } else if (isTsEnum(member)) { + return ; + } else if (isTsTypeAlias(member)) { + return ; + } else { + throw new Error(`"@interface ${name}": unknown member kind "${(member as any).kind}"`); } - if (isTsClass(iface) || isTsInterface(iface)) { - return ; - } - throw new Error(`@interface cannot render ${iface.kind}`); }; TypescriptExample.contextTypes = DocumentationContextTypes; TypescriptExample.displayName = "Docs.TypescriptExample"; From eee719b3cd04de038eda541ef3a7e00e4773b5a6 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:27:25 -0800 Subject: [PATCH 05/19] type IDocsData requires markdown, optional typescript & kss data. --- packages/docs-theme/src/common/context.ts | 15 +++++++++++++-- .../docs-theme/src/components/documentation.tsx | 13 ++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/docs-theme/src/common/context.ts b/packages/docs-theme/src/common/context.ts index 7ffed95e0f..3724ae4f6f 100644 --- a/packages/docs-theme/src/common/context.ts +++ b/packages/docs-theme/src/common/context.ts @@ -7,6 +7,17 @@ import { Utils } from "@blueprintjs/core"; import { IBlock, IKssPluginData, IMarkdownPluginData, ITypescriptPluginData } from "documentalist/dist/client"; +/** This docs theme requires Markdown data and optionally supports Typescript and KSS data. */ +export type IDocsData = IMarkdownPluginData & (ITypescriptPluginData | {}) & (IKssPluginData | {}); + +export function hasTypescriptData(docs: IDocsData): docs is IMarkdownPluginData & ITypescriptPluginData { + return docs != null && (docs as ITypescriptPluginData).typescript != null; +} + +export function hasKssData(docs: IDocsData): docs is IMarkdownPluginData & IKssPluginData { + return docs != null && (docs as IKssPluginData).css != null; +} + /** * Gonna use React context to pass some helpful functions around. * This is basically the pauper's Redux store connector: some central state from the root @@ -14,12 +25,12 @@ import { IBlock, IKssPluginData, IMarkdownPluginData, ITypescriptPluginData } fr * directly to their parent. */ export interface IDocumentationContext { - getDocsData(): IMarkdownPluginData & (ITypescriptPluginData | {}) & (IKssPluginData | {}); + getDocsData(): IDocsData; /** Render a block of Documentalist documentation to a React node. */ renderBlock(block: IBlock): React.ReactNode; - /** Render a Documentalist type string to a React node. */ + /** Render a Documentalist Typescript type string to a React node. */ renderType(type: string): React.ReactNode; } diff --git a/packages/docs-theme/src/components/documentation.tsx b/packages/docs-theme/src/components/documentation.tsx index 392807f745..571c6d95c4 100644 --- a/packages/docs-theme/src/components/documentation.tsx +++ b/packages/docs-theme/src/components/documentation.tsx @@ -5,12 +5,12 @@ */ import * as classNames from "classnames"; -import { IMarkdownPluginData, isPageNode, ITypescriptPluginData, linkify } from "documentalist/dist/client"; +import { isPageNode, linkify } from "documentalist/dist/client"; import * as React from "react"; import { FocusStyleManager, Hotkey, Hotkeys, HotkeysTarget, IProps, Utils } from "@blueprintjs/core"; -import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; +import { DocumentationContextTypes, hasTypescriptData, IDocsData, IDocumentationContext } from "../common/context"; import { eachLayoutNode } from "../common/utils"; import { ITagRendererMap } from "../tags"; import { renderBlock } from "./block"; @@ -26,9 +26,9 @@ export interface IDocumentationProps extends IProps { /** * All the docs data from Documentalist. - * Must include at least `{ nav, pages }` from the MarkdownPlugin. + * This theme requires the Markdown plugin, and optionally supports Typescript and KSS data. */ - docs: IMarkdownPluginData; + docs: IDocsData; /** * Callback invoked whenever the component props or state change (specifically, @@ -93,10 +93,13 @@ export class Documentation extends React.PureComponent this.props.docs, renderBlock: block => renderBlock(block, this.props.tagRenderers), - renderType: type => linkify(type, this.props.docs.typescript, name => ), + renderType: hasTypescriptData(docs) + ? type => linkify(type, docs.typescript, name => ) + : type => type, }; } From 04c5dfa51e0658d9960ea8b528bf50e79171bedc Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:29:02 -0800 Subject: [PATCH 06/19] ApiHeader component now includes kind, inheritance, package/source link --- .../src/components/typescript/apiHeader.tsx | 40 +++++++++++++++++++ packages/docs-theme/src/styles/_props.scss | 4 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 packages/docs-theme/src/components/typescript/apiHeader.tsx diff --git a/packages/docs-theme/src/components/typescript/apiHeader.tsx b/packages/docs-theme/src/components/typescript/apiHeader.tsx new file mode 100644 index 0000000000..9f032a8728 --- /dev/null +++ b/packages/docs-theme/src/components/typescript/apiHeader.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { isTsClass, isTsInterface, ITsDocBase } from "documentalist/dist/client"; +import * as React from "react"; +import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; + +export const ApiHeader: React.SFC = (data, { renderType }: IDocumentationContext) => { + const inheritance = + isTsClass(data) || isTsInterface(data) + ? maybeJoinArray("extends", data.extends) + " " + maybeJoinArray("implements", data.implements) + : ""; + return ( +
+
+ {data.kind} {data.name} {renderType(inheritance)} +
+ + + @blueprintjs/{data.fileName.split("/", 2)[1]} + + + {data.children} +
+ ); +}; +ApiHeader.contextTypes = DocumentationContextTypes; +ApiHeader.displayName = "Docs.ApiHeader"; + +function maybeJoinArray(title: string, array: string[] | undefined): string { + if (array == null || array.length === 0) { + return ""; + } + return `${title} ${array.join(", ")}`; +} + +const GITHUB_URL = "https://github.com/palantir/blueprint/tree/master/packages/"; diff --git a/packages/docs-theme/src/styles/_props.scss b/packages/docs-theme/src/styles/_props.scss index fcf4dcae4d..4af920fba0 100644 --- a/packages/docs-theme/src/styles/_props.scss +++ b/packages/docs-theme/src/styles/_props.scss @@ -70,7 +70,9 @@ } } -.docs-interface-name { +.docs-interface-header { + display: flex; + justify-content: space-between; margin-bottom: $pt-grid-size; border-bottom: 1px solid $pt-divider-black; padding: $pt-grid-size 0; From 1c9a94537c5734349dbe1d1cfc5b2478a347dfe8 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 14:36:07 -0800 Subject: [PATCH 07/19] don't use ApiLink yet (next PR) --- packages/docs-theme/src/components/documentation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs-theme/src/components/documentation.tsx b/packages/docs-theme/src/components/documentation.tsx index 571c6d95c4..b100d64e9f 100644 --- a/packages/docs-theme/src/components/documentation.tsx +++ b/packages/docs-theme/src/components/documentation.tsx @@ -98,7 +98,7 @@ export class Documentation extends React.PureComponent this.props.docs, renderBlock: block => renderBlock(block, this.props.tagRenderers), renderType: hasTypescriptData(docs) - ? type => linkify(type, docs.typescript, name => ) + ? type => linkify(type, docs.typescript, name => {name}) : type => type, }; } From 50ef8b6356865c85e241e99d8db05f94b062e65c Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 15:13:41 -0800 Subject: [PATCH 08/19] createDefaultRenderers() --- packages/docs-app/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs-app/src/index.tsx b/packages/docs-app/src/index.tsx index 689b737a20..3c41504128 100644 --- a/packages/docs-app/src/index.tsx +++ b/packages/docs-app/src/index.tsx @@ -30,7 +30,7 @@ const reactDocs = new ReactDocsTagRenderer(ReactDocs as any); const reactExample = new ReactExampleTagRenderer(reactExamples); const tagRenderers = { - ...createDefaultRenderers(docs), + ...createDefaultRenderers(), reactDocs: reactDocs.render, reactExample: reactExample.render, }; From 6f733248d18e4636160e78e26f311cc260c64607 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 17:40:34 -0800 Subject: [PATCH 09/19] documentalist 1.0.0-beta.2, add docs-data script to root, fix dev:docs --- README.md | 2 +- package.json | 3 ++- packages/docs-data/package.json | 5 +++-- packages/docs-theme/package.json | 2 +- yarn.lock | 6 +++--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bae8855c82..a2734bf432 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Each library has its own dev script which you can run to watch changes to that p Much of Blueprint's documentation lives inside source code as JSDoc comments in `.tsx` files and KSS markup in `.scss` files. This documentation is extracted and converted into static JSON data using [documentalist](https://github.com/palantir/documentalist/). -If you are updating documentation sources (_not_ the docs UI code which lives in `packages/docs-app` or the docs theme in `packages/docs-theme`), you'll need to run `yarn compile` from `packages/docs-data` to see changes reflected in the application. +If you are updating documentation sources (_not_ the docs UI code which lives in `packages/docs-app` or the docs theme in `packages/docs-theme`), you'll need to run `yarn compile` from `packages/docs-data` to see changes reflected in the application. For simplicity, an alias script `yarn docs-data` exists in the root to minimize directory hopping. ### Updating icons diff --git a/package.json b/package.json index c860e2f3f5..be85b4d787 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "copy-landing-app": "cp -rf packages/landing-app/dist/* docs/.", "dev:all": "lerna run dev --parallel --scope '!@blueprintjs/{landing-app,table-dev-app}'", "dev:core": "lerna run dev --parallel --scope '@blueprintjs/{core,docs-app}'", - "dev:docs": "lerna run dev --parallel --scope '@blueprintjs/{docs,docs-app}'", + "dev:docs": "lerna run dev --parallel --scope '@blueprintjs/{docs-app,docs-theme}'", "dev:datetime": "lerna run dev --parallel --scope '@blueprintjs/{core,datetime,docs-app}'", "dev:labs": "lerna run dev --parallel --scope '@blueprintjs/{core,labs,select,docs-app}'", "dev:landing": "lerna run dev --parallel --scope '@blueprintjs/{core,landing-app}'", @@ -25,6 +25,7 @@ "dist:libs": "lerna run dist --parallel --scope '@blueprintjs/{core,datetime,docs-theme,icons,labs,select,table,timezone}'", "dist:apps": "lerna run dist --parallel --scope '@blueprintjs/{docs-app,landing-app,table-dev-app}'", "dist:gh-pages": "run-s clean-gh-pages copy-docs-app copy-landing-app", + "docs-data": "lerna run compile --scope '@blueprintjs/docs-data'", "lint": "lerna run --parallel lint", "lint-fix": "lerna run --parallel lint-fix", "test": "lerna run --parallel test", diff --git a/packages/docs-data/package.json b/packages/docs-data/package.json index 2da7148b69..afa7d28959 100644 --- a/packages/docs-data/package.json +++ b/packages/docs-data/package.json @@ -10,11 +10,12 @@ }, "dependencies": { "@blueprintjs/docs-theme": "^1.3.0", - "documentalist": "^1.0.0-beta.1", + "documentalist": "^1.0.0-beta.2", "glob": "^7.1.2", "highlights": "^3.1.1", "marked": "^0.3.6", - "semver": "^5.4.1" + "semver": "^5.4.1", + "typescript": "2.4.1" }, "repository": { "type": "git", diff --git a/packages/docs-theme/package.json b/packages/docs-theme/package.json index d684ea796a..d606b3514d 100644 --- a/packages/docs-theme/package.json +++ b/packages/docs-theme/package.json @@ -26,7 +26,7 @@ "dependencies": { "@blueprintjs/core": "^1.34.0", "classnames": "^2.2", - "documentalist": "^1.0.0-beta.1", + "documentalist": "^1.0.0-beta.2", "fuzzaldrin-plus": "^0.5.0", "tslib": "^1.5.0" }, diff --git a/yarn.lock b/yarn.lock index a0661fbdb0..c7dc9f6b09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2025,9 +2025,9 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -documentalist@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/documentalist/-/documentalist-1.0.0-beta.1.tgz#8966db913be540ec8f92f09d353692b835f28bb8" +documentalist@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/documentalist/-/documentalist-1.0.0-beta.2.tgz#0da69cb1e3c467146f01f02a61079140e68baf0f" dependencies: "@types/kss" "^3.0.0" glob "^7.1.1" From 46aec7ff87ae7235f433e33523d49345d13fa689 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 17:41:36 -0800 Subject: [PATCH 10/19] minor code cleanup --- .../src/components/typescript/enumTable.tsx | 20 ++++++------------- packages/docs-theme/src/styles/_props.scss | 1 + 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/docs-theme/src/components/typescript/enumTable.tsx b/packages/docs-theme/src/components/typescript/enumTable.tsx index 2fd28fa5b8..03c9fc5f74 100644 --- a/packages/docs-theme/src/components/typescript/enumTable.tsx +++ b/packages/docs-theme/src/components/typescript/enumTable.tsx @@ -6,7 +6,7 @@ import { Classes, Intent, Tag } from "@blueprintjs/core"; import * as classNames from "classnames"; -import { isTsMethod, ITsEnum, ITsEnumMember } from "documentalist/dist/client"; +import { ITsEnum, ITsEnumMember } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; import { ApiHeader } from "./apiHeader"; @@ -44,7 +44,7 @@ export class EnumTable extends React.PureComponent { } private renderPropRow = (entry: ITsEnumMember) => { - const { renderBlock, renderType } = this.context; + const { renderBlock } = this.context; const { flags: { isDeprecated, isExternal, isOptional }, name } = entry; const classes = classNames("docs-prop-name", { @@ -53,24 +53,16 @@ export class EnumTable extends React.PureComponent { "docs-prop-is-required": !isOptional, }); - const typeInfo = isTsMethod(entry) ? ( - <> - {renderType(entry.signatures[0].type)} - - ) : ( - <> - {entry.name} - {entry.defaultValue && {entry.defaultValue}} - - ); - return ( {name} - {typeInfo} + + {entry.name} + {entry.defaultValue} +
{renderBlock(entry.documentation)}

{this.renderTags(entry)}

diff --git a/packages/docs-theme/src/styles/_props.scss b/packages/docs-theme/src/styles/_props.scss index 4af920fba0..e4f31a9fd1 100644 --- a/packages/docs-theme/src/styles/_props.scss +++ b/packages/docs-theme/src/styles/_props.scss @@ -72,6 +72,7 @@ .docs-interface-header { display: flex; + align-items: flex-end; justify-content: space-between; margin-bottom: $pt-grid-size; border-bottom: 1px solid $pt-divider-black; From 8e5c72d931fa697571939ff427d01fd4de9267ca Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Tue, 9 Jan 2018 17:41:50 -0800 Subject: [PATCH 11/19] tsconfigPath option fixes interface inheritance!!! --- packages/docs-data/compile-docs-data | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/docs-data/compile-docs-data b/packages/docs-data/compile-docs-data index 49fd83325f..b4693f1135 100755 --- a/packages/docs-data/compile-docs-data +++ b/packages/docs-data/compile-docs-data @@ -55,10 +55,11 @@ function generateDocumentalistData() { new dm.TypescriptPlugin({ excludeNames: [/I.+State$/], excludePaths: ["node_modules/", "-app/", "test-commons/"], + tsconfigPath: path.resolve(__dirname, "../../config/tsconfig.base.json"), }), ) .use(".scss", new dm.KssPlugin()) - .documentGlobs("../*/src/**/*.{ts,tsx,scss,md}") + .documentGlobs("../*/src/**/*.{scss,md}", "../*/src/index.{ts,tsx}") .then(docs => JSON.stringify(docs, transformDocumentalistData, 2)) .then(content => fs.writeFileSync(path.join(GENERATED_SRC_DIR, DOCS_DATA_FILENAME), content)); } From a6772e77360b4e24161ad0d8603e21f79ec02612 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Wed, 10 Jan 2018 17:35:23 -0800 Subject: [PATCH 12/19] context docs --- packages/docs-theme/src/common/context.ts | 21 ++++++++++++++++++- .../src/components/documentation.tsx | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/docs-theme/src/common/context.ts b/packages/docs-theme/src/common/context.ts index 3724ae4f6f..d5f7d530b0 100644 --- a/packages/docs-theme/src/common/context.ts +++ b/packages/docs-theme/src/common/context.ts @@ -19,12 +19,16 @@ export function hasKssData(docs: IDocsData): docs is IMarkdownPluginData & IKssP } /** - * Gonna use React context to pass some helpful functions around. + * Use React context to transparently provide helpful functions to children. * This is basically the pauper's Redux store connector: some central state from the root * `Documentation` component is exposed to its children so those in the know can speak * directly to their parent. */ export interface IDocumentationContext { + /** + * Get the Documentalist data. + * Use the `hasTypescriptData` and `hasKssData` typeguards before accessing those plugins' data. + */ getDocsData(): IDocsData; /** Render a block of Documentalist documentation to a React node. */ @@ -34,12 +38,27 @@ export interface IDocumentationContext { renderType(type: string): React.ReactNode; } +/** + * To enable context access in a React component, assign `static contextTypes` and declare `context` type: + * + * ```tsx + * export class ContextComponent extends React.PureComponent { + * public static contextTypes = DocumentationContextTypes; + * public context: IDocumentationContext; + * + * public render() { + * return this.context.renderBlock(this.props.block); + * } + * } + * ``` + */ export const DocumentationContextTypes: React.ValidationMap = { getDocsData: assertFunctionProp, renderBlock: assertFunctionProp, renderType: assertFunctionProp, }; +// simple alternative to prop-types dependency function assertFunctionProp(obj: T, key: keyof T) { if (obj[key] != null && Utils.isFunction(obj[key])) { return undefined; diff --git a/packages/docs-theme/src/components/documentation.tsx b/packages/docs-theme/src/components/documentation.tsx index b100d64e9f..f82fb1e922 100644 --- a/packages/docs-theme/src/components/documentation.tsx +++ b/packages/docs-theme/src/components/documentation.tsx @@ -95,7 +95,7 @@ export class Documentation extends React.PureComponent this.props.docs, + getDocsData: () => docs, renderBlock: block => renderBlock(block, this.props.tagRenderers), renderType: hasTypescriptData(docs) ? type => linkify(type, docs.typescript, name => {name}) From b4410ab22d5368b251ebb1a69051efce020126e9 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Mon, 22 Jan 2018 16:37:03 -0800 Subject: [PATCH 13/19] documentalist beta.4, sourceUrl, react class --- packages/docs-data/package.json | 2 +- packages/docs-theme/package.json | 2 +- .../src/components/typescript/apiHeader.tsx | 52 +++++++++++-------- yarn.lock | 6 +-- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/docs-data/package.json b/packages/docs-data/package.json index 3299fcc925..d2a797aad1 100644 --- a/packages/docs-data/package.json +++ b/packages/docs-data/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@blueprintjs/docs-theme": "^2.0.0-beta.1", - "documentalist": "^1.0.0-beta.2", + "documentalist": "^1.0.0-beta.4", "glob": "^7.1.2", "highlights": "^3.1.1", "marked": "^0.3.6", diff --git a/packages/docs-theme/package.json b/packages/docs-theme/package.json index d9c55cfcb7..3cf9c2f2b9 100644 --- a/packages/docs-theme/package.json +++ b/packages/docs-theme/package.json @@ -26,7 +26,7 @@ "dependencies": { "@blueprintjs/core": "^2.0.0-beta.1", "classnames": "^2.2", - "documentalist": "^1.0.0-beta.2", + "documentalist": "^1.0.0-beta.4", "fuzzaldrin-plus": "^0.5.0", "tslib": "^1.5.0" }, diff --git a/packages/docs-theme/src/components/typescript/apiHeader.tsx b/packages/docs-theme/src/components/typescript/apiHeader.tsx index 9f032a8728..0c058d25d2 100644 --- a/packages/docs-theme/src/components/typescript/apiHeader.tsx +++ b/packages/docs-theme/src/components/typescript/apiHeader.tsx @@ -8,27 +8,37 @@ import { isTsClass, isTsInterface, ITsDocBase } from "documentalist/dist/client" import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; -export const ApiHeader: React.SFC = (data, { renderType }: IDocumentationContext) => { - const inheritance = - isTsClass(data) || isTsInterface(data) - ? maybeJoinArray("extends", data.extends) + " " + maybeJoinArray("implements", data.implements) - : ""; - return ( -
-
- {data.kind} {data.name} {renderType(inheritance)} +export class ApiHeader extends React.PureComponent { + public static contextTypes = DocumentationContextTypes; + public static displayName = "Docs.ApiHeader"; + + public context: IDocumentationContext; + + public render() { + return ( +
+
+ {this.props.kind} {this.props.name} {this.renderInheritance()} +
+ + + @blueprintjs/{this.props.fileName.split("/", 2)[1]} + + + {this.props.children}
- - - @blueprintjs/{data.fileName.split("/", 2)[1]} - - - {data.children} -
- ); -}; -ApiHeader.contextTypes = DocumentationContextTypes; -ApiHeader.displayName = "Docs.ApiHeader"; + ); + } + + private renderInheritance() { + if (isTsClass(this.props) || isTsInterface(this.props)) { + const extendsTypes = maybeJoinArray("extends", this.props.extends); + const implementsTypes = maybeJoinArray("implements", this.props.implements); + return this.context.renderType(`${extendsTypes} ${implementsTypes}`); + } + return ""; + } +} function maybeJoinArray(title: string, array: string[] | undefined): string { if (array == null || array.length === 0) { @@ -36,5 +46,3 @@ function maybeJoinArray(title: string, array: string[] | undefined): string { } return `${title} ${array.join(", ")}`; } - -const GITHUB_URL = "https://github.com/palantir/blueprint/tree/master/packages/"; diff --git a/yarn.lock b/yarn.lock index 1bfb25b92e..7b9a5100ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2079,9 +2079,9 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -documentalist@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/documentalist/-/documentalist-1.0.0-beta.2.tgz#0da69cb1e3c467146f01f02a61079140e68baf0f" +documentalist@^1.0.0-beta.4: + version "1.0.0-beta.4" + resolved "https://registry.yarnpkg.com/documentalist/-/documentalist-1.0.0-beta.4.tgz#3b2204d7fc74b38daa2664667155ab105fb8d791" dependencies: "@types/kss" "^3.0.0" glob "^7.1.1" From e3e88ee01a9d91749271b78025c48af73689793c Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Mon, 22 Jan 2018 16:39:57 -0800 Subject: [PATCH 14/19] markdownCode util --- packages/docs-theme/src/common/utils.ts | 13 +++++++++++++ .../src/components/typescript/enumTable.tsx | 13 ++----------- .../src/components/typescript/interfaceTable.tsx | 13 ++----------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/packages/docs-theme/src/common/utils.ts b/packages/docs-theme/src/common/utils.ts index b27b3d19a0..225226a9c1 100644 --- a/packages/docs-theme/src/common/utils.ts +++ b/packages/docs-theme/src/common/utils.ts @@ -71,3 +71,16 @@ export function eachLayoutNode( } }); } + +/** + * Minimal markdown renderer that supports only backtick `code` elements and triple-backtick `pre` elements. + * Does not provide any syntax highlighting. + */ +export function markdownCode(text: string) { + return { + __html: text + .replace("<", "<") + .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) + .replace(/`([^`]+)`/g, (_, code) => `${code}`), + }; +} diff --git a/packages/docs-theme/src/components/typescript/enumTable.tsx b/packages/docs-theme/src/components/typescript/enumTable.tsx index 03c9fc5f74..00c4752f08 100644 --- a/packages/docs-theme/src/components/typescript/enumTable.tsx +++ b/packages/docs-theme/src/components/typescript/enumTable.tsx @@ -9,6 +9,7 @@ import * as classNames from "classnames"; import { ITsEnum, ITsEnumMember } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; +import { markdownCode } from "../../common/utils"; import { ApiHeader } from "./apiHeader"; export type Renderer = (props: T) => React.ReactNode; @@ -76,7 +77,7 @@ export class EnumTable extends React.PureComponent { (isDeprecated === true || typeof isDeprecated === "string") && ( {typeof isDeprecated === "string" ? ( - + ) : ( "Deprecated" )} @@ -85,13 +86,3 @@ export class EnumTable extends React.PureComponent { ); } } - -// HACKHACK support `code` blocks until we get real markdown parsing in ts-quick-docs -function dirtyMarkdown(text: string) { - return { - __html: text - .replace("<", "<") - .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) - .replace(/`([^`]+)`/g, (_, code) => `${code}`), - }; -} diff --git a/packages/docs-theme/src/components/typescript/interfaceTable.tsx b/packages/docs-theme/src/components/typescript/interfaceTable.tsx index 110600ec8e..b14b0e7fab 100644 --- a/packages/docs-theme/src/components/typescript/interfaceTable.tsx +++ b/packages/docs-theme/src/components/typescript/interfaceTable.tsx @@ -9,6 +9,7 @@ import * as classNames from "classnames"; import { isTsProperty, ITsClass, ITsInterface, ITsMethod, ITsProperty } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; +import { markdownCode } from "../../common/utils"; import { ApiHeader } from "./apiHeader"; export type Renderer = (props: T) => React.ReactNode; @@ -92,7 +93,7 @@ export class InterfaceTable extends React.PureComponent { {(isDeprecated === true || typeof isDeprecated === "string") && ( {typeof isDeprecated === "string" ? ( - + ) : ( "Deprecated" )} @@ -107,13 +108,3 @@ export class InterfaceTable extends React.PureComponent { ); } } - -// HACKHACK support `code` blocks until we get real markdown parsing in ts-quick-docs -function dirtyMarkdown(text: string) { - return { - __html: text - .replace("<", "<") - .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) - .replace(/`([^`]+)`/g, (_, code) => `${code}`), - }; -} From 4b05d993a5e9d534552ede2d41c794be700d30a4 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Wed, 24 Jan 2018 16:53:23 -0800 Subject: [PATCH 15/19] Documentation renderViewSourceLinkText prop --- packages/docs-app/src/components/blueprintDocs.tsx | 6 ++++++ packages/docs-theme/src/common/context.ts | 12 +++++++++++- .../docs-theme/src/components/documentation.tsx | 14 ++++++++++++-- .../src/components/typescript/apiHeader.tsx | 2 +- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/docs-app/src/components/blueprintDocs.tsx b/packages/docs-app/src/components/blueprintDocs.tsx index c39bed43b6..068c3734eb 100644 --- a/packages/docs-app/src/components/blueprintDocs.tsx +++ b/packages/docs-app/src/components/blueprintDocs.tsx @@ -7,6 +7,7 @@ import { Menu, MenuItem, Popover, Position, setHotkeysDialogProps } from "@blueprintjs/core"; import { IPackageInfo } from "@blueprintjs/docs-data"; import { Documentation, IDocumentationProps } from "@blueprintjs/docs-theme"; +import { ITsDocBase } from "documentalist/dist/client"; import * as React from "react"; import { NavbarActions } from "./navbarActions"; @@ -59,6 +60,7 @@ export class BlueprintDocs extends React.Component ); @@ -89,6 +91,10 @@ export class BlueprintDocs extends React.Component { diff --git a/packages/docs-theme/src/common/context.ts b/packages/docs-theme/src/common/context.ts index d5f7d530b0..3be4922367 100644 --- a/packages/docs-theme/src/common/context.ts +++ b/packages/docs-theme/src/common/context.ts @@ -5,7 +5,13 @@ */ import { Utils } from "@blueprintjs/core"; -import { IBlock, IKssPluginData, IMarkdownPluginData, ITypescriptPluginData } from "documentalist/dist/client"; +import { + IBlock, + IKssPluginData, + IMarkdownPluginData, + ITsDocBase, + ITypescriptPluginData, +} from "documentalist/dist/client"; /** This docs theme requires Markdown data and optionally supports Typescript and KSS data. */ export type IDocsData = IMarkdownPluginData & (ITypescriptPluginData | {}) & (IKssPluginData | {}); @@ -36,6 +42,9 @@ export interface IDocumentationContext { /** Render a Documentalist Typescript type string to a React node. */ renderType(type: string): React.ReactNode; + + /** Render the text of a "View source" link. */ + renderViewSourceLinkText(entry: ITsDocBase): React.ReactNode; } /** @@ -56,6 +65,7 @@ export const DocumentationContextTypes: React.ValidationMap void; + /** + * Callback invoked to render "View source" links in Typescript interfaces. + * The `href` of the link will be `entry.sourceUrl`. + * @default "View source" + */ + renderViewSourceLinkText?: (entry: ITsDocBase) => React.ReactNode; + /** Tag renderer functions. Unknown tags will log console errors. */ tagRenderers: ITagRendererMap; @@ -93,13 +100,16 @@ export class Documentation extends React.PureComponent docs, renderBlock: block => renderBlock(block, this.props.tagRenderers), renderType: hasTypescriptData(docs) ? type => linkify(type, docs.typescript, name => {name}) : type => type, + renderViewSourceLinkText: Utils.isFunction(renderViewSourceLinkText) + ? renderViewSourceLinkText + : () => "View source", }; } diff --git a/packages/docs-theme/src/components/typescript/apiHeader.tsx b/packages/docs-theme/src/components/typescript/apiHeader.tsx index 0c058d25d2..7ff4403451 100644 --- a/packages/docs-theme/src/components/typescript/apiHeader.tsx +++ b/packages/docs-theme/src/components/typescript/apiHeader.tsx @@ -22,7 +22,7 @@ export class ApiHeader extends React.PureComponent {
- @blueprintjs/{this.props.fileName.split("/", 2)[1]} + {this.context.renderViewSourceLinkText(this.props)} {this.props.children} From 9dc9f9799485e473a31c6e5605d1534204a5cd94 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Wed, 24 Jan 2018 16:56:49 -0800 Subject: [PATCH 16/19] remove unnecessary dependency --- packages/docs-data/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/docs-data/package.json b/packages/docs-data/package.json index d2a797aad1..ee43bbd985 100644 --- a/packages/docs-data/package.json +++ b/packages/docs-data/package.json @@ -14,8 +14,7 @@ "glob": "^7.1.2", "highlights": "^3.1.1", "marked": "^0.3.6", - "semver": "^5.4.1", - "typescript": "2.4.1" + "semver": "^5.4.1" }, "repository": { "type": "git", From c8fb8621db0b44d5f1193f0d9fc53bc63a358f64 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Thu, 25 Jan 2018 11:19:30 -0800 Subject: [PATCH 17/19] DeprecatedTag SFC --- packages/docs-theme/src/common/utils.ts | 13 ------- .../components/typescript/deprecatedTag.tsx | 37 +++++++++++++++++++ .../src/components/typescript/enumTable.tsx | 15 +------- .../components/typescript/interfaceTable.tsx | 12 +----- 4 files changed, 41 insertions(+), 36 deletions(-) create mode 100644 packages/docs-theme/src/components/typescript/deprecatedTag.tsx diff --git a/packages/docs-theme/src/common/utils.ts b/packages/docs-theme/src/common/utils.ts index 225226a9c1..b27b3d19a0 100644 --- a/packages/docs-theme/src/common/utils.ts +++ b/packages/docs-theme/src/common/utils.ts @@ -71,16 +71,3 @@ export function eachLayoutNode( } }); } - -/** - * Minimal markdown renderer that supports only backtick `code` elements and triple-backtick `pre` elements. - * Does not provide any syntax highlighting. - */ -export function markdownCode(text: string) { - return { - __html: text - .replace("<", "<") - .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) - .replace(/`([^`]+)`/g, (_, code) => `${code}`), - }; -} diff --git a/packages/docs-theme/src/components/typescript/deprecatedTag.tsx b/packages/docs-theme/src/components/typescript/deprecatedTag.tsx new file mode 100644 index 0000000000..538393ed5f --- /dev/null +++ b/packages/docs-theme/src/components/typescript/deprecatedTag.tsx @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the terms of the LICENSE file distributed with this project. + */ + +import { Classes, Intent, Tag } from "@blueprintjs/core"; +import * as React from "react"; + +export const DeprecatedTag: React.SFC<{ isDeprecated: boolean | string | undefined }> = ({ isDeprecated }) => { + if (isDeprecated === true || typeof isDeprecated === "string") { + return ( + + {typeof isDeprecated === "string" ? ( + + ) : ( + "Deprecated" + )} + + ); + } + return null; +}; +DeprecatedTag.displayName = "Docs.DeprecatedTag"; + +/** + * Minimal markdown renderer that supports only backtick `code` elements and triple-backtick `pre` elements. + * Does not provide any syntax highlighting. + */ +function markdownCode(text: string) { + return { + __html: text + .replace("<", "<") + .replace(/```([^`]+)```/g, (_, code) => `
${code}
`) + .replace(/`([^`]+)`/g, (_, code) => `${code}`), + }; +} diff --git a/packages/docs-theme/src/components/typescript/enumTable.tsx b/packages/docs-theme/src/components/typescript/enumTable.tsx index 00c4752f08..c449a9e06b 100644 --- a/packages/docs-theme/src/components/typescript/enumTable.tsx +++ b/packages/docs-theme/src/components/typescript/enumTable.tsx @@ -4,13 +4,12 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { Classes, Intent, Tag } from "@blueprintjs/core"; import * as classNames from "classnames"; import { ITsEnum, ITsEnumMember } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; -import { markdownCode } from "../../common/utils"; import { ApiHeader } from "./apiHeader"; +import { DeprecatedTag } from "./deprecatedTag"; export type Renderer = (props: T) => React.ReactNode; @@ -73,16 +72,6 @@ export class EnumTable extends React.PureComponent { private renderTags(entry: ITsEnumMember) { const { flags: { isDeprecated } } = entry; - return ( - (isDeprecated === true || typeof isDeprecated === "string") && ( - - {typeof isDeprecated === "string" ? ( - - ) : ( - "Deprecated" - )} - - ) - ); + return ; } } diff --git a/packages/docs-theme/src/components/typescript/interfaceTable.tsx b/packages/docs-theme/src/components/typescript/interfaceTable.tsx index b14b0e7fab..a70783121c 100644 --- a/packages/docs-theme/src/components/typescript/interfaceTable.tsx +++ b/packages/docs-theme/src/components/typescript/interfaceTable.tsx @@ -9,8 +9,8 @@ import * as classNames from "classnames"; import { isTsProperty, ITsClass, ITsInterface, ITsMethod, ITsProperty } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../../common/context"; -import { markdownCode } from "../../common/utils"; import { ApiHeader } from "./apiHeader"; +import { DeprecatedTag } from "./deprecatedTag"; export type Renderer = (props: T) => React.ReactNode; @@ -90,15 +90,7 @@ export class InterfaceTable extends React.PureComponent { return ( <> {!isOptional && } - {(isDeprecated === true || typeof isDeprecated === "string") && ( - - {typeof isDeprecated === "string" ? ( - - ) : ( - "Deprecated" - )} - - )} + {inheritedFrom && ( Inherited from {renderType(inheritedFrom)} From 697e48c29d74a84c5d972454ff51483515ddee81 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Thu, 25 Jan 2018 11:30:23 -0800 Subject: [PATCH 18/19] class CssExample --- packages/docs-theme/src/tags/css.tsx | 84 +++++++++++++++------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/packages/docs-theme/src/tags/css.tsx b/packages/docs-theme/src/tags/css.tsx index adc3cb1d8e..3318b5067a 100644 --- a/packages/docs-theme/src/tags/css.tsx +++ b/packages/docs-theme/src/tags/css.tsx @@ -4,51 +4,57 @@ * Licensed under the terms of the LICENSE file distributed with this project. */ -import { IKssModifier, IKssPluginData, ITag } from "documentalist/dist/client"; +import { IKssPluginData, ITag } from "documentalist/dist/client"; import * as React from "react"; import { DocumentationContextTypes, IDocumentationContext } from "../common/context"; import { ModifierTable } from "../components/modifierTable"; -export const CssExample: React.SFC = ({ value }, { getDocsData }: IDocumentationContext) => { - const { css } = getDocsData() as IKssPluginData; - if (css == null || css[value] == null) { - return null; +export class CssExample extends React.PureComponent { + public static contextTypes = DocumentationContextTypes; + public static displayName = "Docs.CssExample"; + + public context: IDocumentationContext; + + public render() { + const { value } = this.props; + const { css } = this.context.getDocsData() as IKssPluginData; + if (css == null || css[value] == null) { + return null; + } + const { markup, markupHtml, modifiers, reference } = css[value]; + return ( +
+ {modifiers.length > 0 ? : undefined} +
+ {this.renderMarkupExample(markup)} + {modifiers.map(mod => this.renderMarkupExample(markup, mod.name))} +
+
+
+ ); } - const { markup, markupHtml, modifiers, reference } = css[value]; - return ( -
- {modifiers.length > 0 ? : undefined} -
- {renderMarkupForModifier(markup, DEFAULT_MODIFIER)} - {modifiers.map(mod => renderMarkupForModifier(markup, mod))} + + private renderMarkupExample(markup: string, modifierName = "default") { + return ( +
+ {modifierName} + {this.renderMarkupForModifier(markup, modifierName)}
-
-
- ); -}; -CssExample.contextTypes = DocumentationContextTypes; -CssExample.displayName = "Docs.CssExample"; + ); + } -function renderMarkupForModifier(markup: string, { name }: IKssModifier) { - const html = markup.replace(MODIFIER_PLACEHOLDER, (_, prefix) => { - if (prefix && name.charAt(0) === prefix) { - return name.slice(1); - } else if (!prefix) { - return name; - } else { - return ""; - } - }); - return ( -
- {name} -
-
- ); + private renderMarkupForModifier(markup: string, modifierName: string) { + const html = markup.replace(MODIFIER_PLACEHOLDER_REGEXP, (_, prefix: string) => { + if (prefix && modifierName.charAt(0) === prefix) { + return modifierName.slice(1); + } else if (!prefix) { + return modifierName; + } else { + return ""; + } + }); + return
; + } } -const MODIFIER_PLACEHOLDER = /\{\{([.:]?)modifier\}\}/g; -const DEFAULT_MODIFIER: IKssModifier = { - documentation: "Default", - name: "default", -}; +const MODIFIER_PLACEHOLDER_REGEXP = /\{\{([.:]?)modifier\}\}/g; From 958dfbda3b2ad2de51393bb57832302a24453096 Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Thu, 25 Jan 2018 11:35:07 -0800 Subject: [PATCH 19/19] tag renderers can be SFCs or classes --- packages/docs-theme/src/tags/defaults.ts | 2 +- packages/docs-theme/src/tags/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs-theme/src/tags/defaults.ts b/packages/docs-theme/src/tags/defaults.ts index 48256e9b71..f2d71ca029 100644 --- a/packages/docs-theme/src/tags/defaults.ts +++ b/packages/docs-theme/src/tags/defaults.ts @@ -11,7 +11,7 @@ import { IKssPluginData, IMarkdownPluginData, ITag, ITypescriptPluginData } from export interface IDocsData extends IKssPluginData, IMarkdownPluginData, ITypescriptPluginData {} -export function createDefaultRenderers(): Record> { +export function createDefaultRenderers(): Record> { return { css: tags.CssExample, heading: tags.Heading, diff --git a/packages/docs-theme/src/tags/index.ts b/packages/docs-theme/src/tags/index.ts index be3b6a8e55..ca4d7f1b86 100644 --- a/packages/docs-theme/src/tags/index.ts +++ b/packages/docs-theme/src/tags/index.ts @@ -7,7 +7,7 @@ import { ITag } from "documentalist/dist/client"; export interface ITagRendererMap { - [tagName: string]: React.SFC | undefined; + [tagName: string]: React.ComponentType | undefined; } export * from "./css";