Marky Mark
Marky Mark 是一个用 Swift 编写的解析器,可以将 markdown 转换为原生视图。其外观高度可自定义,支持的 markdown 语法易于扩展。
示例
要运行示例项目,首先克隆仓库,然后从 Example 目录运行 pod install
要求
- iOS 8.0+
- Xcode 8.0+
安装
构建MarkyMark需要CocoaPods 1.0.0+。
要使用CocoaPods将MarkyMark集成到您的Xcode项目中,请在您的Podfile
中指定它。
pod "markymark"
或者,使用Swift Package Manager添加MarkyMark到您的项目中:
https://github.com/M2Mobi/Marky-Mark
简单用法
默认样式视图
let markDownView = MarkDownTextView()
markDownView.text = "# Header\nParagraph"
自定义样式视图
Markymark有很多样式选项,请查看本README文件的样式部分中的示例。一个简单的例子
let markDownView = MarkDownTextView()
markDownView.styling.headingStyling.textColorsForLevels = [
.orange, //H1 (i.e. # Title)
.black, //H2, ... (i.e. ## Subtitle, ### Sub subtitle)
]
markDownView.styling.linkStyling.textColor = .blue
markDownView.styling.paragraphStyling.baseFont = .systemFont(ofSize: 14)
markDownView.text = "# Header\nParagraph"
默认风味中支持的标签
注意:不同的标签可以通过扩展ContentfulFlavor(默认)或者实现一个符合Flavor
类并实现所需的Rule
来支持。
Headings
# H1
## H2
### H3
#### H4
##### H5
###### H6
Lists
- item
- item
* item
* item
+ item
+ item
a. item
b. item
1. item
2. item
Emphasis
*Em*
_Em_
**Strong**
__Strong__
~~Strike through~~
Images

