diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2019-06-17 18:05:43 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-06-28 08:45:43 +0200 |
commit | d835fdaa1d594451b554af805db9869134c716df (patch) | |
tree | 7376c601320e5cb687df7e921c5d151972639796 /server/sonar-web | |
parent | 73e1d5bb27a020277499fe0be5d059184c59c233 (diff) | |
download | sonarqube-d835fdaa1d594451b554af805db9869134c716df.tar.gz sonarqube-d835fdaa1d594451b554af805db9869134c716df.zip |
SONAR-12196 Fix SSF-79
Diffstat (limited to 'server/sonar-web')
46 files changed, 990 insertions, 307 deletions
diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json index 652397674a7..6a94ebb3ea1 100644 --- a/server/sonar-web/package.json +++ b/server/sonar-web/package.json @@ -5,6 +5,7 @@ "repository": "SonarSource/sonarqube", "license": "LGPL-3.0", "dependencies": { + "@types/dompurify": "^0.0.32", "classnames": "2.2.6", "clipboard": "2.0.1", "core-js": "3.0.0", @@ -16,6 +17,7 @@ "d3-shape": "1.2.2", "d3-zoom": "1.7.3", "date-fns": "1.29.0", + "dompurify": "^1.0.11", "formik": "1.2.0", "history": "3.3.0", "intl-relativeformat": "2.1.0", @@ -78,6 +80,7 @@ "@types/react-router": "3.0.20", "@types/react-select": "1.2.6", "@types/react-virtualized": "9.21.0", + "@types/sanitize-html": "1.20.0", "@types/valid-url": "1.0.2", "@typescript-eslint/parser": "1.5.0", "autoprefixer": "9.5.0", diff --git a/server/sonar-web/src/main/js/app/components/search/SearchResult.tsx b/server/sonar-web/src/main/js/app/components/search/SearchResult.tsx index 5ffab5ec6a4..20fd40ae953 100644 --- a/server/sonar-web/src/main/js/app/components/search/SearchResult.tsx +++ b/server/sonar-web/src/main/js/app/components/search/SearchResult.tsx @@ -137,6 +137,7 @@ export default class SearchResult extends React.PureComponent<Props, State> { {component.match ? ( <span className="navbar-search-item-match" + // Safe: comes from the backend dangerouslySetInnerHTML={{ __html: component.match }} /> ) : ( diff --git a/server/sonar-web/src/main/js/app/components/search/SearchShowMore.tsx b/server/sonar-web/src/main/js/app/components/search/SearchShowMore.tsx index 1c3932538f3..d528a1a7369 100644 --- a/server/sonar-web/src/main/js/app/components/search/SearchShowMore.tsx +++ b/server/sonar-web/src/main/js/app/components/search/SearchShowMore.tsx @@ -18,9 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import * as classNames from 'classnames'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { translate } from '../../../helpers/l10n'; interface Props { allowMore: boolean; @@ -61,15 +62,15 @@ export default class SearchShowMore extends React.PureComponent<Props> { href="#" onClick={this.handleMoreClick} onMouseEnter={this.handleMoreMouseEnter}> - <div - className="pull-right text-muted-2 menu-footer-note" - dangerouslySetInnerHTML={{ - __html: translateWithParameters( - 'search.show_more.hint', - '<span class="shortcut-button shortcut-button-small">Enter</span>' - ) - }} - /> + <div className="pull-right text-muted-2 menu-footer-note"> + <FormattedMessage + defaultMessage={translate('search.show_more.hint')} + id={'search.show_more.hint'} + values={{ + key: <span className="shortcut-button shortcut-button-small">Enter</span> + }} + /> + </div> <span>{translate('show_more')}</span> </a> </DeferredSpinner> diff --git a/server/sonar-web/src/main/js/app/components/search/__tests__/__snapshots__/SearchShowMore-test.tsx.snap b/server/sonar-web/src/main/js/app/components/search/__tests__/__snapshots__/SearchShowMore-test.tsx.snap index 9a3d97e3982..71e30b63d9b 100644 --- a/server/sonar-web/src/main/js/app/components/search/__tests__/__snapshots__/SearchShowMore-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/search/__tests__/__snapshots__/SearchShowMore-test.tsx.snap @@ -19,12 +19,21 @@ exports[`should render 1`] = ` > <div className="pull-right text-muted-2 menu-footer-note" - dangerouslySetInnerHTML={ - Object { - "__html": "search.show_more.hint.<span class=\\"shortcut-button shortcut-button-small\\">Enter</span>", + > + <FormattedMessage + defaultMessage="search.show_more.hint" + id="search.show_more.hint" + values={ + Object { + "key": <span + className="shortcut-button shortcut-button-small" + > + Enter + </span>, + } } - } - /> + /> + </div> <span> show_more </span> diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutApp.tsx b/server/sonar-web/src/main/js/apps/about/components/AboutApp.tsx index 9e4e5f939bc..4c8f05066db 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutApp.tsx +++ b/server/sonar-web/src/main/js/apps/about/components/AboutApp.tsx @@ -158,7 +158,11 @@ export class AboutApp extends React.PureComponent<Props, State> { </div> {customText && ( - <div className="about-page-section" dangerouslySetInnerHTML={{ __html: customText }} /> + <div + className="about-page-section" + // Safe: Defined by instance admin + dangerouslySetInnerHTML={{ __html: customText }} + /> )} <AboutLanguages /> diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx index ac5b6325bb9..490b971bab5 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/ActivationFormModal.tsx @@ -224,6 +224,7 @@ export default class ActivationFormModal extends React.PureComponent<Props, Stat )} <div className="note" + // Safe: defined by rule creator (instance admin?) dangerouslySetInnerHTML={{ __html: param.htmlDesc || '' }} /> </div> diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx index afb3a99881f..42b022b64e7 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/CustomRuleFormModal.tsx @@ -304,6 +304,7 @@ export default class CustomRuleFormModal extends React.PureComponent<Props, Stat )} <div className="modal-field-description" + // Safe: defined by rule creator (instance admin?) dangerouslySetInnerHTML={{ __html: param.htmlDesc || '' }} /> </div> diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsDescription.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsDescription.tsx index 0f22be47412..fc0ec48363e 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsDescription.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsDescription.tsx @@ -112,6 +112,7 @@ export default class RuleDetailsDescription extends React.PureComponent<Props, S {this.props.ruleDetails.htmlNote !== undefined && ( <div className="rule-desc spacer-bottom markdown" + // Safe: defined by rule creator (instance admin?) dangerouslySetInnerHTML={{ __html: this.props.ruleDetails.htmlNote }} /> )} @@ -193,6 +194,7 @@ export default class RuleDetailsDescription extends React.PureComponent<Props, S {hasDescription ? ( <div className="coding-rules-detail-description rule-desc markdown" + // Safe: defined by rule creator (instance admin?) dangerouslySetInnerHTML={{ __html: ruleDetails.htmlDesc || '' }} /> ) : ( diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsParameters.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsParameters.tsx index 2679b6f3fd8..57f42d438a1 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsParameters.tsx +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsParameters.tsx @@ -29,7 +29,9 @@ export default class RuleDetailsParameters extends React.PureComponent<Props> { <tr className="coding-rules-detail-parameter" key={param.key}> <td className="coding-rules-detail-parameter-name">{param.key}</td> <td className="coding-rules-detail-parameter-description"> - <p dangerouslySetInnerHTML={{ __html: param.htmlDesc || '' }} /> + <p // Safe: defined by rule creator (instance admin?) + dangerouslySetInnerHTML={{ __html: param.htmlDesc || '' }} + /> {param.defaultValue !== undefined && ( <div className="note spacer-top"> {translate('coding_rules.parameters.default_value')} diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/RuleDetailsParameters-test.tsx b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/RuleDetailsParameters-test.tsx new file mode 100644 index 00000000000..1e017749c54 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/RuleDetailsParameters-test.tsx @@ -0,0 +1,33 @@ +/* + * 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. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import RuleDetailsParameters from '../RuleDetailsParameters'; +import { mockRuleDetailsParameter } from '../../../../helpers/testMocks'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot(); +}); + +function shallowRender(props: Partial<RuleDetailsParameters['props']> = {}) { + const params = [mockRuleDetailsParameter(), mockRuleDetailsParameter()]; + + return shallow(<RuleDetailsParameters params={params} {...props} />); +} diff --git a/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/RuleDetailsParameters-test.tsx.snap b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/RuleDetailsParameters-test.tsx.snap new file mode 100644 index 00000000000..374a33057d7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/RuleDetailsParameters-test.tsx.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly 1`] = ` +<div + className="js-rule-parameters" +> + <h3 + className="coding-rules-detail-title" + > + coding_rules.parameters + </h3> + <table + className="coding-rules-detail-parameters" + > + <tbody> + <tr + className="coding-rules-detail-parameter" + key="1" + > + <td + className="coding-rules-detail-parameter-name" + > + 1 + </td> + <td + className="coding-rules-detail-parameter-description" + > + <p + dangerouslySetInnerHTML={ + Object { + "__html": "description", + } + } + /> + <div + className="note spacer-top" + > + coding_rules.parameters.default_value + <br /> + <span + className="coding-rules-detail-parameter-value" + > + 1 + </span> + </div> + </td> + </tr> + <tr + className="coding-rules-detail-parameter" + key="1" + > + <td + className="coding-rules-detail-parameter-name" + > + 1 + </td> + <td + className="coding-rules-detail-parameter-description" + > + <p + dangerouslySetInnerHTML={ + Object { + "__html": "description", + } + } + /> + <div + className="note spacer-top" + > + coding_rules.parameters.default_value + <br /> + <span + className="coding-rules-detail-parameter-value" + > + 1 + </span> + </div> + </td> + </tr> + </tbody> + </table> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx index d63d251974a..2ca069c1a46 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/components/IssuesSourceViewer.tsx @@ -119,6 +119,7 @@ export default class IssuesSourceViewer extends React.PureComponent<Props> { const component = selectedLocation ? selectedLocation.component : openIssue.component; const allMessagesEmpty = locations !== undefined && locations.every(location => !location.msg); + const highlightedLocations = locations.filter(location => location.component === component); // do not load issues when open another file for a location diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx index fd091c1c940..c1213f0f1d6 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx @@ -18,8 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import * as classNames from 'classnames'; import Helmet from 'react-helmet'; +import { FormattedMessage } from 'react-intl'; +import * as classNames from 'classnames'; import { getMigrationStatus, getSystemStatus, migrateDatabase } from '../../../api/system'; import DateFromNow from '../../../components/intl/DateFromNow'; import TimeFormatter from '../../../components/intl/TimeFormatter'; @@ -201,18 +202,32 @@ export default class App extends React.PureComponent<Props, State> { </h1> {!isSonarCloud() && ( <> - <p - className="maintenance-text" - dangerouslySetInnerHTML={{ - __html: translate('maintenance.sonarqube_is_under_maintenance.1') - }} - /> - <p - className="maintenance-text" - dangerouslySetInnerHTML={{ - __html: translate('maintenance.sonarqube_is_under_maintenance.2') - }} - /> + <p className="maintenance-text"> + <FormattedMessage + defaultMessage={translate('maintenance.sonarqube_is_under_maintenance.1')} + id="maintenance.sonarqube_is_under_maintenance.1" + values={{ + link: ( + <a href="https://redirect.sonarsource.com/doc/plugin-library.html"> + {translate('maintenance.sonarqube_is_under_maintenance_link.1')} + </a> + ) + }} + /> + </p> + <p className="maintenance-text"> + <FormattedMessage + defaultMessage={translate('maintenance.sonarqube_is_under_maintenance.2')} + id="maintenance.sonarqube_is_under_maintenance.2" + values={{ + link: ( + <a href="https://redirect.sonarsource.com/doc/upgrading.html"> + {translate('maintenance.sonarqube_is_under_maintenance_link.2')} + </a> + ) + }} + /> + </p> </> )} </> diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap index 7c718fdcb7e..e0606efd1df 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap @@ -24,20 +24,38 @@ exports[`Maintenance Page should render DB_MIGRATION_NEEDED status 1`] = ` </h1> <p className="maintenance-text" - dangerouslySetInnerHTML={ - Object { - "__html": "maintenance.sonarqube_is_under_maintenance.1", + > + <FormattedMessage + defaultMessage="maintenance.sonarqube_is_under_maintenance.1" + id="maintenance.sonarqube_is_under_maintenance.1" + values={ + Object { + "link": <a + href="https://redirect.sonarsource.com/doc/plugin-library.html" + > + maintenance.sonarqube_is_under_maintenance_link.1 + </a>, + } } - } - /> + /> + </p> <p className="maintenance-text" - dangerouslySetInnerHTML={ - Object { - "__html": "maintenance.sonarqube_is_under_maintenance.2", + > + <FormattedMessage + defaultMessage="maintenance.sonarqube_is_under_maintenance.2" + id="maintenance.sonarqube_is_under_maintenance.2" + values={ + Object { + "link": <a + href="https://redirect.sonarsource.com/doc/upgrading.html" + > + maintenance.sonarqube_is_under_maintenance_link.2 + </a>, + } } - } - /> + /> + </p> </div> </div> </Fragment> @@ -67,20 +85,38 @@ exports[`Maintenance Page should render DB_MIGRATION_RUNNING status 1`] = ` </h1> <p className="maintenance-text" - dangerouslySetInnerHTML={ - Object { - "__html": "maintenance.sonarqube_is_under_maintenance.1", + > + <FormattedMessage + defaultMessage="maintenance.sonarqube_is_under_maintenance.1" + id="maintenance.sonarqube_is_under_maintenance.1" + values={ + Object { + "link": <a + href="https://redirect.sonarsource.com/doc/plugin-library.html" + > + maintenance.sonarqube_is_under_maintenance_link.1 + </a>, + } } - } - /> + /> + </p> <p className="maintenance-text" - dangerouslySetInnerHTML={ - Object { - "__html": "maintenance.sonarqube_is_under_maintenance.2", + > + <FormattedMessage + defaultMessage="maintenance.sonarqube_is_under_maintenance.2" + id="maintenance.sonarqube_is_under_maintenance.2" + values={ + Object { + "link": <a + href="https://redirect.sonarsource.com/doc/upgrading.html" + > + maintenance.sonarqube_is_under_maintenance_link.2 + </a>, + } } - } - /> + /> + </p> </div> </div> </Fragment> diff --git a/server/sonar-web/src/main/js/apps/projectBranches/components/SettingForm.tsx b/server/sonar-web/src/main/js/apps/projectBranches/components/SettingForm.tsx index e27eda543b5..7dadf716969 100644 --- a/server/sonar-web/src/main/js/apps/projectBranches/components/SettingForm.tsx +++ b/server/sonar-web/src/main/js/apps/projectBranches/components/SettingForm.tsx @@ -21,6 +21,7 @@ import * as React from 'react'; import { setSimpleSettingValue, resetSettingValue } from '../../../api/settings'; import { Button, SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { sanitizeTranslation } from '../../settings/utils'; interface Props { branch?: string; @@ -96,7 +97,9 @@ export default class SettingForm extends React.PureComponent<Props, State> { <div className="modal-body"> <div className="big-spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: translate(`property.${setting.key}.description`) }} + dangerouslySetInnerHTML={{ + __html: sanitizeTranslation(translate(`property.${setting.key}.description`)) + }} /> <div className="modal-field"> <input diff --git a/server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts index 5d4ae3ae9cd..642fb09c98f 100644 --- a/server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts +++ b/server/sonar-web/src/main/js/apps/settings/__tests__/utils-test.ts @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { getEmptyValue, getDefaultValue } from '../utils'; +import { getEmptyValue, getDefaultValue, sanitizeTranslation } from '../utils'; const fields = [ { key: 'foo', type: 'STRING' } as T.SettingFieldDefinition, @@ -76,3 +76,106 @@ describe('#getDefaultValue()', () => { it('should work for boolean field when passing "false"', () => check('false', 'settings.boolean.false')); }); + +describe('sanitizeTranslation', () => { + it('should preserve formatting tags', () => { + const allowed = ` + Hi this is <i>in italics</i> and <ul> + <li> lists </li> + <li> are allowed</li> + </ul> + <p> + as well. This is <b>Amazing</b> and this <strong>bold</strong> <br> + and <code>code.is.accepted too</code> + </p> + `; + + const clean = sanitizeTranslation(allowed); + expect(clean).toBe(allowed); + }); + + /* + * Test code borrowed from OWASP's sanitizer tests + * https://github.com/OWASP/java-html-sanitizer/blob/master/src/test/resources/org/owasp/html/htmllexerinput1.html + */ + it('should strip everything else', () => { + const clean = sanitizeTranslation(`<?xml version="not-even-close"?> + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + + <!-- a test input for HtmlLexer --> + + <html> + <head> + <title>Test File For HtmlLexer & HtmlParser</title> + <link rel=stylesheet type="text/css" src=foo/bar.css /> + <body + bgcolor=white + linkcolor = "blue" + onload="document.writeln( + "<p>properly escaped code in a handler</p>");" + > + + <script type="text/javascript"><!-- + document.writeln("<p>Some initialization code in global context</p>"); + --></script> + + <script type="text/javascript"> + // hi there + document.writeln("<p>More initialization</p>"); + </script> + + <div id=clickydiv onclick="handleClicky(event)" + ondblclick=this.onclick(event);return(false)> + Clicky + </div> + + <input id=foo> + <gxp:attr name="onchange">alert("<b>hi</b>");</gxp:attr> + </input> + + <pre><div id=notarealtag onclick=notcode()></pre> + + <!-- some tokenization corner cases --> + + < notatag <atag/> + + </ notatag> </redundantlyclosed/> + + <messyattributes a=b=c d="e"f=g h =i j= k l = m checked n="o"/> + + < < < all in one text block > > > + + <xmp>Make sure that <!-- comments don't obscure the xmp close</xmp> + <% # some php code here + write("<pre>$horriblySyntacticConstruct1</pre>\n\n"); + %> + <script type="text/javascript"><!-- + alert("hello world"); + // --></script> + + <script>/* </script> */alert('hi');</script> + <script><!--/* </script> */alert('hi');--></script> + + <xmp style=color:blue><!--/* </xmp> */alert('hi');--></xmp> + + <style><!-- p { contentf: '</style>' } --></style> + <style>Foo<!-- > </style> --></style> + <textarea><!-- Zoicks </textarea>--></textarea> + <!-- An escaping text span start may share its U+002D HYPHEN-MINUS characters + - with its corresponding escaping text span end. --> + <script><!--></script> + <script><!---></script> + <script><!----></script> + </body> + </html> + <![CDATA[ No such thing as a CDATA> section in HTML ]]> + <script>a<b</script> + <img src=foo.gif /><a href=><a href=/> + <span title=malformed attribs' do=don't id=foo checked onclick="a<b">Bar</span>`); + + expect(clean.replace(/\s+/g, '')).toBe( + `Clickyalert("<b>hi</b>");<divid=notarealtagonclick=notcode()><notatag<<<allinonetextblock>>>Makesurethat<%#somephpcodeherewrite("$horriblySyntacticConstruct1");%>*/alert('hi');*/alert('hi');-->*/alert('hi');-->'}-->--><!--Zoicks-->sectioninHTML]]>Bar` + ); + }); +}); diff --git a/server/sonar-web/src/main/js/apps/settings/components/Definition.tsx b/server/sonar-web/src/main/js/apps/settings/components/Definition.tsx index d17d9ead8a1..9be3fb3820b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/Definition.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/Definition.tsx @@ -26,7 +26,8 @@ import { getPropertyName, getPropertyDescription, getSettingValue, - isDefaultOrInherited + isDefaultOrInherited, + sanitizeTranslation } from '../utils'; import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon'; import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon'; @@ -142,7 +143,7 @@ export class Definition extends React.PureComponent<Props, State> { {description && ( <div className="markdown small spacer-top" - dangerouslySetInnerHTML={{ __html: description }} + dangerouslySetInnerHTML={{ __html: sanitizeTranslation(description) }} /> )} diff --git a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx index 9e5dc895b7b..7733c37c709 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { groupBy, isEqual, sortBy } from 'lodash'; import DefinitionsList from './DefinitionsList'; import EmailForm from './EmailForm'; -import { getSubCategoryName, getSubCategoryDescription } from '../utils'; +import { getSubCategoryName, getSubCategoryDescription, sanitizeTranslation } from '../utils'; interface Props { category: string; @@ -74,7 +74,7 @@ export default class SubCategoryDefinitionsList extends React.PureComponent<Prop {subCategory.description != null && ( <div className="settings-sub-category-description markdown" - dangerouslySetInnerHTML={{ __html: subCategory.description }} + dangerouslySetInnerHTML={{ __html: sanitizeTranslation(subCategory.description) }} /> )} <DefinitionsList diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx index a11187e7a45..84b235cd2fc 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx @@ -76,10 +76,32 @@ export default class GenerateSecretKeyForm extends React.PureComponent<Props, St <ClipboardButton className="little-spacer-left" copyValue={secretKey} /> </div> <h3 className="spacer-bottom">{translate('encryption.how_to_use')}</h3> - <div - className="markdown" - dangerouslySetInnerHTML={{ __html: translate('encryption.how_to_use.content') }} - /> + <div className="markdown"> + <ul> + <li> + <FormattedMessage + defaultMessage={translate('encryption.how_to_use.content1')} + id="encryption.how_to_use.content1" + values={{ + secret_file: <code>~/.sonar/sonar-secret.txt</code>, + property: <code>sonar.secretKeyPath</code>, + propreties_file: <code>conf/sonar.properties</code> + }} + /> + </li> + <li>{translate('encryption.how_to_use.content2')}</li> + <li> + <FormattedMessage + defaultMessage={translate('encryption.how_to_use.content3')} + id="encryption.how_to_use.content3" + values={{ + property: <code>sonar.secretKeyPath</code> + }} + /> + </li> + <li>{translate('encryption.how_to_use.content4')}</li> + </ul> + </div> </> ) : ( <form id="generate-secret-key-form" onSubmit={this.handleSubmit}> diff --git a/server/sonar-web/src/main/js/apps/settings/utils.ts b/server/sonar-web/src/main/js/apps/settings/utils.ts index 09484304223..990a6933591 100644 --- a/server/sonar-web/src/main/js/apps/settings/utils.ts +++ b/server/sonar-web/src/main/js/apps/settings/utils.ts @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { sanitize } from 'dompurify'; import { translate, hasMessage } from '../../helpers/l10n'; export const DEFAULT_CATEGORY = 'general'; @@ -35,6 +36,12 @@ export interface DefaultInputProps { value: any; } +export function sanitizeTranslation(html: string) { + return sanitize(html, { + ALLOWED_TAGS: ['b', 'br', 'code', 'i', 'li', 'p', 'strong', 'ul'] + }); +} + export function getPropertyName(definition: T.SettingDefinition) { const key = `property.${definition.key}.name`; return hasMessage(key) ? translate(key) : definition.name; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx index 829c09c02d6..3f16344c420 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/BuildWrapper.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import { translate } from '../../../../helpers/l10n'; import { getBaseUrl } from '../../../../helpers/urls'; @@ -38,12 +39,15 @@ export default function BuildWrapper(props: Props) { <h4 className="spacer-bottom"> {translate('onboarding.analysis.build_wrapper.header', props.os)} </h4> - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ - __html: translate('onboarding.analysis.build_wrapper.text', props.os) - }} - /> + <p className="spacer-bottom markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.build_wrapper.text')} + id="onboarding.analysis.build_wrapper.text" + values={{ + env_var: <code>{props.os === 'win' ? '%PATH%' : 'PATH'}</code> + }} + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx index c36574af7d8..43958932470 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/ClangGCC.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import SQScanner from './SQScanner'; import BuildWrapper from './BuildWrapper'; import CodeSnippet from '../../../../components/common/CodeSnippet'; @@ -63,19 +64,26 @@ export default function ClangGCC(props: Props) { {translate('onboarding.analysis.sq_scanner.execute')} </h4> <InstanceMessage message={translate('onboarding.analysis.sq_scanner.execute.text')}> - {transformedMessage => ( - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: transformedMessage }} - /> - )} + {transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>} </InstanceMessage> <CodeSnippet isOneLine={props.small} snippet={command1} /> <CodeSnippet isOneLine={props.os === 'win'} snippet={command2} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.sq_scanner.docs') }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.sq_scanner.docs')} + id="onboarding.analysis.sq_scanner.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.sq_scanner.docs_link')} + </a> + ) + }} + /> + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/DotNet.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/DotNet.tsx index 1bf82ddb0b3..a6fe98e0c2e 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/DotNet.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/DotNet.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import MSBuildScanner from './MSBuildScanner'; import CodeSnippet from '../../../../components/common/CodeSnippet'; import InstanceMessage from '../../../../components/common/InstanceMessage'; @@ -52,20 +53,27 @@ export default function DotNet(props: Props) { {translate('onboarding.analysis.msbuild.execute')} </h4> <InstanceMessage message={translate('onboarding.analysis.msbuild.execute.text')}> - {transformedMessage => ( - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: transformedMessage }} - /> - )} + {transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>} </InstanceMessage> <CodeSnippet isOneLine={true} snippet={command1} /> <CodeSnippet isOneLine={false} snippet={command2} /> <CodeSnippet isOneLine={props.small} snippet={command3} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.docs') }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.docs')} + id="onboarding.analysis.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.msbuild.docs_link')} + </a> + ) + }} + /> + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaGradle.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaGradle.tsx index d33568362bb..dfe6ff42834 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaGradle.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaGradle.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import CodeSnippet from '../../../../components/common/CodeSnippet'; import InstanceMessage from '../../../../components/common/InstanceMessage'; import { translate } from '../../../../helpers/l10n'; @@ -45,10 +46,16 @@ export default function JavaGradle(props: Props) { <h4 className="spacer-bottom">{translate('onboarding.analysis.java.gradle.header')}</h4> <InstanceMessage message={translate('onboarding.analysis.java.gradle.text.1')}> {transformedMessage => ( - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: transformedMessage }} - /> + <p className="spacer-bottom markdown"> + <FormattedMessage + defaultMessage={transformedMessage} + id="onboarding.analysis.java.gradle.text.1" + values={{ + plugin_code: <code>org.sonarqube</code>, + filename: <code>build.gradle</code> + }} + /> + </p> )} </InstanceMessage> <CodeSnippet snippet={config} /> @@ -56,18 +63,27 @@ export default function JavaGradle(props: Props) { {translate('onboarding.analysis.java.gradle.text.2')} </p> <CodeSnippet snippet={command} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.java.gradle.docs') }} - /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ - __html: props.projectKey - ? translate('onboarding.analysis.auto_refresh_after_analysis') - : translate('onboarding.analysis.browse_url_after_analysis') - }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.docs')} + id="onboarding.analysis.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/gradle.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.java.gradle.docs_link')} + </a> + ) + }} + /> + </p> + <p className="big-spacer-top markdown"> + {props.projectKey + ? translate('onboarding.analysis.auto_refresh_after_analysis') + : translate('onboarding.analysis.browse_url_after_analysis')} + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaMaven.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaMaven.tsx index 3bc233aa041..778796e0eb0 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaMaven.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/JavaMaven.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import CodeSnippet from '../../../../components/common/CodeSnippet'; import InstanceMessage from '../../../../components/common/InstanceMessage'; import { translate } from '../../../../helpers/l10n'; @@ -45,18 +46,27 @@ export default function JavaMaven(props: Props) { <InstanceMessage message={translate('onboarding.analysis.java.maven.text')} /> </p> <CodeSnippet snippet={command} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.java.maven.docs') }} - /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ - __html: props.projectKey - ? translate('onboarding.analysis.auto_refresh_after_analysis') - : translate('onboarding.analysis.browse_url_after_analysis') - }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.docs')} + id="onboarding.analysis.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.java.maven.docs_link')} + </a> + ) + }} + /> + </p> + <p className="big-spacer-top markdown"> + {props.projectKey + ? translate('onboarding.analysis.auto_refresh_after_analysis') + : translate('onboarding.analysis.browse_url_after_analysis')} + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/MSBuildScanner.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/MSBuildScanner.tsx index 86ea954d2ca..02c69437a2c 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/MSBuildScanner.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/MSBuildScanner.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import { translate } from '../../../../helpers/l10n'; interface Props { @@ -28,10 +29,13 @@ export default function MSBuildScanner(props: Props) { return ( <div className={props.className}> <h4 className="spacer-bottom">{translate('onboarding.analysis.msbuild.header')}</h4> - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.text') }} - /> + <p className="spacer-bottom markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.msbuild.text')} + id="onboarding.analysis.msbuild.text" + values={{ code: <code>%PATH%</code> }} + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx index 5066cc1ede3..36fbab52778 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/Msvc.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import MSBuildScanner from './MSBuildScanner'; import BuildWrapper from './BuildWrapper'; import CodeSnippet from '../../../../components/common/CodeSnippet'; @@ -55,20 +56,27 @@ export default function Msvc(props: Props) { {translate('onboarding.analysis.msbuild.execute')} </h4> <InstanceMessage message={translate('onboarding.analysis.msbuild.execute.text')}> - {transformedMessage => ( - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: transformedMessage }} - /> - )} + {transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>} </InstanceMessage> <CodeSnippet isOneLine={true} snippet={command1} /> <CodeSnippet isOneLine={props.small} snippet={command2} /> <CodeSnippet isOneLine={props.small} snippet={command3} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.docs') }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.docs')} + id="onboarding.analysis.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.msbuild.docs_link')} + </a> + ) + }} + /> + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/Other.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/Other.tsx index 8c4a6529ea7..c9445156179 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/Other.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/Other.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import SQScanner from './SQScanner'; import CodeSnippet from '../../../../components/common/CodeSnippet'; import InstanceMessage from '../../../../components/common/InstanceMessage'; @@ -51,18 +52,25 @@ export default function Other(props: Props) { {translate('onboarding.analysis.sq_scanner.execute')} </h4> <InstanceMessage message={translate('onboarding.analysis.sq_scanner.execute.text')}> - {transformedMessage => ( - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ __html: transformedMessage }} - /> - )} + {transformedMessage => <p className="spacer-bottom markdown">{transformedMessage}</p>} </InstanceMessage> <CodeSnippet isOneLine={props.os === 'win'} snippet={command} /> - <p - className="big-spacer-top markdown" - dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.sq_scanner.docs') }} - /> + <p className="big-spacer-top markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.sq_scanner.docs')} + id="onboarding.analysis.sq_scanner.docs" + values={{ + link: ( + <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank"> + {translate('onboarding.analysis.sq_scanner.docs_link')} + </a> + ) + }} + /> + </p> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/SQScanner.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/commands/SQScanner.tsx index 0ce14360992..674b59e3d50 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/SQScanner.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/SQScanner.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { FormattedMessage } from 'react-intl'; import { translate } from '../../../../helpers/l10n'; interface Props { @@ -31,12 +32,16 @@ export default function SQScanner(props: Props) { <h4 className="spacer-bottom"> {translate('onboarding.analysis.sq_scanner.header', props.os)} </h4> - <p - className="spacer-bottom markdown" - dangerouslySetInnerHTML={{ - __html: translate('onboarding.analysis.sq_scanner.text', props.os) - }} - /> + <p className="spacer-bottom markdown"> + <FormattedMessage + defaultMessage={translate('onboarding.analysis.sq_scanner.text')} + id="onboarding.analysis.sq_scanner.text" + values={{ + dir: <code>bin</code>, + env_var: <code>{props.os === 'win' ? '%PATH%' : 'PATH'}</code> + }} + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap index 07e8eb45f0a..85f98bb085d 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/BuildWrapper-test.tsx.snap @@ -9,12 +9,19 @@ exports[`renders correctly 1`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.build_wrapper.text.win", + > + <FormattedMessage + defaultMessage="onboarding.analysis.build_wrapper.text" + id="onboarding.analysis.build_wrapper.text" + values={ + Object { + "env_var": <code> + %PATH% + </code>, + } } - } - /> + /> + </p> <p> <a className="button" @@ -37,12 +44,19 @@ exports[`renders correctly 2`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.build_wrapper.text.linux", + > + <FormattedMessage + defaultMessage="onboarding.analysis.build_wrapper.text" + id="onboarding.analysis.build_wrapper.text" + values={ + Object { + "env_var": <code> + PATH + </code>, + } } - } - /> + /> + </p> <p> <a className="button" @@ -65,12 +79,19 @@ exports[`renders correctly 3`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.build_wrapper.text.mac", + > + <FormattedMessage + defaultMessage="onboarding.analysis.build_wrapper.text" + id="onboarding.analysis.build_wrapper.text" + values={ + Object { + "env_var": <code> + PATH + </code>, + } } - } - /> + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap index 7a765aa9112..be959ee6158 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap @@ -38,12 +38,23 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -85,12 +96,23 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -133,11 +155,22 @@ exports[`renders correctly 3`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/DotNet-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/DotNet-test.tsx.snap index b296291fc1c..f455da670c8 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/DotNet-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/DotNet-test.tsx.snap @@ -39,12 +39,23 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.msbuild.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.msbuild.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -88,11 +99,22 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.msbuild.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.msbuild.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap index 55ca37b75f9..7e1208e8dce 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaGradle-test.tsx.snap @@ -35,20 +35,28 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.gradle.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/gradle.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.gradle.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.browse_url_after_analysis", - } - } - /> + > + onboarding.analysis.browse_url_after_analysis + </p> </div> `; @@ -87,20 +95,28 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.gradle.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/gradle.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.gradle.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.browse_url_after_analysis", - } - } - /> + > + onboarding.analysis.browse_url_after_analysis + </p> </div> `; @@ -139,19 +155,27 @@ exports[`renders with projectKey 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.gradle.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/gradle.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.gradle.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.auto_refresh_after_analysis", - } - } - /> + > + onboarding.analysis.auto_refresh_after_analysis + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap index af3ff510ca6..7ee4d3becba 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/JavaMaven-test.tsx.snap @@ -27,20 +27,28 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.maven.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.maven.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.browse_url_after_analysis", - } - } - /> + > + onboarding.analysis.browse_url_after_analysis + </p> </div> `; @@ -71,20 +79,28 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.maven.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.maven.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.browse_url_after_analysis", - } - } - /> + > + onboarding.analysis.browse_url_after_analysis + </p> </div> `; @@ -115,19 +131,27 @@ exports[`renders with projectKey 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.java.maven.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.java.maven.docs_link + </a>, + } } - } - /> + /> + </p> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.auto_refresh_after_analysis", - } - } - /> + > + onboarding.analysis.auto_refresh_after_analysis + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap index 740e26ed12b..094b637da72 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/MSBuildScanner-test.tsx.snap @@ -9,12 +9,19 @@ exports[`renders correctly 1`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.msbuild.text", + > + <FormattedMessage + defaultMessage="onboarding.analysis.msbuild.text" + id="onboarding.analysis.msbuild.text" + values={ + Object { + "code": <code> + %PATH% + </code>, + } } - } - /> + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Msvc-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Msvc-test.tsx.snap index 875ae78edc4..3181496e14b 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Msvc-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Msvc-test.tsx.snap @@ -43,12 +43,23 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.msbuild.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.msbuild.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -97,11 +108,22 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.msbuild.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.docs" + id="onboarding.analysis.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.msbuild.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Other-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Other-test.tsx.snap index 8fe780fe094..bcd28ca14b2 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Other-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/Other-test.tsx.snap @@ -30,12 +30,23 @@ exports[`renders correctly 1`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -69,12 +80,23 @@ exports[`renders correctly 2`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; @@ -108,11 +130,22 @@ exports[`renders correctly 3`] = ` /> <p className="big-spacer-top markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.docs", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.docs" + id="onboarding.analysis.sq_scanner.docs" + values={ + Object { + "link": <a + href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" + rel="noopener noreferrer" + target="_blank" + > + onboarding.analysis.sq_scanner.docs_link + </a>, + } } - } - /> + /> + </p> </div> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap index cf6a8de4ce3..6ad4425a0a8 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/tutorials/components/commands/__tests__/__snapshots__/SQScanner-test.tsx.snap @@ -9,12 +9,22 @@ exports[`renders correctly 1`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.text.win", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.text" + id="onboarding.analysis.sq_scanner.text" + values={ + Object { + "dir": <code> + bin + </code>, + "env_var": <code> + %PATH% + </code>, + } } - } - /> + /> + </p> <p> <a className="button" @@ -37,12 +47,22 @@ exports[`renders correctly 2`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.text.linux", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.text" + id="onboarding.analysis.sq_scanner.text" + values={ + Object { + "dir": <code> + bin + </code>, + "env_var": <code> + PATH + </code>, + } } - } - /> + /> + </p> <p> <a className="button" @@ -65,12 +85,22 @@ exports[`renders correctly 3`] = ` </h4> <p className="spacer-bottom markdown" - dangerouslySetInnerHTML={ - Object { - "__html": "onboarding.analysis.sq_scanner.text.mac", + > + <FormattedMessage + defaultMessage="onboarding.analysis.sq_scanner.text" + id="onboarding.analysis.sq_scanner.text" + values={ + Object { + "dir": <code> + bin + </code>, + "env_var": <code> + PATH + </code>, + } } - } - /> + /> + </p> <p> <a className="button" diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx index 304f28eb2f7..bd6c63de706 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx +++ b/server/sonar-web/src/main/js/apps/web-api/components/Action.tsx @@ -171,6 +171,7 @@ export default class Action extends React.PureComponent<Props, State> { <div className="boxed-group-inner"> <div className="web-api-action-description markdown" + // Safe: comes from the backend dangerouslySetInnerHTML={{ __html: action.description }} /> diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx index 6df2b62096f..d7e4ab6ee4d 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx +++ b/server/sonar-web/src/main/js/apps/web-api/components/Domain.tsx @@ -52,6 +52,7 @@ export default function Domain({ domain, query }: Props) { {domain.description && ( <div className="web-api-domain-description markdown" + // Safe: comes from the backend dangerouslySetInnerHTML={{ __html: domain.description }} /> )} diff --git a/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx b/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx index 5cf2d7c0a90..7dbf8b77860 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx +++ b/server/sonar-web/src/main/js/apps/web-api/components/Params.tsx @@ -99,6 +99,7 @@ export default class Params extends React.PureComponent<Props> { <td> <div className="markdown" + // Safe: comes from the backend dangerouslySetInnerHTML={{ __html: param.description }} /> </td> diff --git a/server/sonar-web/src/main/js/components/charts/TreeMapRect.tsx b/server/sonar-web/src/main/js/components/charts/TreeMapRect.tsx index 5d82b9c919a..bf21da958f5 100644 --- a/server/sonar-web/src/main/js/components/charts/TreeMapRect.tsx +++ b/server/sonar-web/src/main/js/components/charts/TreeMapRect.tsx @@ -84,10 +84,6 @@ export default class TreeMapRect extends React.PureComponent<Props> { const isTextVisible = this.props.width >= 40 && this.props.height >= 45; const isIconVisible = this.props.width >= 24 && this.props.height >= 26; - const label = this.props.prefix - ? `${this.props.prefix}<br>${this.props.label.substr(this.props.prefix.length)}` - : this.props.label; - return ( <div className="treemap-cell" @@ -101,9 +97,16 @@ export default class TreeMapRect extends React.PureComponent<Props> { {this.props.icon} </span> )} - {isTextVisible && ( - <span className="treemap-text" dangerouslySetInnerHTML={{ __html: label }} /> - )} + {isTextVisible && + (this.props.prefix ? ( + <span className="treemap-text"> + {this.props.prefix} + <br /> + {this.props.label.substr(this.props.prefix.length)} + </span> + ) : ( + <span className="treemap-text">{this.props.label}</span> + ))} </div> {this.renderLink()} </div> diff --git a/server/sonar-web/src/main/js/components/charts/__tests__/TreeMap-test.tsx b/server/sonar-web/src/main/js/components/charts/__tests__/TreeMap-test.tsx index e6ae0718d07..0f5959e5fe2 100644 --- a/server/sonar-web/src/main/js/components/charts/__tests__/TreeMap-test.tsx +++ b/server/sonar-web/src/main/js/components/charts/__tests__/TreeMap-test.tsx @@ -18,17 +18,28 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; import TreeMap from '../TreeMap'; +import TreeMapRect from '../TreeMapRect'; +import { mockEvent } from '../../../helpers/testMocks'; -it('should display', () => { +it('should render correctly', () => { const items = [ { key: '1', size: 10, color: '#777', label: 'SonarQube :: Server' }, { key: '2', size: 30, color: '#777', label: 'SonarQube :: Web' }, { key: '3', size: 20, color: '#777', label: 'SonarQube :: Search' } ]; - const chart = shallow( - <TreeMap height={100} items={items} onRectangleClick={() => {}} width={100} /> + const onRectClick = jest.fn(); + const chart = mount( + <TreeMap height={100} items={items} onRectangleClick={onRectClick} width={100} /> ); - expect(chart.find('TreeMapRect')).toHaveLength(3); + const rects = chart.find(TreeMapRect); + expect(rects).toHaveLength(3); + + const event: React.MouseEvent<HTMLAnchorElement> = mockEvent({ stopPropagation: jest.fn() }); + (rects.first().instance() as TreeMapRect).handleLinkClick(event); + expect(event.stopPropagation).toHaveBeenCalled(); + + (rects.first().instance() as TreeMapRect).handleRectClick(); + expect(onRectClick).toHaveBeenCalledWith('2'); }); diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.tsx index 66de3381072..09de825c56a 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.tsx +++ b/server/sonar-web/src/main/js/components/issue/components/IssueCommentLine.tsx @@ -89,6 +89,7 @@ export default class IssueCommentLine extends React.PureComponent<Props, State> </div> <div className="issue-comment-text markdown" + // Safe: Comes from the backend, after markdown transformation to html dangerouslySetInnerHTML={{ __html: comment.htmlText }} /> <div className="issue-comment-age"> diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts index 66c6a639e6f..9fd2c05f8f9 100644 --- a/server/sonar-web/src/main/js/helpers/testMocks.ts +++ b/server/sonar-web/src/main/js/helpers/testMocks.ts @@ -619,6 +619,18 @@ export function mockRuleDetails(overrides: Partial<T.RuleDetails> = {}): T.RuleD }; } +export function mockRuleDetailsParameter( + overrides: Partial<T.RuleParameter> = {} +): T.RuleParameter { + return { + defaultValue: '1', + htmlDesc: 'description', + key: '1', + type: 'number', + ...overrides + }; +} + export function mockShortLivingBranch( overrides: Partial<T.ShortLivingBranch> = {} ): T.ShortLivingBranch { diff --git a/server/sonar-web/yarn.lock b/server/sonar-web/yarn.lock index f3cd22159f4..41f5e5e3342 100644 --- a/server/sonar-web/yarn.lock +++ b/server/sonar-web/yarn.lock @@ -967,6 +967,23 @@ "@types/d3-interpolate" "*" "@types/d3-selection" "*" +"@types/domhandler@*": + version "2.4.1" + resolved "https://repox.jfrog.io/repox/api/npm/npm/@types/domhandler/-/domhandler-2.4.1.tgz#7b3b347f7762180fbcb1ece1ce3dd0ebbb8c64cf" + integrity sha1-ezs0f3diGA+8sezhzj3Q67uMZM8= + +"@types/dompurify@^0.0.32": + version "0.0.32" + resolved "https://repox.jfrog.io/repox/api/npm/npm/@types/dompurify/-/dompurify-0.0.32.tgz#ccc4148d7f2e0598006611e82e840806fab4b268" + integrity sha1-zMQUjX8uBZgAZhHoLoQIBvq0smg= + +"@types/domutils@*": + version "1.7.2" + resolved "https://repox.jfrog.io/repox/api/npm/npm/@types/domutils/-/domutils-1.7.2.tgz#89422e579c165994ad5c09ce90325da596cc105d" + integrity sha1-iUIuV5wWWZStXAnOkDJdpZbMEF0= + dependencies: + "@types/domhandler" "*" + "@types/enzyme@3.9.1": version "3.9.1" resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.9.1.tgz#3a0ce07e30066dbc26cd3474c8e680af2d249e26" @@ -994,6 +1011,15 @@ resolved "https://registry.yarnpkg.com/@types/history/-/history-3.2.3.tgz#2416fee5cac641da2d05a905de5af5cb50162f60" integrity sha512-s4SNWd31cmFP52ilv3LKCh344ayIXmfmcfExsegGspgnk/pQh75Yo6v49uzSE1oFMXp+Sz4GVnesL7rgybX9tQ== +"@types/htmlparser2@*": + version "3.10.0" + resolved "https://repox.jfrog.io/repox/api/npm/npm/@types/htmlparser2/-/htmlparser2-3.10.0.tgz#b94d3b08f813c9eec12990ac6a34d8b17a7aebc9" + integrity sha1-uU07CPgTye7BKZCsajTYsXp668k= + dependencies: + "@types/domhandler" "*" + "@types/domutils" "*" + "@types/node" "*" + "@types/istanbul-lib-coverage@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" @@ -1106,6 +1132,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/sanitize-html@1.20.0": + version "1.20.0" + resolved "https://repox.jfrog.io/repox/api/npm/npm/@types/sanitize-html/-/sanitize-html-1.20.0.tgz#b3beaa9eacab0e0fa5022d5faa727fea8fb9fc5d" + integrity sha1-s76qnqyrDg+lAi1fqnJ/6o+5/F0= + dependencies: + "@types/htmlparser2" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -3408,6 +3441,11 @@ domhandler@^2.3.0: dependencies: domelementtype "1" +dompurify@^1.0.11: + version "1.0.11" + resolved "https://repox.jfrog.io/repox/api/npm/npm/dompurify/-/dompurify-1.0.11.tgz#fe0f4a40d147f7cebbe31a50a1357539cfc1eb4d" + integrity sha1-/g9KQNFH98674xpQoTV1Oc/B600= + domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" |