Skip to content

Commit 9b0fe8d

Browse files
authored
Merge pull request #10 from i-stack/1.4.0_dev
Enhance STMarkdown components with new styling and header management
2 parents 97c4ba0 + e188949 commit 9b0fe8d

4 files changed

Lines changed: 241 additions & 60 deletions

File tree

Example/STBaseProjectExampleTests/STMarkdownFixTests.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,47 @@ final class STMarkdownTableViewModelCitationTests: XCTestCase {
259259
@MainActor
260260
final class STMarkdownTableViewCitationTapTests: XCTestCase {
261261

262+
func testCustomHeaderItemsAreVisibleAfterLayout() {
263+
let image = self.makeTestIcon()
264+
let style = STMarkdownStyle(
265+
font: .systemFont(ofSize: 14),
266+
textColor: .label,
267+
lineHeight: 18,
268+
kern: 0,
269+
tableHeaderItems: [
270+
STMarkdownTableHeaderItem(identifier: "custom-copy", image: image) { _ in },
271+
STMarkdownTableHeaderItem(identifier: "custom-fullscreen", image: image) { _ in }
272+
],
273+
tableHeaderButtonWidth: 16
274+
)
275+
let tableView = STMarkdownTableView(style: style)
276+
277+
tableView.frame = CGRect(x: 0, y: 0, width: 320, height: 120)
278+
tableView.layoutIfNeeded()
279+
280+
let buttons = self.headerButtons(in: tableView)
281+
XCTAssertEqual(buttons.map(\.accessibilityIdentifier), ["custom-copy", "custom-fullscreen"])
282+
XCTAssertTrue(buttons.allSatisfy { !$0.frame.isEmpty }, "自定义 headerItems 按钮应有稳定非零布局尺寸")
283+
XCTAssertTrue(buttons.allSatisfy { $0.image(for: .normal) != nil }, "自定义 headerItems 按钮应保留配置的图片")
284+
}
285+
286+
func testReassigningHeaderItemsRemovesOldButtons() {
287+
let image = self.makeTestIcon()
288+
let tableView = STMarkdownTableView(style: .default)
289+
tableView.headerItems = [
290+
STMarkdownTableHeaderItem(identifier: "first", image: image) { _ in },
291+
STMarkdownTableHeaderItem(identifier: "second", image: image) { _ in }
292+
]
293+
tableView.headerItems = [
294+
STMarkdownTableHeaderItem(identifier: "third", image: image) { _ in }
295+
]
296+
297+
tableView.frame = CGRect(x: 0, y: 0, width: 320, height: 120)
298+
tableView.layoutIfNeeded()
299+
300+
XCTAssertEqual(self.headerButtons(in: tableView).map(\.accessibilityIdentifier), ["third"])
301+
}
302+
262303
func testCitationTapCallbackFiredWhenCellSelected() {
263304
let style = STMarkdownStyle.default
264305
let tableView = STMarkdownTableView(style: style)
@@ -481,4 +522,22 @@ final class STMarkdownTableViewCitationTapTests: XCTestCase {
481522
private func gradientLayer(named name: String, in view: UIView) -> CAGradientLayer? {
482523
view.layer.sublayers?.first(where: { $0.name == name }) as? CAGradientLayer
483524
}
525+
526+
private func headerButtons(in view: UIView) -> [UIButton] {
527+
view.subviews.flatMap { subview -> [UIButton] in
528+
var buttons = self.headerButtons(in: subview)
529+
if let button = subview as? UIButton {
530+
buttons.insert(button, at: 0)
531+
}
532+
return buttons
533+
}
534+
}
535+
536+
private func makeTestIcon() -> UIImage {
537+
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 16, height: 16))
538+
return renderer.image { context in
539+
UIColor.black.setFill()
540+
context.fill(CGRect(x: 3, y: 3, width: 10, height: 10))
541+
}
542+
}
484543
}

Sources/STMarkdown/Core/STMarkdownStyle.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ public struct STMarkdownStyle: @unchecked Sendable {
5454
public var tableHeaderTextColor: UIColor?
5555
public var tableBorderColor: UIColor?
5656
public var tableBackgroundColor: UIColor?
57+
/// 顶部工具条背景色(nil 时回退到 tableBackgroundColor → secondarySystemBackground)
58+
public var tableHeaderBarBackgroundColor: UIColor?
59+
/// 表格行最小高度,同步影响 UICollectionView 布局与 computeSize
60+
public var tableMinimumRowHeight: CGFloat
61+
/// 单元格字体,非 nil 时在 configure 阶段覆盖 attributedContent 中的字体大小(保留粗/斜等修饰)
62+
public var tableFont: UIFont?
63+
/// 工具条按钮项(nil → makeDefaultHeaderItems();外界通过 style 统一分发)
64+
public var tableHeaderItems: [STMarkdownTableHeaderItem]?
65+
/// 工具条按钮触控区宽度
66+
public var tableHeaderButtonWidth: CGFloat
67+
/// 容器圆角蒙版,默认四角全圆
68+
public var tableCornerMask: CACornerMask
5769
public var imagePlaceholderTextColor: UIColor?
5870
public var imagePlaceholderBackgroundColor: UIColor?
5971
public var imagePlaceholderCaptionColor: UIColor?
@@ -158,6 +170,13 @@ public struct STMarkdownStyle: @unchecked Sendable {
158170
tableHeaderTextColor: UIColor? = nil,
159171
tableBorderColor: UIColor? = nil,
160172
tableBackgroundColor: UIColor? = nil,
173+
tableHeaderBarBackgroundColor: UIColor? = nil,
174+
tableMinimumRowHeight: CGFloat = 35,
175+
tableFont: UIFont? = nil,
176+
tableHeaderItems: [STMarkdownTableHeaderItem]? = nil,
177+
tableHeaderButtonWidth: CGFloat = 30,
178+
tableCornerMask: CACornerMask = [.layerMinXMinYCorner, .layerMaxXMinYCorner,
179+
.layerMinXMaxYCorner, .layerMaxXMaxYCorner],
161180
imagePlaceholderTextColor: UIColor? = nil,
162181
imagePlaceholderBackgroundColor: UIColor? = nil,
163182
imagePlaceholderCaptionColor: UIColor? = nil,
@@ -223,6 +242,12 @@ public struct STMarkdownStyle: @unchecked Sendable {
223242
self.tableHeaderTextColor = tableHeaderTextColor
224243
self.tableBorderColor = tableBorderColor
225244
self.tableBackgroundColor = tableBackgroundColor
245+
self.tableHeaderBarBackgroundColor = tableHeaderBarBackgroundColor
246+
self.tableMinimumRowHeight = tableMinimumRowHeight
247+
self.tableFont = tableFont
248+
self.tableHeaderItems = tableHeaderItems
249+
self.tableHeaderButtonWidth = tableHeaderButtonWidth
250+
self.tableCornerMask = tableCornerMask
226251
self.imagePlaceholderTextColor = imagePlaceholderTextColor
227252
self.imagePlaceholderBackgroundColor = imagePlaceholderBackgroundColor
228253
self.imagePlaceholderCaptionColor = imagePlaceholderCaptionColor

Sources/STMarkdown/Table/STMarkdownTableCell.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,20 @@ public final class STMarkdownTableCell: UICollectionViewCell {
5454
}
5555

5656
func configure(with cellData: STMarkdownTableCellData, style: STMarkdownStyle) {
57-
self.contentLabel.attributedText = cellData.attributedContent
57+
let displayText: NSAttributedString
58+
if let tableFont = style.tableFont {
59+
let mutable = NSMutableAttributedString(attributedString: cellData.attributedContent)
60+
let fullRange = NSRange(location: 0, length: mutable.length)
61+
mutable.enumerateAttribute(.font, in: fullRange, options: []) { value, range, _ in
62+
if let originalFont = value as? UIFont {
63+
mutable.addAttribute(.font, value: originalFont.withSize(tableFont.pointSize), range: range)
64+
}
65+
}
66+
displayText = mutable
67+
} else {
68+
displayText = cellData.attributedContent
69+
}
70+
self.contentLabel.attributedText = displayText
5871
let bgColor = style.tableBackgroundColor ?? UIColor.secondarySystemBackground
5972
self.contentView.backgroundColor = cellData.role.isHeader
6073
? bgColor.withAlphaComponent(0.92)

0 commit comments

Comments
 (0)