Maaku 0.9.2

Maaku 0.9.2

Kristopher Baker 维护。



Maaku 0.9.2

  • Kristopher Baker

Maaku

Build Status Swift CocoaPods Compatible Carthage compatible Swift Package Manager compatible Platform

Maaku 框架提供了对 cmark-gfm 的 Swift 包装,并添加了 Swift 友好的 AST 表示。支持表格、删除线、自动链接和标签过滤器等 gfm 扩展。

Maaku 还支持插件约定,自定义渲染器可以使用。提供了一个插件示例。

TexturedMaaku 基于 Maaku 和 Texture,为 Swift 提供了本地 iOS CommonMark 渲染框架。

安装

CocoaPods

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

Carthage 是一个去中心化的依赖管理器,它构建您的依赖关系,并为您提供二进制框架。

您可以使用以下命令通过 Homebrew 安装 Carthage

$ brew update
$ brew install carthage

要使用 Carthage 将 Maaku 集成到您的 Xcode 项目中,请在 Cartfile 中指定它

github "KristopherGBaker/Maaku" ~> 0.6.0

运行 carthage update 命令来构建框架,并将构建好的 Maaku.framework 拖入您的 Xcode 项目中。

Swift 包管理器

Swift 包管理器(https://swiftlang.cn/package-manager/)是一个用于自动分发 Swift 代码的工具,并集成到 swift 编译器中。它处于早期开发阶段,但 Maaku 支持在支持平台上使用。

您设置好 Swift 包之后,将 Maaku 作为依赖项添加到您的 Package.swift 中的 dependencies 值就像添加任何其他依赖项一样简单。

dependencies: [
    .package(url: "https://github.com/KristopherGBaker/Maaku.git", from: "0.6.0")
]

使用 Swift PM 构建

为 macOS 构建
$ swift build -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.14"
运行测试
$ swift test -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.14"

核心

Document 是使用 Maaku 的主要接口。Document 可以通过传递表示 CommonMark 的 Data 或 String 来初始化。

let document = try Document(text: commonMark)

初始化 Document 将解析 CommonMark 并创建一个可访问的 AST。文档包含一个顶层块元素列表,每个元素可能包含其他块元素或内联元素。块元素可能是容器块或叶块。容器块可以包含其他块,而叶块则不能。

样式

采用节点协议的核心数据类型支持通过attributedText方法转换为NSAttributedString(大多数类型都得到支持,但当前存在一些限制,尤其是在嵌入式图像和HTML方面——包括内嵌和块形式的HTML)。

可通过Style类型指定由attributedText方法使用的字体和颜色。提供了带有DefaultStyle的默认实现。

CMark

CMark*类型(部分灵感来自CocoaMarkdown)在cmark-gfm之上为Swift提供了一组友好的接口。CMark类型可以独立于Core使用,只需在Podfile中包含Maaku/CMark子规约即可。

插件

插件遵循一种约定,即插件以CommonMark文本中段落中单个链接的形式出现。以下是一个CommonMark中YouTube插件可能出现的形式示例

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相同,但不需要相同。

PluginParser示例

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

将原始链接地址传递给解析方法。你可以决定如何处理文本值来初始化你的插件,但也为插件提供了便利方法来简化此过程。

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() {

    }
}

注册插件

在 Maaku 解析器使用之前,必须使用 PluginManager 注册 PluginParser。如果您不注册插件,它将作为链接或文本而非插件出现。

要注册 PluginParser,先对其进行初始化,并将其传递给 PluginManager.registerParsers

对于 YouTube 例子

PluginManager.registerParsers([YoutubePluginParser()])