Skip to content

Commit b031417

Browse files
authored
Merge pull request #78 from ZhgChgLi/fix/p-space-and-ios18-crash
fix: breakline and space bug
2 parents 73e145f + a091c0f commit b031417

File tree

1 file changed

+52
-26
lines changed

1 file changed

+52
-26
lines changed

Sources/ZMarkupParser/Core/Processor/MarkupNSAttributedStringVisitor.swift

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct MarkupNSAttributedStringVisitor: MarkupVisitor {
2222

2323
func visit(_ markup: BreakLineMarkup) -> Result {
2424
let style = collectMarkupStyle(markup)
25-
return makeString(in: markup, string: Self.breakLineSymbol, attributes: [.breaklinePlaceholder: NSAttributedString.Key.BreaklinePlaceholder.breaklineTag], style: style)
25+
return makeString(in: markup, string: Self.breakLineSymbol, attributes: [.breaklinePlaceholder: BreaklineTag()], style: style)
2626
}
2727

2828
func visit(_ markup: RawStringMarkup) -> Result {
@@ -119,7 +119,16 @@ struct MarkupNSAttributedStringVisitor: MarkupVisitor {
119119

120120
func visit(_ markup: ParagraphMarkup) -> Result {
121121
let attributedString = collectAttributedString(markup)
122-
let thisAttributedString = NSMutableAttributedString(attributedString: attributedString)
122+
var thisAttributedString = NSMutableAttributedString(attributedString: attributedString)
123+
124+
// This code replicates browser behavior by trimming leading and trailing whitespace around HTML tags.
125+
// It removes unnecessary spaces and newlines at the beginning and end of the NSAttributedString.
126+
// If the entire content is just whitespace, it replaces it with an empty string.
127+
128+
if thisAttributedString.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
129+
thisAttributedString = NSMutableAttributedString(string: "")
130+
}
131+
123132
thisAttributedString.markPrefixTagBoundaryBreakline()
124133
thisAttributedString.markSuffixTagBoundaryBreakline()
125134

@@ -221,35 +230,37 @@ extension MarkupNSAttributedStringVisitor {
221230
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)
222231
let totalLength = mutableAttributedString.string.utf16.count
223232

233+
var rangesToDelete: [NSRange] = []
234+
224235
// merge tag Boundary Breakline, e.g. </p></div> -> /n/n -> /n
225-
var pre: (NSRange, NSAttributedString.Key.BreaklinePlaceholder)?
236+
var pre: (NSRange, any BreaklinePlaceholder)?
226237
mutableAttributedString.enumerateAttribute(.breaklinePlaceholder, in: NSMakeRange(0, totalLength)) { value, range, _ in
227-
if let breaklinePlaceholder = value as? NSAttributedString.Key.BreaklinePlaceholder {
238+
if let breaklinePlaceholder = value as? any BreaklinePlaceholder {
228239
if range.location == 0 {
229-
mutableAttributedString.deleteCharacters(in: range)
240+
rangesToDelete.append(range)
230241
} else if let pre = pre {
231242
let preRange = pre.0
232243
let preBreaklinePlaceholder = pre.1
233244

234245
switch (preBreaklinePlaceholder, breaklinePlaceholder) {
235-
case (.breaklineTag, .tagBoundarySuffix):
246+
case (is BreaklineTag, is TagBoundarySuffix):
236247
// <br/></div> -> /n/n -> /n
237-
mutableAttributedString.deleteCharacters(in: preRange)
238-
case (.breaklineTag, .tagBoundaryPrefix):
248+
rangesToDelete.append(preRange)
249+
case (is BreaklineTag, is TagBoundaryPrefix):
239250
// <br/><p> -> /n/n -> /n
240-
mutableAttributedString.deleteCharacters(in: preRange)
241-
case (.tagBoundarySuffix, .tagBoundarySuffix):
251+
rangesToDelete.append(preRange)
252+
case (is TagBoundarySuffix, is TagBoundarySuffix):
242253
// </div></div> -> /n/n -> /n
243-
mutableAttributedString.deleteCharacters(in: preRange)
244-
case (.tagBoundarySuffix, .tagBoundaryPrefix):
254+
rangesToDelete.append(preRange)
255+
case (is TagBoundarySuffix, is TagBoundaryPrefix):
245256
// </div><p> -> /n/n -> /n
246-
mutableAttributedString.deleteCharacters(in: preRange)
247-
case (.tagBoundaryPrefix, .tagBoundaryPrefix):
257+
rangesToDelete.append(preRange)
258+
case (is TagBoundaryPrefix, is TagBoundaryPrefix):
248259
// <div><p> -> /n/n -> /n
249-
mutableAttributedString.deleteCharacters(in: preRange)
250-
case (.tagBoundaryPrefix, .tagBoundarySuffix):
260+
rangesToDelete.append(preRange)
261+
case (is TagBoundaryPrefix, is TagBoundarySuffix):
251262
// <p></p> -> /n/n -> /n
252-
mutableAttributedString.deleteCharacters(in: preRange)
263+
rangesToDelete.append(preRange)
253264
default:
254265
break
255266
}
@@ -260,6 +271,11 @@ extension MarkupNSAttributedStringVisitor {
260271
}
261272
}
262273

274+
// Delete ranges in reverse order to avoid range shifting issues
275+
for range in rangesToDelete.reversed() {
276+
mutableAttributedString.deleteCharacters(in: range)
277+
}
278+
263279
return mutableAttributedString
264280
}
265281

@@ -338,23 +354,33 @@ private extension MarkupNSAttributedStringVisitor {
338354
}
339355
}
340356

357+
private protocol BreaklinePlaceholder: Hashable {
358+
359+
}
360+
361+
private class TagBoundaryPrefix: NSObject, BreaklinePlaceholder{
362+
363+
}
364+
365+
private class TagBoundarySuffix: NSObject, BreaklinePlaceholder{
366+
367+
}
368+
369+
private class BreaklineTag: NSObject, BreaklinePlaceholder{
370+
371+
}
372+
373+
341374
private extension NSAttributedString.Key {
342375
static let breaklinePlaceholder: NSAttributedString.Key = .init("breaklinePlaceholder")
343-
struct BreaklinePlaceholder: OptionSet {
344-
let rawValue: Int
345-
346-
static let tagBoundaryPrefix = BreaklinePlaceholder(rawValue: 1)
347-
static let tagBoundarySuffix = BreaklinePlaceholder(rawValue: 2)
348-
static let breaklineTag = BreaklinePlaceholder(rawValue: 3)
349-
}
350376
}
351377

352378
private extension NSMutableAttributedString {
353379
func markPrefixTagBoundaryBreakline() {
354-
self.insert(NSAttributedString(string: MarkupNSAttributedStringVisitor.breakLineSymbol, attributes: [.breaklinePlaceholder: NSAttributedString.Key.BreaklinePlaceholder.tagBoundaryPrefix]), at: 0)
380+
self.insert(NSAttributedString(string: MarkupNSAttributedStringVisitor.breakLineSymbol, attributes: [.breaklinePlaceholder: TagBoundaryPrefix()]), at: 0)
355381
}
356382

357383
func markSuffixTagBoundaryBreakline() {
358-
self.append(NSAttributedString(string: MarkupNSAttributedStringVisitor.breakLineSymbol, attributes: [.breaklinePlaceholder: NSAttributedString.Key.BreaklinePlaceholder.tagBoundarySuffix]))
384+
self.append(NSAttributedString(string: MarkupNSAttributedStringVisitor.breakLineSymbol, attributes: [.breaklinePlaceholder: TagBoundarySuffix()]))
359385
}
360386
}

0 commit comments

Comments
 (0)