起因
最近在仿写一款优秀的写作软件,优秀的写作软件支持markdown的解析自然是一个必不可少的功能,在思考如何实现解析器的同时,恰好阅读了钟颖大佬出品的关于“代码编辑器”的技术文章,发现可以使用 WebView
封装 markdown-it 和 highlightjs.org 一类的web项目,低成本地实现一个有着不错效果的CommonMark解析器。
实现过程
1. HTML文件创建
创建本地文件 index.html
,并输入代码。页面中用到的js文件和资源需要后续创建和生成。<body>
标签中唯一的<div>
将用于后续插入通过 markdown-it
渲染的代码,页面的样式布局通过css文件实现和优化。
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="./main.css" />
<script src="./main.js"></script>
</head>
<body>
<div class="container" id="contents"></div>
</body>
</html>
2. JS文件创建
创建本地文件 index.js
,在文件中编写需要注入网页的js代码。
import hljs from 'highlight.js'
import MarkdownIt from 'markdown-it'
import emoji from 'markdown-it-emoji'
import './../css/bootstrap.css'
import './../css/gist.css'
import './../css/github.css'
import './../css/index.css'
window.showMarkdown = (percentEncodedMarkdown, enableImage = true) => {
if (!percentEncodedMarkdown) {
return
}
const markdownText = decodeURIComponent(percentEncodedMarkdown)
let markdown = new MarkdownIt({
html: true,
breaks: true,
linkify: true,
highlight: function(code){
return hljs.highlightAuto(code).value;
}
})
if (!enableImage) {
markdown = markdown.disable('image')
}
markdown.use(emoji)
markdown.use(require('markdown-it-latex2img'))
let html = markdown.render(markdownText)
document.getElementById('contents').innerHTML = html
let tables = document.querySelectorAll('table')
tables.forEach((table) => {
table.classList.add('table')
})
let codes = document.querySelectorAll('pre code')
codes.forEach((code) => {
hljs.highlightBlock(code)
})
}
主要用到的js库有:
markdown-it
:100% CommonMark 语法解析
highlight.js
:代码高亮
markdown-it-emoji
:emoji语法支持
markdown-it-latex2img
:基于服务器端的MathJax解析器
代码的基本逻辑主要是: 1.由于markdown格式的内容被传入时事先进行了编码操作,所以这里需要调用decodeURIComponent()函数对内容先进行解码。 2.使用 markdown-it
别结合所需插件对内容进行渲染,更多关于 markdown-it
的使用和插件支持,可以参考官方的API文档:《markdown-it 中文文档》。 3.将渲染后的代码插入 index.html
页面的对应位置,并支持表格(内嵌功能)和代码高亮的显示。
3. 控件封装
业务逻辑:创建 WKWebView
,并注入js代码(showMarkdown()函数调用) 关键代码:
@objc public func load(markdown: String?, enableImage: Bool = true) {
guard let markdown = markdown else { return }
if let url = htmlURL {
let templateRequest = URLRequest(url: url)
let escapedMarkdown = self.escape(markdown: markdown) ?? ""
let imageOption = enableImage ? "true" : "false"
let script = "window.showMarkdown('\(escapedMarkdown)', \(imageOption));"
let userScript = WKUserScript(source: script, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let controller = WKUserContentController()
controller.addUserScript(userScript)
let configuration = WKWebViewConfiguration()
configuration.userContentController = controller
let wv = WKWebView(frame: self.bounds, configuration: configuration)
wv.scrollView.isScrollEnabled = self.isScrollEnabled
wv.translatesAutoresizingMaskIntoConstraints = false
wv.navigationDelegate = self
addSubview(wv)
// 代码省略:布局约束、空间样式
// ...
wv.load(templateRequest)
} else {
// TODO: raise error
}
}
private func escape(markdown: String) -> String? {
return markdown.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics)
}
4. 资源文件打包
到此,代码层面的工作就可以结束了。 最后我们需要使用 Webpack
工具将js应用程序打包成方便使用的静态资源,输出名为 main.js
的文件,将其放置在 index.html
文件相同的目录下。这里提供一个可供参考的配置文件:webpack.config.js。
写在最后
本文所描述的实现过程,主要参考了三方库 MarkdownView,因为需要支持LaTeX的解析,我稍微重写了showMarkdown函数,加入了 markdown-it-latex2img
库的使用,能够将数学公式以图片的形式进行展示。过程中,还学习了 Webpack
工具的使用和js静态资源的打包。Webview
项目的封装能够为原生提供更丰富的功能,能够为复杂的业务实现提供更多的思路和扩展,希望本文能够对需要的人有所帮助。
参考资料:
Taio开发笔记
Webpack教程
markdown-it API文档
keitaoouchi/MarkdownView
今天的文章如何封装一个支持LaTex的Markdown解析器分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16460.html