# 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) 文件。