1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.doclets.formats.html.markup; 27 28 import java.util.*; 29 30 import javax.lang.model.element.ModuleElement; 31 import javax.lang.model.element.PackageElement; 32 import javax.lang.model.element.TypeElement; 33 34 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration; 35 import jdk.javadoc.internal.doclets.formats.html.SectionName; 36 import jdk.javadoc.internal.doclets.toolkit.Content; 37 import jdk.javadoc.internal.doclets.toolkit.Messages; 38 import jdk.javadoc.internal.doclets.toolkit.util.DocFile; 39 import jdk.javadoc.internal.doclets.toolkit.util.DocLink; 40 import jdk.javadoc.internal.doclets.toolkit.util.DocPath; 41 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; 42 43 44 /** 45 * Class for the Html Format Code Generation specific to JavaDoc. 46 * This Class contains methods related to the Html Code Generation which 47 * are used by the Sub-Classes in the package jdk.javadoc.internal.tool.standard. 48 * 49 * <p><b>This is NOT part of any supported API. 50 * If you write code that depends on this, you do so at your own risk. 51 * This code and its internal interfaces are subject to change or 52 * deletion without notice.</b> 53 * 54 * @author Atul M Dambalkar 55 * @author Robert Field 56 */ 57 public abstract class HtmlDocWriter extends HtmlWriter { 58 59 public static final String CONTENT_TYPE = "text/html"; 60 61 private final HtmlConfiguration configuration; 62 private final DocPath pathToRoot; 63 64 /** 65 * Constructor. Initializes the destination file name through the super 66 * class HtmlWriter. 67 * 68 * @param configuration the configuration for this doclet 69 * @param filename String file name. 70 */ 71 public HtmlDocWriter(HtmlConfiguration configuration, DocPath filename) { 72 super(configuration, filename); 73 this.configuration = configuration; 74 this.pathToRoot = filename.parent().invert(); 75 Messages messages = configuration.getMessages(); 76 messages.notice("doclet.Generating_0", 77 DocFile.createFileForOutput(configuration, filename).getPath()); 78 } 79 80 public Content getHyperLink(DocPath link, String label) { 81 return getHyperLink(link, new StringContent(label), false, "", "", ""); 82 } 83 84 /** 85 * Get Html Hyper Link Content. 86 * 87 * @param where Position of the link in the file. Character '#' is not 88 * needed. 89 * @param label Tag for the link. 90 * @return a content tree for the hyper link 91 */ 92 public Content getHyperLink(String where, 93 Content label) { 94 return getHyperLink(getDocLink(where), label, "", ""); 95 } 96 97 /** 98 * Get Html Hyper Link Content. 99 * 100 * @param sectionName The section name to which the link will be created. 101 * @param label Tag for the link. 102 * @return a content tree for the hyper link 103 */ 104 public Content getHyperLink(SectionName sectionName, 105 Content label) { 106 return getHyperLink(getDocLink(sectionName), label, "", ""); 107 } 108 109 /** 110 * Get Html Hyper Link Content. 111 * 112 * @param sectionName The section name combined with where to which the link 113 * will be created. 114 * @param where The fragment combined with sectionName to which the link 115 * will be created. 116 * @param label Tag for the link. 117 * @return a content tree for the hyper link 118 */ 119 public Content getHyperLink(SectionName sectionName, String where, 120 Content label) { 121 return getHyperLink(getDocLink(sectionName, where), label, "", ""); 122 } 123 124 /** 125 * Get the link. 126 * 127 * @param where Position of the link in the file. 128 * @return a DocLink object for the hyper link 129 */ 130 public DocLink getDocLink(String where) { 131 return DocLink.fragment(getName(where)); 132 } 133 134 /** 135 * Get the link. 136 * 137 * @param sectionName The section name to which the link will be created. 138 * @return a DocLink object for the hyper link 139 */ 140 public DocLink getDocLink(SectionName sectionName) { 141 return DocLink.fragment(sectionName.getName()); 142 } 143 144 /** 145 * Get the link. 146 * 147 * @param sectionName The section name combined with where to which the link 148 * will be created. 149 * @param where The fragment combined with sectionName to which the link 150 * will be created. 151 * @return a DocLink object for the hyper link 152 */ 153 public DocLink getDocLink(SectionName sectionName, String where) { 154 return DocLink.fragment(sectionName.getName() + getName(where)); 155 } 156 157 /** 158 * Convert the name to a valid HTML name. 159 * 160 * @param name the name that needs to be converted to valid HTML name. 161 * @return a valid HTML name string. 162 */ 163 public String getName(String name) { 164 /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions 165 * that the name/id should begin with a letter followed by other valid characters. 166 * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction 167 * is that it should be at least one character long and should not contain spaces. 168 * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute. 169 * 170 * For HTML 4, we need to check for non-characters at the beginning of the name and 171 * substitute it accordingly, "_" and "$" can appear at the beginning of a member name. 172 * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z". 173 */ 174 175 if (configuration.isOutputHtml5()) { 176 return name.replaceAll(" +", ""); 177 } 178 179 StringBuilder sb = new StringBuilder(); 180 for (int i = 0; i < name.length(); i++) { 181 char ch = name.charAt(i); 182 switch (ch) { 183 case '(': 184 case ')': 185 case '<': 186 case '>': 187 case ',': 188 sb.append('-'); 189 break; 190 case ' ': 191 case '[': 192 break; 193 case ']': 194 sb.append(":A"); 195 break; 196 // Any appearance of $ needs to be substituted with ":D" and not with hyphen 197 // since a field name "P$$ and a method P(), both valid member names, can end 198 // up as "P--". A member name beginning with $ needs to be substituted with 199 // "Z:Z:D". 200 case '$': 201 if (i == 0) 202 sb.append("Z:Z"); 203 sb.append(":D"); 204 break; 205 // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor 206 // names can only begin with a letter. 207 case '_': 208 if (i == 0) 209 sb.append("Z:Z"); 210 sb.append(ch); 211 break; 212 default: 213 sb.append(ch); 214 } 215 } 216 return sb.toString(); 217 } 218 219 /** 220 * Get Html hyperlink. 221 * 222 * @param link path of the file. 223 * @param label Tag for the link. 224 * @return a content tree for the hyper link 225 */ 226 public Content getHyperLink(DocPath link, Content label) { 227 return getHyperLink(link, label, "", ""); 228 } 229 230 public Content getHyperLink(DocLink link, Content label) { 231 return getHyperLink(link, label, "", ""); 232 } 233 234 public Content getHyperLink(DocPath link, 235 Content label, boolean strong, 236 String stylename, String title, String target) { 237 return getHyperLink(new DocLink(link), label, strong, 238 stylename, title, target); 239 } 240 241 public Content getHyperLink(DocLink link, 242 Content label, boolean strong, 243 String stylename, String title, String target) { 244 Content body = label; 245 if (strong) { 246 body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body); 247 } 248 if (stylename != null && stylename.length() != 0) { 249 HtmlTree t = new HtmlTree(HtmlTag.FONT, body); 250 t.addAttr(HtmlAttr.CLASS, stylename); 251 body = t; 252 } 253 HtmlTree l = HtmlTree.A(link.toString(), body); 254 if (title != null && title.length() != 0) { 255 l.addAttr(HtmlAttr.TITLE, title); 256 } 257 if (target != null && target.length() != 0) { 258 l.addAttr(HtmlAttr.TARGET, target); 259 } 260 return l; 261 } 262 263 /** 264 * Get Html Hyper Link. 265 * 266 * @param link String name of the file. 267 * @param label Tag for the link. 268 * @param title String that describes the link's content for accessibility. 269 * @param target Target frame. 270 * @return a content tree for the hyper link. 271 */ 272 public Content getHyperLink(DocPath link, Content label, String title, String target) { 273 return getHyperLink(new DocLink(link), label, title, target); 274 } 275 276 public Content getHyperLink(DocLink link, Content label, String title, String target) { 277 HtmlTree anchor = HtmlTree.A(link.toString(), label); 278 if (title != null && title.length() != 0) { 279 anchor.addAttr(HtmlAttr.TITLE, title); 280 } 281 if (target != null && target.length() != 0) { 282 anchor.addAttr(HtmlAttr.TARGET, target); 283 } 284 return anchor; 285 } 286 287 public Content getModuleFramesHyperLink(ModuleElement mdle, Content label, String target) { 288 DocLink mdlLink = new DocLink(DocPaths.moduleFrame(mdle)); 289 DocLink mtFrameLink = new DocLink(DocPaths.moduleTypeFrame(mdle)); 290 DocLink cFrameLink = new DocLink(DocPaths.moduleSummary(mdle)); 291 HtmlTree anchor = HtmlTree.A(mdlLink.toString(), label); 292 String onclickStr = "updateModuleFrame('" + mtFrameLink + "','" + cFrameLink + "');"; 293 anchor.addAttr(HtmlAttr.TARGET, target); 294 anchor.addAttr(HtmlAttr.ONCLICK, onclickStr); 295 return anchor; 296 } 297 298 /** 299 * Get the enclosed name of the package 300 * 301 * @param te TypeElement 302 * @return the name 303 */ 304 public String getEnclosingPackageName(TypeElement te) { 305 306 PackageElement encl = configuration.utils.containingPackage(te); 307 return (encl.isUnnamed()) ? "" : (encl.getQualifiedName() + "."); 308 } 309 310 /** 311 * Returns a link to the stylesheet file. 312 * 313 * @param configuration the configuration for this doclet 314 * @return an HtmlTree for the lINK tag which provides the stylesheet location 315 */ 316 public HtmlTree getStyleSheetProperties(HtmlConfiguration configuration) { 317 String stylesheetfile = configuration.stylesheetfile; 318 DocPath stylesheet; 319 if (stylesheetfile.isEmpty()) { 320 stylesheet = DocPaths.STYLESHEET; 321 } else { 322 DocFile file = DocFile.createFileForInput(configuration, stylesheetfile); 323 stylesheet = DocPath.create(file.getName()); 324 } 325 HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", 326 pathToRoot.resolve(stylesheet).getPath(), 327 "Style"); 328 return link; 329 } 330 331 protected Comment getGeneratedBy(boolean timestamp) { 332 String text = "Generated by javadoc"; // marker string, deliberately not localized 333 if (timestamp) { 334 Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); 335 Date today = calendar.getTime(); 336 text += " ("+ configuration.getDocletSpecificBuildDate() + ") on " + today; 337 } 338 return new Comment(text); 339 } 340 }