Links
[Link text](https://www.example.net)
Code
`code`
```code```
自定义默认样式
默认样式实例
var styling = DefaultStyling()
段落(普通文本)
Markdown 示例:一些文本
styling.paragraphStyling.baseFont = .systemFont(ofSize: 14)
styling.paragraphStyling.textColor = .black
styling.paragraphStyling.contentInsets = UIEdgeInsets(top:0, left: 0, bottom: 5, right: 0)
styling.paragraphStyling.lineHeight = 4
styling.paragraphStyling.isBold = false
styling.paragraphStyling.isItalic = false
styling.paragraphStyling.textAlignment = .left
标题
Markdown 示例:# 标题
或 ##副标题
等。
styling.headingStyling.fontsForLevels = [
UIFont.boldSystemFontOfSize(24), //H1
UIFont.systemFontOfSize(18), //H2
UIFont.systemFontOfSize(16) //H3, ... (last item will be next levels as well)
]
styling.headingStyling.colorsForLevels = [
.red, //H1
.black, //H2, ... (last item will be next levels as well)
]
// Margins
styling.headingStyling.contentInsetsForLevels = [
UIEdgeInsets(top: 5, left: 0, bottom: 15, right: 10), // H1
UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 10) //H2, ... (last item will be next levels as well)
]
styling.headingStyling.isBold = false
styling.headingStyling.isItalic = false
styling.headingStyling.isUnderlined = false
styling.headingStyling.textAlignment = .left
链接样式
Markdown 示例 [Google](http://www.google.com)
styling.linkStyling.textColor = .black
styling.linkStyling.baseFont = nil // Default: nil. Setting baseFont to nil will inherit font from paragraphStyling
styling.linkStyling.isBold = false
styling.linkStyling.isItalic = false
styling.linkStyling.isUnderlined = true
列表样式
Markdown 示例
- List item 1
- List item 2
- Nested List item
// By default a font will be used with the bullet character `•`. Use the follow properties to configure it's size and color:
styling.listStyling.bulletFont = .systemFont(ofSize: 14)
styling.listStyling.bulletColor = .black
// Bullets can also be images for more complex styling. When setting images, bullet font and color won't be used anymore
// Array of images used as bullet for each level of nested list items
styling.listStyling.bulletImages = [
UIImage(named: "circle"),
UIImage(named: "emptyCircle"),
UIImage(named: "line"),
UIImage(named: "square")
]
// Size of the images
styling.listStyling.bulletViewSize = CGSize(width: 16, height: 16)
styling.listStyling.baseFont = .systemFont(ofSize: 14)
styling.listStyling.contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 10)
//Amount of space underneath each list item
styling.listStyling.bottomListItemSpacing = 5
// Number of pixels to indent for each nested list level
styling.listStyling.listIdentSpace = 15
styling.listStyling.textColor = .black
样式同样适用于
styling.paragraphStyling
styling.italicStyling
styling.boldStyling
styling.strikeThroughStyling
styling.imageStyling
styling.linkStyling
styling.horizontalLineStyling
styling.codeBlockStyling
styling.inlineCodeBlockStyling
styling.quoteStyling
请查阅 DefaultStyling
类以获取更多信息
无障碍:动态类型(字体缩放)
启用 MarkDownTextView 上的动态类型
markDownView.hasScalableFonts = true
在某些情况下,您可能希望为每个字体配置最大尺寸(默认为 nil
)。以下是如何限制段落字体大小的示例
markDownView.styling.paragraphStyling.maximumPointSize = 26
要设置标题的最大字体点大小,您可以在 headingStyling 上设置 'maximumPointSizeForLevels'。以下示例设置了 heading1、heading2、heading3 的最大尺寸
markDownView.styling.headingStyling.maximumPointSizeForLevels = [36, 20, 18]
高级用法
高级用法仅适用于非常特定的情况。创建样式子集、制作不同的样式组合、支持不同的Markdown规则(语法)或修改之后生成的某些视图。
自定义样式对象
struct CustomMarkyMarkStyling: Styling {
var headerStyling = CustomHeaderStyling()
var paragraphStyling = ParagraphStyling()
var linkStyling = ListStyling()
var itemStylingRules: [ItemStyling] {
return [headerStyling, paragraphStyling, linkStyling]
}
}
您可以通过查看其他 Styling
对象的实现方式,如 HeaderStyling
,来实现 CustomHeaderStyling
。确保您的 CustomHeaderStyling
符合所有您希望自定义样式支持的样式规则。例如,符合 TextColorStylingRule
以支持您的自定义样式的 textStyle。
每个样式规则都可以通过符合 ItemStyling
并实现所需的方法来应用到 MarkdownItem 上。
public func isApplicableOn(_ markDownItem: MarkDownItem) -> Bool {
return markDownItem is HeaderMarkDownItem
}
这将让机制知道应该将您的样式应用到 HeaderMarkdownItem 上。
您可以通过将其传递给 MarkdownTextView
构造函数来注入您的新样式对象。
MarkDownTextView(styling: CustomMarkyMarkStyling())
添加您自己的规则
添加新规则需要基于以下协议创建三个新类
Rule
能够识别所需 Markdown 语法MarkdownItem
用于您的新元素,该元素由您的新规则创建LayoutBlockBuilder
能够将您的 MarkdownItem 转换为布局
将规则添加到 MarkyMark
markyMark.addRule(MyCustomRule())
或在使用 MarkdownTextView 时
markdownTextView.add(rule: MyCustomRule())
将块构建器添加到您的布局转换器中
converter.addLayoutBlockBuilder(MyCustomLayoutBlockBuilder())
或在使用 MarkdownTextView 时使用以下任一选项(取决于配置视图或 attributedString)
markdownTextView.addViewLayoutBlockBuilder(MyCustomLayoutBlockBuilder())
markdownTextView.addAttributedStringLayoutBlockBuilder(MyCustomLayoutBlockBuilder())
如果需要,您还可以将自定义样式类添加到默认样式
styling.addStyling(MyCustomStyling())
转换器钩子
转换器有一个回调方法,每次将 MarkdownItem
转换为布局时都会被调用。
converter.didConvertElement = {
markDownItem, view in
// Do something with markDownItem and / or view here
}
当使用 MarkdownTextView 时
markDownTextView.onDidConvertMarkDownItemToView = {
markDownItem, view in
}
链接行为
默认情况下,Markymark 使用 UIApplication.shared.delegate.open(_:open:options)
打开 URL。只有在实现了此方法时才会打开链接。Markymark 允许通过传递自定义 URLOpener,一个符合 URLOpener
协议的对象来更改此行为。
let markDownView = MarkDownTextView()
markDownTextView?.urlOpener = MyCustomerURLOpener()
在 Extensions 中使用 Markymark
Markymark 同样支持 Today 扩展的用法。默认情况下,点击 URL 不起作用,因为扩展没有权限访问 UIApplication.shared,为了支持链接,你可以向 MarkyDownTextView 传递不同的 URL 打开器。请参考 Example 项目查看一个工作示例
markDownTextView?.urlOpener = ExtensionContextURLOpener(extensionContext: self.extensionContext)
作者
M2mobi, [email protected]
许可证
MarkyMark 基于 MIT 许可证。请参阅 LICENSE 文件获取更多信息。