mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Add support for <details> and <summary> tags (#6077)
This commit is contained in:
@@ -24,6 +24,7 @@ nonisolated protocol MentionBuilderProtocol: Sendable {
|
||||
|
||||
nonisolated extension NSAttributedString.Key {
|
||||
static let MatrixBlockquote: NSAttributedString.Key = .init(rawValue: BlockquoteAttribute.name)
|
||||
static let MatrixDetails: NSAttributedString.Key = .init(rawValue: DetailsAttribute.name)
|
||||
static let MatrixUserID: NSAttributedString.Key = .init(rawValue: UserIDAttribute.name)
|
||||
static let MatrixUserDisplayName: NSAttributedString.Key = .init(rawValue: UserDisplayNameAttribute.name)
|
||||
static let MatrixRoomDisplayName: NSAttributedString.Key = .init(rawValue: RoomDisplayNameAttribute.name)
|
||||
@@ -203,6 +204,22 @@ nonisolated struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
content = attributedString(element: childElement, documentBody: documentBody, preserveFormatting: preserveFormatting, listTag: listTag, listIndex: &childIndex, indentLevel: indentLevel)
|
||||
content.addAttribute(.MatrixBlockquote, value: true, range: NSRange(location: 0, length: content.length))
|
||||
|
||||
case "details":
|
||||
// Pull the summary out of the tree so that it isn't rendered inline with the content,
|
||||
// it is used as the title of the collapsed component instead.
|
||||
let summaryElement = childElement.getChildNodes()
|
||||
.lazy
|
||||
.compactMap { $0 as? Element }
|
||||
.first { $0.tagName().lowercased() == "summary" }
|
||||
let summary = summaryElement.flatMap { try? $0.text() } ?? ""
|
||||
try? summaryElement?.remove()
|
||||
|
||||
content = attributedString(element: childElement, documentBody: documentBody, preserveFormatting: preserveFormatting, listTag: listTag, listIndex: &childIndex, indentLevel: indentLevel)
|
||||
|
||||
// Browsers fall back to a default title when the summary is missing, match them.
|
||||
let title = summary.isEmpty ? L10n.a11yViewDetails : summary
|
||||
content.addAttribute(.MatrixDetails, value: title, range: NSRange(location: 0, length: content.length))
|
||||
|
||||
case "code", "pre":
|
||||
let isCodeBlock = tag == "pre"
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
import Foundation
|
||||
|
||||
nonisolated struct AttributedStringBuilderComponent: Hashable, Identifiable {
|
||||
enum ComponentType {
|
||||
enum ComponentType: Hashable {
|
||||
case plainText
|
||||
case blockquote
|
||||
case codeBlock
|
||||
case details(summary: String)
|
||||
}
|
||||
|
||||
/// Identifier for the `Identifiable` conformance, allows edits to the `FormattedBodyText` to animate seamlessly
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum BlockquoteAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
static let name = "MXBlockquoteAttribute"
|
||||
}
|
||||
|
||||
enum UserIDAttribute: AttributedStringKey {
|
||||
typealias Value = String
|
||||
static let name = "MXUserIDAttribute"
|
||||
@@ -65,6 +60,17 @@ enum AllUsersMentionAttribute: AttributedStringKey {
|
||||
static let name = "MXAllUsersMentionAttribute"
|
||||
}
|
||||
|
||||
enum BlockquoteAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
static let name = "MXBlockquoteAttribute"
|
||||
}
|
||||
|
||||
/// Marks the content of a `<details>` element, carrying its `<summary>` as the value.
|
||||
enum DetailsAttribute: AttributedStringKey {
|
||||
typealias Value = String
|
||||
static let name = "MXDetailsAttribute"
|
||||
}
|
||||
|
||||
enum CodeBlockAttribute: AttributedStringKey {
|
||||
typealias Value = Bool
|
||||
static let name = "MXCodeBlockAttribute"
|
||||
@@ -78,6 +84,7 @@ enum InlineCodeAttribute: AttributedStringKey {
|
||||
nonisolated extension AttributeScopes {
|
||||
struct ElementXAttributes: AttributeScope {
|
||||
let blockquote: BlockquoteAttribute
|
||||
let details: DetailsAttribute
|
||||
|
||||
let userID: UserIDAttribute
|
||||
// periphery:ignore - required to make NSAttributedString to AttributedString conversion even if not used directly
|
||||
|
||||
@@ -19,6 +19,7 @@ nonisolated enum HTMLFixtures: String, CaseIterable {
|
||||
case wideCodeBlock
|
||||
case unorderedList
|
||||
case orderedList
|
||||
case details
|
||||
|
||||
var rawValue: String {
|
||||
switch self {
|
||||
@@ -123,6 +124,13 @@ nonisolated enum HTMLFixtures: String, CaseIterable {
|
||||
<li>Skittles</li>
|
||||
</ol>
|
||||
"""
|
||||
case .details:
|
||||
"""
|
||||
Text before the details\
|
||||
<details><summary>Expand me</summary><p>Hidden <b>content</b> with a <a href="https://www.matrix.org">link</a> in it.</p></details>\
|
||||
<details><p>These details have no summary.</p></details>\
|
||||
Text after the details
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user