8219946: Set class on body elements
authorjjg
Tue, 05 Mar 2019 10:35:29 -0800
changeset 54002 fb9541185457
parent 54001 b4e59fc5edd1
child 54003 f3468c1bdf5f
8219946: Set class on body elements Reviewed-by: hannesw
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java
test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java
test/langtools/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java
test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java
test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java
test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Tue Mar 05 10:35:29 2019 -0800
@@ -96,6 +96,7 @@
     protected void generateFrameFile() throws DocFileIOException {
         Content frame = getFrameDetails();
         HtmlTree body = new HtmlTree(HtmlTag.BODY);
+        body.addAttr(HtmlAttr.CLASS, "frames");
         body.addAttr(HtmlAttr.ONLOAD, "loadFrames()");
         String topFilePath = configuration.topFile.getPath();
         Script script = new Script(
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Mar 05 10:35:29 2019 -0800
@@ -26,6 +26,7 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.Head;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 
 import java.util.*;
@@ -2197,6 +2198,8 @@
      */
     public HtmlTree getBody(boolean includeScript, String title) {
         HtmlTree body = new HtmlTree(HtmlTag.BODY);
+        body.addAttr(HtmlAttr.CLASS, getBodyClass());
+
         // Set window title string which is later printed
         this.winTitle = title;
         // Don't print windowtitle script for overview-frame, allclasses-frame
@@ -2210,6 +2213,15 @@
         return body;
     }
 
+    public String getBodyClass() {
+        return getClass().getSimpleName()
+                .replaceAll("(Writer)?(Impl)?$", "")
+                .replaceAll("AnnotationType", "Class")
+                .replaceAll("(.)([A-Z])", "$1-$2")
+                .replaceAll("(?i)^(module|package|class)$", "$1-declaration")
+                .toLowerCase(Locale.US);
+    }
+
     Script getMainBodyScript() {
         return mainBodyScript;
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java	Tue Mar 05 10:35:29 2019 -0800
@@ -107,7 +107,8 @@
 
         bodyContent.addContent(HtmlTree.P(HtmlTree.A(targetPath, new StringContent(targetPath))));
 
-        Content body = new HtmlTree(HtmlTag.BODY);
+        Content body = new HtmlTree(HtmlTag.BODY)
+                .addAttr(HtmlAttr.CLASS, "index-redirect");
         HtmlTree main = HtmlTree.MAIN(bodyContent);
         body.addContent(main);
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Tue Mar 05 10:35:29 2019 -0800
@@ -37,6 +37,7 @@
 
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -264,7 +265,7 @@
      * @return the header content for the HTML file
      */
     private static Content getHeader() {
-        return new HtmlTree(HtmlTag.BODY);
+        return new HtmlTree(HtmlTag.BODY).addAttr(HtmlAttr.CLASS, "source");
     }
 
     /**
--- a/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java	Tue Mar 05 10:35:29 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -56,13 +56,13 @@
         checkExit(Exit.OK);
         checkOutput("overview-summary.html", true,
                 "<script type=\"text/javascript\">",
-                "<body>");
+                "<body class=\"package-index\">");
 
         // Test that "onload" is not present in BODY tag:
-        checkOutput("p1/package-summary.html", true, "<body>");
-        checkOutput("overview-frame.html", true, "<body>");
-        checkOutput("allclasses-frame.html", true, "<body>");
-        checkOutput("p1/package-frame.html", true, "<body>");
+        checkOutput("p1/package-summary.html", true, "<body class=\"package-declaration\">");
+        checkOutput("overview-frame.html", true, "<body class=\"package-index-frame\">");
+        checkOutput("allclasses-frame.html", true, "<body class=\"all-classes-frame\">");
+        checkOutput("p1/package-frame.html", true, "<body class=\"package-frame\">");
 
         // Test that win title javascript is followed by NOSCRIPT code.
         checkOutput("p1/C.html", true,
--- a/test/langtools/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java	Tue Mar 05 10:35:29 2019 -0800
@@ -330,7 +330,7 @@
             checkOutput("index.html", frames,
                     "<iframe ",
                     "</iframe>",
-                    "<body onload=\"loadFrames()\">\n"
+                    "<body class=\"frames\" onload=\"loadFrames()\">\n"
                     + "<script type=\"text/javascript\">\n"
                     + "if (targetPage == \"\" || targetPage == \"undefined\")");
 
--- a/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java	Tue Mar 05 10:35:29 2019 -0800
@@ -591,7 +591,7 @@
         checkOutput("index.html", true,
                 "<!DOCTYPE HTML>",
                 "<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
-                "<body onload=\"loadFrames()\">\n"
+                "<body class=\"frames\" onload=\"loadFrames()\">\n"
                 + "<script type=\"text/javascript\">\n"
                 + "if (targetPage == \"\" || targetPage == \"undefined\")\n"
                 + "     window.location.replace('overview-summary.html');\n"
--- a/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testJavascript/TestJavascript.java	Tue Mar 05 10:35:29 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, 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
@@ -115,7 +115,7 @@
                 + "</script>");
 
         checkOutput("index.html", true,
-                "<body onload=\"loadFrames()\"");
+                "<body class=\"frames\" onload=\"loadFrames()\"");
 
         //Make sure title javascript only runs if is-external is not true
         checkOutput("pkg/C.html", true,
--- a/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java	Tue Mar 05 18:53:54 2019 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testMetadata/TestMetadata.java	Tue Mar 05 10:35:29 2019 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8218998
+ * @bug 8218998 8219946
  * @summary Add metadata to generated API documentation files
  * @library /tools/lib ../../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -62,6 +62,7 @@
     enum Source { PACKAGES, MODULES };
 
     final ToolBox tb = new ToolBox();
+    final Set<String> allBodyClassesFound = new HashSet<>();
     final Set<String> allGeneratorsFound = new HashSet<>();
 
     public void runTests() throws Exception {
@@ -93,6 +94,7 @@
                      }
                      javadoc(args.toArray(new String[args.size()]));
                      checkExit(Exit.OK);
+                     checkBodyClasses();
                      checkMetadata();
 
                      // spot check the descriptions for declarations
@@ -126,10 +128,91 @@
             failed("not found: " + notFound);
         }
 
+        checking ("all body classes");
+        if (allBodyClassesFound.equals(allBodyClasses)) {
+            passed("all gbody classes found");
+        } else {
+            Set<String> notFound = new TreeSet<>(allBodyClasses);
+            notFound.removeAll(allBodyClassesFound);
+            failed("not found: " + notFound);
+        }
+
         printSummary();
     }
 
     final Pattern nl = Pattern.compile("[\\r\\n]+");
+    final Pattern bodyPattern = Pattern.compile("<body [^>]*class=\"([^\"]+)\"");
+    final Set<String> allBodyClasses = Set.of(
+        "all-classes-frame",
+        "all-classes-index",
+        "all-packages-index",
+        "class-declaration",
+        "class-use",
+        "constants-summary",
+        "deprecated-list",
+        "doc-file",
+        "frames",
+        "help",
+        "index-redirect",
+        "module-declaration",
+        "module-frame",
+        "module-index",
+        "module-index-frame",
+        "module-package-index-frame",
+        "package-declaration",
+        "package-frame",
+        "package-index",
+        "package-index-frame",
+        "package-tree",
+        "package-use",
+        "serialized-form",
+        "single-index",
+        "source",
+        "split-index",
+        "tree"
+    );
+
+    void checkBodyClasses() throws IOException {
+        Path outputDirPath = outputDir.toPath();
+        for (Path p : tb.findFiles(".html", outputDirPath)) {
+            checkBodyClass(outputDirPath.relativize(p));
+        }
+    }
+
+    void checkBodyClass(Path p) {
+        checking("Check body: " + p);
+
+        List<String> bodyLines = nl.splitAsStream(readOutputFile(p.toString()))
+                .filter(s -> s.contains("<body class="))
+                .collect(Collectors.toList());
+
+        String bodyLine;
+        switch (bodyLines.size()) {
+            case 0:
+                 failed("Not found: <body class=");
+                 return;
+            case 1:
+                 bodyLine = bodyLines.get(0);
+                 break;
+            default:
+                 failed("Multiple found: <body class=");
+                 return;
+        }
+
+        Matcher m = bodyPattern.matcher(bodyLine);
+        if (m.find()) {
+            String bodyClass = m.group(1);
+            if (allBodyClasses.contains(bodyClass)) {
+                passed("found: " + bodyClass);
+                allBodyClassesFound.add(bodyClass);
+            } else {
+                failed("Unrecognized body class: " + bodyClass);
+            }
+        } else {
+            failed("Unrecognized line:\n" + bodyLine);
+        }
+    }
+
     final Pattern contentPattern = Pattern.compile("content=\"([^\"]+)\">");
     final Pattern generatorPattern = Pattern.compile("content=\"javadoc/([^\"]+)\">");
     final Set<String> allGenerators = Set.of(