⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htmlrepairer.java

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* gnu.classpath.tools.doclets.xmldoclet.HtmlRepairer.java
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

package gnu.classpath.tools.doclets.xmldoclet;

import java.io.*;
import java.util.*;
import com.sun.javadoc.DocErrorReporter;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MemberDoc;

/**
 *  Provides methods for tidying up HTML source.
 *
 *  @author Julian Scheid
 */
public final class HtmlRepairer {

   private static class TagInfo {

      private Set parentTags = new HashSet();

      public TagInfo(String parentTag) {
	 this.parentTags.add(parentTag);
      }

      public TagInfo(String[] parentTagArr) {
	 for (int i=0; i<parentTagArr.length; ++i) {
	    this.parentTags.add(parentTagArr[i]);
	 }
      }

      public boolean isLegalParentTag(String tag) {
	 return this.parentTags.contains(tag);
      }
   }

   private DocErrorReporter warningReporter;
   private boolean noWarn;
   private boolean noEmailWarn;
   private ClassDoc contextClass;
   private MemberDoc contextMember;
   private StringBuffer output = new StringBuffer();
   private Stack tagStack = new Stack();
   private boolean isLeadingTag = true;
   private boolean throwAwayLeadingPara = false;

   private static Map tagInfoMap;

   private static Set noTextParentTags;

   static {
      tagInfoMap = new HashMap();
      tagInfoMap.put("li", new TagInfo(new String[] { "ul", "ol", "nl", "menu", "dir" }));
      tagInfoMap.put("td", new TagInfo(new String[] { "tr" }));
      tagInfoMap.put("th", new TagInfo(new String[] { "tr" }));
      tagInfoMap.put("tr", new TagInfo(new String[] { "table" }));
      tagInfoMap.put("dt", new TagInfo(new String[] { "dl" }));
      tagInfoMap.put("dd", new TagInfo(new String[] { "dl" }));
      tagInfoMap.put("param", new TagInfo(new String[] { "applet" }));

      String[] noTextParentTagArr = {
         "area", "base", "body", "br", "dd", "dt", "head", "hr", "html", 
         "img", "input", "link", "map", "meta", "ol", "optgroup", "param",
         "select", "table", "tbody", "tfoot", "thead", "tr", "ul",
      };

      noTextParentTags = new HashSet();
      for (int i=0; i<noTextParentTagArr.length; ++i) {
         noTextParentTags.add(noTextParentTagArr[i]);
      }
   }

   public HtmlRepairer(DocErrorReporter warningReporter, 
		       boolean noWarn, boolean noEmailWarn,
		       ClassDoc contextClass, MemberDoc contextMember,
                       boolean throwAwayLeadingPara) {
      this.warningReporter = warningReporter;
      this.noWarn = noWarn;
      this.noEmailWarn = noEmailWarn;
      this.contextClass = contextClass;
      this.contextMember = contextMember;
      this.throwAwayLeadingPara = throwAwayLeadingPara;
   }
  
   private static String replaceStr(String haystack, String needle, String replacement) {
      int ndx=haystack.indexOf(needle);
      if (ndx<0) 
	 return haystack;
      else 
	 return haystack.substring(0, ndx)+replacement
	    + replaceStr(haystack.substring(ndx+needle.length()), needle, replacement);
   }
 
   private void haveText(String text) {

      if (isLeadingTag && throwAwayLeadingPara) {
         if (0 != text.trim().length()) {
            isLeadingTag = false;
         }
      }

      if (tagStack.isEmpty() || !noTextParentTags.contains(tagStack.peek())) {

         text = replaceStr(text, "&lt1", "&lt;1");
         text = replaceStr(text, "&&", "&amp;&amp;");
         text = replaceStr(text, "& ", "&amp; ");
         text = replaceStr(text, "&\t", "&amp;\t");
         text = replaceStr(text, "&\r", "&amp;\r");
         text = replaceStr(text, "&\n", "&amp;\n");
         for (char c='0'; c<='9'; ++c)
            text = replaceStr(text, "&"+c, "&amp;"+c);
         text = replaceStr(text, "\u00a7", "&sect;");
         output.append(text);
      }
      else {
         printWarning("Discarded text in <" + tagStack.peek() + "> element");
      }
   }

