# MarkdownUIKit
**Repository Path**: kaelinda/markdown-uikit
## Basic Information
- **Project Name**: MarkdownUIKit
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-12-25
- **Last Updated**: 2025-01-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: Markdown, Swift, UIKit
## README
# MarkdownUIKit
一个基于 Down 库的轻量级 UIKit Markdown 渲染器。
## 特性
- 支持所有常用的 Markdown 语法
- 标题(H1-H6)
- 段落和文本样式(加粗、斜体、删除线)
- 列表(有序列表、无序列表、任务列表)
- 代码块(支持语法高亮)
- 表格(支持对齐方式)
- 图片(支持缩放和查看)
- 链接(支持自定义处理)
- 引用块
- HTML 标签支持
- 主题系统
- 内置亮色和暗色主题
- 支持自定义主题
- 支持动态切换主题
- 代码语法高亮
- 支持多种编程语言
- 内置多种高亮主题(Xcode、Dracula等)
- 支持复制代码
- 图片处理
- 基于 Kingfisher 的图片加载和缓存
- 支持图片预览和缩放
- 支持图片加载进度显示
- 支持图片加载失败处理
- 链接处理
- 支持自定义链接处理
- 支持外部链接和内部链接区分
- 支持链接点击回调
- 自定义功能
- 支持自定义 HTML 标签映射为原生视图
- 支持自定义视图的点击事件和数据传递
- 支持扩展新的 Markdown 语法
## 系统要求
- iOS 13.0+
- Swift 5.0+
- Xcode 13.0+
## 安装
### CocoaPods
在 Podfile 中添加:
```ruby
pod 'MarkdownUIKit'
```
然后运行:
```bash
pod install
```
### Swift Package Manager
在 Xcode 中选择 File > Swift Packages > Add Package Dependency,输入:
```
https://github.com/yourusername/MarkdownUIKit.git
```
## 快速开始
### 基本使用
```swift
import MarkdownUIKit
class ViewController: UIViewController {
private let markdownView = MarkdownView()
override func viewDidLoad() {
super.viewDidLoad()
// 添加到视图层级
view.addSubview(markdownView)
// 设置约束
markdownView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
// 渲染 Markdown 文本
markdownView.render("# Hello, World!")
}
}
```
### 主题配置
```swift
// 使用内置主题
markdownView.updateTheme(.light) // 或 .dark
// 自定义主题
let customTheme = MarkdownTheme(
text: TextConfig(
font: .systemFont(ofSize: 16),
textColor: .label
),
// ... 其他配置
)
markdownView.updateTheme(customTheme)
```
### 代码块配置
```swift
// 设置代码块样式
let codeBlockStyle = CodeBlockStyle(
font: .monospacedSystemFont(ofSize: 14, weight: .regular),
textColor: .label,
backgroundColor: .systemBackground,
// ... 其他配置
)
markdownView.updateCodeBlockStyle(codeBlockStyle)
// 切换代码块主题
markdownView.updateSyntaxTheme(.xcode) // 或 .dracula
```
### 自定义链接处理
```swift
extension ViewController: MarkdownContentViewDelegate {
func markdownContentView(_ view: MarkdownContentView, shouldHandleLink url: URL) -> Bool {
// 自定义链接处理逻辑
if url.scheme == "custom" {
// 处理自定义链接
return false
}
return true
}
}
```
### 自定义 HTML 标签处理
```swift
// 注册自定义标签处理器
markdownView.registerCustomTag("button") { tagInfo in
let button = UIButton(type: .system)
button.setTitle(tagInfo.content, for: .normal)
// ... 配置按钮
return button
}
```
## 高级功能
### 表格支持
支持标准的 Markdown 表格语法:
```markdown
| 标题1 | 标题2 | 标题3 |
|:------|:-----:|------:|
| 左对齐 | 居中 | 右对齐 |
| 内容1 | 内容2 | 内容3 |
```
### 任务列表
支持可交互的任务列表:
```markdown
- [x] 已完成任务
- [ ] 未完成任务
```
### 自定义标签
支持自定义 HTML 标签转换为原生视图,可以实现复杂的交互功能:
#### 基本使用
```markdown
@用户名
#热门话题#
用户信息卡片
```
#### 注册自定义标签
```swift
// 1. 注册简单按钮
markdownView.registerCustomTag("button") { tagInfo in
let button = UIButton(type: .system)
button.setTitle(tagInfo.content, for: .normal)
// 根据 class 设置样式
if tagInfo.className == "primary" {
button.backgroundColor = .systemBlue
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 5
}
// 设置大小
if tagInfo.attributes["size"] == "large" {
button.contentEdgeInsets = UIEdgeInsets(top: 12, left: 20, bottom: 12, right: 20)
button.titleLabel?.font = .systemFont(ofSize: 18, weight: .medium)
}
return button
}
// 2. 注册用户标签
markdownView.registerCustomTag("tag") { tagInfo in
let label = PaddingLabel()
label.text = tagInfo.content
label.font = .systemFont(ofSize: 14)
label.padding = UIEdgeInsets(top: 2, left: 6, bottom: 2, right: 6)
label.layer.cornerRadius = 4
label.clipsToBounds = true
// 根据 type 设置样式
switch tagInfo.attributes["type"] {
case "user":
label.backgroundColor = .systemBlue.withAlphaComponent(0.1)
label.textColor = .systemBlue
case "topic":
if let color = tagInfo.attributes["color"],
let backgroundColor = UIColor(hex: color) {
label.backgroundColor = backgroundColor.withAlphaComponent(0.1)
label.textColor = backgroundColor
}
default:
break
}
return label
}
// 3. 注册复杂的用户卡片
markdownView.registerCustomTag("userCard") { tagInfo in
let cardView = UserCardView()
cardView.userId = tagInfo.attributes["id"]
cardView.userName = tagInfo.attributes["name"]
cardView.avatarURL = URL(string: tagInfo.attributes["avatar"] ?? "")
cardView.content = tagInfo.content
return cardView
}
```
#### 处理点击事件
```swift
// 1. 实现代理方法
extension ViewController: MarkdownContentViewDelegate {
func markdownContentView(_ view: MarkdownContentView, didTapCustomTag tagInfo: ParsedTagInfo) {
switch tagInfo.tag {
case "button":
// 处理按钮点击
if let action = tagInfo.attributes["action"] {
handleButtonAction(action)
}
case "tag":
// 处理标签点击
if tagInfo.attributes["type"] == "user" {
handleUserTagTap(tagInfo.content)
} else if tagInfo.attributes["type"] == "topic" {
handleTopicTagTap(tagInfo.content)
}
case "userCard":
// 处理用户卡片点击
if let userId = tagInfo.attributes["id"] {
handleUserCardTap(userId)
}
default:
break
}
}
// 处理具体事件
private func handleButtonAction(_ action: String) {
switch action {
case "login":
// 处理登录
presentLoginViewController()
case "share":
// 处理分享
showShareSheet()
default:
break
}
}
private func handleUserTagTap(_ username: String) {
// 跳转到用户主页
let userProfileVC = UserProfileViewController(username: username)
navigationController?.pushViewController(userProfileVC, animated: true)
}
private func handleTopicTagTap(_ topic: String) {
// 跳转到话题页
let topicVC = TopicViewController(topic: topic)
navigationController?.pushViewController(topicVC, animated: true)
}
private func handleUserCardTap(_ userId: String) {
// 处理用户卡片点击
let userDetailVC = UserDetailViewController(userId: userId)
present(userDetailVC, animated: true)
}
}
// 2. 设置代理
markdownView.delegate = self
```
#### 自定义视图示例
```swift
// 自定义用户卡片视图
class UserCardView: UIView {
var userId: String?
var userName: String?
var avatarURL: URL?
var content: String?
private let avatarImageView = UIImageView()
private let nameLabel = UILabel()
private let contentLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupUI()
}
private func setupUI() {
// 设置基本样式
backgroundColor = .systemBackground
layer.cornerRadius = 8
layer.borderWidth = 1
layer.borderColor = UIColor.separator.cgColor
// 添加子视图
addSubview(avatarImageView)
addSubview(nameLabel)
addSubview(contentLabel)
// 配置头像
avatarImageView.contentMode = .scaleAspectFill
avatarImageView.clipsToBounds = true
avatarImageView.layer.cornerRadius = 20
// 配置标签
nameLabel.font = .systemFont(ofSize: 16, weight: .medium)
contentLabel.font = .systemFont(ofSize: 14)
contentLabel.textColor = .secondaryLabel
contentLabel.numberOfLines = 2
// 设置约束
avatarImageView.snp.makeConstraints { make in
make.left.top.equalToSuperview().offset(12)
make.width.height.equalTo(40)
}
nameLabel.snp.makeConstraints { make in
make.left.equalTo(avatarImageView.snp.right).offset(8)
make.right.equalToSuperview().offset(-12)
make.centerY.equalTo(avatarImageView)
}
contentLabel.snp.makeConstraints { make in
make.left.equalTo(avatarImageView)
make.right.equalToSuperview().offset(-12)
make.top.equalTo(avatarImageView.snp.bottom).offset(8)
make.bottom.equalToSuperview().offset(-12)
}
}
// 更新视图内容
func updateContent() {
nameLabel.text = userName
contentLabel.text = content
if let url = avatarURL {
avatarImageView.kf.setImage(
with: url,
placeholder: UIImage(systemName: "person.circle.fill")
)
}
}
}
```
通过以上配置,你可以:
1. 在 Markdown 中使用自定义标签
2. 为标签添加自定义属性和样式
3. 处理标签的点击事件
4. 传递和处理自定义数据
5. 创建复杂的自定义视图组件
## 文档
完整的文档请访问我们的 [Wiki](https://github.com/yourusername/MarkdownUIKit/wiki)
## 贡献指南
我们欢迎所有形式的贡献,包括但不限于:
- 提交问题和建议
- 改进文档
- 提交代码改进
- 添加新功能
请查看 [贡献指南](CONTRIBUTING.md) 了解更多信息。
## 许可证
MarkdownUIKit 使用 MIT 许可证。详情请查看 [LICENSE](LICENSE) 文件。