I am looking to support rendering markdown text while adding corporate branding styles (typography and colors for headers specified by the design team, etc).
All was going well until I encountered Ordered List and began seeing some unexpected behavior.
Lets take for example some sample markdown as shown below.
let sampleMarkdown: String = """
# Ordered List Test
This is some sample markdown used to test ordered lists.
1. Line item one of a sample markdown ordered list.
2. This is the second line item of a sample markdown ordered list.
3. And finally, the third line item of a sample markdown ordered list.
"""
Now, let's say for each item in the ordered list, I would like to assign a random foreground color to the text. This is straightforward as I can loop over the runs
of an attributed string and should I encounter an intentType.kind
of .orderedList
I can apply the random foreground color as so with clode along the lines of such:
for run in pulseAttributedString.runs {
if let presentationIntent = run.presentationIntent {
for intentType in presentationIntent.components {
switch intentType.kind {
case .orderedList:
let colors: [UIColor] = [.green, .systemPink, ...]
container[AttributeScopes.UIKitAttributes.ForegroundColorAttribute.self] = colors.randomElement()
}
}
}
}
Upon setting the random foreground color to the attribute container, and running in the Simulator you can see the following output. This is very much close to what I'd expect although frustratingly the parser seemed to have stripped out the 1.
2.
etc.
I'm not sure what the reasoning for that is, or why the .orderedList
does not have an associated value representing the index of the line item in the list, similar to how case header(level: Int)
includes an associated value for header level.
Upon closer inspection, I also see that there is another presentation intent kind of case listItem(ordinal: Int)
.
When I add a case in my switch statement for listItem
I see it too is included within the presentation intent components.
With that said, I need to restore the 1.
, 2.
etc, would I use case listItem(ordinal: Int)
or .orderedList
. And what would be the difference between the two? Would someone be able to explain that to me since the documentation for listemItem seems to make no effort to do so.
This now leads me to the next issue I was encountering where if I then add emphasis to some words within the ordered list, essentially the same sample markdown above but with emphais on the word one
and second
:
let sampleMarkdown: String = """
# Ordered List Test
This is some sample markdown used to test ordered lists.
1. Line item *one* of a sample markdown ordered list.
2. This is the *second* line item of a sample markdown ordered list.
3. And finally, the third line item of a sample markdown ordered list.
"""
I now encounter the unexpected behavior where the words that received the emphasis also have a paragraph attribute associated with them, as shown in the screenshot below.
I can log the presentationIntent
and confirm that in my console that there are now presentation intent components for listItem
, orderedList
and now a paragraph
.
[paragraph (id 5), listItem 1 (id 4), orderedList (id 3)]
So now it appears that in addition to having to restore and insert the 1.
, 2.
etc, to the line items, but now I also need to make sure I strip out the added paragraph intent that gets added to a piece of text has emphaisis within an orderedList
line item?
This doesn't seem to make sense to me, am I doing something wrong?