From aa6c06e1665cd44ae880824aedb3c861f0951cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Thu, 26 Feb 2026 18:50:45 +0000 Subject: [PATCH] 8309748: Improve host selection in `External Specifications` page Reviewed-by: nbenalla --- .../share/classes/java/lang/Character.java | 14 ++--- .../formats/html/ExternalSpecsWriter.java | 62 +++++++++++++++++-- .../html/resources/standard.properties | 5 +- .../formats/html/resources/stylesheet.css | 4 +- .../doclet/testSpecTag/TestSpecTag.java | 43 +++++++++---- 5 files changed, 98 insertions(+), 30 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index ffda729a45a..33284d86e2d 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -11233,7 +11233,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character is an Emoji; * {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isEmoji(int codePoint) { @@ -11252,7 +11252,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character has the Emoji Presentation * property; {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isEmojiPresentation(int codePoint) { @@ -11271,7 +11271,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character is an Emoji Modifier; * {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isEmojiModifier(int codePoint) { @@ -11290,7 +11290,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character is an Emoji Modifier Base; * {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isEmojiModifierBase(int codePoint) { @@ -11309,7 +11309,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character is an Emoji Component; * {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isEmojiComponent(int codePoint) { @@ -11328,7 +11328,7 @@ class Character implements java.io.Serializable, Comparable, Constabl * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character is an Extended Pictographic; * {@code false} otherwise. - * @spec https://unicode.org/reports/tr51/ Unicode Emoji + * @spec https://www.unicode.org/reports/tr51/ Unicode Emoji * @since 21 */ public static boolean isExtendedPictographic(int codePoint) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ExternalSpecsWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ExternalSpecsWriter.java index 0115de5558f..b8767dd9913 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ExternalSpecsWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ExternalSpecsWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,11 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; import jdk.javadoc.internal.doclets.toolkit.util.IndexItem; import jdk.javadoc.internal.html.Content; import jdk.javadoc.internal.html.ContentBuilder; +import jdk.javadoc.internal.html.HtmlAttr; +import jdk.javadoc.internal.html.HtmlId; +import jdk.javadoc.internal.html.HtmlTag; import jdk.javadoc.internal.html.HtmlTree; +import jdk.javadoc.internal.html.Script; import jdk.javadoc.internal.html.Text; import static java.util.stream.Collectors.groupingBy; @@ -108,6 +112,24 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, contents.getContent("doclet.External_Specifications")))) .addMainContent(mainContent) + .addMainContent(new Script(""" + let select = document.getElementById('specs-by-domain'); + select.addEventListener("change", selectHost); + addEventListener("pageshow", selectHost); + function selectHost() { + const selectedClass = select.value ? "external-specs-tab" + select.value : "external-specs"; + let tabPanel = document.getElementById("external-specs.tabpanel"); + let count = 0; + tabPanel.querySelectorAll("div.external-specs").forEach(function(elem) { + elem.style.display = elem.classList.contains(selectedClass) ? "" : "none"; + if (elem.style.display === "") { + let isEvenRow = count++ % 4 < 2; + toggleStyle(elem.classList, isEvenRow, evenRowColor, oddRowColor); + } + }); + } + selectHost(); + """).asContent()) .setFooter(getFooter())); printHtmlDocument(null, "external specifications", body); @@ -180,7 +202,7 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { boolean noHost = false; for (var searchIndexItems : searchIndexMap.values()) { try { - URI uri = getSpecURI(searchIndexItems.get(0)); + URI uri = getSpecURI(searchIndexItems.getFirst()); String host = uri.getHost(); if (host != null) { hostNamesSet.add(host); @@ -191,14 +213,19 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { // ignore } } - var hostNamesList = new ArrayList<>(hostNamesSet); var table = new Table(HtmlStyles.summaryTable) .setCaption(contents.externalSpecifications) .setHeader(new TableHeader(contents.specificationLabel, contents.referencedIn)) .setColumnStyles(HtmlStyles.colFirst, HtmlStyles.colLast) - .setId(HtmlIds.EXTERNAL_SPECS); + .setId(HtmlIds.EXTERNAL_SPECS) + .setDefaultTab(contents.externalSpecifications) + .setRenderTabs(false); + + var hostNamesList = new ArrayList<>(hostNamesSet); + Content selector = Text.EMPTY; if ((hostNamesList.size() + (noHost ? 1 : 0)) > 1) { + selector = createHostSelect(hostNamesList, noHost); for (var host : hostNamesList) { table.addTab(Text.of(host), u -> host.equals(u.getHost())); } @@ -207,10 +234,9 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { u -> u.getHost() == null); } } - table.setDefaultTab(Text.of(resources.getText("doclet.External_Specifications.All_Specifications"))); for (List searchIndexItems : searchIndexMap.values()) { - IndexItem ii = searchIndexItems.get(0); + IndexItem ii = searchIndexItems.getFirst(); Content specName = createSpecLink(ii); Content referencesList = HtmlTree.UL(HtmlStyles.refList, searchIndexItems, item -> HtmlTree.LI(createLink(item))); @@ -227,6 +253,7 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { table.addRow(specName, references); } } + content.add(selector); content.add(table); } @@ -235,6 +262,29 @@ public class ExternalSpecsWriter extends HtmlDocletWriter { .collect(groupingBy(IndexItem::getLabel, () -> new TreeMap<>(getTitleComparator()), toList())); } + private Content createHostSelect(List hosts, boolean hasLocal) { + var index = 1; + var id = HtmlId.of("specs-by-domain"); + var specsByHost = resources.getText("doclet.External_Specifications.by-host"); + var select = HtmlTree.of(HtmlTag.SELECT) + .setId(id) + .add(HtmlTree.of(HtmlTag.OPTION) + .put(HtmlAttr.VALUE, "") + .add(Text.of(resources.getText("doclet.External_Specifications.all-hosts")))); + + for (var host : hosts) { + select.add(HtmlTree.of(HtmlTag.OPTION) + .put(HtmlAttr.VALUE, Integer.toString(index++)) + .add(Text.of(host))); + } + if (hasLocal) { + select.add(HtmlTree.of(HtmlTag.OPTION) + .put(HtmlAttr.VALUE, Integer.toString(index)) + .add(Text.of("Local"))); + } + return new ContentBuilder(HtmlTree.LABEL(id.name(), Text.of(specsByHost)), Text.of(" "), select); + } + Comparator getTitleComparator() { Collator collator = Collator.getInstance(); return (s1, s2) -> { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 4366295477b..1aba5c9862b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -180,7 +180,8 @@ doclet.Inheritance_Tree=Inheritance Tree doclet.DefinedIn=Defined In doclet.ReferencedIn=Referenced In doclet.External_Specifications=External Specifications -doclet.External_Specifications.All_Specifications=All Specifications +doclet.External_Specifications.by-host=Show specifications by host name: +doclet.External_Specifications.all-hosts=All host names doclet.External_Specifications.no-host=Local doclet.Specification=Specification doclet.Summary_Page=Summary Page diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index 6198df5c2f3..5bd14f7cf33 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ @@ -1228,7 +1228,7 @@ input::placeholder { input:focus::placeholder { color: transparent; } -select#search-modules { +select { margin: 0 10px 10px 2px; font-size: var(--nav-font-size); padding: 3px 5px; diff --git a/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java b/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java index e914f8022fd..1c3e8306d7b 100644 --- a/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSpecTag/TestSpecTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6251738 8226279 8297802 8305407 + * @bug 6251738 8226279 8297802 8305407 8309748 * @summary JDK-8226279 javadoc should support a new at-spec tag * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -343,16 +343,15 @@ public class TestSpecTag extends JavadocTester { checkOutput("external-specs.html", true, """ -
\ - \ - \ -
+ +
+
+
External Specifications
+
Specification
@@ -369,7 +368,25 @@ public class TestSpecTag extends JavadocTester { -
"""); +
""", + """ + """); } @Test