aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWouter Admiraal <wouter.admiraal@sonarsource.com>2019-01-04 16:46:00 +0100
committersonartech <sonartech@sonarsource.com>2019-01-16 09:42:17 +0100
commit47068be19be3b7e80b27c34ccb9278c2e83ae9de (patch)
tree0171e51153b38ba3f78a6ef2bdb4bd1593f36a42
parent355a3b65066e968e3669a97892df81ef15770a55 (diff)
downloadsonarqube-47068be19be3b7e80b27c34ccb9278c2e83ae9de.tar.gz
sonarqube-47068be19be3b7e80b27c34ccb9278c2e83ae9de.zip
SONAR-11608 Conditional formatting broken when used within a table
-rw-r--r--server/sonar-docs/gatsby-config.js2
-rw-r--r--server/sonar-docs/plugins/sonarsource-source-filesystem/gatsby-node.js23
-rw-r--r--server/sonar-docs/plugins/sonarsource-source-filesystem/index.js57
-rw-r--r--server/sonar-docs/plugins/sonarsource-source-filesystem/package.json12
-rw-r--r--server/sonar-docs/src/templates/page.js28
-rw-r--r--server/sonar-web/src/main/js/components/docs/__tests__/DocMarkdownBlock-test.tsx32
-rw-r--r--server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocMarkdownBlock-test.tsx.snap82
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/markdown-test.ts.snap57
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/markdown-test.ts47
-rw-r--r--server/sonar-web/src/main/js/helpers/markdown.js6
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.
}
/**