]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20221 Fix issue message code highlighting
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Fri, 25 Aug 2023 13:58:00 +0000 (15:58 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 28 Aug 2023 20:03:20 +0000 (20:03 +0000)
server/sonar-web/design-system/src/components/IssueMessageHighlighting.tsx
server/sonar-web/design-system/src/components/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap
server/sonar-web/src/main/js/apps/issues/issues-subnavigation/SubnavigationIssue.tsx
server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotHeader.tsx
server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotPrimaryLocationBox.tsx
server/sonar-web/src/main/js/components/issue/IssueMessageHighlighting.tsx [deleted file]
server/sonar-web/src/main/js/components/issue/__tests__/IssueMessageHighlighting-test.tsx [deleted file]
server/sonar-web/src/main/js/components/issue/__tests__/__snapshots__/IssueMessageHighlighting-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/issue/components/IssueMessage.tsx
server/sonar-web/src/main/js/components/locations/SingleFileLocationNavigator.tsx

index f16621bd419359f129083eb04f5ed2eccc018525..2c93770516047f1a72f82ce118f5a44328724b3d 100644 (file)
@@ -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) {
           <React.Fragment key={`${message}-${start}-${end}`}>
             {message.slice(beginning, start)}
             {type === MessageFormattingType.CODE ? (
-              <SingleLineSnippet className="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid">
+              <SingleLineSnippet className="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid">
                 {message.slice(start, end)}
               </SingleLineSnippet>
             ) : (
@@ -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`}
+  }
 `;
index 008c32eca0aa4d8eba4d21a666ce12eb169995b1..932cc06d0f83899f1a79b74f3184bddac8cc5ca8 100644 (file)
@@ -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;
 }
 
 <span>
     m
     <span
-      class="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
+      class="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
     >
       ess
     </span>
     a
     <span
-      class="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
+      class="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
     >
       g
     </span>
@@ -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;
 }
 
 <span>
     a somewhat longer message with overlapping range
     <span
-      class="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
+      class="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
     >
       s
     </span>
@@ -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;
 }
 
 <span>
     a 
     <span
-      class="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
+      class="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
     >
       somewhat longer message
     </span>
@@ -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;
 }
 
 <span>
     a 
     <span
-      class="sw-code sw-rounded-1 sw-py-1/2 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
+      class="sw-code sw-rounded-1 sw-px-1 sw-border sw-border-solid emotion-0 emotion-1"
     >
       somewhat longer message with
     </span>
index 5ae7f0a9bf95f2da10fb56499cda690fa9a3eda3..5587252136ff842a23946dd76f5828495143e55a 100644 (file)
  * 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) {
       >
         <div className="sw-w-full">
           <StyledIssueTitle aria-current={selected} className="sw-mb-2">
-            {issue.message}
+            <IssueMessageHighlighting
+              message={issue.message}
+              messageFormattings={issue.messageFormattings}
+            />
           </StyledIssueTitle>
           <IssueInfo className="sw-flex sw-justify-between sw-gap-2">
             <IssueItemLocationsQuantity issue={issue} />
index ba7c40d5266cbc5edf79647bb69326c1d0ca2f79..3752781483a1c5f6a97c3632e07c47cf429973d9 100644 (file)
@@ -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 {
index 2103715dbf931350779abfeecedddf1d84ffc037..9b4aa315029e6c77c9210f319c735181f66b40fb 100644 (file)
@@ -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 (file)
index 6111f4a..0000000
+++ /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 (
-    <span>
-      {sanitizedFormattings.map(({ start, end, type }) => {
-        const beginning = previousEnd;
-        previousEnd = end;
-
-        return (
-          <React.Fragment key={`${message}-${start}-${end}`}>
-            {message.slice(beginning, start)}
-            <span
-              className={classNames({
-                'issue-message-highlight-CODE': type === MessageFormattingType.CODE,
-              })}
-            >
-              {message.slice(start, end)}
-            </span>
-          </React.Fragment>
-        );
-      })}
-
-      {message.slice(previousEnd)}
-    </span>
-  );
-}
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 (file)
index 349c1e3..0000000
+++ /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<IssueMessageHighlightingProps> = {}) {
-  return renderComponent(<IssueMessageHighlighting {...props} />);
-}
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 (file)
index 00802d0..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should format the string with highlights 1`] = `<DocumentFragment />`;
-
-exports[`should format the string with highlights 2`] = `
-<DocumentFragment>
-  message
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 3`] = `
-<DocumentFragment>
-  message
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 4`] = `
-<DocumentFragment>
-  <span>
-    message
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 5`] = `
-<DocumentFragment>
-  <span>
-    m
-    <span
-      class="issue-message-highlight-CODE"
-    >
-      ess
-    </span>
-    a
-    <span
-      class="issue-message-highlight-CODE"
-    >
-      g
-    </span>
-    e
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 6`] = `
-<DocumentFragment>
-  <span>
-    a somewhat longer message with overlapping ranges
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 7`] = `
-<DocumentFragment>
-  <span>
-    a somewhat longer message with overlapping range
-    <span
-      class="issue-message-highlight-CODE"
-    >
-      s
-    </span>
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 8`] = `
-<DocumentFragment>
-  <span>
-    a somewhat longer message with overlapping ranges
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 9`] = `
-<DocumentFragment>
-  <span>
-    a 
-    <span
-      class="issue-message-highlight-CODE"
-    >
-      somewhat longer message
-    </span>
-     with overlapping ranges
-  </span>
-</DocumentFragment>
-`;
-
-exports[`should format the string with highlights 10`] = `
-<DocumentFragment>
-  <span>
-    a 
-    <span
-      class="issue-message-highlight-CODE"
-    >
-      somewhat longer message with
-    </span>
-     overlapping ranges
-  </span>
-</DocumentFragment>
-`;
index ba011b04b1f6d3ce7826fa552573ca7fc6cd9833..a1bae5c76ef5f6b96858dae8724e224f4a8b79e0 100644 (file)
@@ -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;
index 45703b11791eff92dec960c5cb2c4004e7fa1f92..a53f1f0d307b5325d580ea574523200e70468ec4 100644 (file)
  */
 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 {