import React, { Children, cloneElement } from 'react'; import { FormattedMessage, injectIntl } from 'react-intl'; import { Helmet } from 'react-helmet-async'; import { getChildren } from 'jsonml.js/lib/utils'; import { Timeline, Alert, Affix } from 'antd'; import EditButton from './EditButton'; import { getMetaDescription } from '../utils'; interface LocaleString { [locale: string]: string; } export interface ArticleProps { titleRegionClassName?: string; location: { pathname: string; }; content: { meta: { toc?: boolean; timeline?: boolean; title: string | LocaleString; subtitle?: string; filename?: string; }; description?: any[]; toc: string[]; content: any[]; api?: any; }; intl: { locale: string }; utils: { toReactComponent: (content: any[]) => React.ReactElement; }; } class Article extends React.Component { shouldComponentUpdate(nextProps: ArticleProps) { const { location } = this.props; const { location: nextLocation } = nextProps; if (nextLocation.pathname === location.pathname) { return false; } return true; } onResourceClick: React.MouseEventHandler = event => { const { target } = (event as unknown) as { target: HTMLAnchorElement }; if (!window.gtag) { return; } const cardNode = target.closest('.resource-card') as HTMLAnchorElement; if (cardNode) { window.gtag('event', 'resource', { event_category: 'Download', event_label: cardNode.href, }); } if ( window.location.href.indexOf('docs/react/recommendation') > 0 && target.matches('.markdown > table td > a[href]') ) { window.gtag('event', 'recommendation', { event_category: 'Click', event_label: target.href, }); } }; getArticle(article: React.ReactElement) { const { content } = this.props; const { meta } = content; if (!meta.timeline) { return article; } const timelineItems = []; let temp: React.ReactNode[] = []; let i = 1; Children.forEach(article.props.children, child => { if (child.type === 'h2' && temp.length > 0) { timelineItems.push({temp}); temp = []; i += 1; } temp.push(child); }); if (temp.length > 0) { timelineItems.push({temp}); } return cloneElement(article, { children: {timelineItems}, }); } render() { const { titleRegionClassName, content, intl: { locale }, utils, } = this.props; const { meta, description } = content; const { title, subtitle, filename } = meta; const isNotTranslated = locale === 'en-US' && typeof title === 'object'; const helmetTitle = `${(title as LocaleString)[locale] || title} - Ant Design`; const helmetDesc = getMetaDescription(description); const contentChild = getMetaDescription(getChildren(content.content)); const metaDesc = helmetDesc || contentChild; return (
{helmetTitle && {helmetTitle}} {helmetTitle && } {metaDesc && } {isNotTranslated && ( This article has not been translated yet. Wanna help us out?  See this issue on GitHub. } /> )}

{(title as LocaleString)[locale] || title} {!subtitle || locale === 'en-US' ? null : {subtitle}} } filename={filename} />

{!description ? null : utils.toReactComponent( ['section', { className: 'markdown' }].concat(getChildren(description)), )}
{!content.toc || content.toc.length <= 1 || meta.toc === false ? null : ( {utils.toReactComponent(['ul', { className: 'toc' }].concat(getChildren(content.toc)))} )} {this.getArticle( utils.toReactComponent( ['section', { className: 'markdown' }].concat(getChildren(content.content)), ), )} {utils.toReactComponent( [ 'section', { className: 'markdown api-container', }, ].concat(getChildren(content.api || ['placeholder'])), )}
); } } export default (injectIntl(Article as any) as any) as React.ComponentClass;