org.jspringbot.syntax.HighlighterUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.jspringbot.syntax.HighlighterUtils.java

Source

/*
 * Copyright (c) 2015. JSpringBot. All Rights Reserved.
 *
 * See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The JSpringBot licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jspringbot.syntax;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import syntaxhighlight.ParseResult;
import syntaxhighlight.Style;
import syntaxhighlight.Theme;
import syntaxhighlighter.SyntaxHighlighterParser;
import syntaxhighlighter.brush.*;
import syntaxhighlighter.theme.*;

import java.awt.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.List;

/**
 * Highlighter utility class
 */
public class HighlighterUtils {

    public static final String DEFAULT_THEME = "default";

    public static final Map<String, Theme> THEME_MAP = new HashMap<String, Theme>() {
        {
            put(DEFAULT_THEME, new ThemeDefault());
            put("django", new ThemeDjango());
            put("eclipse", new ThemeEclipse());
            put("emacs", new ThemeEmacs());
            put("grey", new ThemeFadeToGrey());
            put("mdultra", new ThemeMDUltra());
            put("midnight", new ThemeMidnight());
            put("rdark", new ThemeRDark());
        }
    };

    public static final HighlighterUtils INSTANCE = new HighlighterUtils();

    public static HighlighterUtils instance() {
        return INSTANCE;
    }

    private boolean enable = false;

    private Theme theme;

    private String fontSize = "12px";

    private Map<String, SyntaxHighlighterParser> parserMap;

    private HighlighterUtils() {
        parserMap = new HashMap<String, SyntaxHighlighterParser>();

        parserMap.put("xml", new SyntaxHighlighterParser(new BrushXml()));
        parserMap.put("css", new SyntaxHighlighterParser(new BrushCss()));
        parserMap.put("locator", new SyntaxHighlighterParser(new BrushLocator()));
        parserMap.put("json", new SyntaxHighlighterParser(new BrushJScript()));
        parserMap.put("javascript", new SyntaxHighlighterParser(new BrushJScript()));
        parserMap.put("expression", new SyntaxHighlighterParser(new BrushExpression()));
        parserMap.put("sql", new SyntaxHighlighterParser(new BrushSql()));
        parserMap.put("text", new SyntaxHighlighterParser(new BrushPlain()));
        parserMap.put("clojure", new SyntaxHighlighterParser(new BrushJScript()));

        theme = THEME_MAP.get(DEFAULT_THEME);
    }

    public boolean isEnable() {
        return enable;
    }

    public void setTheme(String theme) {
        this.theme = THEME_MAP.get(theme);

        if (this.theme == null) {
            this.theme = THEME_MAP.get(DEFAULT_THEME);
        }
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    public void setFontSize(String fontSize) {
        this.fontSize = fontSize;
    }

    public String highlightProperties(Properties properties, String comment) {
        try {
            StringWriter writer = new StringWriter();
            properties.store(writer, comment);
            return highlight(writer.toString(), "properties");
        } catch (IOException e) {
            return properties.toString();
        }
    }

    public String highlightNormal(String code) {
        return highlight(code, "text");
    }

    public String highlightText(String code) {
        return highlight(code, "javascript");
    }

    public String highlightXML(String code) {
        return highlight(code, "xml", true);
    }

    public String highlightJSON(String code) {
        return highlight(code, "json", true);
    }

    public String highlightJavascript(String code) {
        return highlight(code, "javascript", true);
    }

    public String highlightCss(String code) {
        return highlight(code, "css", true);
    }

    public String highlightLocator(String code) {
        return highlight(code, "locator", true);
    }

    public String highlightExpression(String code) {
        return highlight(code, "expression", true);
    }

    public String highlightSQL(String code) {
        return highlight(code, "sql", true);
    }

    public String highlight(String code, String type) {
        return highlight(code, type, false);
    }

    public String highlight(String code, String type, boolean linenumber) {
        try {
            return getString(code, type);
        } catch (StackOverflowError e) {
            return "\n((StackOverflowError&lt;fallback&gt;))\n" + StringEscapeUtils.escapeHtml(code);
        }
    }

    private String getString(String code, String type) {
        if (!enable) {
            return "\n" + StringEscapeUtils.escapeHtml(code);
        }

        SyntaxHighlighterParser parser = parserMap.get(type);
        if (parser == null) {
            return "\n" + StringEscapeUtils.escapeHtml(code);
        }

        int i = 0;
        StringBuilder buf = new StringBuilder("<pre style=\"padding:3px;");

        if (theme.getBackground() != null) {
            cssColor(buf, "background-color", theme.getBackground());
        }
        if (theme.getFont() != null) {
            buf.append("font-family:")
                    .append("Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Consolas, monospace");
        }
        buf.append("font-size:").append(fontSize).append(";");
        buf.append(
                "white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;");
        buf.append("\">");

        for (ParseResult result : parser.parse(code)) {
            if (i > result.getOffset())
                continue;

            String before = StringUtils.substring(code, i, result.getOffset());
            if (!StringUtils.isEmpty(before)) {
                style(buf, "plain", before);
            }

            String token = StringUtils.substring(code, result.getOffset(), result.getOffset() + result.getLength());
            String keys = result.getStyleKeysString();

            if (StringUtils.equals(type, "json") && StringUtils.equals(keys, "string")
                    && isLastStringJsonKeyword(code, result.getOffset())) {
                style(buf, "keyword", token);
            } else {
                style(buf, result.getStyleKeys(), token);
            }

            i = result.getOffset() + result.getLength();
        }

        String before = StringUtils.substring(code, i, i + code.length());
        if (!StringUtils.isEmpty(before)) {
            style(buf, "plain", before);
        }

        return buf.append("</pre>").toString();
    }

    private boolean isLastStringJsonKeyword(String code, int i) {
        for (; i >= 0; i--) {
            char ch = code.charAt(i);

            if (!StringUtils.contains("\n\r\t\" ", ch)) {
                return StringUtils.contains("{,", ch);
            }
        }

        return false;
    }

    private void style(StringBuilder buf, String style, String token) {
        style(buf, Collections.singletonList(style), token);
    }

    private void style(StringBuilder buf, List<String> styles, String token) {
        buf.append("<span");

        if (CollectionUtils.isNotEmpty(styles)) {
            buf.append(" style=\"");

            for (String styleKey : styles) {
                Style style = theme.getStyle(styleKey);

                if (style.isBold()) {
                    buf.append("font-weight:bold;");
                }
                if (style.isItalic()) {
                    buf.append("font-style:italic;");
                }
                if (style.isUnderline()) {
                    buf.append("text-decoration:underline;");
                }

                Color foreColor = style.getColor();
                Color bgColor = style.getBackground();

                if (foreColor != null) {
                    cssColor(buf, "color", foreColor);
                }
                if (bgColor != null) {
                    cssColor(buf, "background-color", bgColor);
                }
            }

            buf.append("\"");
        }

        buf.append(">");
        buf.append(StringEscapeUtils.escapeHtml(token));
        buf.append("</span>");
    }

    private static void cssColor(StringBuilder buf, String style, Color color) {
        String rgb = Integer.toHexString(color.getRGB());
        rgb = rgb.substring(2, rgb.length());

        buf.append(style).append(":#").append(StringUtils.lowerCase(rgb)).append(";");
    }
}