diff --git a/package-lock.json b/package-lock.json index c6dfc54..4700878 100644 --- a/package-lock.json +++ b/package-lock.json @@ -314,7 +314,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "extend": { "version": "3.0.2", @@ -340,12 +340,12 @@ "format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==" + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=" }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -399,7 +399,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -432,7 +432,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "2.1.0", @@ -455,12 +455,12 @@ "is-empty": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", - "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==" + "integrity": "sha1-3pu1snhzigWgsJpX4ftNSjQan2s=" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-glob": { "version": "4.0.3", @@ -840,7 +840,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } @@ -1508,7 +1508,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "to-regex-range": { "version": "5.0.1", @@ -1548,7 +1548,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "unified": { "version": "10.1.0", @@ -1686,7 +1686,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "vfile": { "version": "5.0.2", @@ -1761,7 +1761,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { "version": "4.0.0", diff --git a/pom.xml b/pom.xml index ea52c13..d535e98 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,9 @@ 1.28.0-3 -SNAPSHOT - 2.319 + + 2.346 + 2.346.3 ${project.groupId}.prism @@ -51,6 +53,7 @@ io.jenkins.plugins font-awesome-api + 6.2.0-3 io.jenkins.plugins diff --git a/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java b/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java index 9b1053e..c9177d6 100644 --- a/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java +++ b/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java @@ -9,9 +9,11 @@ import edu.hm.hafner.util.VisibleForTesting; import j2html.tags.ContainerTag; +import j2html.tags.DomContent; import j2html.tags.UnescapedText; import io.jenkins.plugins.fontawesome.api.SvgTag; +import io.jenkins.plugins.fontawesome.api.SvgTag.FontAwesomeStyle; import io.jenkins.plugins.util.JenkinsFacade; import static j2html.TagCreator.*; @@ -29,6 +31,7 @@ class SourcePrinter { private static final ColumnMarker COLUMN_MARKER = new ColumnMarker("-n/a-"); private static final String LINE_NUMBERS = "line-numbers"; private static final String MATCH_BRACES = "match-braces"; + private static final String ICON_MD = "icon-md"; private final JenkinsFacade jenkinsFacade; @@ -91,19 +94,29 @@ private String createInfoPanel(final Marker marker) { private ContainerTag createBox(final Marker marker) { if (StringUtils.isEmpty(marker.getDescription())) { - return createTitle(marker.getTitle(), marker.getIcon(), false); + return createTitle(marker, false); } else { - return createTitleAndCollapsedDescription(marker.getTitle(), - marker.getDescription(), marker.getIcon()); + return createTitleAndCollapsedDescription(marker, marker.getDescription()); } } - private ContainerTag createTitle(final String message, final String iconUrl, final boolean isCollapseVisible) { + private DomContent createIcon(final String name) { + if (name.startsWith("symbol")) { + // TODO: replace with Jenkins symbol tag once https://github.com/jenkinsci/jenkins/pull/6659 is merged + return new UnescapedText( + new SvgTag("bookmark", jenkinsFacade, FontAwesomeStyle.REGULAR) + .withClasses(ICON_MD) + .render()); + } + return img().withSrc(jenkinsFacade.getImagePath(name)).withClasses(ICON_MD); + } + + private ContainerTag createTitle(final Marker marker, final boolean isCollapseVisible) { return div().with(table().withClass("analysis-title").with(tr().with( - td().with(img().withSrc(iconUrl)), + td().with(createIcon(marker.getIcon())), td().withClass("analysis-title-column") - .with(div().withClass("analysis-warning-title").with(replaceNewLine(message))), + .with(div().withClass("analysis-warning-title").with(replaceNewLine(marker.getTitle()))), createCollapseButton(isCollapseVisible) ))); } @@ -111,24 +124,22 @@ private ContainerTag createTitle(final String message, final String iconUrl, fin private ContainerTag createCollapseButton(final boolean isCollapseVisible) { ContainerTag td = td(); if (isCollapseVisible) { - td.with(new UnescapedText(new SvgTag("chevron-circle-down", jenkinsFacade) + td.with(new UnescapedText(new SvgTag("circle-chevron-down", jenkinsFacade) .withClasses("analysis-collapse-icon").render())); } return td; } - private ContainerTag createTitleAndCollapsedDescription(final String message, final String description, - final String iconUrl) { + private ContainerTag createTitleAndCollapsedDescription(final Marker marker, final String description) { return div().with( - div().withClass("analysis-collapse-button").with(createTitle(message, iconUrl, true)), + div().withClass("analysis-collapse-button").with(createTitle(marker, true)), div().withClasses("collapse", "analysis-detail") .with(unescape(description)) .withId("analysis-description")); } private UnescapedText replaceNewLine(final String message) { - String m = message.replace("\n", "
"); - return unescape(m); + return unescape(message.replace("\n", "
")); } private UnescapedText unescape(final String message) { @@ -208,7 +219,7 @@ private String asMarkedCode(final StringBuilder text, final Marker marker, final } String sanitized = SANITIZER.render(StringEscapeUtils.escapeHtml4(marked.toString())); - String markerReplaced = COLUMN_MARKER.replacePlaceHolderWithHtmlTag(sanitized); + String markerReplaced = COLUMN_MARKER.replacePlaceHolderWithHtmlTag(sanitized); return code().withClasses(classes).with(new UnescapedText(markerReplaced)).render(); } @@ -217,8 +228,8 @@ private String asCode(final StringBuilder text, final String... classes) { } /** - * Encloses columns between {@code start} and {@code end} with an HTML tag (see {@code openingTag} and {@code - * closingTag}). + * Encloses columns between {@code start} and {@code end} with an HTML tag (see {@code openingTag} and + * {@code closingTag}). */ static final class ColumnMarker { private static final String OPENING_TAG = ""; @@ -228,8 +239,9 @@ static final class ColumnMarker { * Creates a {@link ColumnMarker} that will use {@code placeHolderText} for enclosing. * * @param placeHolderText - * Used to construct an opening and closing text that can later be replaced with the HTML tag {@code - * openingTag} {@code closingTag}. It should be a text that is unlikely to appear in any source code. + * Used to construct an opening and closing text that can later be replaced with the HTML tag + * {@code openingTag} {@code closingTag}. It should be a text that is unlikely to appear in any source + * code. */ ColumnMarker(final String placeHolderText) { openingTagPlaceHolder = "OpEn" + placeHolderText; diff --git a/src/main/webapp/css/custom-prism.css b/src/main/webapp/css/custom-prism.css index 4cf0dec..13c0af7 100644 --- a/src/main/webapp/css/custom-prism.css +++ b/src/main/webapp/css/custom-prism.css @@ -71,11 +71,11 @@ pre > code.highlight { background-color: #FFF59D; } -.analysis-collapse-button svg { +.analysis-collapse-button .analysis-collapse-icon { transition: .3s transform ease-in-out; } -.analysis-collapse-button.open svg { +.analysis-collapse-button.open .analysis-collapse-icon { transform: rotate(180deg); } diff --git a/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java b/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java index de73ebc..83975a2 100644 --- a/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java +++ b/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java @@ -25,6 +25,7 @@ class SourcePrinterTest extends ResourceTest { private static final String MESSAGE = "Hello Message"; private static final String DESCRIPTION = "Hello Description"; private static final String FILE_NAME = "filename.txt"; + private static final String ICON = "/plugin/xyz/icon"; @Test void shouldCreateSourceWithoutLineNumber() { @@ -84,15 +85,17 @@ void shouldCreateSourceWithoutDescription() { @Test void shouldCreateIcon() { MarkerBuilder builder = new MarkerBuilder(); - Marker issue = builder.withLineStart(7).withTitle("Hello Message").withIcon("icon").build(); + Marker issue = builder.withLineStart(7).withTitle("Hello Message").withIcon(ICON).build(); - SourcePrinter printer = new SourcePrinter(); + JenkinsFacade jenkins = mock(JenkinsFacade.class); + when(jenkins.getImagePath(ICON)).thenReturn("/resolved"); + SourcePrinter printer = new SourcePrinter(jenkins); Document document = Jsoup.parse(printer.render(FILE_NAME, asStream("format-java.txt"), issue)); assertThatCodeIsEqualToSourceText(document); - assertThat(document.getElementsByClass("analysis-title").html()).contains(""); + assertThat(document.getElementsByClass("analysis-title").html()).contains(""); } @Test