   private void haveStartOrEndTag(String tag) {

      boolean _isLeadingTag = isLeadingTag;
      isLeadingTag = false;

      tag = tag.trim();

      boolean isEndTag = tag.startsWith("/");
      boolean isAtomTag = tag.endsWith("/");

      if (isEndTag && isAtomTag) {
	 // got something like '</a/>' which is invalid.
	 // suppose a close tag was intended.
	 tag = tag.substring(0, tag.length()-1);
      }

      if (tag.length() < 1) {
         printWarning("Deleting broken tag");
         return;
      }

      String tagName = tag.substring(isEndTag?1:0, isAtomTag?tag.length()-1:tag.length());
      String tagAttributes = "";

      for (int i=0; i<tagName.length(); ++i) {
	 if (" \t\r\n".indexOf(tagName.charAt(i))>=0) {
	    tagAttributes = tagName.substring(i).trim();
	    tagName = tagName.substring(0, i);
	    break;
	 }
      }

      if (!isEndTag && tagName.indexOf('@')>0) {
	 if (!noEmailWarn) {
	    printWarning("Tag looks like email address: <"+tagName+">");
	 }
	 output.append("&lt;"+tag+"&gt;");
	 return;
      }

      tagName = tagName.toLowerCase();

      if (_isLeadingTag && "p".equals(tagName) && !isEndTag && throwAwayLeadingPara) {
         return;
      }

      if ("p".equals(tagName) || "br".equals(tagName) || "hr".equals(tagName)) {
	 // throw away </p> and </br>
	 if (isEndTag) {
	    return;
	 }
	 // make sure every <p> is a <p/> and every <br> is a <br/>
	 else if (!isAtomTag) {
	    tag += "/";
	    isAtomTag = true;
	 }
      }

      if (isEndTag) {

	 // check whether this close tag is on the stack
	 // if yes, close all tags up to this tag
	 if (tagStack.contains(tagName)) {
	    String popped;
	    do {
	       popped = (String)tagStack.pop();
	       if (!popped.equals(tagName)) 
		  printWarning("Inserting '</"+popped+">");
	       output.append("</"+popped+">");
	    }
	    while (!popped.equals(tagName));
	 }
	 // if not, just throw it away
	 else {
	    printWarning("Deleting <"+tag+">");
	 }
      }
      else {

	 final int STATE_INITIAL = 1;
	 final int STATE_EXPECT_ATTRIBUTENAME = 2;
	 final int STATE_UNQUOTED_ATTRIBUTEVALUE = 3;
	 final int STATE_SINGLEQUOTE_ATTRIBUTEVALUE = 4;
	 final int STATE_DOUBLEQUOTE_ATTRIBUTEVALUE = 5;
	 final int STATE_EXPECT_ATTRIBUTEVALUE = 6;
	 final int STATE_EXPECT_EQUALSIGN = 7;

	 int state = STATE_INITIAL;
	       
	 String newAttributes = "";
	 String attributeName = null;
	 StringBuffer buf = new StringBuffer();

	 char[] attrsAsChars = tagAttributes.toCharArray();
	 for (int i=0, ilim=attrsAsChars.length+1; i<ilim; ++i) {
	    int c;
	    if (i<attrsAsChars.length)
	       c = (int)attrsAsChars[i];
	    else
	       c = -1;

	    switch (state) {

	    case STATE_INITIAL:
	       if (" \t\r\n".indexOf(c)>=0){
		  continue;
	       }
	       else if (-1==c) {
		  continue;
	       }
	       else {
		  state = STATE_EXPECT_ATTRIBUTENAME;
		  buf.append((char)c);
	       }
	       break;

	    case STATE_EXPECT_ATTRIBUTENAME:
	       if ('='==c) {
		  attributeName = buf.toString();
		  buf.setLength(0);
		  state = STATE_EXPECT_ATTRIBUTEVALUE;
	       }
	       else if (-1==c) {
		  attributeName = buf.toString();
		  buf.setLength(0);
		  printWarning("In Tag '"+tag+"':\nAttribute name without a value, inserting value =\""+attributeName+"\"");
	       }
	       else if (" \t\r\n".indexOf(c)>=0) {
		  state = STATE_EXPECT_EQUALSIGN;
	       }
	       else {
		  buf.append((char)c);
	       }
	       break;

	    case STATE_EXPECT_EQUALSIGN:
	       if (" \t\r\n".indexOf(c)>=0){
		  continue;
	       }
	       else if ('='==c) {
		  state = STATE_EXPECT_ATTRIBUTEVALUE;
		  attributeName = buf.toString();
		  buf.setLength(0);
	       }
	       else {
		  attributeName = buf.toString();
		  buf.setLength(0);
		  printWarning("In Tag '"+tag+"':\nAttribute name without a value, inserting value =\""+attributeName+"\"");
		  newAttributes += " "+attributeName+"=\""+attributeName+"\"";
		  buf.append((char)c);
		  state = STATE_EXPECT_ATTRIBUTENAME;
	       }
	       break;

	    case STATE_EXPECT_ATTRIBUTEVALUE:
	       if (" \t\r\n".indexOf(c)>=0){
		  continue;
	       }
	       else if ('\"'==c) {
		  state = STATE_DOUBLEQUOTE_ATTRIBUTEVALUE;
	       }
	       else if ('\''==c) {
		  state = STATE_SINGLEQUOTE_ATTRIBUTEVALUE;
	       }
	       else {
		  state = STATE_UNQUOTED_ATTRIBUTEVALUE;
		  buf.append((char)c);
	       }
	       break;

	    case STATE_UNQUOTED_ATTRIBUTEVALUE:
	       if (-1==c || " \t\r\n".indexOf(c)>=0){
		  state = STATE_INITIAL;
		  newAttributes += " "+attributeName + "=\"" + buf.toString() + "\"";
		  buf.setLength(0);
	       }
	       else {
		  buf.append((char)c);
	       }
	       break;

	    case STATE_SINGLEQUOTE_ATTRIBUTEVALUE:
	       if ('\''==c) {
		  state = STATE_INITIAL;
		  newAttributes += " "+attributeName + "=\"" + buf.toString() + "\"";
		  buf.setLength(0);
	       }
	       else {
		  buf.append((char)c);
	       }
	       break;

	    case STATE_DOUBLEQUOTE_ATTRIBUTEVALUE:
	       if ('\"'==c) {
		  state = STATE_INITIAL;
		  newAttributes += " "+attributeName + "=\"" + buf.toString() + "\"";
		  buf.setLength(0);
	       }
	       else {
		  buf.append((char)c);
	       }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -