diff --git a/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java b/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java index 96f4682..5549e8c 100644 --- a/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java +++ b/src/main/java/io/jenkins/plugins/prism/SourcePrinter.java @@ -5,6 +5,7 @@ import org.jenkins.ui.symbol.Symbol; import org.jenkins.ui.symbol.SymbolRequest; import org.jenkins.ui.symbol.SymbolRequest.Builder; +import org.apache.commons.lang3.Strings; import edu.hm.hafner.util.LookaheadStream; import edu.hm.hafner.util.VisibleForTesting; @@ -29,6 +30,7 @@ class SourcePrinter { private static final Sanitizer SANITIZER = new Sanitizer(); private static final ColumnMarker COLUMN_MARKER = new ColumnMarker("-n/a-"); + private static final String QT_LINGUIST_PATTERN = ""; private static final String LINE_NUMBERS = "line-numbers"; private static final String MATCH_BRACES = "match-braces"; private static final String ICON_MD = "icon-md"; @@ -69,7 +71,7 @@ String render(final String fileName, final Stream lines, final Marker ma StringBuilder marked = readBlockUntilLine(stream, end); StringBuilder after = readBlockUntilLine(stream, Integer.MAX_VALUE); - String language = selectLanguageClass(fileName); + String language = selectLanguageClass(fileName, before); String code = asCode(before, language, LINE_NUMBERS, MATCH_BRACES) + asMarkedCode(marked, marker, language, LINE_NUMBERS, "highlight", MATCH_BRACES) + createInfoPanel(marker) @@ -150,8 +152,14 @@ private UnescapedText unescape(final String message) { } @SuppressWarnings({"javancss", "PMD.CyclomaticComplexity"}) - private String selectLanguageClass(final String fileName) { - return switch (StringUtils.substringAfterLast(fileName, ".")) { + private String selectLanguageClass(final String fileName, final StringBuilder before) { + String extension = StringUtils.substringAfterLast(fileName, "."); + + if ("ts".equals(extension) && Strings.CS.contains(before, QT_LINGUIST_PATTERN)) { + return "language-markup"; + } + + return switch (extension) { case "htm", "html", "xml", "xsd" -> "language-markup"; case "css" -> "language-css"; case "js" -> "language-javascript"; diff --git a/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java b/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java index 975e4ae..d491464 100644 --- a/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java +++ b/src/test/java/io/jenkins/plugins/prism/SourcePrinterTest.java @@ -11,6 +11,8 @@ import io.jenkins.plugins.prism.Marker.MarkerBuilder; import io.jenkins.plugins.util.JenkinsFacade; +import java.util.stream.Stream; + import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -221,6 +223,49 @@ void shouldRenderXmlFiles() { assertThat(pre.text()).isEqualToIgnoringWhitespace(expectedFile); } + @Test + @org.junitpioneer.jupiter.Issue("JENKINS-64584") + void shouldRenderTypeScriptFileAsTypeScript() { + Marker issue = new MarkerBuilder().build(); + SourcePrinter printer = new SourcePrinter(); + + Document document = Jsoup.parse(printer.render("sample.ts", Stream.of("const answer: number = 42;"), issue)); + + assertThat(document.getElementsByTag("code").first()) + .isNotNull(); + assertThat(document.getElementsByTag("code").first().classNames()) + .contains("language-typescript"); + } + + @Test + @org.junitpioneer.jupiter.Issue("JENKINS-64584") + void shouldRenderQtTranslationFileAsMarkup() { + Marker issue = new MarkerBuilder().withLineStart(7).build(); + SourcePrinter printer = new SourcePrinter(); + + Document document = Jsoup.parse(printer.render("sample.ts", Stream.of( + "", + "", + "", + " ", + " MainWindow", + " ", + " Hello, world!", + " Hello, world!", + " ", + " ", + " File not found", + " File not found", + " ", + " ", + ""), issue)); + + assertThat(document.getElementsByTag("code").first()) + .isNotNull(); + assertThat(document.getElementsByTag("code").first().classNames()) + .contains("language-markup"); + } + private JenkinsFacade createJenkinsFacade() { JenkinsFacade jenkinsFacade = mock(JenkinsFacade.class); when(jenkinsFacade.getImagePath(anyString())).thenReturn("/path/to/icon");