I have developed a workaround. Basically, you can copy each cell, using the first table object found for a given set of table cells. It's ugly, but does seem to work. Including some code below to show how you can do it.
class ViewController: NSViewController {
@IBOutlet var textView: NSTextView!
override func viewDidAppear() {
super.viewDidAppear()
let html =
"""
<html>
<head>
<title>Testing Tables</title>
<style>
td {
border: 1px solid;
padding: 10px;
}
</style>
</head>
<body>
<table>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</table>
</body>
</html>
"""
let data = html.data(using: .utf8)!
let string = NSMutableAttributedString(html: data, documentAttributes: nil)!
let wholeRange = NSMakeRange(0, string.length)
var table: NSTextTable?
string.enumerateAttribute(.paragraphStyle, in: wholeRange) { value, range, _ in
guard let paragraphStyle = value as? NSParagraphStyle else { return }
let tableBlocks = paragraphStyle.textBlocks.compactMap { $0 as? NSTextTableBlock }
for block in tableBlocks {
if table == nil { table = block.table } // Keep first table found
let newBlock = block.copy(for: table!)
let newStyle = paragraphStyle.mutableCopy() as! NSMutableParagraphStyle
newStyle.textBlocks = [newBlock]
string.addAttribute(.paragraphStyle, value: newStyle, range: range)
}
if tableBlocks.isEmpty { table = nil }
}
textView.textStorage!.setAttributedString(string)
}
}
extension NSTextTableBlock {
func copy(for table: NSTextTable) -> NSTextTableBlock {
let newBlock = NSTextTableBlock(table: table, startingRow: startingRow,
rowSpan: rowSpan, startingColumn: startingColumn, columnSpan: columnSpan)
newBlock.backgroundColor = backgroundColor
newBlock.verticalAlignment = verticalAlignment
for edge: NSRectEdge in [.minX, .minY, .maxX, .maxY] {
for layer: NSTextBlock.Layer in [.border, .margin, .padding] {
let width = width(for: layer, edge: edge)
let valueType = widthValueType(for: layer, edge: edge)
newBlock.setWidth(width, type: valueType, for: layer, edge: edge)
}
newBlock.setBorderColor(borderColor(for: edge), for: edge)
}
for dimension: NSTextBlock.Dimension in [.height, .maximumHeight, .maximumWidth, .minimumHeight, .minimumWidth, .width] {
let value = value(for: dimension)
let valueType = valueType(for: dimension)
newBlock.setValue(value, type: valueType, for: dimension)
}
return newBlock
}
}