html 中 Java 代码的语法高亮显示
Posted
技术标签:
【中文标题】html 中 Java 代码的语法高亮显示【英文标题】:Syntax-Highlighting for Java-Code in html 【发布时间】:2020-11-08 15:13:23 【问题描述】:我要做什么
我正在开发一个突出显示 html 中 java 代码的语法高亮器(示例如下)。
示例输出
我已经使用以下 java-code (caesar-encryption) 测试了代码:
//Encryption
public static String encrypt(String text, int n)
int x = 0;
int y = 0;
String out = ""; //Empty string for result.
while (x < text.length())
if (text.charAt(x) > 64 && text.charAt(x) < 91)
if (text.charAt(x) + n > 90)
y = 26;
out = out + (char) (text.charAt(x) + n - y);
else
out = out + text.charAt(x);
x++;
y = 0;
return out;
输出如下所示:
<!-- Code begins here -->
<div style = "background: LightGray; font: monospace; width: fit-content; height: min-height;"><pre><code>
<span style='color:green; font-weight:bold; '>//Encryption
</span><span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>static</span> <span style='color:#7f0055; font-weight:bold; '>String</span> encrypt(<span style='color:#7f0055; font-weight:bold; '>String</span> text, <span style='color:#7f0055; font-weight:bold; '>int</span> n)
<span style='color:#7f0055; font-weight:bold; '>int</span> x = 0;
<span style='color:#7f0055; font-weight:bold; '>int</span> y = 0;
<span style='color:#7f0055; font-weight:bold; '>String</span> out = <span style='color:blue; font-weight:bold; '>""</span>; <span style='color:green; font-weight:bold; '>//Empty string <span style='color:#7f0055; font-weight:bold; '>for</span> result.
</span> <span style='color:#7f0055; font-weight:bold; '>while</span> (x < text.length())
<span style='color:#7f0055; font-weight:bold; '>if</span> (text.charAt(x) > 64 && text.charAt(x) < 91)
<span style='color:#7f0055; font-weight:bold; '>if</span> (text.charAt(x) + n > 90)
y = 26;
out = out + (<span style='color:#7f0055; font-weight:bold; '>char</span>) (text.charAt(x) + n - y);
<span style='color:#7f0055; font-weight:bold; '>else</span>
out = out + text.charAt(x);
x++;
y = 0;
<span style='color:#7f0055; font-weight:bold; '>return</span> out;
</pre></code></div>
<!-- Code ends here -->
如果你用浏览器打开这段代码,它看起来像这样:
代码
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class Gui
private JTextArea inputArea;
private JTextArea outputArea;
private boolean inputAreaClicked = false;
public Gui()
//JFrame
JFrame frame = new JFrame("Syntax-Highlighter");
frame.setSize(700, 700);
frame.setMinimumSize(new Dimension(700, 700));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel
JPanel panel = new JPanel(new GridBagLayout());
//Creating textArea for input
inputArea = new JTextArea("Enter text here...");
inputArea.setLineWrap(true);
inputArea.setTabSize(1);
inputArea.setFont(new Font("monospaced", Font.ITALIC, 12));
inputArea.addMouseListener(new MouseAdapter() //Set text to "" the first time the inputArea is clicked
@Override
public void mouseClicked(MouseEvent e)
if(!inputAreaClicked)
inputArea.setText("");
inputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
inputAreaClicked = true;
);
JScrollPane input = new JScrollPane(inputArea);
input.setPreferredSize(new Dimension(600, 110));
input.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
input.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
//Creating buttons
JPanel buttonPanel = new JPanel(new FlowLayout(0, 50, 10)); //FlowLayout(align, hgap, vgap)
JButton button = new JButton("Highlight");
button.setFont(new Font("Arial", Font.PLAIN, 20));
button.addActionListener(e -> hightlight(inputArea.getText()));
button.setPreferredSize(new Dimension(140,30));
//Creating textArea for output
outputArea = new JTextArea();
outputArea.setEditable(false);
outputArea.setTabSize(1);
outputArea.setLineWrap(false);
outputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
JScrollPane output = new JScrollPane(outputArea);
output.setPreferredSize(new Dimension(600, 400));
output.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
output.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
//Layout
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 5;
gbc.gridwidth = GridBagConstraints.REMAINDER;
//Add everything to panel
buttonPanel.add(button);
panel.add(input, gbc);
panel.add(buttonPanel, gbc);
panel.add(output, gbc);
//Add everything to frame
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);
private void hightlight(String text)
//Keywords
String[] array =
"abstract", "assert", "boolean", "break", "byte", "case",
"catch", "char", "class", "const", "continue", "default", "do",
"double", "else", "enum", "extends", "false", "final", "finally", "float",
"for", "goto", "if", "implements", "import", "instanceof", "int",
"interface", "long", "native", "new", "null", "package", "private", "protected",
"public", "return", "short", "static", "String", "strictfp", "super", "switch", "synchronized",
"System", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"
;
//Highlight every keyword with color:#7f0055
for(int i = 0; i < array.length; i++)
text = text.replaceAll(array[i] + "(?![a-zA-Z])", "<span style='color:#7f0055; font-weight:bold; '>" + array[i] + "</span>");
//Highlight Strings
text = text.replaceAll("\"(?<render>.*?)\"", "<span style='color:blue; font-weight:bold; '>" + "\"$render\"" + "</span>");
//Highlight import-statements
text = text.replaceAll("import(?<render>.*?);", "<span style='color:#7f0055; font-weight:bold; '>" + "import$render;" + "</span>");
//Highlight multiline-comments
Pattern p = Pattern.compile("/\\*(?<render>.*?)\\*/", Pattern.DOTALL);
Matcher m = p.matcher(text);
text = m.replaceAll("<span style='color:green; font-weight:bold; '>" + "/\\*$render\\*/" + "</span>");
//Highlight single-line-comments
text = text.replaceAll("//(?<render>.*?)\n", "<span style='color:green; font-weight:bold; '>" + "//$render\n" + "</span>");
text = "<!-- Code begins here -->\n<div style = \"background: LightGray; font: monospace; width: fit-content; height: min-height;\"><pre><code>\n"
+ text + "\n</pre></code></div>\n<!-- Code ends here -->\n";
outputArea.setText(text);
问题
如上图所示,cmets中的关键字仍然以关键字高亮显示。
您知道如何解决这个问题吗?
我的尝试
我尝试使用以下代码(在反向引用中替换),但没有成功:
// Highlight single-line-comments
text = text.replaceAll("//(?<render>.*?)\n", "<span style='color:green; font-weight:bold; '>"
+ "//" + "$render".replaceAll("color: #7f0055", "color: green") + "\\n</span>");
很遗憾,这不起作用?如何纠正?
【问题讨论】:
一个相当老套的解决方案:<span style='color:green !important; font-weight:bold; '>
.
@Sweeper 不幸的是,这没有帮助。你有别的想法吗?
要正确突出 Java 代码,您需要正确解析它,没有任何 hacky 解决方案可以解决所有问题(想想多行 cmets ... Java 字符串文字 ...)。
【参考方案1】:
我建议遍历文本,一次处理一个标记:
为要检测的不同类型的输入定义正则表达式列表,以\\G
开头强制从输入开始进行匹配
为您想要跳过的内容添加一个表达式,这样即使您没有找到任何要突出显示的内容,您也能取得进展
对内容有一个外循环,对表达式列表有一个内循环。对于每个检测到的类型,从输入中删除匹配的字符串,将替换添加到输出并推进外循环。
第 1 步中的列表实际上应该是对应 HTML 替换字符串的映射。
附:该过程基于标记化,类似于 Java 解析器在最低级别所做的 - 我认为您不需要完整的 Java 解析器(正如其中一个 cmets 所建议的那样)。分离输入和输出确保您无需担心双重处理输入,还允许您正确地对输出进行 HTML 转义(这很重要,因为 cmets 和字符串可能包含 HTML)。
【讨论】:
以上是关于html 中 Java 代码的语法高亮显示的主要内容,如果未能解决你的问题,请参考以下文章