📄 tohtml.java
字号:
/* * This file is part of a syntax highlighting package * Copyright (C) 1999-2002 Stephen Ostermiller * http://ostermiller.org/contact.pl?regarding=Syntax+Highlighting * * This program 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 of the License, or * (at your option) any later version. * * This program 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. * * See COPYING.TXT for details. */package com.Ostermiller.Syntax;import java.io.*;import com.Ostermiller.Syntax.Lexer.*;import com.Ostermiller.bte.*;import gnu.getopt.*;import java.util.*;import java.text.*;import com.Ostermiller.util.*;import java.lang.reflect.*;import java.net.MalformedURLException;/** * ToHTML will take source and convert it into an html document with * syntax highlighting. All the special characters in the html will be * replaced by their escape sequences. * <p> * A typical use of this class might be: * <pre> * try { * ToHTML toHTML = new ToHTML(); * toHTML.setInput(new FileReader("Source.java")); * toHTML.setOutput(new FileWriter("Source.java.html")); * toHTML.setMimeType("text/x-java"); * toHTML.setFileExt("java") * toHTML.writeFullHTML(); * } catch (InvocationTargetException x){ * // can only happen if setLexerType(java.lang.String) method is used. * } catch (CompileException x){ * // can only happen if setTemplate(java.lang.String) method is used. * } catch (IOException x){ * System.err.println(x.getMessage()); * } * </pre> * <p> * A ToHTML instance may be reused, however it is not thread safe and should only be * used by one thread at a time without external synchronization. */public class ToHTML { private static ToHTML defaultToHTML = new ToHTML(); private PrintWriter out; private Reader in; private String fileExt; private String mimeType; private Lexer lexer; private String lexerType; private String styleSheet; private HashSet ignoreStyles = new HashSet(); private HashMap translateStyles = new HashMap(); private String bteSuper; private String title; private String docName; private HashMap lexers = new HashMap(); private static HashMap registeredMimeTypes = new HashMap(); private static HashMap registeredFileExtensions = new HashMap(); static { register( "com.Ostermiller.Syntax.Lexer.HTMLLexer1", new String[] { "text/html", }, new String[] { "htm", "html", } ); register( "com.Ostermiller.Syntax.Lexer.JavaLexer", new String[] { "text/x-java", "text/java", // for backwards compatibility, but not correct }, new String[] { "jav", "java", } ); register( "com.Ostermiller.Syntax.Lexer.SQLLexer", new String[] { "text/x-sql", "application/x-sql", }, new String[] { "sql", } ); register( "com.Ostermiller.Syntax.Lexer.CLexer", new String[] { "text/x-c++hdr", "text/x-csrc", "text/x-chdr", "text/x-csrc", "text/c", // for backwards compatibility, but not correct }, new String[] { "c", "h", "cc", "cpp", "cxx", "c++", "hpp", "hxx", "hh", } ); register( "com.Ostermiller.Syntax.Lexer.PropertiesLexer", new String[] { "text/x-properties", }, new String[] { "props", "properties", } ); register( "com.Ostermiller.Syntax.Lexer.LatexLexer", new String[] { "application/x-latex", "text/x-latex", "application/x-tex", "text/x-tex", }, new String[] { "tex", "sty", "cls", "dtx", "ins", "latex", } ); register( "com.Ostermiller.Syntax.Lexer.PlainLexer", new String[] { "text/plain", "text", }, new String[] { "txt", "text", } ); } /** * Register a lexer to handle the given mime types and fileExtensions. * <p> * If a document has a type "text/plain" it will first match a registered * mime type of "text/plain" and then a registered mime type of "text". * * @param lexer String representing the fully qualified java name of the lexer. * @param mimeTypes array of mime types that the lexer can handle. * @param fileExtensions array of fileExtensions the lexer can handle. (case insensitive) */ public static void register(String lexer, String[] mimeTypes, String[] fileExtensions){ for (int i=0; i<mimeTypes.length; i++){ registeredMimeTypes.put(mimeTypes[i], lexer); } for (int i=0; i<fileExtensions.length; i++){ registeredFileExtensions.put(fileExtensions[i].toLowerCase(), lexer); } } /** * Open a span if needed for the given style. * * @param description style description. * @param out place to write output. */ private void openSpan(String description, PrintWriter out) throws IOException { if (translateStyles.containsKey(description)){ description = (String)translateStyles.get(description); } if (!ignoreStyles.contains(description)){ out.print("<span class=" + description + ">"); } } /** * Close a span if needed for the given style. * * @param description style description. * @param out place to write output. */ private void closeSpan(String description, PrintWriter out) throws IOException { if (translateStyles.containsKey(description)){ description = (String)translateStyles.get(description); } if (!ignoreStyles.contains(description)){ out.print("</span>"); } } /** * Write a highlighted document html fragment. * * @param lexer Lexer from which to get input. * @param out place to write output. * @throws IOException if an I/O error occurs. */ private void writeHTMLFragment(Lexer lexer, PrintWriter out) throws IOException { String currentDescription = null; Token token; out.println(); out.print("<pre>"); while ((token = lexer.getNextToken()) != null){ // optimization implemented here: // ignored white space can be put in the same span as the stuff // around it. This saves space because spans don't have to be // opened and closed. if ((token.isWhiteSpace() && ignoreStyles.contains("whitespace")) || (currentDescription != null && token.getDescription().equals(currentDescription))){ writeEscapedHTML(token.getContents(), out); } else { if (currentDescription != null) closeSpan(currentDescription, out); currentDescription = token.getDescription(); openSpan(currentDescription, out); writeEscapedHTML(token.getContents(), out); } } if (currentDescription != null) closeSpan(currentDescription, out); out.println("</pre>"); } /** * Write a HTML fragment to the output location that has been set for this class. * <p> * The type of syntax highlighting done will be determined first by the class name for the lexer, * then by the mime type, then by the file extension. * <p> * To save space in the resulting output, it is often a good idea to ignore whitespace. If * whitespace is ignored, it will be merged with surrounding tags. * * @throws IOException if an I/O error occurs. * @throws InvocationTargetException if a lexer class is specified which can't be instantiated. */ public void writeHTMLFragment() throws IOException, InvocationTargetException { Lexer lexer = this.lexer; if (lexer == null) lexer = getLexerFromClass(lexerType); if (lexer == null) lexer = getLexerFromMime(); if (lexer == null) lexer = getLexerFromExt(); writeHTMLFragment(lexer, out); out.flush(); } /** * Format for date. */ private static SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM dd yyyy 'at' HH:mm"); /** * Cache of a potentially large buffer */ private CircularCharBuffer circularBuffer= null; /** * Cache of BTE files. */ private com.Ostermiller.bte.Compiler compiler = null; /** * Write a full HTML document to the output location that has been set for this class. * If a template URL is specified, and <a href="http://ostermiller.org/bte/">template libraries</a> * are installed, templates will be used. * <p> * The type of syntax highlighting done will be determined first by the class name for the lexer, * then by the mime type, then by the file extension. * <p> * To save space in the resulting output, it is often a good idea to ignore whitespace. If * whitespace is ignored, it will be merged with surrounding tags. * <p> * If templates are used, the following sections are available to the template:<br> * date<br> * highlightedDocument<br> * fileExtension<br> * fileName (minus the extension)<br> * styleSheet (if specified)<br> * title (if specified)<br> * The <a href="http://ostermiller.org/syntax/page.bte">default template</a> may be used as a guide. * * @throws IOException if an I/O error occurs. * @throws InvocationTargetException if a lexer class is specified which can't be instantiated. * @throws CompileException if a bte template is specified which can't be compiled. */ public void writeFullHTML() throws IOException, InvocationTargetException, CompileException { Lexer lexer = this.lexer; if (lexer == null) lexer = getLexerFromClass(lexerType); if (lexer == null) lexer = getLexerFromMime(); if (lexer == null) lexer = getLexerFromExt(); boolean noBTE = false; try { if (bteSuper == null){ noBTE = true; } else { if (compiler == null){ compiler = new com.Ostermiller.bte.Compiler(); } if (circularBuffer == null){ circularBuffer = new CircularCharBuffer(CircularCharBuffer.INFINITE_SIZE); } else { circularBuffer.clear(); } PrintWriter bteOut = new PrintWriter(circularBuffer.getWriter()); bteOut.print("<%bte.doc super='" + bteSuper + "' %>\n"); bteOut.print("<%bte.tpl name=date %>" + dateFormat.format(new Date()) + "<%/bte.tpl%>\n"); if (title != null){ bteOut.print("<%bte.tpl name=title %>" + title + "<%/bte.tpl%>\n"); } if (fileExt != null){ bteOut.print("<%bte.tpl name=fileExtension %>" + fileExt + "<%/bte.tpl%>\n"); } if (docName != null){ bteOut.print("<%bte.tpl name=fileName %>" + docName + "<%/bte.tpl%>\n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -