From dc1c42dca42ec2d5d6e4cedd0fdfcc26b58946e2 Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Fri, 25 Aug 2023 15:58:00 +0200 Subject: [PATCH] SONAR-20221 Fix issue message code highlighting --- .../components/IssueMessageHighlighting.tsx | 10 +- .../IssueMessageHighlighting-test.tsx.snap | 34 +++++- .../SubnavigationIssue.tsx | 13 ++- .../components/HotspotHeader.tsx | 2 +- .../components/HotspotPrimaryLocationBox.tsx | 3 +- .../issue/IssueMessageHighlighting.tsx | 102 ------------------ .../IssueMessageHighlighting-test.tsx | 74 ------------- .../IssueMessageHighlighting-test.tsx.snap | 100 ----------------- .../issue/components/IssueMessage.tsx | 3 +- .../locations/SingleFileLocationNavigator.tsx | 3 +- 10 files changed, 52 insertions(+), 292 deletions(-) delete mode 100644 server/sonar-web/src/main/js/components/issue/IssueMessageHighlighting.tsx delete mode 100644 server/sonar-web/src/main/js/components/issue/__tests__/IssueMessageHighlighting-test.tsx delete mode 100644 server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap diff --git a/server/sonar-web/design-system/src/components/IssueMessageHighlighting.tsx b/server/sonar-web/design-system/src/components/IssueMessageHighlighting.tsx index f16621bd419..2c937705160 100644 --- a/server/sonar-web/design-system/src/components/IssueMessageHighlighting.tsx +++ b/server/sonar-web/design-system/src/components/IssueMessageHighlighting.tsx @@ -19,6 +19,7 @@ */ import styled from '@emotion/styled'; import * as React from 'react'; +import tw from 'twin.macro'; import { themeColor } from '../helpers'; export interface MessageFormatting { @@ -39,7 +40,7 @@ export interface IssueMessageHighlightingProps { export function IssueMessageHighlighting(props: IssueMessageHighlightingProps) { const { message, messageFormattings } = props; - if (!message) { + if (message === undefined || message === '') { return null; } @@ -96,7 +97,7 @@ export function IssueMessageHighlighting(props: IssueMessageHighlightingProps) { {message.slice(beginning, start)} {type === MessageFormattingType.CODE ? ( - + {message.slice(start, end)} ) : ( @@ -115,4 +116,9 @@ const SingleLineSnippet = styled.span` background: ${themeColor('codeSnippetBackground')}; border-color: ${themeColor('codeSnippetBorder')}; color: ${themeColor('codeSnippetInline')}; + ${tw`sw-py-1/2`} + + a & { + ${tw`sw-pb-0`} + } `; diff --git a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap index 008c32eca0a..932cc06d0f8 100644 --- a/server/sonar-web/design-system/src/components/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap +++ b/server/sonar-web/design-system/src/components/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap @@ -28,18 +28,24 @@ exports[`should format the string with highlights 5`] = ` background: rgb(252,252,253); border-color: rgb(225,230,243); color: rgb(62,67,87); + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +a .emotion-0 { + padding-bottom: 0; } m ess a g @@ -62,12 +68,18 @@ exports[`should format the string with highlights 7`] = ` background: rgb(252,252,253); border-color: rgb(225,230,243); color: rgb(62,67,87); + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +a .emotion-0 { + padding-bottom: 0; } a somewhat longer message with overlapping range s @@ -89,12 +101,18 @@ exports[`should format the string with highlights 9`] = ` background: rgb(252,252,253); border-color: rgb(225,230,243); color: rgb(62,67,87); + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +a .emotion-0 { + padding-bottom: 0; } a somewhat longer message @@ -109,12 +127,18 @@ exports[`should format the string with highlights 10`] = ` background: rgb(252,252,253); border-color: rgb(225,230,243); color: rgb(62,67,87); + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + +a .emotion-0 { + padding-bottom: 0; } a somewhat longer message with diff --git a/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssue.tsx b/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssue.tsx index 5ae7f0a9bf9..5587252136f 100644 --- a/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssue.tsx +++ b/server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssue.tsx @@ -18,7 +18,13 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; -import { BareButton, SubnavigationItem, themeColor, themeContrast } from 'design-system'; +import { + BareButton, + IssueMessageHighlighting, + SubnavigationItem, + themeColor, + themeContrast, +} from 'design-system'; import { noop } from 'lodash'; import * as React from 'react'; import { Issue } from '../../../types/types'; @@ -60,7 +66,10 @@ export default function SubnavigationIssue(props: ConciseIssueProps) { >
- {issue.message} + diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotHeader.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotHeader.tsx index ba7c40d5266..3752781483a 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotHeader.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotHeader.tsx @@ -21,6 +21,7 @@ import { withTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { ClipboardIconButton, + IssueMessageHighlighting, LAYOUT_GLOBAL_NAV_HEIGHT, LAYOUT_PROJECT_NAV_HEIGHT, LightLabel, @@ -33,7 +34,6 @@ import { themeShadow, } from 'design-system'; import React from 'react'; -import { IssueMessageHighlighting } from '../../../components/issue/IssueMessageHighlighting'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; import { diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotPrimaryLocationBox.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotPrimaryLocationBox.tsx index 2103715dbf9..9b4aa315029 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotPrimaryLocationBox.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotPrimaryLocationBox.tsx @@ -17,9 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { LineFinding } from 'design-system'; +import { IssueMessageHighlighting, LineFinding } from 'design-system'; import * as React from 'react'; -import { IssueMessageHighlighting } from '../../../components/issue/IssueMessageHighlighting'; import { Hotspot } from '../../../types/security-hotspots'; const SCROLL_DELAY = 100; diff --git a/server/sonar-web/src/main/js/components/issue/IssueMessageHighlighting.tsx b/server/sonar-web/src/main/js/components/issue/IssueMessageHighlighting.tsx deleted file mode 100644 index 6111f4a9e3e..00000000000 --- a/server/sonar-web/src/main/js/components/issue/IssueMessageHighlighting.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 classNames from 'classnames'; -import * as React from 'react'; -import { MessageFormatting, MessageFormattingType } from '../../types/issues'; - -export interface IssueMessageHighlightingProps { - message?: string; - messageFormattings?: MessageFormatting[]; -} - -export function IssueMessageHighlighting(props: IssueMessageHighlightingProps) { - const { message, messageFormattings } = props; - - if (!message) { - return null; - } - - if (!(messageFormattings && messageFormattings.length > 0)) { - return <>{message}; - } - - let previousEnd = 0; - - const sanitizedFormattings = [...messageFormattings] - .sort((a, b) => a.start - b.start) - .reduce((acc, messageFormatting) => { - const { type } = messageFormatting; - - if (type !== MessageFormattingType.CODE) { - return acc; - } - - const { start } = messageFormatting; - let { end } = messageFormatting; - - end = Math.min(message.length, end); - - if (start < 0 || end === start || end < start) { - return acc; - } - - if (acc.length > 0) { - const { start: previousStart, end: previousEnd } = acc[acc.length - 1]; - - if (start <= previousEnd) { - acc[acc.length - 1] = { - start: previousStart, - end: Math.max(previousEnd, end), - type, - }; - - return acc; - } - } - - acc.push({ start, end, type }); - - return acc; - }, [] as typeof messageFormattings); - - return ( - - {sanitizedFormattings.map(({ start, end, type }) => { - const beginning = previousEnd; - previousEnd = end; - - return ( - - {message.slice(beginning, start)} - - {message.slice(start, end)} - - - ); - })} - - {message.slice(previousEnd)} - - ); -} diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/IssueMessageHighlighting-test.tsx b/server/sonar-web/src/main/js/components/issue/__tests__/IssueMessageHighlighting-test.tsx deleted file mode 100644 index 349c1e36000..00000000000 --- a/server/sonar-web/src/main/js/components/issue/__tests__/IssueMessageHighlighting-test.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 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 React from 'react'; -import { renderComponent } from '../../../helpers/testReactTestingUtils'; -import { MessageFormattingType } from '../../../types/issues'; -import { - IssueMessageHighlighting, - IssueMessageHighlightingProps, -} from '../IssueMessageHighlighting'; - -it.each([ - [undefined, undefined], - ['message', undefined], - ['message', []], - ['message', [{ start: 1, end: 4, type: 'something else' as MessageFormattingType }]], - [ - 'message', - [ - { start: 5, end: 6, type: MessageFormattingType.CODE }, - { start: 1, end: 4, type: MessageFormattingType.CODE }, - ], - ], - [ - 'a somewhat longer message with overlapping ranges', - [{ start: -1, end: 1, type: MessageFormattingType.CODE }], - ], - [ - 'a somewhat longer message with overlapping ranges', - [{ start: 48, end: 70, type: MessageFormattingType.CODE }], - ], - [ - 'a somewhat longer message with overlapping ranges', - [{ start: 0, end: 0, type: MessageFormattingType.CODE }], - ], - [ - 'a somewhat longer message with overlapping ranges', - [ - { start: 11, end: 17, type: MessageFormattingType.CODE }, - { start: 2, end: 25, type: MessageFormattingType.CODE }, - { start: 25, end: 2, type: MessageFormattingType.CODE }, - ], - ], - [ - 'a somewhat longer message with overlapping ranges', - [ - { start: 18, end: 30, type: MessageFormattingType.CODE }, - { start: 2, end: 25, type: MessageFormattingType.CODE }, - ], - ], -])('should format the string with highlights', (message, messageFormattings) => { - const { asFragment } = renderIssueMessageHighlighting({ message, messageFormattings }); - expect(asFragment()).toMatchSnapshot(); -}); - -function renderIssueMessageHighlighting(props: Partial = {}) { - return renderComponent(); -} diff --git a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap deleted file mode 100644 index 00802d08bc0..00000000000 --- a/server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap +++ /dev/null @@ -1,100 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should format the string with highlights 1`] = ``; - -exports[`should format the string with highlights 2`] = ` - - message - -`; - -exports[`should format the string with highlights 3`] = ` - - message - -`; - -exports[`should format the string with highlights 4`] = ` - - - message - - -`; - -exports[`should format the string with highlights 5`] = ` - - - m - - ess - - a - - g - - e - - -`; - -exports[`should format the string with highlights 6`] = ` - - - a somewhat longer message with overlapping ranges - - -`; - -exports[`should format the string with highlights 7`] = ` - - - a somewhat longer message with overlapping range - - s - - - -`; - -exports[`should format the string with highlights 8`] = ` - - - a somewhat longer message with overlapping ranges - - -`; - -exports[`should format the string with highlights 9`] = ` - - - a - - somewhat longer message - - with overlapping ranges - - -`; - -exports[`should format the string with highlights 10`] = ` - - - a - - somewhat longer message with - - overlapping ranges - - -`; diff --git a/server/sonar-web/src/main/js/components/issue/components/IssueMessage.tsx b/server/sonar-web/src/main/js/components/issue/components/IssueMessage.tsx index ba011b04b1f..a1bae5c76ef 100644 --- a/server/sonar-web/src/main/js/components/issue/components/IssueMessage.tsx +++ b/server/sonar-web/src/main/js/components/issue/components/IssueMessage.tsx @@ -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 { StandoutLink } from 'design-system'; +import { IssueMessageHighlighting, StandoutLink } from 'design-system'; import * as React from 'react'; import { ComponentContext } from '../../../app/components/componentContext/ComponentContext'; import { areMyIssuesSelected, parseQuery, serializeQuery } from '../../../apps/issues/utils'; @@ -27,7 +27,6 @@ import { getComponentIssuesUrl, getIssuesUrl } from '../../../helpers/urls'; import { BranchLike } from '../../../types/branch-like'; import { Issue } from '../../../types/types'; import { useLocation } from '../../hoc/withRouter'; -import { IssueMessageHighlighting } from '../IssueMessageHighlighting'; export interface IssueMessageProps { issue: Issue; diff --git a/server/sonar-web/src/main/js/components/locations/SingleFileLocationNavigator.tsx b/server/sonar-web/src/main/js/components/locations/SingleFileLocationNavigator.tsx index 45703b11791..a53f1f0d307 100644 --- a/server/sonar-web/src/main/js/components/locations/SingleFileLocationNavigator.tsx +++ b/server/sonar-web/src/main/js/components/locations/SingleFileLocationNavigator.tsx @@ -19,12 +19,11 @@ */ import styled from '@emotion/styled'; import classNames from 'classnames'; -import { LocationMarker, StyledMarker, themeColor } from 'design-system'; +import { IssueMessageHighlighting, LocationMarker, StyledMarker, themeColor } from 'design-system'; import * as React from 'react'; import { translateWithParameters } from '../../helpers/l10n'; import { MessageFormatting } from '../../types/issues'; import LocationMessage from '../common/LocationMessage'; -import { IssueMessageHighlighting } from '../issue/IssueMessageHighlighting'; import './SingleFileLocationNavigator.css'; interface Props { -- 2.39.5