@@ -18,24 +18,22 @@ open class Node: Codable {
1818 enum CodingKeys : String , CodingKey {
1919 case type
2020 case version
21+ case styles
2122 }
2223
2324 public var key : NodeKey
2425 var parent : NodeKey ?
25- public var type : NodeType
2626 public var version : Int
2727
28- public init ( ) {
29- self . type = Node . getType ( )
30- self . version = 1
31- self . key = LexicalConstants . uninitializedNodeKey
28+ // Use style APIs to manipulate styles: see Styles.swift
29+ var styles : StylesDict = [ : ]
3230
33- _ = try ? generateKey ( node: self )
34- }
35-
36- public init ( _ key: NodeKey ? ) {
37- self . type = Node . getType ( )
31+ // This change will be a code-breaking change for subclasses, which must now all implement this method. However,
32+ // the effort required to update each class will be minimal. The rationale for this breaking change is to avoid
33+ // bugs where styles disappear when nodes are copied, etc.
34+ public required init ( styles: StylesDict , key: NodeKey ? ) {
3835 self . version = 1
36+ self . styles = styles
3937
4038 if let key, key != LexicalConstants . uninitializedNodeKey {
4139 self . key = key
@@ -49,17 +47,45 @@ open class Node: Codable {
4947 public required init ( from decoder: Decoder ) throws {
5048 let values = try decoder. container ( keyedBy: CodingKeys . self)
5149 key = LexicalConstants . uninitializedNodeKey
52- type = try NodeType ( rawValue: values. decode ( String . self, forKey: . type) )
5350 version = try values. decode ( Int . self, forKey: . version)
5451
52+ // styles
53+ if let styleContainer = try ? values. nestedContainer ( keyedBy: StyleCodingKeys . self, forKey: . styles) {
54+ guard let editor = getActiveEditor ( ) else {
55+ throw LexicalError . internal ( " Could not get active editor " )
56+ }
57+ // try each style and see if there's a value
58+ var newStyles : StylesDict = [ : ]
59+ for (styleName, style) in editor. registeredStyles {
60+ guard let styleKey = StyleCodingKeys ( stringValue: styleName. rawValue) else { continue }
61+ guard let superDecoder = try ? styleContainer. superDecoder ( forKey: styleKey) else { continue }
62+ if let value = try ? styleValueFromDecoder ( style, decoder: superDecoder) {
63+ newStyles [ styleName] = value
64+ }
65+ }
66+ self . styles = newStyles
67+ }
68+
5569 _ = try ? generateKey ( node: self )
5670 }
5771
5872 /// Used when serialising node to JSON
5973 open func encode( to encoder: Encoder ) throws {
6074 var container = encoder. container ( keyedBy: CodingKeys . self)
61- try container. encode ( self . type. rawValue, forKey: . type)
6275 try container. encode ( self . version, forKey: . version)
76+
77+ // styles
78+ if styles. count > 0 {
79+ var stylesContainer = container. nestedContainer ( keyedBy: StyleCodingKeys . self, forKey: . styles)
80+ guard let editor = getActiveEditor ( ) else {
81+ throw LexicalError . internal ( " Could not get active editor " )
82+ }
83+ for (styleName, style) in editor. registeredStyles {
84+ guard let styleValue = self . getStyle ( style) ,
85+ let styleKey = StyleCodingKeys ( stringValue: styleName. rawValue) else { continue }
86+ try stylesContainer. encode ( styleValue, forKey: styleKey)
87+ }
88+ }
6389 }
6490
6591 /**
@@ -68,13 +94,16 @@ open class Node: Codable {
6894 */
6995 open func didMoveTo( newEditor editor: Editor ) { }
7096
71- // This is an initial value for `type`.
72- // static methods cannot be overridden in swift so,
73- // each subclass needs to assign the type property in their init method
74- static func getType( ) -> NodeType {
97+ open class func getType( ) -> NodeType {
7598 NodeType . unknown
7699 }
77100
101+ public var type : NodeType {
102+ get {
103+ Self . getType ( )
104+ }
105+ }
106+
78107 /// Provides the **preamble** part of the node's content. Typically the preamble is used for control characters to represent embedded objects (see ``DecoratorNode``).
79108 ///
80109 /// In Lexical iOS, a node's content is split into four parts: preamble, children, text, postamble. ``ElementNode`` subclasses can implement preamble/postamble, and TextNode subclasses can implement the text part.
@@ -124,7 +153,17 @@ open class Node: Codable {
124153
125154 /// Lets the node provide attributes for TextKit to use to render the node's content.
126155 open func getAttributedStringAttributes( theme: Theme ) -> [ NSAttributedString . Key : Any ] {
127- [ : ]
156+ let node = getLatest ( )
157+ let attributesDict = theme. getValue ( node. type, withSubtype: nil ) ?? [ : ]
158+ guard let editor = getActiveEditor ( ) else {
159+ return attributesDict
160+ }
161+ let styleAttributeDicts : [ Theme . AttributeDict ] = node. styles. map { ( key: StyleName , value: Any ) in
162+ guard let styleType = editor. registeredStyles [ key] else { return [ : ] }
163+ return styleAttributesDictFor ( node: node, style: styleType, theme: theme)
164+ }
165+ let dicts = [ attributesDict] + styleAttributeDicts
166+ return dicts. reduce ( [ : ] ) { $0. merging ( $1) { ( _, next) in next } }
128167 }
129168
130169 /**
0 commit comments