一、背景
笔者在开发这套博客系统时使用 Editormd 作为 Markdown 编辑器,由于不满足其代码高亮的样式,因此选用 highlight.js 插件来实现代码高亮功能。但是,highlight.js 插件不提供行号的设置功能,于是有了该文章。
二、实现原理
html 的代码块都是通过 <code></code> 进行封装,我们可以将其内容取出封装到 <ol><li></li></ol> 从而实现设置行号的效果。
三、实现方式
下边提供两种实现方式。
3.1 后端修饰
笔者使用的是 commonmark 库来实现 markdown 转换成 html。
3.1.1 添加依赖:
1 2 3 4 5
| <dependency> <groupId>com.atlassian.commonmark</groupId> <artifactId>commonmark</artifactId> <version>0.11.0</version> </dependency>
|
3.1.2 工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public abstract class MarkdownUtil {
public static List<Extension> extensions = Arrays.asList(TablesExtension.create()); private static final Parser parser = Parser.builder().extensions(extensions).build(); private static final HtmlRenderer renderer = HtmlRenderer.builder().extensions(extensions) // 修饰代码块内容 .nodeRendererFactory(context -> new NodeRenderer() {
@Override public Set<Class<? extends Node>> getNodeTypes() { return Collections.singleton(FencedCodeBlock.class); }
@Override public void render(Node node) {
HtmlWriter html = context.getWriter(); FencedCodeBlock codeBlock = (FencedCodeBlock) node; Map<String,String> attrs = new HashMap<>(); if (!StringUtils.isEmpty(codeBlock.getInfo())) { attrs.put("class","language-" + codeBlock.getInfo()); } html.line(); html.tag("pre"); html.tag("code",attrs); html.tag("ol"); String data = codeBlock.getLiteral(); String[] split = data.split("\n"); for (String s : split) { html.tag("li"); html.text(s + "\n"); html.tag("/li"); } html.tag("/ol"); html.tag("/code"); html.tag("/pre"); html.line();
} }).build();
/** * markdown 转 html * @param markdown * @return */ public static String md2html(String markdown) { Node document = parser.parse(markdown); String result = renderer.render(document); return result; } }
|
如果不使用上边的 NodeRendererFactory 对 html 进行修饰,输出的 html 的代码块就只是 <pre><code></code></pre> 的形式。
3.2 前端修饰
使用 js 代码实现代码修饰:
1 2 3
| $("code").each(function(){ $(this).html("<ol><li>" + $(this).html().replace(/\n/g,"\n</li><li>") +"\n</li></ol>"); });
|
3.3 css 样式
由于 <ol><li></li></ol> 默认行号效果不友好,我们进行样式设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| .hljs { border: 0; font-size: 12px; display: block; padding: 1px; margin: 0; width: 100%; font-weight: 200; color: #333; white-space: pre-wrap } .hljs ol { list-style: decimal; margin: 0px 0px 0 40px !important; padding: 0px; } .hljs ol li { list-style: decimal-leading-zero; border-left: 1px solid #ddd !important; padding: 5px!important; margin: 0 !important; white-space: pre; }
|
实现的效果正是读者正在看到的效果。