highlight.js 设置行号

2,364 阅读2分钟
原文链接: www.extlight.com

一、背景

笔者在开发这套博客系统时使用 Editormd 作为 Markdown 编辑器,由于不满足其代码高亮的样式,因此选用 highlight.js 插件来实现代码高亮功能。但是,highlight.js 插件不提供行号的设置功能,于是有了该文章。

二、实现原理

html 的代码块都是通过 <code></code> 进行封装,我们可以将其内容取出封装到 <ol><li></li></ol> 从而实现设置行号的效果。

三、实现方式

下边提供两种实现方式。

3.1 后端修饰

笔者使用的是 commonmark 库来实现 markdown 转换成 html。

3.1.1 添加依赖:

<dependency>

	<groupId>com.atlassian.commonmark</groupId>

	<artifactId>commonmark</artifactId>

	<version>0.11.0</version>

</dependency>


3.1.2 工具类:

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 代码实现代码修饰:

$("code").each(function(){

  $(this).html("<ul><li>" + $(this).html().replace(/\n/g,"\n</li><li>") +"\n</li></ul>");

});


3.3 css 样式

由于 <ol><li></li></ol> 默认行号效果不友好,我们进行样式设置。

.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;

}


实现的效果正是读者正在看到的效果。