From b998b44aafeff3726122bbc491e2c84aed284b61 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Fri, 13 Jul 2018 12:27:02 +0200 Subject: SONAR-11013 Add search capabilities to the embedded documentation (#513) --- .../src/main/js/components/docs/DocInclude.tsx | 75 ---------------------- .../main/js/components/docs/DocMarkdownBlock.tsx | 23 +------ .../src/main/js/components/docs/DocParagraph.tsx | 35 ---------- .../src/main/js/components/docs/DocTooltip.tsx | 71 +++++++------------- .../components/docs/__tests__/DocTooltip-test.tsx | 17 ++--- .../__snapshots__/DocMarkdownBlock-test.tsx.snap | 36 +++++------ .../__snapshots__/DocTooltip-test.tsx.snap | 16 +---- 7 files changed, 46 insertions(+), 227 deletions(-) delete mode 100644 server/sonar-web/src/main/js/components/docs/DocInclude.tsx delete mode 100644 server/sonar-web/src/main/js/components/docs/DocParagraph.tsx (limited to 'server/sonar-web/src/main/js/components/docs') diff --git a/server/sonar-web/src/main/js/components/docs/DocInclude.tsx b/server/sonar-web/src/main/js/components/docs/DocInclude.tsx deleted file mode 100644 index d499b27c22c..00000000000 --- a/server/sonar-web/src/main/js/components/docs/DocInclude.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { lazyLoad } from '../lazyLoad'; - -const DocMarkdownBlock = lazyLoad(() => import('./DocMarkdownBlock')); - -interface Props { - className?: string; - path: string; -} - -interface State { - content?: string; -} - -export default class DocInclude extends React.PureComponent { - mounted = false; - state: State = {}; - - componentDidMount() { - this.mounted = true; - this.fetchContent(); - } - - componentWillReceiveProps(nextProps: Props) { - if (nextProps.path !== this.props.path) { - this.setState({ content: undefined }); - } - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.path !== this.props.path) { - this.fetchContent(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchContent = () => { - // even if `this.props.path` starts with `/`, - // it is important to keep `Docs/` in the string to let webpack correctly resolve imports - import(`Docs/${this.props.path.substr(1)}.md`).then( - ({ default: content }) => { - if (this.mounted) { - this.setState({ content }); - } - }, - () => {} - ); - }; - - render() { - return ; - } -} diff --git a/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx b/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx index 0bc5350b297..c61a7212c52 100644 --- a/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx +++ b/server/sonar-web/src/main/js/components/docs/DocMarkdownBlock.tsx @@ -23,11 +23,9 @@ import remark from 'remark'; import reactRenderer from 'remark-react'; import remarkToc from 'remark-toc'; import DocLink from './DocLink'; -import DocParagraph from './DocParagraph'; import DocImg from './DocImg'; import DocTooltipLink from './DocTooltipLink'; -import { separateFrontMatter } from '../../helpers/markdown'; -import { isSonarCloud } from '../../helpers/system'; +import { separateFrontMatter, filterContent } from '../../helpers/markdown'; import { scrollToElement } from '../../helpers/scrolling'; interface Props { @@ -59,7 +57,6 @@ export default class DocMarkdownBlock extends React.PureComponent { {displayH1 &&

{parsed.frontmatter.title}

} { remark() - // .use(remarkInclude) .use(remarkToc, { maxDepth: 3 }) .use(reactRenderer, { remarkReactComponents: { @@ -69,8 +66,6 @@ export default class DocMarkdownBlock extends React.PureComponent { a: isTooltip ? withChildProps(DocTooltipLink, childProps) : withChildProps(DocLink, { onAnchorClick: this.handleAnchorClick }), - // used to handle `@include` - p: DocParagraph, // use custom img tag to render documentation images img: DocImg }, @@ -91,19 +86,3 @@ function withChildProps

( return ; }; } - -function filterContent(content: string) { - const beginning = isSonarCloud() ? '' : ''; - const ending = isSonarCloud() ? '' : ''; - - let newContent = content; - let start = newContent.indexOf(beginning); - let end = newContent.indexOf(ending); - while (start !== -1 && end !== -1) { - newContent = newContent.substring(0, start) + newContent.substring(end + ending.length); - start = newContent.indexOf(beginning); - end = newContent.indexOf(ending); - } - - return newContent; -} diff --git a/server/sonar-web/src/main/js/components/docs/DocParagraph.tsx b/server/sonar-web/src/main/js/components/docs/DocParagraph.tsx deleted file mode 100644 index 54b34660482..00000000000 --- a/server/sonar-web/src/main/js/components/docs/DocParagraph.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import DocInclude from './DocInclude'; - -const INCLUDE = '@include'; - -export default function DocParagraph(props: React.HTMLAttributes) { - if (Array.isArray(props.children) && props.children.length === 1) { - const child = props.children[0]; - if (typeof child === 'string' && child.startsWith(INCLUDE)) { - const includePath = child.substr(INCLUDE.length + 1); - return ; - } - } - - return

; -} diff --git a/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx b/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx index 3f7d4ec0195..a912b43c7b3 100644 --- a/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx +++ b/server/sonar-web/src/main/js/components/docs/DocTooltip.tsx @@ -26,82 +26,55 @@ const DocMarkdownBlock = lazyLoad(() => import('./DocMarkdownBlock')); interface Props { className?: string; children?: React.ReactNode; - /** Key of the documentation chunk */ - doc: string; + // Use as `import(/* webpackMode: "eager" */ 'Docs/tooltips/foo/bar.md')` + doc: Promise<{ default: string }>; overlayProps?: { [k: string]: string }; } interface State { content?: string; - loading: boolean; open: boolean; } export default class DocTooltip extends React.PureComponent { - mounted = false; - state: State = { loading: false, open: false }; + state: State = { open: false }; componentDidMount() { - this.mounted = true; + this.props.doc.then( + ({ default: content }) => { + this.setState({ content }); + }, + () => {} + ); document.addEventListener('scroll', this.close, true); } - componentWillReceiveProps(nextProps: Props) { - if (nextProps.doc !== this.props.doc) { - this.setState({ content: undefined, loading: false, open: false }); - } - } - componentWillUnmount() { - this.mounted = false; document.removeEventListener('scroll', this.close, true); } - fetchContent = () => { - this.setState({ loading: true }); - import(`Docs/tooltips/${this.props.doc}.md`).then( - ({ default: content }) => { - if (this.mounted) { - this.setState({ content, loading: false }); - } - }, - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - }; - close = () => { this.setState({ open: false }); }; - renderOverlay() { - return ( -

- {this.state.loading ? ( - - ) : ( - - )} -
- ); - } - render() { - return ( + return this.state.content ? ( + overlay={ +
+ +
+ }> {this.props.children}
+ ) : ( + this.props.children || null ); } } diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/DocTooltip-test.tsx b/server/sonar-web/src/main/js/components/docs/__tests__/DocTooltip-test.tsx index 570b68e37c0..8e933bddbcd 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/DocTooltip-test.tsx +++ b/server/sonar-web/src/main/js/components/docs/__tests__/DocTooltip-test.tsx @@ -20,20 +20,11 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import DocTooltip from '../DocTooltip'; +import { waitAndUpdate } from '../../../helpers/testUtils'; -jest.useFakeTimers(); - -it('should render', () => { - const wrapper = shallow(); - wrapper.setState({ content: 'this is *bold* text', open: true, loading: true }); +it('should render', async () => { + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); - wrapper.setState({ loading: false }); + await waitAndUpdate(wrapper); expect(wrapper).toMatchSnapshot(); }); - -it('should reset state when receiving new doc', () => { - const wrapper = shallow(); - wrapper.setState({ content: 'this is *bold* text', open: true }); - wrapper.setProps({ doc: 'baz' }); - expect(wrapper.state()).toEqual({ content: undefined, loading: false, open: false }); -}); diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocMarkdownBlock-test.tsx.snap b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocMarkdownBlock-test.tsx.snap index c47b4d7fe4b..c84fe63dedf 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocMarkdownBlock-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocMarkdownBlock-test.tsx.snap @@ -7,39 +7,39 @@ exports[`should cut sonarqube/sonarcloud content 1`] = ` - some - +

- sonarqube - +

- long - +

- multiline - +

- text - +

`; @@ -51,25 +51,25 @@ exports[`should cut sonarqube/sonarcloud content 2`] = ` - some - +

- sonarcloud - +

- text - +

`; @@ -81,7 +81,7 @@ exports[`should render simple markdown 1`] = ` - this is @@ -91,7 +91,7 @@ exports[`should render simple markdown 1`] = ` bold text - +

`; diff --git a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap index f19fea4d065..2c996886133 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocTooltip-test.tsx.snap @@ -1,23 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render 1`] = ` - - - - } -/> -`; +exports[`should render 1`] = `""`; exports[`should render 2`] = `