Maaku 框架提供了一个 Swift 包装器,围绕 cmark-gfm 构建,并添加了对 AST 的 Swift 友好的表示。 支持 gfm 扩展,包括表格、删除线、自动链接和标签过滤器。
Maaku 还支持插件约定,自定义渲染器可以使用该约定。 提供了一个插件作为示例。
TexturedMaaku 基于 Maaku 和 Texture 构建,提供了一个原生的 iOS CommonMark 渲染框架,使用 Swift 编写。
CocoaPods 是 Cocoa 项目的依赖管理器。 您可以使用以下命令安装它:
$ gem install cocoapods
要使用 CocoaPods 将 Maaku 集成到您的 Xcode 项目中,请在您的 Podfile
中指定它:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'Maaku'
end
然后,运行以下命令:
$ pod install
Carthage 是一个去中心化的依赖管理器,它可以构建您的依赖项并为您提供二进制框架。
您可以使用 Homebrew 安装 Carthage,使用以下命令:
$ brew update
$ brew install carthage
要使用 Carthage 将 Maaku 集成到您的 Xcode 项目中,请在您的 Cartfile
中指定它:
github "KristopherGBaker/Maaku" ~> 0.6.0
运行 carthage update
以构建框架,并将构建的 Maaku.framework
拖到您的 Xcode 项目中。
Swift Package Manager 是一种用于自动化 Swift 代码分发的工具,并已集成到 swift
编译器中。 它还处于早期开发阶段,但 Maaku 确实支持在支持的平台上使用它。
一旦您设置好 Swift 包,添加 Maaku 作为依赖项就像将其添加到您的 Package.swift
的 dependencies
值一样简单。
dependencies: [
.package(url: "https://github.com/KristopherGBaker/Maaku.git", from: "0.6.0")
]
$ swift build -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.14"
$ swift test -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.14"
Document
是使用 Maaku 的主要接口。 可以通过传递表示 CommonMark 的 Data 或 String 来初始化 Document。
let document = try Document(text: commonMark)
初始化 Document 将解析 CommonMark 并创建一个您可以访问的 AST。 该文档包含顶级块元素列表,每个块元素可以包含其他块元素或内联元素。 块元素可以是容器块或叶块。 容器块可以包含其他块,而叶块不能。
采用 Node 协议的核心类型支持使用 attributedText
方法转换为 NSAttributedString (大多数类型都支持,但目前存在一些限制,特别是内联图像和 HTML - 包括内联和块)。
可以使用 Style
类型指定 attributedText 方法使用的字体和颜色。 Style
的默认实现由 DefaultStyle
提供。
CMark* 类型(部分受到 CocoaMarkdown 的启发)在 cmark-gfm 之上提供了一个 Swift 友好的接口。 只需在您的 Podfile 中包含 Maaku/CMark
子规范,即可单独使用 CMark 类型,而无需 Core。
插件遵循一种约定,即插件以 CommonMark 文本中的单个链接的形式出现。 这是一个 youtube 插件在 CommonMark 中可能显示的样子示例:
Some other markdown text.
[youtubevideo](https://youtu.be/kkdBB1hVLX0)
More markdown.
要添加对此插件的支持,我们需要实现两个协议:Plugin 和 PluginParser(在 Plugin.swift 中定义,并在下面显示以供参考)。
public protocol Plugin: LeafBlock {
static var pluginName: PluginName { get }
}
public protocol PluginParser {
var name: String { get }
func parse(text: String) -> Plugin?
}
Youtube 插件在框架中作为示例提供(如果您使用 CocoaPods 安装,则作为可选子规范)。
public struct YoutubePlugin: Plugin {
public static let pluginName: PluginName = "youtubevideo"
public let url: URL
public var videoId: String? {
return url.path.components(separatedBy: "/").last
}
public init(url: URL) {
self.url = url
}
}
pluginName
值对于插件应该是唯一的。 它可以与用于 PluginParser 的 name
相同,但不需要。
public struct YoutubePluginParser: PluginParser {
public let name = "youtubevideo"
public func parse(text: String) -> Plugin? {
guard let url = parseURL(text) else {
return nil
}
return YoutubePlugin(url: url)
}
public init() {
}
}
name
值应与您用于插件的链接文本匹配。 由于 Youtube 插件看起来像 [youtubevideo](https://youtu.be/kkdBB1hVLX0)
,因此 youtubevideo
用于 name
。
原始链接目标被传递给 parse 方法。 您可以决定如何处理文本值以初始化您的插件,但有可用的便捷方法可以简化此过程。
splitPluginParams
方法支持链接目标中多个插件参数的以下格式:
param1::value1|param2::value2|param3::value3
splitPluginParams
将以该格式拆分参数为一个字典,您可以使用该字典来初始化您的插件。
假设一个 Youtube 插件看起来像这样
[youtubevideo](source::https://youtu.be/kkdBB1hVLX0||caption::Checkout this video)
然后插件将更新为如下所示
public struct YoutubePlugin: Plugin {
public static let pluginName: PluginName = "youtubevideo"
public let url: URL
public let caption: String?
public var videoId: String? {
return url.path.components(separatedBy: "/").last
}
public init(url: URL, caption: String?) {
self.url = url
self.caption = caption
}
}
而 PluginParser 可能会看起来像
public struct YoutubePluginParser: PluginParser {
public let name = "youtubevideo"
public func parse(text: String) -> Plugin? {
let parameters = splitPluginParams(text)
guard parameters.count > 0,
let source = parameters["source"],
let url = URL(string: source) else {
return nil
}
let caption = parameters["caption"]
return YoutubePlugin(url: url, caption: caption)
}
public init() {
}
}
PluginParser 必须先在 PluginManager
中注册,然后才能被 Maaku 解析器使用。 如果您不注册插件,它将显示为 Link 或 Text 而不是 Plugin。
要注册 PluginParser,请初始化它并将其传递给 PluginManager.registerParsers
。
对于 Youtube 示例
PluginManager.registerParsers([YoutubePluginParser()])