Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions Examples/Demo/Demo/SyntaxHighlighter/TextOutputFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct TextOutputFormat: OutputFormat {
extension TextOutputFormat {
struct Builder: OutputBuilder {
private let theme: Theme
private var accumulatedText: [Text]
private var accumulatedText: [AttributedString]

fileprivate init(theme: Theme) {
self.theme = theme
Expand All @@ -25,21 +25,24 @@ extension TextOutputFormat {

mutating func addToken(_ token: String, ofType type: TokenType) {
let color = self.theme.tokenColors[type] ?? self.theme.plainTextColor
self.accumulatedText.append(Text(token).foregroundColor(.init(uiColor: color)))
var aster = AttributedString(token)
aster.foregroundColor = .init(uiColor: color)
self.accumulatedText.append(aster)
}

mutating func addPlainText(_ text: String) {
self.accumulatedText.append(
Text(text).foregroundColor(.init(uiColor: self.theme.plainTextColor))
)
var aster = AttributedString(text)
aster.foregroundColor = .init(uiColor: self.theme.plainTextColor)
self.accumulatedText.append(aster)
}

mutating func addWhitespace(_ whitespace: String) {
self.accumulatedText.append(Text(whitespace))
self.accumulatedText.append(AttributedString(whitespace))
}

func build() -> Text {
self.accumulatedText.reduce(Text(""), +)
let text = self.accumulatedText.reduce(AttributedString(""), +)
return Text(text)
}
}
}
8 changes: 7 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@ let package = Package(
.library(
name: "MarkdownUI",
targets: ["MarkdownUI"]
)
),
.library(name: "YYText", targets: ["YYText"])
],
dependencies: [
.package(url: "https://github.com/gonzalezreal/NetworkImage", from: "6.0.0"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.10.0"),
.package(url: "https://github.com/swiftlang/swift-cmark", from: "0.4.0"),
],
targets: [
.target(
name: "YYText",
path: "Sources/YYText"
),
.target(
name: "MarkdownUI",
dependencies: [
"YYText",
.product(name: "cmark-gfm", package: "swift-cmark"),
.product(name: "cmark-gfm-extensions", package: "swift-cmark"),
.product(name: "NetworkImage", package: "NetworkImage"),
Expand Down
28 changes: 28 additions & 0 deletions Sources/MarkdownUI/Event/MDEventManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// MDEventManager.swift
// MarkdownTest
//
// Created by Ericmao on 2025/1/4.
//

import Foundation
import UIKit

class MDEventManager {
static let shared = MDEventManager()

private init() {

}

//点击 Markdown 中的数字索引
@objc func onIndexClicked(_ tapgr: UITapGestureRecognizer) {
if let label = tapgr.view as? UILabel {
let text = label.text
let frame = label.frame

print("On Link Index clicked:\(String(describing: text)) \(frame)")
}
}

}
29 changes: 29 additions & 0 deletions Sources/MarkdownUI/Extensibility/LinkURLDecode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// File.swift
// swift-markdown-ui
//
// Created by aterzhang on 2024/12/17.
//

import Foundation

public func parseMarkdownLink(_ inputString: String?) -> (String, String)? {
guard let markdown = inputString else {
return nil
}
let pattern = "\\[(.*?)\\]\\((.*?)\\)"
let regex = try? NSRegularExpression(pattern: pattern, options: [])

if let match = regex?.firstMatch(in: markdown, options: [], range: NSRange(location: 0, length: markdown.utf16.count)) {
let textRange = Range(match.range(at: 1), in: markdown)
let urlRange = Range(match.range(at: 2), in: markdown)

if let textRange = textRange, let urlRange = urlRange {
let textContent = String(markdown[textRange])
let urlContent = String(markdown[urlRange])
return (textContent, urlContent)
}
}

return nil
}
22 changes: 18 additions & 4 deletions Sources/MarkdownUI/Renderer/AttributedStringInlineRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import Foundation

let LINK_SEPERATOR = "|||"

extension InlineNode {
func renderAttributedString(
baseURL: URL?,
textStyles: InlineTextStyles,
softBreakMode: SoftBreak.Mode,
attributes: AttributeContainer
attributes: AttributeContainer,
textReplacer: ((String, String) -> String)?
) -> AttributedString {
var renderer = AttributedStringInlineRenderer(
baseURL: baseURL,
textStyles: textStyles,
softBreakMode: softBreakMode,
attributes: attributes
attributes: attributes,
textReplacer: textReplacer
)
renderer.render(self)
return renderer.result.resolvingFonts()
return renderer.result
}
}

Expand All @@ -26,17 +30,20 @@ private struct AttributedStringInlineRenderer {
private let softBreakMode: SoftBreak.Mode
private var attributes: AttributeContainer
private var shouldSkipNextWhitespace = false
private var textReplacer: ((String, String) -> String)?

init(
baseURL: URL?,
textStyles: InlineTextStyles,
softBreakMode: SoftBreak.Mode,
attributes: AttributeContainer
attributes: AttributeContainer,
textReplacer: ((String, String) -> String)?
) {
self.baseURL = baseURL
self.textStyles = textStyles
self.softBreakMode = softBreakMode
self.attributes = attributes
self.textReplacer = textReplacer
}

mutating func render(_ inline: InlineNode) {
Expand Down Expand Up @@ -66,6 +73,13 @@ private struct AttributedStringInlineRenderer {

private mutating func renderText(_ text: String) {
var text = text
if let urlStr = self.attributes.link?.absoluteString {
self.attributes.link = URL(string: "[\(text)](\(urlStr))", relativeTo: self.baseURL)

if let replacer = self.textReplacer {
text = replacer(text, urlStr)
}
}

if self.shouldSkipNextWhitespace {
self.shouldSkipNextWhitespace = false
Expand Down
Loading