diff options
author | Wouter Admiraal <wouter.admiraal@sonarsource.com> | 2019-01-04 16:46:00 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-01-16 09:42:17 +0100 |
commit | 47068be19be3b7e80b27c34ccb9278c2e83ae9de (patch) | |
tree | 0171e51153b38ba3f78a6ef2bdb4bd1593f36a42 | |
parent | 355a3b65066e968e3669a97892df81ef15770a55 (diff) | |
download | sonarqube-47068be19be3b7e80b27c34ccb9278c2e83ae9de.tar.gz sonarqube-47068be19be3b7e80b27c34ccb9278c2e83ae9de.zip |
SONAR-11608 Conditional formatting broken when used within a table
10 files changed, 206 insertions, 140 deletions
diff --git a/server/sonar-docs/gatsby-config.js b/server/sonar-docs/gatsby-config.js index fc20659d2d7..843b36e3683 100644 --- a/server/sonar-docs/gatsby-config.js +++ b/server/sonar-docs/gatsby-config.js @@ -26,7 +26,7 @@ module.exports = { }, plugins: [ { - resolve: 'gatsby-source-filesystem', + resolve: `sonarsource-source-filesystem`, options: { name: 'src', path: `${__dirname}/src/` } }, 'gatsby-plugin-react-helmet', diff --git a/server/sonar-docs/plugins/sonarsource-source-filesystem/gatsby-node.js b/server/sonar-docs/plugins/sonarsource-source-filesystem/gatsby-node.js new file mode 100644 index 00000000000..0fd7c88dd1e --- /dev/null +++ b/server/sonar-docs/plugins/sonarsource-source-filesystem/gatsby-node.js @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 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. + */ +const { sourceNodes, setFieldsOnGraphQLNodeType } = require('gatsby-source-filesystem/gatsby-node'); + +exports.sourceNodes = sourceNodes; +exports.setFieldsOnGraphQLNodeType = setFieldsOnGraphQLNodeType; diff --git a/server/sonar-docs/plugins/sonarsource-source-filesystem/index.js b/server/sonar-docs/plugins/sonarsource-source-filesystem/index.js new file mode 100644 index 00000000000..4ed6bec103d --- /dev/null +++ b/server/sonar-docs/plugins/sonarsource-source-filesystem/index.js @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 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. + */ +const { createFilePath, createRemoteFileNode } = require('gatsby-source-filesystem'); +const fs = require('fs-extra'); + +function loadNodeContent(fileNode) { + const content = fs.readFileSync(fileNode.absolutePath, 'utf-8'); + return new Promise((resolve, reject) => { + let newContent = cutSonarCloudContent(content); + newContent = removeRemainingContentTags(newContent); + resolve(newContent); + }); +} + +function removeRemainingContentTags(content) { + const regexBase = '<!-- \\/?(sonarqube|sonarcloud|static) -->'; + return content + .replace(new RegExp(`^${regexBase}(\n|\r|\r\n|$)`, 'gm'), '') // First, remove single-line ones, including ending carriage-returns. + .replace(new RegExp(`${regexBase}`, 'g'), ''); // Now remove all remaining ones. +} + +function cutSonarCloudContent(content) { + const beginning = '<!-- sonarcloud -->'; + const ending = '<!-- /sonarcloud -->'; + + 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; +} + +exports.createFilePath = createFilePath; +exports.createRemoteFileNode = createRemoteFileNode; +exports.loadNodeContent = loadNodeContent; diff --git a/server/sonar-docs/plugins/sonarsource-source-filesystem/package.json b/server/sonar-docs/plugins/sonarsource-source-filesystem/package.json new file mode 100644 index 00000000000..03199f7d46f --- /dev/null +++ b/server/sonar-docs/plugins/sonarsource-source-filesystem/package.json @@ -0,0 +1,12 @@ +{ + "name": "sonarsource-source-filesystem", + "version": "1.0.0", + "description": "", + "main": "create-file-node.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/server/sonar-docs/src/templates/page.js b/server/sonar-docs/src/templates/page.js index 164ff5909ac..d627cd7a338 100644 --- a/server/sonar-docs/src/templates/page.js +++ b/server/sonar-docs/src/templates/page.js @@ -46,15 +46,13 @@ export default class Page extends React.PureComponent { render() { const page = this.props.data.markdownRemark; - let htmlWithInclusions = cutSonarCloudContent(page.html).replace( - /<p>@include (.*)<\/p>/, - (_, path) => { - const chunk = data.allMarkdownRemark.edges.find(edge => edge.node.fields.slug === path); - return chunk ? chunk.node.html : ''; - } - ); + let htmlWithInclusions = page.html.replace(/<p>@include (.*)<\/p>/, (_, path) => { + const chunk = data.allMarkdownRemark.edges.find(edge => edge.node.fields.slug === path); + return chunk ? chunk.node.html : ''; + }); const realHeadingsList = removeExtraHeadings(page.html, page.headings); + htmlWithInclusions = removeTableOfContents(htmlWithInclusions); htmlWithInclusions = createAnchorForHeadings(htmlWithInclusions, realHeadingsList); htmlWithInclusions = replaceDynamicLinks(htmlWithInclusions); @@ -190,19 +188,3 @@ function createAnchorForHeadings(content, headings) { function removeTableOfContents(content) { return content.replace(/<h[1-9]>Table Of Contents<\/h[1-9]>/i, ''); } - -function cutSonarCloudContent(content) { - const beginning = '<!-- sonarcloud -->'; - const ending = '<!-- /sonarcloud -->'; - - 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/__tests__/DocMarkdownBlock-test.tsx b/server/sonar-web/src/main/js/components/docs/__tests__/DocMarkdownBlock-test.tsx index b7574befa1c..afacbd5ec0a 100644 --- a/server/sonar-web/src/main/js/components/docs/__tests__/DocMarkdownBlock-test.tsx +++ b/server/sonar-web/src/main/js/components/docs/__tests__/DocMarkdownBlock-test.tsx @@ -20,7 +20,6 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import DocMarkdownBlock from '../DocMarkdownBlock'; -import { isSonarCloud } from '../../../helpers/system'; const CONTENT_WITH_TOC = ` ## Table of Contents @@ -75,37 +74,6 @@ it('should use custom component for links', () => { ).toMatchSnapshot(); }); -it('should cut sonarqube/sonarcloud/static content', () => { - const content = ` -some - -<!-- sonarqube --> -sonarqube -<!-- /sonarqube --> - -<!-- sonarcloud --> -sonarcloud -<!-- /sonarcloud --> - -<!-- static --> -static -<!-- /static --> - -<!-- sonarqube --> - long - - multiline -<!-- /sonarqube --> - -text`; - - (isSonarCloud as jest.Mock).mockImplementation(() => false); - expect(shallowRender({ content })).toMatchSnapshot(); - - (isSonarCloud as jest.Mock).mockImplementation(() => true); - expect(shallowRender({ content })).toMatchSnapshot(); -}); - it('should render with custom props for links', () => { expect( shallowRender({ 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 90d7b35cab4..ae537c7f712 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 @@ -1,87 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should cut sonarqube/sonarcloud/static content 1`] = ` -<div - className="markdown" -> - <div - className="markdown-content" - > - <Block - key="h-1" - > - <p - key="h-2" - > - some - </p> - - - <p - key="h-3" - > - sonarqube - </p> - - - <p - key="h-4" - > - long - </p> - - - <p - key="h-5" - > - multiline - </p> - - - <p - key="h-6" - > - text - </p> - </Block> - </div> -</div> -`; - -exports[`should cut sonarqube/sonarcloud/static content 2`] = ` -<div - className="markdown" -> - <div - className="markdown-content" - > - <Block - key="h-1" - > - <p - key="h-2" - > - some - </p> - - - <p - key="h-3" - > - sonarcloud - </p> - - - <p - key="h-4" - > - text - </p> - </Block> - </div> -</div> -`; - exports[`should render a TOC if available 1`] = ` <div className="markdown" diff --git a/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/markdown-test.ts.snap b/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/markdown-test.ts.snap new file mode 100644 index 00000000000..4d075b242b0 --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/markdown-test.ts.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should cut sonarqube/sonarcloud/static content 1`] = ` +" +This text has inline text for SonarQube. Donec sed nulla magna. + +This is text for SonarQube, multi-line. Consectetur adipiscing elit. Duis dignissim nulla at massa iaculis interdum. +Aenean sit amet lacus a tortor ullamcorper interdum. Donec sed nulla magna. + + + + + +This is text for SonarQube, single line. + +* In hac habitasse +* Duis sagittis semper sapien nec tempor +* This is a bullet point for SonarQube + +* Platea dictumst + +Duis sagittis semper sapien nec tempor. Nullam vehicula nisi vitae nisi interdum aliquam. + +| Parameter Name | Description | +| --------------------- | ------------------ | +| sonar.pullrequest.github.repository | SLUG of the GitHub Repo | +| sonar.pullrequest.github.endpoint | The API url for your GitHub instance. | +" +`; + +exports[`should cut sonarqube/sonarcloud/static content 2`] = ` +" +This text has inline text for SonarCloud. Donec sed nulla magna. + + + +This is text for SonarCloud, multi-line. In hac habitasse platea dictumst. Duis sagittis semper sapien nec tempor. Nullam vehicula nisi vitae nisi interdum aliquam. Mauris volutpat nunc non fermentum rhoncus. Aenean laoreet, orci vitae tempor bibendum, +metus nisl euismod neque, vitae euismod nibh nisl eu velit. Vivamus luctus suscipit elit vel semper. + + + + + +* In hac habitasse +* Duis sagittis semper sapien nec tempor + +* This is a bullet point for SonarCloud +* Platea dictumst + +Duis sagittis semper sapien nec tempor. Nullam vehicula nisi vitae nisi interdum aliquam. + +| Parameter Name | Description | +| --------------------- | ------------------ | +| sonar.pullrequest.github.repository | SLUG of the GitHub Repo | + +" +`; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/markdown-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/markdown-test.ts index b2b2a1c0b64..b292f321cf3 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/markdown-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/markdown-test.ts @@ -18,10 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { getFrontMatter, separateFrontMatter, filterContent } from '../markdown'; +import { isSonarCloud } from '../system'; jest.mock('../system', () => ({ getInstance: () => 'SonarQube', - isSonarCloud: () => false + isSonarCloud: jest.fn().mockReturnValue(false) })); it('returns parsed frontmatter of one item', () => { @@ -116,3 +117,47 @@ it('replaces {instance}', () => { filterContent('This is {instance} content. It replaces all {instance}{instance} messages') ).toBe('This is SonarQube content. It replaces all SonarQubeSonarQube messages'); }); + +it('should cut sonarqube/sonarcloud/static content', () => { + const content = ` +This text has inline text for <!-- sonarqube -->SonarQube<!-- /sonarqube --><!-- sonarcloud -->SonarCloud<!-- /sonarcloud -->. Donec sed nulla magna. + +<!-- sonarqube --> +This is text for SonarQube, multi-line. Consectetur adipiscing elit. Duis dignissim nulla at massa iaculis interdum. +Aenean sit amet lacus a tortor ullamcorper interdum. Donec sed nulla magna. +<!-- /sonarqube --> + +<!-- sonarcloud --> +This is text for SonarCloud, multi-line. In hac habitasse platea dictumst. Duis sagittis semper sapien nec tempor. Nullam vehicula nisi vitae nisi interdum aliquam. Mauris volutpat nunc non fermentum rhoncus. Aenean laoreet, orci vitae tempor bibendum, +metus nisl euismod neque, vitae euismod nibh nisl eu velit. Vivamus luctus suscipit elit vel semper. +<!-- /sonarcloud --> + +<!-- static --> +This is static text. +<!-- /static --> + +<!-- sonarqube --> +This is text for SonarQube, single line. +<!-- /sonarqube --> + +* In hac habitasse +* Duis sagittis semper sapien nec tempor +<!-- sonarqube -->* This is a bullet point for SonarQube<!-- /sonarqube --> +<!-- sonarcloud -->* This is a bullet point for SonarCloud<!-- /sonarcloud --> +* Platea dictumst + +Duis sagittis semper sapien nec tempor. Nullam vehicula nisi vitae nisi interdum aliquam. + +| Parameter Name | Description | +| --------------------- | ------------------ | +| sonar.pullrequest.github.repository | SLUG of the GitHub Repo | +<!-- sonarqube --> +| sonar.pullrequest.github.endpoint | The API url for your GitHub instance. | +<!-- /sonarqube --> +`; + + expect(filterContent(content)).toMatchSnapshot(); + + (isSonarCloud as jest.Mock).mockReturnValueOnce(true); + expect(filterContent(content)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/helpers/markdown.js b/server/sonar-web/src/main/js/helpers/markdown.js index b92c05e04dd..1b7f29c25bf 100644 --- a/server/sonar-web/src/main/js/helpers/markdown.js +++ b/server/sonar-web/src/main/js/helpers/markdown.js @@ -71,12 +71,16 @@ function parseFrontMatter(lines) { * @returns {string} */ function filterContent(content) { + const regexBase = '<!-- \\/?(sonarqube|sonarcloud|static) -->'; const { isSonarCloud, getInstance } = require('./system'); const contentWithInstance = content.replace(/{instance}/gi, getInstance()); const contentWithoutStatic = cutConditionalContent(contentWithInstance, 'static'); - return isSonarCloud() + const filteredContent = isSonarCloud() ? cutConditionalContent(contentWithoutStatic, 'sonarqube') : cutConditionalContent(contentWithoutStatic, 'sonarcloud'); + return filteredContent + .replace(new RegExp(`^${regexBase}(\n|\r|\r\n|$)`, 'gm'), '') // First, remove single-line ones, including ending carriage-returns. + .replace(new RegExp(`${regexBase}`, 'g'), ''); // Now remove all remaining ones. } /** |