原文地址:highlight.js 設置行號
博客地址:http://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("<ol><li>" + $(this).html().replace(/\n/g,"\n</li><li>") +"\n</li></ol>");
});
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;
}
實現的效果正是讀者正在看到的效果。