diff --git a/Aztec.xcodeproj/project.pbxproj b/Aztec.xcodeproj/project.pbxproj index ee844c96d..ad3e2cbc0 100644 --- a/Aztec.xcodeproj/project.pbxproj +++ b/Aztec.xcodeproj/project.pbxproj @@ -18,7 +18,7 @@ 599F25361D8BC9A1002871D6 /* Converter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F25061D8BC9A1002871D6 /* Converter.swift */; }; 599F25371D8BC9A1002871D6 /* InAttributeConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250A1D8BC9A1002871D6 /* InAttributeConverter.swift */; }; 599F25381D8BC9A1002871D6 /* InAttributesConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250B1D8BC9A1002871D6 /* InAttributesConverter.swift */; }; - 599F25391D8BC9A1002871D6 /* InHTMLConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250C1D8BC9A1002871D6 /* InHTMLConverter.swift */; }; + 599F25391D8BC9A1002871D6 /* HTMLParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250C1D8BC9A1002871D6 /* HTMLParser.swift */; }; 599F253A1D8BC9A1002871D6 /* InNodeConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250D1D8BC9A1002871D6 /* InNodeConverter.swift */; }; 599F253B1D8BC9A1002871D6 /* InNodesConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F250E1D8BC9A1002871D6 /* InNodesConverter.swift */; }; 599F25471D8BC9A1002871D6 /* HTMLConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F25201D8BC9A1002871D6 /* HTMLConstants.swift */; }; @@ -33,10 +33,6 @@ 599F25531D8BC9A1002871D6 /* TextStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F25311D8BC9A1002871D6 /* TextStorage.swift */; }; 599F25541D8BC9A1002871D6 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 599F25321D8BC9A1002871D6 /* TextView.swift */; }; 599F255C1D8BCDB4002871D6 /* Gridicons.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 599F255B1D8BCDB4002871D6 /* Gridicons.framework */; }; - 59FEA0741D8BDFA700D138DF /* ElementNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59FEA0651D8BDFA700D138DF /* ElementNodeTests.swift */; }; - 59FEA0751D8BDFA700D138DF /* NodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59FEA0661D8BDFA700D138DF /* NodeTests.swift */; }; - 59FEA0781D8BDFA700D138DF /* HTMLToAttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59FEA06A1D8BDFA700D138DF /* HTMLToAttributedStringTests.swift */; }; - 59FEA07A1D8BDFA700D138DF /* InHTMLConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59FEA06C1D8BDFA700D138DF /* InHTMLConverterTests.swift */; }; B50CE7321F1FA6260018CAA1 /* NSAttributedString+Strip.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50CE7311F1FA6260018CAA1 /* NSAttributedString+Strip.swift */; }; B50CE7341F1FABA00018CAA1 /* content.html in Resources */ = {isa = PBXBuildFile; fileRef = B50CE7331F1FABA00018CAA1 /* content.html */; }; B524228D1F30C039002E7C6C /* HTMLDiv.swift in Sources */ = {isa = PBXBuildFile; fileRef = B524228C1F30C039002E7C6C /* HTMLDiv.swift */; }; @@ -45,15 +41,11 @@ B5375F491EC2569500F5D7EC /* StringHTMLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5375F481EC2569500F5D7EC /* StringHTMLTests.swift */; }; B542D6421E9EB122009D12D3 /* PreFormaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B542D6411E9EB122009D12D3 /* PreFormaterTests.swift */; }; B551A4A01E770B3800EE3A7F /* UIFont+Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = B551A49F1E770B3800EE3A7F /* UIFont+Emoji.swift */; }; - B5657C151EE99A8600579FE1 /* NSAttributedStringToNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5657C141EE99A8600579FE1 /* NSAttributedStringToNodes.swift */; }; - B5657C181EE99AF500579FE1 /* NSAttributedStringToNodesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5657C171EE99AF500579FE1 /* NSAttributedStringToNodesTests.swift */; }; B572AC281E817CFE008948C2 /* CommentAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B572AC271E817CFE008948C2 /* CommentAttachment.swift */; }; B57534501F267D0B009D4904 /* Array+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B575344F1F267D0B009D4904 /* Array+Helpers.swift */; }; B57534521F267D63009D4904 /* ArrayHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57534511F267D63009D4904 /* ArrayHelperTests.swift */; }; B57D1C3D1E92C38000EA4B16 /* HTMLAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57D1C3C1E92C38000EA4B16 /* HTMLAttachment.swift */; }; B59C9F9F1DF74BB80073B1D6 /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59C9F9E1DF74BB80073B1D6 /* UIFont+Traits.swift */; }; - B5A5277C1EF1B44800E7D2FD /* UnsupportedHTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5277B1EF1B44800E7D2FD /* UnsupportedHTML.swift */; }; - B5A5277E1EF1BAC000E7D2FD /* HTMLNodeToNSAttributedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5277D1EF1BAC000E7D2FD /* HTMLNodeToNSAttributedStringTests.swift */; }; B5A99D841EBA073D00DED081 /* HTMLStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A99D831EBA073D00DED081 /* HTMLStorage.swift */; }; B5AF89321E93CFC80051EFDB /* RenderableAttachmentDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AF89311E93CFC80051EFDB /* RenderableAttachmentDelegate.swift */; }; B5B86D371DA3EC250083DB3F /* NSRange+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18733C41DA096EE005AEB80 /* NSRange+Helpers.swift */; }; @@ -67,8 +59,7 @@ B5D575871F2288E2003A62F6 /* TextStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D575841F2288E2003A62F6 /* TextStorageTests.swift */; }; B5D575881F2288E2003A62F6 /* TextViewStubAttachmentDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D575851F2288E2003A62F6 /* TextViewStubAttachmentDelegate.swift */; }; B5D575891F2288E2003A62F6 /* TextViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D575861F2288E2003A62F6 /* TextViewTests.swift */; }; - B5DA1C1D1EBD1CCE000AAB45 /* OutHTMLConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DA1C1C1EBD1CCE000AAB45 /* OutHTMLConverter.swift */; }; - B5DA1C1F1EBD1EA7000AAB45 /* OutHTMLConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DA1C1E1EBD1EA7000AAB45 /* OutHTMLConverterTests.swift */; }; + B5DA1C1D1EBD1CCE000AAB45 /* HTMLSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DA1C1C1EBD1CCE000AAB45 /* HTMLSerializer.swift */; }; B5E607331DA56EC700C8A389 /* TextListFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E607321DA56EC700C8A389 /* TextListFormatterTests.swift */; }; B5F84B611E70595B0089A76C /* NSAttributedString+Analyzers.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84B601E70595B0089A76C /* NSAttributedString+Analyzers.swift */; }; B5F84B631E706B720089A76C /* NSAttributedStringAnalyzerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F84B621E706B720089A76C /* NSAttributedStringAnalyzerTests.swift */; }; @@ -85,12 +76,8 @@ F11326B21EF1AA91007FEE9A /* HTMLPre.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11326AC1EF1AA91007FEE9A /* HTMLPre.swift */; }; F11326B31EF1AA91007FEE9A /* ParagraphProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11326AD1EF1AA91007FEE9A /* ParagraphProperty.swift */; }; F11326B41EF1AA91007FEE9A /* TextList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11326AE1EF1AA91007FEE9A /* TextList.swift */; }; - F11904A51D9D857500BFF9A1 /* TextNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11904A41D9D857500BFF9A1 /* TextNodeTests.swift */; }; F127F7121F058B20008A00D7 /* StandardAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = F127F7111F058B20008A00D7 /* StandardAttribute.swift */; }; F127F7141F0591AD008A00D7 /* CSSProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F127F7131F0591AD008A00D7 /* CSSProperty.swift */; }; - F127F7161F05933C008A00D7 /* CSSPropertyRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F127F7151F05933C008A00D7 /* CSSPropertyRepresentation.swift */; }; - F1288BAF1DD0B1EF00E67ABC /* HTMLNodeToNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1288BAD1DD0B1EF00E67ABC /* HTMLNodeToNSAttributedString.swift */; }; - F1288BB01DD0B1EF00E67ABC /* HTMLToAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1288BAE1DD0B1EF00E67ABC /* HTMLToAttributedString.swift */; }; F12F58631EF20394008AE298 /* AttributeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12F58511EF20394008AE298 /* AttributeFormatter.swift */; }; F12F58651EF20394008AE298 /* ParagraphAttributeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12F58531EF20394008AE298 /* ParagraphAttributeFormatter.swift */; }; F12F58661EF20394008AE298 /* StandardAttributeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12F58541EF20394008AE298 /* StandardAttributeFormatter.swift */; }; @@ -109,13 +96,26 @@ F13CE53E1F4DD05E0043368D /* PipelineProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F13CE53D1F4DD05E0043368D /* PipelineProcessor.swift */; }; F13CE5401F4DD08E0043368D /* RegexProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F13CE53F1F4DD08E0043368D /* RegexProcessor.swift */; }; F14665451EA7C230008DE2B8 /* NSMutableAttributedStringReplaceOcurrencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F14665441EA7C230008DE2B8 /* NSMutableAttributedStringReplaceOcurrencesTests.swift */; }; - F16DD2CB1EE99B850083A098 /* HTMLRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16DD2CA1EE99B850083A098 /* HTMLRepresentation.swift */; }; + F17BC86B1F4E466100398E2B /* NSAttributedString+HTMLInitializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC86A1F4E466100398E2B /* NSAttributedString+HTMLInitializer.swift */; }; + F17BC8751F4E48FF00398E2B /* NSAttributedStringHTMLInitializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8741F4E48FF00398E2B /* NSAttributedStringHTMLInitializerTests.swift */; }; + F17BC8921F4E4BA500398E2B /* CSSPropertyRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC88F1F4E4BA500398E2B /* CSSPropertyRepresentation.swift */; }; + F17BC8931F4E4BA500398E2B /* HTMLRepresentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8901F4E4BA500398E2B /* HTMLRepresentation.swift */; }; + F17BC8941F4E4BA500398E2B /* UnsupportedHTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8911F4E4BA500398E2B /* UnsupportedHTML.swift */; }; + F17BC8A21F4E4F5A00398E2B /* HTMLSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC89D1F4E4F5A00398E2B /* HTMLSerializerTests.swift */; }; + F17BC8A31F4E4F5A00398E2B /* ElementNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC89F1F4E4F5A00398E2B /* ElementNodeTests.swift */; }; + F17BC8A41F4E4F5A00398E2B /* NodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8A01F4E4F5A00398E2B /* NodeTests.swift */; }; + F17BC8A51F4E4F5A00398E2B /* TextNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8A11F4E4F5A00398E2B /* TextNodeTests.swift */; }; + F17BC8AA1F4E512800398E2B /* AttributedStringParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8A81F4E512800398E2B /* AttributedStringParser.swift */; }; + F17BC8AB1F4E512800398E2B /* AttributedStringSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8A91F4E512800398E2B /* AttributedStringSerializer.swift */; }; + F17BC8B51F4E517100398E2B /* AttributedStringParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8B31F4E517100398E2B /* AttributedStringParserTests.swift */; }; + F17BC8B61F4E517100398E2B /* AttributedStringSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17BC8B41F4E517100398E2B /* AttributedStringSerializerTests.swift */; }; F18733C81DA09737005AEB80 /* NSRangeComparisonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18733C71DA09737005AEB80 /* NSRangeComparisonTests.swift */; }; F18986E11EF2040A0060EDBA /* FontFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18986E01EF2040A0060EDBA /* FontFormatter.swift */; }; F18986E31EF204180060EDBA /* BoldFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18986E21EF204180060EDBA /* BoldFormatter.swift */; }; F18986E51EF2043E0060EDBA /* ItalicFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18986E41EF2043E0060EDBA /* ItalicFormatter.swift */; }; F18B81EB1EA5601000885F43 /* StringUnicodeScalarView+RangeConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18B81EA1EA5601000885F43 /* StringUnicodeScalarView+RangeConversion.swift */; }; F18B81ED1EA560B700885F43 /* StringUTF16+RangeConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18B81EC1EA560B700885F43 /* StringUTF16+RangeConversion.swift */; }; + F1953E251F4E544A00C717C9 /* HTMLParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1953E241F4E544A00C717C9 /* HTMLParserTests.swift */; }; F1C05B991E37F99D007510EA /* Character+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1C05B981E37F99D007510EA /* Character+Name.swift */; }; F1C05B9D1E37FA77007510EA /* String+CharacterName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1C05B9C1E37FA77007510EA /* String+CharacterName.swift */; }; F1C05B9F1E37FD2F007510EA /* NSAttributedString+CharacterName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1C05B9E1E37FD2F007510EA /* NSAttributedString+CharacterName.swift */; }; @@ -186,7 +186,7 @@ 599F25061D8BC9A1002871D6 /* Converter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Converter.swift; sourceTree = ""; }; 599F250A1D8BC9A1002871D6 /* InAttributeConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAttributeConverter.swift; sourceTree = ""; }; 599F250B1D8BC9A1002871D6 /* InAttributesConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAttributesConverter.swift; sourceTree = ""; }; - 599F250C1D8BC9A1002871D6 /* InHTMLConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InHTMLConverter.swift; sourceTree = ""; }; + 599F250C1D8BC9A1002871D6 /* HTMLParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLParser.swift; sourceTree = ""; }; 599F250D1D8BC9A1002871D6 /* InNodeConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InNodeConverter.swift; sourceTree = ""; }; 599F250E1D8BC9A1002871D6 /* InNodesConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InNodesConverter.swift; sourceTree = ""; }; 599F25201D8BC9A1002871D6 /* HTMLConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLConstants.swift; sourceTree = ""; }; @@ -203,11 +203,7 @@ 599F25571D8BCA01002871D6 /* libxml2-umbrella.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "libxml2-umbrella.h"; sourceTree = ""; }; 599F25581D8BCA01002871D6 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; 599F255B1D8BCDB4002871D6 /* Gridicons.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Gridicons.framework; path = Example/Carthage/Build/iOS/Gridicons.framework; sourceTree = ""; }; - 59FEA0651D8BDFA700D138DF /* ElementNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementNodeTests.swift; sourceTree = ""; }; - 59FEA0661D8BDFA700D138DF /* NodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodeTests.swift; sourceTree = ""; }; - 59FEA06A1D8BDFA700D138DF /* HTMLToAttributedStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLToAttributedStringTests.swift; sourceTree = ""; }; 59FEA06B1D8BDFA700D138DF /* InAttributeConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAttributeConverterTests.swift; sourceTree = ""; }; - 59FEA06C1D8BDFA700D138DF /* InHTMLConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InHTMLConverterTests.swift; sourceTree = ""; }; 59FEA06D1D8BDFA700D138DF /* InNodeConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InNodeConverterTests.swift; sourceTree = ""; }; B50CE7311F1FA6260018CAA1 /* NSAttributedString+Strip.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Strip.swift"; sourceTree = ""; }; B50CE7331F1FABA00018CAA1 /* content.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = content.html; path = Example/Example/SampleContent/content.html; sourceTree = SOURCE_ROOT; }; @@ -217,15 +213,11 @@ B5375F481EC2569500F5D7EC /* StringHTMLTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StringHTMLTests.swift; path = Extensions/StringHTMLTests.swift; sourceTree = ""; }; B542D6411E9EB122009D12D3 /* PreFormaterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreFormaterTests.swift; sourceTree = ""; }; B551A49F1E770B3800EE3A7F /* UIFont+Emoji.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Emoji.swift"; sourceTree = ""; }; - B5657C141EE99A8600579FE1 /* NSAttributedStringToNodes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSAttributedStringToNodes.swift; sourceTree = ""; }; - B5657C171EE99AF500579FE1 /* NSAttributedStringToNodesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSAttributedStringToNodesTests.swift; sourceTree = ""; }; B572AC271E817CFE008948C2 /* CommentAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentAttachment.swift; sourceTree = ""; }; B575344F1F267D0B009D4904 /* Array+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Helpers.swift"; sourceTree = ""; }; B57534511F267D63009D4904 /* ArrayHelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ArrayHelperTests.swift; path = Extensions/ArrayHelperTests.swift; sourceTree = ""; }; B57D1C3C1E92C38000EA4B16 /* HTMLAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLAttachment.swift; sourceTree = ""; }; B59C9F9E1DF74BB80073B1D6 /* UIFont+Traits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = ""; }; - B5A5277B1EF1B44800E7D2FD /* UnsupportedHTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsupportedHTML.swift; sourceTree = ""; }; - B5A5277D1EF1BAC000E7D2FD /* HTMLNodeToNSAttributedStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLNodeToNSAttributedStringTests.swift; sourceTree = ""; }; B5A99D831EBA073D00DED081 /* HTMLStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLStorage.swift; sourceTree = ""; }; B5AF89311E93CFC80051EFDB /* RenderableAttachmentDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RenderableAttachmentDelegate.swift; sourceTree = ""; }; B5B96DAA1E01B2F300791315 /* UIPasteboard+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIPasteboard+Helpers.swift"; sourceTree = ""; }; @@ -238,8 +230,7 @@ B5D575841F2288E2003A62F6 /* TextStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TextStorageTests.swift; path = TextKit/TextStorageTests.swift; sourceTree = ""; }; B5D575851F2288E2003A62F6 /* TextViewStubAttachmentDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TextViewStubAttachmentDelegate.swift; path = TextKit/TextViewStubAttachmentDelegate.swift; sourceTree = ""; }; B5D575861F2288E2003A62F6 /* TextViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TextViewTests.swift; path = TextKit/TextViewTests.swift; sourceTree = ""; }; - B5DA1C1C1EBD1CCE000AAB45 /* OutHTMLConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutHTMLConverter.swift; sourceTree = ""; }; - B5DA1C1E1EBD1EA7000AAB45 /* OutHTMLConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutHTMLConverterTests.swift; sourceTree = ""; }; + B5DA1C1C1EBD1CCE000AAB45 /* HTMLSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLSerializer.swift; sourceTree = ""; }; B5E607321DA56EC700C8A389 /* TextListFormatterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextListFormatterTests.swift; sourceTree = ""; }; B5F84B601E70595B0089A76C /* NSAttributedString+Analyzers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Analyzers.swift"; sourceTree = ""; }; B5F84B621E706B720089A76C /* NSAttributedStringAnalyzerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSAttributedStringAnalyzerTests.swift; path = Extensions/NSAttributedStringAnalyzerTests.swift; sourceTree = ""; }; @@ -256,12 +247,8 @@ F11326AC1EF1AA91007FEE9A /* HTMLPre.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLPre.swift; sourceTree = ""; }; F11326AD1EF1AA91007FEE9A /* ParagraphProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParagraphProperty.swift; sourceTree = ""; }; F11326AE1EF1AA91007FEE9A /* TextList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextList.swift; sourceTree = ""; }; - F11904A41D9D857500BFF9A1 /* TextNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextNodeTests.swift; sourceTree = ""; }; F127F7111F058B20008A00D7 /* StandardAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandardAttribute.swift; sourceTree = ""; }; F127F7131F0591AD008A00D7 /* CSSProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSProperty.swift; sourceTree = ""; }; - F127F7151F05933C008A00D7 /* CSSPropertyRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSPropertyRepresentation.swift; sourceTree = ""; }; - F1288BAD1DD0B1EF00E67ABC /* HTMLNodeToNSAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLNodeToNSAttributedString.swift; sourceTree = ""; }; - F1288BAE1DD0B1EF00E67ABC /* HTMLToAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLToAttributedString.swift; sourceTree = ""; }; F12F58511EF20394008AE298 /* AttributeFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributeFormatter.swift; sourceTree = ""; }; F12F58531EF20394008AE298 /* ParagraphAttributeFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParagraphAttributeFormatter.swift; sourceTree = ""; }; F12F58541EF20394008AE298 /* StandardAttributeFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandardAttributeFormatter.swift; sourceTree = ""; }; @@ -280,7 +267,19 @@ F13CE53D1F4DD05E0043368D /* PipelineProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PipelineProcessor.swift; sourceTree = ""; }; F13CE53F1F4DD08E0043368D /* RegexProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegexProcessor.swift; sourceTree = ""; }; F14665441EA7C230008DE2B8 /* NSMutableAttributedStringReplaceOcurrencesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSMutableAttributedStringReplaceOcurrencesTests.swift; sourceTree = ""; }; - F16DD2CA1EE99B850083A098 /* HTMLRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLRepresentation.swift; sourceTree = ""; }; + F17BC86A1F4E466100398E2B /* NSAttributedString+HTMLInitializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+HTMLInitializer.swift"; sourceTree = ""; }; + F17BC8741F4E48FF00398E2B /* NSAttributedStringHTMLInitializerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSAttributedStringHTMLInitializerTests.swift; path = Extensions/NSAttributedStringHTMLInitializerTests.swift; sourceTree = ""; }; + F17BC88F1F4E4BA500398E2B /* CSSPropertyRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSPropertyRepresentation.swift; sourceTree = ""; }; + F17BC8901F4E4BA500398E2B /* HTMLRepresentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLRepresentation.swift; sourceTree = ""; }; + F17BC8911F4E4BA500398E2B /* UnsupportedHTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnsupportedHTML.swift; sourceTree = ""; }; + F17BC89D1F4E4F5A00398E2B /* HTMLSerializerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLSerializerTests.swift; sourceTree = ""; }; + F17BC89F1F4E4F5A00398E2B /* ElementNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementNodeTests.swift; sourceTree = ""; }; + F17BC8A01F4E4F5A00398E2B /* NodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodeTests.swift; sourceTree = ""; }; + F17BC8A11F4E4F5A00398E2B /* TextNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextNodeTests.swift; sourceTree = ""; }; + F17BC8A81F4E512800398E2B /* AttributedStringParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedStringParser.swift; sourceTree = ""; }; + F17BC8A91F4E512800398E2B /* AttributedStringSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedStringSerializer.swift; sourceTree = ""; }; + F17BC8B31F4E517100398E2B /* AttributedStringParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedStringParserTests.swift; sourceTree = ""; }; + F17BC8B41F4E517100398E2B /* AttributedStringSerializerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedStringSerializerTests.swift; sourceTree = ""; }; F18733C41DA096EE005AEB80 /* NSRange+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSRange+Helpers.swift"; sourceTree = ""; }; F18733C71DA09737005AEB80 /* NSRangeComparisonTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSRangeComparisonTests.swift; path = Extensions/NSRangeComparisonTests.swift; sourceTree = ""; }; F18986E01EF2040A0060EDBA /* FontFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontFormatter.swift; sourceTree = ""; }; @@ -288,6 +287,7 @@ F18986E41EF2043E0060EDBA /* ItalicFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItalicFormatter.swift; sourceTree = ""; }; F18B81EA1EA5601000885F43 /* StringUnicodeScalarView+RangeConversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StringUnicodeScalarView+RangeConversion.swift"; sourceTree = ""; }; F18B81EC1EA560B700885F43 /* StringUTF16+RangeConversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StringUTF16+RangeConversion.swift"; sourceTree = ""; }; + F1953E241F4E544A00C717C9 /* HTMLParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTMLParserTests.swift; sourceTree = ""; }; F1C05B981E37F99D007510EA /* Character+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Character+Name.swift"; sourceTree = ""; }; F1C05B9C1E37FA77007510EA /* String+CharacterName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+CharacterName.swift"; sourceTree = ""; }; F1C05B9E1E37FD2F007510EA /* NSAttributedString+CharacterName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+CharacterName.swift"; sourceTree = ""; }; @@ -383,14 +383,13 @@ isa = PBXGroup; children = ( 5951CB9E1D8BC93600E1866F /* Info.plist */, - B50CE7351F1FABA40018CAA1 /* Resources */, - 59FEA05D1D8BDFA700D138DF /* Exporter */, - B5657C161EE99AE000579FE1 /* Converters */, F18733C61DA0970E005AEB80 /* Extensions */, B5E607311DA56EB000C8A389 /* Formatters */, - 59FEA0641D8BDFA700D138DF /* HTML */, + F17BC89B1F4E4F5A00398E2B /* HTML */, 59FEA0691D8BDFA700D138DF /* Importer */, + F17BC8B11F4E517100398E2B /* NSAttributedString */, FF20D6451EDC3B3900294B78 /* Processor */, + B50CE7351F1FABA40018CAA1 /* Resources */, F10DB19F1E63390700358E7E /* TextKit */, ); path = AztecTests; @@ -401,7 +400,6 @@ children = ( 599F251F1D8BC9A1002871D6 /* Constants */, 599F25031D8BC9A1002871D6 /* Converter */, - F1288BAC1DD0B1EF00E67ABC /* Converters */, 599F25241D8BC9A1002871D6 /* Extensions */, B5B86D3A1DA41A550083DB3F /* Formatters */, 599F25281D8BC9A1002871D6 /* GUI */, @@ -448,7 +446,7 @@ children = ( 599F250A1D8BC9A1002871D6 /* InAttributeConverter.swift */, 599F250B1D8BC9A1002871D6 /* InAttributesConverter.swift */, - 599F250C1D8BC9A1002871D6 /* InHTMLConverter.swift */, + 599F250C1D8BC9A1002871D6 /* HTMLParser.swift */, 599F250D1D8BC9A1002871D6 /* InNodeConverter.swift */, 599F250E1D8BC9A1002871D6 /* InNodesConverter.swift */, ); @@ -458,7 +456,7 @@ 599F250F1D8BC9A1002871D6 /* Out */ = { isa = PBXGroup; children = ( - B5DA1C1C1EBD1CCE000AAB45 /* OutHTMLConverter.swift */, + B5DA1C1C1EBD1CCE000AAB45 /* HTMLSerializer.swift */, ); path = Out; sourceTree = ""; @@ -490,6 +488,7 @@ 599F25251D8BC9A1002871D6 /* NSAttributedString+Attachments.swift */, F1C05B9E1E37FD2F007510EA /* NSAttributedString+CharacterName.swift */, FF7C89AF1E3BC52F000472A8 /* NSAttributedString+FontTraits.swift */, + F17BC86A1F4E466100398E2B /* NSAttributedString+HTMLInitializer.swift */, B5BC4FED1DA2C17800614582 /* NSAttributedString+Lists.swift */, F10BE6191EA7AE9D002E4625 /* NSAttributedString+ReplaceOcurrences.swift */, B50CE7311F1FA6260018CAA1 /* NSAttributedString+Strip.swift */, @@ -584,30 +583,10 @@ path = Documentation; sourceTree = ""; }; - 59FEA05D1D8BDFA700D138DF /* Exporter */ = { - isa = PBXGroup; - children = ( - B5DA1C1E1EBD1EA7000AAB45 /* OutHTMLConverterTests.swift */, - ); - path = Exporter; - sourceTree = ""; - }; - 59FEA0641D8BDFA700D138DF /* HTML */ = { - isa = PBXGroup; - children = ( - 59FEA0651D8BDFA700D138DF /* ElementNodeTests.swift */, - 59FEA0661D8BDFA700D138DF /* NodeTests.swift */, - F11904A41D9D857500BFF9A1 /* TextNodeTests.swift */, - ); - path = HTML; - sourceTree = ""; - }; 59FEA0691D8BDFA700D138DF /* Importer */ = { isa = PBXGroup; children = ( - 59FEA06A1D8BDFA700D138DF /* HTMLToAttributedStringTests.swift */, 59FEA06B1D8BDFA700D138DF /* InAttributeConverterTests.swift */, - 59FEA06C1D8BDFA700D138DF /* InHTMLConverterTests.swift */, 59FEA06D1D8BDFA700D138DF /* InNodeConverterTests.swift */, ); path = Importer; @@ -621,23 +600,6 @@ name = Resources; sourceTree = ""; }; - B5657C161EE99AE000579FE1 /* Converters */ = { - isa = PBXGroup; - children = ( - B5657C171EE99AF500579FE1 /* NSAttributedStringToNodesTests.swift */, - B5A5277D1EF1BAC000E7D2FD /* HTMLNodeToNSAttributedStringTests.swift */, - ); - path = Converters; - sourceTree = ""; - }; - B5A5277A1EF1B44800E7D2FD /* Styles */ = { - isa = PBXGroup; - children = ( - B5A5277B1EF1B44800E7D2FD /* UnsupportedHTML.swift */, - ); - path = Styles; - sourceTree = ""; - }; B5B86D3A1DA41A550083DB3F /* Formatters */ = { isa = PBXGroup; children = ( @@ -685,16 +647,6 @@ path = ParagraphProperty; sourceTree = ""; }; - F1288BAC1DD0B1EF00E67ABC /* Converters */ = { - isa = PBXGroup; - children = ( - F1288BAD1DD0B1EF00E67ABC /* HTMLNodeToNSAttributedString.swift */, - F1288BAE1DD0B1EF00E67ABC /* HTMLToAttributedString.swift */, - B5657C141EE99A8600579FE1 /* NSAttributedStringToNodes.swift */, - ); - path = Converters; - sourceTree = ""; - }; F12F58501EF20394008AE298 /* Base */ = { isa = PBXGroup; children = ( @@ -738,21 +690,76 @@ F16DD2C51EE998280083A098 /* NSAttributedString */ = { isa = PBXGroup; children = ( - F16DD2C91EE99B850083A098 /* HTML */, - B5A5277A1EF1B44800E7D2FD /* Styles */, + F17BC88E1F4E4BA500398E2B /* Attributes */, + F17BC8A71F4E512800398E2B /* Conversions */, ); path = NSAttributedString; sourceTree = ""; }; - F16DD2C91EE99B850083A098 /* HTML */ = { + F17BC88E1F4E4BA500398E2B /* Attributes */ = { isa = PBXGroup; children = ( - F127F7151F05933C008A00D7 /* CSSPropertyRepresentation.swift */, - F16DD2CA1EE99B850083A098 /* HTMLRepresentation.swift */, + F17BC88F1F4E4BA500398E2B /* CSSPropertyRepresentation.swift */, + F17BC8901F4E4BA500398E2B /* HTMLRepresentation.swift */, + F17BC8911F4E4BA500398E2B /* UnsupportedHTML.swift */, + ); + path = Attributes; + sourceTree = ""; + }; + F17BC89B1F4E4F5A00398E2B /* HTML */ = { + isa = PBXGroup; + children = ( + F17BC89C1F4E4F5A00398E2B /* Conversions */, + F17BC89E1F4E4F5A00398E2B /* Nodes */, ); path = HTML; sourceTree = ""; }; + F17BC89C1F4E4F5A00398E2B /* Conversions */ = { + isa = PBXGroup; + children = ( + F1953E241F4E544A00C717C9 /* HTMLParserTests.swift */, + F17BC89D1F4E4F5A00398E2B /* HTMLSerializerTests.swift */, + ); + path = Conversions; + sourceTree = ""; + }; + F17BC89E1F4E4F5A00398E2B /* Nodes */ = { + isa = PBXGroup; + children = ( + F17BC89F1F4E4F5A00398E2B /* ElementNodeTests.swift */, + F17BC8A01F4E4F5A00398E2B /* NodeTests.swift */, + F17BC8A11F4E4F5A00398E2B /* TextNodeTests.swift */, + ); + path = Nodes; + sourceTree = ""; + }; + F17BC8A71F4E512800398E2B /* Conversions */ = { + isa = PBXGroup; + children = ( + F17BC8A81F4E512800398E2B /* AttributedStringParser.swift */, + F17BC8A91F4E512800398E2B /* AttributedStringSerializer.swift */, + ); + path = Conversions; + sourceTree = ""; + }; + F17BC8B11F4E517100398E2B /* NSAttributedString */ = { + isa = PBXGroup; + children = ( + F17BC8B21F4E517100398E2B /* Conversions */, + ); + path = NSAttributedString; + sourceTree = ""; + }; + F17BC8B21F4E517100398E2B /* Conversions */ = { + isa = PBXGroup; + children = ( + F17BC8B31F4E517100398E2B /* AttributedStringParserTests.swift */, + F17BC8B41F4E517100398E2B /* AttributedStringSerializerTests.swift */, + ); + path = Conversions; + sourceTree = ""; + }; F18733C61DA0970E005AEB80 /* Extensions */ = { isa = PBXGroup; children = ( @@ -760,6 +767,7 @@ B5F84B621E706B720089A76C /* NSAttributedStringAnalyzerTests.swift */, B5BC4FF11DA2D17000614582 /* NSAttributedStringListsTests.swift */, F10BE61B1EA7B1DB002E4625 /* NSAttributedStringReplaceOcurrencesTests.swift */, + F17BC8741F4E48FF00398E2B /* NSAttributedStringHTMLInitializerTests.swift */, F14665441EA7C230008DE2B8 /* NSMutableAttributedStringReplaceOcurrencesTests.swift */, F18733C71DA09737005AEB80 /* NSRangeComparisonTests.swift */, F1000CE81EAA5C720000B15B /* StringEndOfLineTests.swift */, @@ -954,9 +962,11 @@ FF7A1C511E5651EA00C4C7C8 /* LineAttachment.swift in Sources */, FF20D6441EDC395E00294B78 /* NSTextingResult+Helpers.swift in Sources */, F12F586C1EF20394008AE298 /* HTMLParagraphFormatter.swift in Sources */, + F17BC86B1F4E466100398E2B /* NSAttributedString+HTMLInitializer.swift in Sources */, F12F58661EF20394008AE298 /* StandardAttributeFormatter.swift in Sources */, B5A99D841EBA073D00DED081 /* HTMLStorage.swift in Sources */, F13CE53E1F4DD05E0043368D /* PipelineProcessor.swift in Sources */, + F17BC8AA1F4E512800398E2B /* AttributedStringParser.swift in Sources */, 599F25471D8BC9A1002871D6 /* HTMLConstants.swift in Sources */, 599F25371D8BC9A1002871D6 /* InAttributeConverter.swift in Sources */, B57534501F267D0B009D4904 /* Array+Helpers.swift in Sources */, @@ -965,15 +975,14 @@ F1FA0E861E6EF514009D98EE /* Node.swift in Sources */, 599F254B1D8BC9A1002871D6 /* String+RangeConversion.swift in Sources */, 599F25481D8BC9A1002871D6 /* Metrics.swift in Sources */, - F1288BAF1DD0B1EF00E67ABC /* HTMLNodeToNSAttributedString.swift in Sources */, B59C9F9F1DF74BB80073B1D6 /* UIFont+Traits.swift in Sources */, F10BE61A1EA7AE9D002E4625 /* NSAttributedString+ReplaceOcurrences.swift in Sources */, F11326B41EF1AA91007FEE9A /* TextList.swift in Sources */, F18986E51EF2043E0060EDBA /* ItalicFormatter.swift in Sources */, F11326B01EF1AA91007FEE9A /* Header.swift in Sources */, F1C05B9F1E37FD2F007510EA /* NSAttributedString+CharacterName.swift in Sources */, + F17BC8921F4E4BA500398E2B /* CSSPropertyRepresentation.swift in Sources */, FF20D6411EDC389A00294B78 /* HTMLProcessor.swift in Sources */, - F16DD2CB1EE99B850083A098 /* HTMLRepresentation.swift in Sources */, B5C99D3F1E72E2E700335355 /* UIStackView+Helpers.swift in Sources */, F1C05B991E37F99D007510EA /* Character+Name.swift in Sources */, FF20D6421EDC389A00294B78 /* Processor.swift in Sources */, @@ -986,6 +995,7 @@ F12F58701EF20394008AE298 /* StrikethroughFormatter.swift in Sources */, FF4E26601EA8DF1E005E8E42 /* ImageAttachment.swift in Sources */, 599F254F1D8BC9A1002871D6 /* FormatBarItem.swift in Sources */, + F17BC8931F4E4BA500398E2B /* HTMLRepresentation.swift in Sources */, F18B81ED1EA560B700885F43 /* StringUTF16+RangeConversion.swift in Sources */, F12F58631EF20394008AE298 /* AttributeFormatter.swift in Sources */, 599F254E1D8BC9A1002871D6 /* FormatBarDelegate.swift in Sources */, @@ -994,10 +1004,7 @@ FFFEC7DB1EA7698900F4210F /* VideoAttachment.swift in Sources */, F12F586D1EF20394008AE298 /* ImageFormatter.swift in Sources */, F12F58671EF20394008AE298 /* BlockquoteFormatter.swift in Sources */, - B5A5277C1EF1B44800E7D2FD /* UnsupportedHTML.swift in Sources */, - F127F7161F05933C008A00D7 /* CSSPropertyRepresentation.swift in Sources */, - F1288BB01DD0B1EF00E67ABC /* HTMLToAttributedString.swift in Sources */, - B5DA1C1D1EBD1CCE000AAB45 /* OutHTMLConverter.swift in Sources */, + B5DA1C1D1EBD1CCE000AAB45 /* HTMLSerializer.swift in Sources */, F12F58681EF20394008AE298 /* ColorFormatter.swift in Sources */, 599F25351D8BC9A1002871D6 /* CLinkedListToArrayConverter.swift in Sources */, 599F25521D8BC9A1002871D6 /* MediaAttachment.swift in Sources */, @@ -1012,6 +1019,7 @@ F12F58721EF20394008AE298 /* UnderlineFormatter.swift in Sources */, F12F58711EF20394008AE298 /* TextListFormatter.swift in Sources */, F11326B21EF1AA91007FEE9A /* HTMLPre.swift in Sources */, + F17BC8AB1F4E512800398E2B /* AttributedStringSerializer.swift in Sources */, F18986E11EF2040A0060EDBA /* FontFormatter.swift in Sources */, F12F586B1EF20394008AE298 /* HRFormatter.swift in Sources */, FFA61E891DF18F3D00B71BF6 /* ParagraphStyle.swift in Sources */, @@ -1022,8 +1030,7 @@ F1FA0E821E6EF514009D98EE /* CommentNode.swift in Sources */, B57D1C3D1E92C38000EA4B16 /* HTMLAttachment.swift in Sources */, F1FA0E871E6EF514009D98EE /* StandardElementType.swift in Sources */, - B5657C151EE99A8600579FE1 /* NSAttributedStringToNodes.swift in Sources */, - 599F25391D8BC9A1002871D6 /* InHTMLConverter.swift in Sources */, + 599F25391D8BC9A1002871D6 /* HTMLParser.swift in Sources */, F10BE6181EA7ADA6002E4625 /* NSMutableAttributedString+ReplaceOcurrences.swift in Sources */, F11326AF1EF1AA91007FEE9A /* Blockquote.swift in Sources */, FFA61EC21DF6C1C900B71BF6 /* NSAttributedString+Archive.swift in Sources */, @@ -1042,6 +1049,7 @@ 599F254D1D8BC9A1002871D6 /* FormatBar.swift in Sources */, F1FA0E881E6EF514009D98EE /* TextNode.swift in Sources */, 599F253A1D8BC9A1002871D6 /* InNodeConverter.swift in Sources */, + F17BC8941F4E4BA500398E2B /* UnsupportedHTML.swift in Sources */, F12F586F1EF20394008AE298 /* PreFormatter.swift in Sources */, B50CE7321F1FA6260018CAA1 /* NSAttributedString+Strip.swift in Sources */, B5B86D371DA3EC250083DB3F /* NSRange+Helpers.swift in Sources */, @@ -1059,33 +1067,33 @@ FF7DCB4B1E815F9400AB77CB /* UIColorHexParserTests.swift in Sources */, B5D575891F2288E2003A62F6 /* TextViewTests.swift in Sources */, 594C9D741D8BE6C700D74542 /* InNodeConverterTests.swift in Sources */, - B5A5277E1EF1BAC000E7D2FD /* HTMLNodeToNSAttributedStringTests.swift in Sources */, B5F84B631E706B720089A76C /* NSAttributedStringAnalyzerTests.swift in Sources */, F10BE61C1EA7B1DB002E4625 /* NSAttributedStringReplaceOcurrencesTests.swift in Sources */, - 59FEA0751D8BDFA700D138DF /* NodeTests.swift in Sources */, - 59FEA0781D8BDFA700D138DF /* HTMLToAttributedStringTests.swift in Sources */, B5375F491EC2569500F5D7EC /* StringHTMLTests.swift in Sources */, B57534521F267D63009D4904 /* ArrayHelperTests.swift in Sources */, F14665451EA7C230008DE2B8 /* NSMutableAttributedStringReplaceOcurrencesTests.swift in Sources */, + F17BC8B51F4E517100398E2B /* AttributedStringParserTests.swift in Sources */, + F17BC8A31F4E4F5A00398E2B /* ElementNodeTests.swift in Sources */, F18733C81DA09737005AEB80 /* NSRangeComparisonTests.swift in Sources */, B5E607331DA56EC700C8A389 /* TextListFormatterTests.swift in Sources */, FF20D6471EDC3B3900294B78 /* HTMLProcessorTests.swift in Sources */, 594C9D731D8BE6C300D74542 /* InAttributeConverterTests.swift in Sources */, B5D575831F22820A003A62F6 /* HTMLRepresentationTests.swift in Sources */, B5D575871F2288E2003A62F6 /* TextStorageTests.swift in Sources */, - F11904A51D9D857500BFF9A1 /* TextNodeTests.swift in Sources */, + F17BC8B61F4E517100398E2B /* AttributedStringSerializerTests.swift in Sources */, FF152D8E1E68552A00FF596C /* StringRangeConversionTests.swift in Sources */, - 59FEA07A1D8BDFA700D138DF /* InHTMLConverterTests.swift in Sources */, + F17BC8A41F4E4F5A00398E2B /* NodeTests.swift in Sources */, E11B77601DBA14B40024E455 /* BlockquoteFormatterTests.swift in Sources */, + F17BC8A21F4E4F5A00398E2B /* HTMLSerializerTests.swift in Sources */, + F1953E251F4E544A00C717C9 /* HTMLParserTests.swift in Sources */, B5C16A631F4DF77300B113CF /* HeaderFormatterTests.swift in Sources */, B5D575881F2288E2003A62F6 /* TextViewStubAttachmentDelegate.swift in Sources */, - B5DA1C1F1EBD1EA7000AAB45 /* OutHTMLConverterTests.swift in Sources */, F1000CE91EAA5C720000B15B /* StringEndOfLineTests.swift in Sources */, - B5657C181EE99AF500579FE1 /* NSAttributedStringToNodesTests.swift in Sources */, + F17BC8751F4E48FF00398E2B /* NSAttributedStringHTMLInitializerTests.swift in Sources */, B542D6421E9EB122009D12D3 /* PreFormaterTests.swift in Sources */, - 59FEA0741D8BDFA700D138DF /* ElementNodeTests.swift in Sources */, B5BC4FF21DA2D17000614582 /* NSAttributedStringListsTests.swift in Sources */, B5D575811F226FF4003A62F6 /* UnsupportedHTMLTests.swift in Sources */, + F17BC8A51F4E4F5A00398E2B /* TextNodeTests.swift in Sources */, FFD436981E3180A500A0E26F /* FontFormatterTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Aztec/Classes/Converters/HTMLToAttributedString.swift b/Aztec/Classes/Converters/HTMLToAttributedString.swift deleted file mode 100644 index d1a6d18dc..000000000 --- a/Aztec/Classes/Converters/HTMLToAttributedString.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation -import UIKit - -class HTMLToAttributedString: SafeConverter { - - /// The default font descriptor that will be used as a base for conversions. - /// - let defaultFontDescriptor: UIFontDescriptor - - required init(usingDefaultFontDescriptor defaultFontDescriptor: UIFontDescriptor) { - self.defaultFontDescriptor = defaultFontDescriptor - } - - func convert(_ html: String) -> (rootNode: RootNode, attributedString: NSAttributedString) { - let htmlToNode = InHTMLConverter() - let nodeToAttributedString = HTMLNodeToNSAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let rootNode = htmlToNode.convert(html) - - if rootNode.children.count == 0 { - rootNode.children.append(TextNode(text: html)) - } - - let attributedString = nodeToAttributedString.convert(rootNode) - - return (rootNode, attributedString) - } -} diff --git a/Aztec/Classes/Extensions/NSAttributedString+HTMLInitializer.swift b/Aztec/Classes/Extensions/NSAttributedString+HTMLInitializer.swift new file mode 100644 index 000000000..2f1a69927 --- /dev/null +++ b/Aztec/Classes/Extensions/NSAttributedString+HTMLInitializer.swift @@ -0,0 +1,16 @@ +import Foundation +import UIKit + +extension NSAttributedString { + + convenience init(withHTML html: String, usingDefaultFontDescriptor descriptor: UIFontDescriptor) { + + let htmlParser = HTMLParser() + let rootNode = htmlParser.parse(html) + + let serializer = AttributedStringSerializer(usingDefaultFontDescriptor: descriptor) + let attributedString = serializer.serialize(rootNode) + + self.init(attributedString: attributedString) + } +} diff --git a/Aztec/Classes/Libxml2/Converters/In/InHTMLConverter.swift b/Aztec/Classes/Libxml2/Converters/In/HTMLParser.swift similarity index 85% rename from Aztec/Classes/Libxml2/Converters/In/InHTMLConverter.swift rename to Aztec/Classes/Libxml2/Converters/In/HTMLParser.swift index 76c92d8e3..6db4da181 100644 --- a/Aztec/Classes/Libxml2/Converters/In/InHTMLConverter.swift +++ b/Aztec/Classes/Libxml2/Converters/In/HTMLParser.swift @@ -2,20 +2,20 @@ import Foundation import libxml2 -class InHTMLConverter: SafeConverter { +class HTMLParser { enum Error: String, Swift.Error { case NoRootNode = "No root node" } - /// Converts HTML data into an HTML Node representing the same data. + /// Parses HTML data into an HTML Node representing the same data. /// /// - Parameters: - /// - html: the HTML string to convert. + /// - html: the HTML string to parse. /// /// - Returns: the HTML root node. /// - func convert(_ html: String) -> RootNode { + func parse(_ html: String) -> RootNode { // We wrap the HTML into a special root node, since it helps avoid conversion issues // with libxml2, where the library would add custom tags to "fix" the HTML code we @@ -69,7 +69,13 @@ class InHTMLConverter: SafeConverter { guard let rootNode = rootNodePtr?.pointee, let node = nodeConverter.convert(rootNode) as? RootNode else { - return RootNode(children: []) + return RootNode(children: [TextNode(text: "")]) + } + + // Don't let this method return an empty root node. + // + if node.children.count == 0 { + node.children.append(TextNode(text: html)) } return node diff --git a/Aztec/Classes/Libxml2/Converters/Out/OutHTMLConverter.swift b/Aztec/Classes/Libxml2/Converters/Out/HTMLSerializer.swift similarity index 74% rename from Aztec/Classes/Libxml2/Converters/Out/OutHTMLConverter.swift rename to Aztec/Classes/Libxml2/Converters/Out/HTMLSerializer.swift index 5268fa2d5..693cf4173 100644 --- a/Aztec/Classes/Libxml2/Converters/Out/OutHTMLConverter.swift +++ b/Aztec/Classes/Libxml2/Converters/Out/HTMLSerializer.swift @@ -2,9 +2,9 @@ import Foundation import libxml2 -// MARK: - HTML Prettifier! -// -class OutHTMLConverter: Converter { +/// Composes the provided nodes into its HTML representation. +/// +class HTMLSerializer { /// Indentation Spaces to be applied /// @@ -14,7 +14,6 @@ class OutHTMLConverter: Converter { /// let prettyPrint: Bool - /// Default Initializer /// /// - Parameters: @@ -27,55 +26,53 @@ class OutHTMLConverter: Converter { } - /// Converts a Node into it's HTML String Representation + /// Serializes a node into its HTML representation /// - func convert(_ rawNode: Node) -> String { - return convert(node: rawNode).trimmingCharacters(in: CharacterSet.newlines) + func serialize(_ node: Node) -> String { + return serialize(node: node).trimmingCharacters(in: CharacterSet.newlines) } } -// MARK: - Nodes: Serialization +// MARK: - Nodes: Composition // -private extension OutHTMLConverter { +private extension HTMLSerializer { - /// Serializes a Node into it's HTML String Representation + /// Serializes a node into its HTML representation /// - func convert(node: Node, level: Int = 0) -> String { + func serialize(node: Node, level: Int = 0) -> String { switch node { case let node as RootNode: - return convert(root: node) + return serialize(root: node) case let node as CommentNode: - return convert(comment: node) + return serialize(comment: node) case let node as ElementNode: - return convert(element: node, level: level) + return serialize(element: node, level: level) case let node as TextNode: - return convert(text: node) + return serialize(text: node) default: fatalError("We're missing support for a node type. This should not happen.") } } - /// Serializes a RootNode into it's HTML String Representation + /// Serializes a `RootNode` into its HTML representation /// - private func convert(root node: RootNode) -> String { + private func serialize(root node: RootNode) -> String { return node.children.reduce("") { (result, node) in - return result + convert(node: node) + return result + serialize(node: node) } } - - /// Serializes a CommentNode into it's HTML String Representation + /// Serializes a `CommentNode` into its HTML representation /// - private func convert(comment node: CommentNode) -> String { + private func serialize(comment node: CommentNode) -> String { return "" } - - /// Serializes an ElementNode into it's HTML String Representation + /// Serializes an `ElementNode` into its HTML representation /// - private func convert(element node: ElementNode, level: Int) -> String { + private func serialize(element node: ElementNode, level: Int) -> String { let opening = openingTag(for: node, at: level) guard let closing = closingTag(for: node, at: level) else { @@ -83,16 +80,15 @@ private extension OutHTMLConverter { } let children = node.children.reduce("") { (html, child)in - return html + convert(node: child, level: level + 1) + return html + serialize(node: child, level: level + 1) } return opening + children + closing } - - /// Serializes a TextNode into it's HTML String Representation + /// Serializes an `TextNode` into its HTML representation /// - private func convert(text node: TextNode) -> String { + private func serialize(text node: TextNode) -> String { return node.text().escapeHtmlNamedEntities() } } @@ -101,13 +97,13 @@ private extension OutHTMLConverter { // MARK: - ElementNode: Helpers // -private extension OutHTMLConverter { +private extension HTMLSerializer { /// Returns the Opening Tag for a given Element Node /// func openingTag(for node: ElementNode, at level: Int) -> String { let prefix = requiresOpeningTagPrefix(node) ? prefixForTag(at: level) : "" - let attributes = convert(attributes: node.attributes) + let attributes = serialize(attributes: node.attributes) return prefix + "<" + node.name + attributes + ">" } @@ -184,11 +180,11 @@ private extension OutHTMLConverter { // MARK: - Attributes: Serialization // -private extension OutHTMLConverter { +private extension HTMLSerializer { - /// Serializes a collection of Attributes into their HTML Form + /// Serializes an array of attributes into their HTML representation /// - func convert(attributes: [Attribute]) -> String { + func serialize(attributes: [Attribute]) -> String { return attributes.reduce("") { (html, attribute) in return html + String(.space) + attribute.toString() } @@ -199,7 +195,7 @@ private extension OutHTMLConverter { // MARK: - Private Constants // -private extension OutHTMLConverter { +private extension HTMLSerializer { struct Constants { diff --git a/Aztec/Classes/NSAttributedString/HTML/CSSPropertyRepresentation.swift b/Aztec/Classes/NSAttributedString/Attributes/CSSPropertyRepresentation.swift similarity index 100% rename from Aztec/Classes/NSAttributedString/HTML/CSSPropertyRepresentation.swift rename to Aztec/Classes/NSAttributedString/Attributes/CSSPropertyRepresentation.swift diff --git a/Aztec/Classes/NSAttributedString/HTML/HTMLRepresentation.swift b/Aztec/Classes/NSAttributedString/Attributes/HTMLRepresentation.swift similarity index 100% rename from Aztec/Classes/NSAttributedString/HTML/HTMLRepresentation.swift rename to Aztec/Classes/NSAttributedString/Attributes/HTMLRepresentation.swift diff --git a/Aztec/Classes/NSAttributedString/Styles/UnsupportedHTML.swift b/Aztec/Classes/NSAttributedString/Attributes/UnsupportedHTML.swift similarity index 100% rename from Aztec/Classes/NSAttributedString/Styles/UnsupportedHTML.swift rename to Aztec/Classes/NSAttributedString/Attributes/UnsupportedHTML.swift diff --git a/Aztec/Classes/Converters/NSAttributedStringToNodes.swift b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift similarity index 97% rename from Aztec/Classes/Converters/NSAttributedStringToNodes.swift rename to Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift index 8a66dc44e..eaaa5d5d8 100644 --- a/Aztec/Classes/Converters/NSAttributedStringToNodes.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringParser.swift @@ -2,19 +2,18 @@ import Foundation import UIKit import libxml2 +/// Parses an attributed string into an HTML tree. +/// +class AttributedStringParser { -// MARK: - NSAttributedStringToNodes -// -class NSAttributedStringToNodes: Converter { - - /// Converts an Attributed String Instance into it's HTML Tree Representation. + /// Parses an attributed string and returns the corresponding HTML tree. /// /// - Parameters: - /// - attrString: Attributed String that should be converted. + /// - attrString: the attributed string to parse /// - /// - Returns: RootNode, representing the DOM Tree. + /// - Returns: the HTML tree. /// - func convert(_ attrString: NSAttributedString) -> RootNode { + func parse(_ attrString: NSAttributedString) -> RootNode { var nodes = [Node]() var previous: [Node]? @@ -112,7 +111,7 @@ class NSAttributedStringToNodes: Converter { // MARK: - Merge: Helpers // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Defines a Tree Branch: Collection of Nodes, with a set of Leaves /// @@ -161,7 +160,7 @@ private extension NSAttributedStringToNodes { // MARK: - Merge: Styles // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Given a collection of branches, this method will iterate branch by branch and will: /// @@ -309,7 +308,7 @@ private extension NSAttributedStringToNodes { // MARK: - Merge: Paragraphs // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Attempts to merge the Right array of Element Nodes (Paragraph Level) into the Left array of Nodes. /// @@ -379,7 +378,7 @@ private extension NSAttributedStringToNodes { // MARK: - Paragraph Nodes Extraction // -extension NSAttributedStringToNodes { +extension AttributedStringParser { /// Returns the "Rightmost" Blocklevel Node from a collection fo nodes. /// @@ -422,7 +421,7 @@ extension NSAttributedStringToNodes { // MARK: - Paragraph Nodes: Alloc'ation // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Extracts the ElementNodes contained within a Paragraph's AttributedString. /// @@ -619,7 +618,7 @@ private extension NSAttributedStringToNodes { // MARK: - Style Nodes: Alloc'ation // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Extracts all of the Style Nodes contained within a collection of AttributedString Attributes. /// @@ -771,9 +770,9 @@ private extension NSAttributedStringToNodes { } -// MARK: - Leaf Nodes: Alloc'ation +// MARK: - Leaf Nodes: Allocation // -private extension NSAttributedStringToNodes { +private extension AttributedStringParser { /// Extract all of the Leaf Nodes contained within an Attributed String. We consider the following as Leaf: /// Plain Text, Attachments of any kind [Line, Comment, HTML, Image]. @@ -847,9 +846,9 @@ private extension NSAttributedStringToNodes { return [] } - let converter = InHTMLConverter() + let htmlParser = HTMLParser() - let rootNode = converter.convert(attachment.rawHTML) + let rootNode = htmlParser.parse(attachment.rawHTML) guard let firstChild = rootNode.children.first else { return processTextNodes(from: attachment.rawHTML) diff --git a/Aztec/Classes/Converters/HTMLNodeToNSAttributedString.swift b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringSerializer.swift similarity index 86% rename from Aztec/Classes/Converters/HTMLNodeToNSAttributedString.swift rename to Aztec/Classes/NSAttributedString/Conversions/AttributedStringSerializer.swift index 0564c2441..76ef6ba6c 100644 --- a/Aztec/Classes/Converters/HTMLNodeToNSAttributedString.swift +++ b/Aztec/Classes/NSAttributedString/Conversions/AttributedStringSerializer.swift @@ -1,13 +1,14 @@ import Foundation import UIKit -class HTMLNodeToNSAttributedString: SafeConverter { +/// Composes an attributed string from an HTML tree. +/// +class AttributedStringSerializer { /// The default font descriptor that will be used as a base for conversions. /// let defaultFontDescriptor: UIFontDescriptor - // MARK: - Initializers required init(usingDefaultFontDescriptor defaultFontDescriptor: UIFontDescriptor) { @@ -22,19 +23,18 @@ class HTMLNodeToNSAttributedString: SafeConverter { // MARK: - Conversion - /// Main conversion method. + /// Serializes an attributed string with the specified node hierarchy. /// /// - Parameters: - /// - node: the node to convert to `NSAttributedString`. + /// - node: the head of the tree to compose into an attributed string. /// - /// - Returns: the converted node as an `NSAttributedString`. + /// - Returns: the requested attributed string. /// - func convert(_ node: Node) -> NSAttributedString { - return convert(node, inheriting: defaultAttributes) + func serialize(_ node: Node) -> NSAttributedString { + return serialize(node, inheriting: defaultAttributes) } - /// Recursive conversion method. Useful for maintaining the font style of parent nodes when - /// converting. + /// Recursive serialization method. Useful for maintaining the font style of parent nodes. /// /// - Parameters: /// - node: the node to convert to `NSAttributedString`. @@ -42,20 +42,20 @@ class HTMLNodeToNSAttributedString: SafeConverter { /// /// - Returns: the converted node as an `NSAttributedString`. /// - fileprivate func convert(_ node: Node, inheriting attributes: [String:Any]) -> NSAttributedString { + fileprivate func serialize(_ node: Node, inheriting attributes: [String:Any]) -> NSAttributedString { switch node { case let textNode as TextNode: - return convert(textNode, inheriting: attributes) + return serialize(textNode, inheriting: attributes) case let commentNode as CommentNode: - return convert(commentNode, inheriting: attributes) + return serialize(commentNode, inheriting: attributes) case let elementNode as ElementNode: - return convert(elementNode, inheriting: attributes) + return serialize(elementNode, inheriting: attributes) default: fatalError("Nodes can be either text, comment or element nodes.") } } - /// Converts a `TextNode` to `NSAttributedString`. + /// Serializes a `TextNode`. /// /// - Parameters: /// - node: the node to convert to `NSAttributedString`. @@ -63,7 +63,7 @@ class HTMLNodeToNSAttributedString: SafeConverter { /// /// - Returns: the converted node as an `NSAttributedString`. /// - fileprivate func convert(_ node: TextNode, inheriting attributes: [String:Any]) -> NSAttributedString { + fileprivate func serialize(_ node: TextNode, inheriting attributes: [String:Any]) -> NSAttributedString { let string: NSAttributedString @@ -80,7 +80,7 @@ class HTMLNodeToNSAttributedString: SafeConverter { return string } - /// Converts a `CommentNode` to `NSAttributedString`. + /// Serializes a `CommentNode`. /// /// - Parameters: /// - node: the node to convert to `NSAttributedString`. @@ -88,14 +88,14 @@ class HTMLNodeToNSAttributedString: SafeConverter { /// /// - Returns: the converted node as an `NSAttributedString`. /// - fileprivate func convert(_ node: CommentNode, inheriting attributes: [String:Any]) -> NSAttributedString { + fileprivate func serialize(_ node: CommentNode, inheriting attributes: [String:Any]) -> NSAttributedString { let attachment = CommentAttachment() attachment.text = node.comment return NSAttributedString(attachment: attachment, attributes: attributes) } - /// Converts an `ElementNode` to `NSAttributedString`. + /// Serializes an `ElementNode`. /// /// - Parameters: /// - node: the node to convert to `NSAttributedString`. @@ -103,10 +103,10 @@ class HTMLNodeToNSAttributedString: SafeConverter { /// /// - Returns: the converted node as an `NSAttributedString`. /// - fileprivate func convert(_ element: ElementNode, inheriting attributes: [String: Any]) -> NSAttributedString { + fileprivate func serialize(_ element: ElementNode, inheriting attributes: [String: Any]) -> NSAttributedString { guard element.isSupportedByEditor() else { - return convert(unsupported: element, inheriting: attributes) + return serialize(unsupported: element, inheriting: attributes) } let childAttributes = self.attributes(for: element, inheriting: attributes) @@ -116,7 +116,7 @@ class HTMLNodeToNSAttributedString: SafeConverter { content.append(representation) } else { for child in element.children { - let childContent = convert(child, inheriting: childAttributes) + let childContent = serialize(child, inheriting: childAttributes) content.append(childContent) } } @@ -128,12 +128,14 @@ class HTMLNodeToNSAttributedString: SafeConverter { return content } - fileprivate func convert(unsupported element: ElementNode, inheriting attributes: [String:Any]) -> NSAttributedString { - let converter = OutHTMLConverter() + /// Serializes an unsupported element. + /// + fileprivate func serialize(unsupported element: ElementNode, inheriting attributes: [String:Any]) -> NSAttributedString { + let serializer = HTMLSerializer() let attachment = HTMLAttachment() attachment.rootTagName = element.name - attachment.rawHTML = converter.convert(element) + attachment.rawHTML = serializer.serialize(element) return NSAttributedString(attachment: attachment, attributes: attributes) } @@ -198,7 +200,7 @@ class HTMLNodeToNSAttributedString: SafeConverter { } } -private extension HTMLNodeToNSAttributedString { +private extension AttributedStringSerializer { // MARK: - NSAttributedString attribute generation @@ -286,7 +288,7 @@ private extension HTMLNodeToNSAttributedString { } } -extension HTMLNodeToNSAttributedString { +extension AttributedStringSerializer { // MARK: - Formatters @@ -314,7 +316,7 @@ extension HTMLNodeToNSAttributedString { } } -private extension HTMLNodeToNSAttributedString { +private extension AttributedStringSerializer { // MARK: - Implicit Representations diff --git a/Aztec/Classes/TextKit/HTMLAttachment.swift b/Aztec/Classes/TextKit/HTMLAttachment.swift index 9e93e8d6a..bf3b5b56a 100644 --- a/Aztec/Classes/TextKit/HTMLAttachment.swift +++ b/Aztec/Classes/TextKit/HTMLAttachment.swift @@ -54,7 +54,7 @@ open class HTMLAttachment: NSTextAttachment { /// Extracts the root tag name from a given HTML string /// private func extractRootTagName(from html: String) -> String { - let root = InHTMLConverter().convert(html) + let root = HTMLParser().parse(html) let firstChildren = root.children.first return firstChildren?.name ?? NSLocalizedString("Unknown", comment: "Unknown Tag Name") @@ -64,11 +64,11 @@ open class HTMLAttachment: NSTextAttachment { /// Returns the Pretty Printed version of the contained HTML /// open func prettyHTML() -> String { - let inParser = InHTMLConverter() - let outParser = OutHTMLConverter(prettyPrint: true) + let htmlParser = HTMLParser() + let serializer = HTMLSerializer(prettyPrint: true) - let inNode = inParser.convert(rawHTML) - return outParser.convert(inNode) + let inNode = htmlParser.parse(rawHTML) + return serializer.serialize(inNode) } diff --git a/Aztec/Classes/TextKit/TextStorage.swift b/Aztec/Classes/TextKit/TextStorage.swift index 028bf1ec3..31ec3b255 100644 --- a/Aztec/Classes/TextKit/TextStorage.swift +++ b/Aztec/Classes/TextKit/TextStorage.swift @@ -305,21 +305,19 @@ open class TextStorage: NSTextStorage { // MARK: - HTML Interaction open func getHTML(prettyPrint: Bool = false) -> String { - let converter = NSAttributedStringToNodes() - let rootNode = converter.convert(self) + let parser = AttributedStringParser() + let rootNode = parser.parse(self) - let serializer = OutHTMLConverter(prettyPrint: prettyPrint) - return serializer.convert(rootNode) + let serializer = HTMLSerializer(prettyPrint: prettyPrint) + return serializer.serialize(rootNode) } func setHTML(_ html: String, withDefaultFontDescriptor defaultFontDescriptor: UIFontDescriptor) { let originalLength = textStore.length - let converter = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - let (_, attributedString) = converter.convert(html) - textStore = NSMutableAttributedString(attributedString: attributedString) + textStore = NSMutableAttributedString(withHTML: html, usingDefaultFontDescriptor: defaultFontDescriptor) textStore.enumerateAttachmentsOfType(ImageAttachment.self) { [weak self] (attachment, _, _) in attachment.delegate = self diff --git a/Aztec/Classes/TextKit/TextView.swift b/Aztec/Classes/TextKit/TextView.swift index 57c857ae4..837c1faa8 100644 --- a/Aztec/Classes/TextKit/TextView.swift +++ b/Aztec/Classes/TextKit/TextView.swift @@ -460,7 +460,7 @@ open class TextView: UITextView { /// /// - Returns: The HTML version of the current Attributed String. /// - open func getHTML(prettyPrint: Bool = true) -> String { + public func getHTML(prettyPrint: Bool = true) -> String { let html = storage.getHTML(prettyPrint: prettyPrint) let processedHTML = outputProcessor?.process(html) ?? html @@ -468,12 +468,11 @@ open class TextView: UITextView { return processedHTML } - /// Loads the specified HTML into the editor. /// /// - Parameter html: The raw HTML we'd be editing. /// - open func setHTML(_ html: String) { + public func setHTML(_ html: String) { let processedHTML = inputProcessor?.process(html) ?? html @@ -486,9 +485,11 @@ open class TextView: UITextView { font = defaultFont storage.setHTML(processedHTML, withDefaultFontDescriptor: font!.fontDescriptor) + if storage.length > 0 && selectedRange.location < storage.length { typingAttributes = storage.attributes(at: selectedRange.location, effectiveRange: nil) } + delegate?.textViewDidChange?(self) formattingDelegate?.textViewCommandToggledAStyle() } diff --git a/AztecTests/Extensions/NSAttributedStringHTMLInitializerTests.swift b/AztecTests/Extensions/NSAttributedStringHTMLInitializerTests.swift new file mode 100644 index 000000000..6d92e322a --- /dev/null +++ b/AztecTests/Extensions/NSAttributedStringHTMLInitializerTests.swift @@ -0,0 +1,18 @@ +import XCTest +@testable import Aztec + +class NSAttributedStringHTMLInitializerTests: XCTestCase { + + let defaultFontDescriptor = UIFont.systemFont(ofSize: 12).fontDescriptor + + /// Test that text contained within script tags, parsed by libxml as CData, does not trigger a crash. + /// + /// Example: + /// + func testScriptTagWithCDataDoesNotTriggerACrash() { + + let html = "" + + XCTAssertNoThrow(NSAttributedString(withHTML: html, usingDefaultFontDescriptor: defaultFontDescriptor)) + } +} diff --git a/AztecTests/Importer/InHTMLConverterTests.swift b/AztecTests/HTML/Conversions/HTMLParserTests.swift similarity index 88% rename from AztecTests/Importer/InHTMLConverterTests.swift rename to AztecTests/HTML/Conversions/HTMLParserTests.swift index 4db619d54..f4f9a4886 100644 --- a/AztecTests/Importer/InHTMLConverterTests.swift +++ b/AztecTests/HTML/Conversions/HTMLParserTests.swift @@ -1,14 +1,14 @@ import XCTest @testable import Aztec -class InHTMLConverterTests: XCTestCase { +class HTMLParserTests: XCTestCase { func testSimpleHTMLConversion() { - let parser = InHTMLConverter() + let parser = HTMLParser() let html = "Hello!" - let rootNode = parser.convert(html) + let rootNode = parser.parse(html) XCTAssertEqual(rootNode.children.count, 1) @@ -29,11 +29,11 @@ class InHTMLConverterTests: XCTestCase { } func testComplexHTMLConversion() { - let parser = InHTMLConverter() + let parser = HTMLParser() let html = "
Hello World!
" - let rootNode = parser.convert(html) + let rootNode = parser.parse(html) XCTAssertEqual(rootNode.children.count, 1) @@ -68,11 +68,11 @@ class InHTMLConverterTests: XCTestCase { } func testNonASCIIConversion() { - let parser = InHTMLConverter() + let parser = HTMLParser() let html = "Otro año más" - let rootNode = parser.convert(html) + let rootNode = parser.parse(html) XCTAssertEqual(rootNode.children.count, 1) diff --git a/AztecTests/Exporter/OutHTMLConverterTests.swift b/AztecTests/HTML/Conversions/HTMLSerializerTests.swift similarity index 69% rename from AztecTests/Exporter/OutHTMLConverterTests.swift rename to AztecTests/HTML/Conversions/HTMLSerializerTests.swift index 461c2e837..8e29f6722 100644 --- a/AztecTests/Exporter/OutHTMLConverterTests.swift +++ b/AztecTests/HTML/Conversions/HTMLSerializerTests.swift @@ -1,14 +1,7 @@ import XCTest @testable import Aztec - -// MARK: - OutHTMLConverterTests -// -class OutHTMLConverterTests: XCTestCase { - - typealias InConverter = InHTMLConverter - typealias OutConverter = OutHTMLConverter - +class HTMLSerializerTests: XCTestCase { /// Verifies that single level lists gets properly prettified and indented. /// @@ -16,8 +9,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "
  • Item
  • Item
" let expected = "
    \n
  • Item
  • \n
  • Item
  • \n
" - let inNode = InConverter().convert(sample) - let outHtml = OutConverter(prettyPrint: true).convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer(prettyPrint: true).serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -28,8 +21,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "
    1. Nested 1
    2. Nested 2
  • Regular
" let expected = "
    \n
  • \n
      \n
    1. Nested 1
    2. \n
    3. Nested 2
    4. \n
    \n
  • \n
  • Regular
  • \n
" - let inNode = InConverter().convert(sample) - let outHtml = OutConverter(prettyPrint: true).convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer(prettyPrint: true).serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -41,8 +34,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "

Header

Tail" let expected = "

Header

\nTail" - let inNode = InConverter().convert(sample) - let outHtml = OutConverter(prettyPrint: true).convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer(prettyPrint: true).serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -54,8 +47,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "something something " let expected = "something something " - let inNode = InConverter().convert(sample) - let outHtml = OutConverter(prettyPrint: true).convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer(prettyPrint: true).serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -66,8 +59,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "something something " let expected = "something something " - let inNode = InConverter().convert(sample) - let outHtml = OutConverter(prettyPrint: true).convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer(prettyPrint: true).serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -78,8 +71,8 @@ class OutHTMLConverterTests: XCTestCase { let sample = "

italic heading

" let expected = "

italic heading

" - let inNode = InConverter().convert(sample) - let outHtml = OutConverter().convert(inNode) + let inNode = HTMLParser().parse(sample) + let outHtml = HTMLSerializer().serialize(inNode) XCTAssertEqual(outHtml, expected) } @@ -89,8 +82,8 @@ class OutHTMLConverterTests: XCTestCase { func testConverterProperlySerializesImportedHtml() { let html = "Hello!" - let inNode = InConverter().convert(html) - let outHtml = OutConverter().convert(inNode) + let inNode = HTMLParser().parse(html) + let outHtml = HTMLSerializer().serialize(inNode) XCTAssertEqual(outHtml, html) } @@ -100,8 +93,8 @@ class OutHTMLConverterTests: XCTestCase { func testConverterProperlySerializesImportedHtmlWithComments() { let html = "Hello!" - let inNode = InConverter().convert(html) - let outHtml = OutConverter().convert(inNode) + let inNode = HTMLParser().parse(html) + let outHtml = HTMLSerializer().serialize(inNode) XCTAssertEqual(outHtml, html) } diff --git a/AztecTests/HTML/ElementNodeTests.swift b/AztecTests/HTML/Nodes/ElementNodeTests.swift similarity index 100% rename from AztecTests/HTML/ElementNodeTests.swift rename to AztecTests/HTML/Nodes/ElementNodeTests.swift diff --git a/AztecTests/HTML/NodeTests.swift b/AztecTests/HTML/Nodes/NodeTests.swift similarity index 100% rename from AztecTests/HTML/NodeTests.swift rename to AztecTests/HTML/Nodes/NodeTests.swift diff --git a/AztecTests/HTML/TextNodeTests.swift b/AztecTests/HTML/Nodes/TextNodeTests.swift similarity index 100% rename from AztecTests/HTML/TextNodeTests.swift rename to AztecTests/HTML/Nodes/TextNodeTests.swift diff --git a/AztecTests/Importer/HTMLToAttributedStringTests.swift b/AztecTests/Importer/HTMLToAttributedStringTests.swift deleted file mode 100644 index 91e275818..000000000 --- a/AztecTests/Importer/HTMLToAttributedStringTests.swift +++ /dev/null @@ -1,310 +0,0 @@ -import XCTest -@testable import Aztec - -class HTMLToAttributedStringTests: XCTestCase { - - let defaultFontDescriptor = UIFont.systemFont(ofSize: 12).fontDescriptor - - - /// Test the conversion of a single tag at the root level to `NSAttributedString`. - /// - /// Example: Hello - /// - func testSimpleTagToStringConversion() { - - let tagNames = ["bold", "italic", "customTag", "div", "p", "a"] - - for (index, tagName) in tagNames.enumerated() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let nodeText = "Hello" - let html = "<\(tagName)>\(nodeText)" - - let output = parser.convert(html) - - let rootNode = output.rootNode - - guard rootNode.children.count == 1, - let mainNode = rootNode.children[0] as? ElementNode else { - - XCTFail("Expected to find the first node.") - return - } - - XCTAssert(mainNode.parent == rootNode) - XCTAssert(mainNode.name == tagNames[index].lowercased()) - - guard mainNode.children.count == 1, - let textNode = mainNode.children[0] as? TextNode else { - - XCTFail("Expected to find the text node.") - return - } - - XCTAssertEqual(textNode.text(), nodeText) - } - } - - /// Test the conversion of a single tag at a non-root level to `NSAttributedString`. - /// - /// Example: Hello world! - /// - func testSimpleTagAtNonRootLevelToStringConversion() { - - let tagNames = ["bold", "italic", "customTag", "div", "p", "a"] - - for (index, tagName) in tagNames.enumerated() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let firstText = "Hello " - let secondText = "world" - let thirdText = "!" - let html = "\(firstText)<\(tagName)>\(secondText)\(thirdText)" - - let output = parser.convert(html) - - let rootNode = output.rootNode - - guard rootNode.children.count == 3, - let firstTextNode = rootNode.children[0] as? TextNode, - let elementNode = rootNode.children[1] as? ElementNode, - let thirdTextNode = rootNode.children[2] as? TextNode else { - - XCTFail("Expected to find the main paragraph child nodes.") - return - } - - XCTAssertEqual(firstTextNode.text(), firstText) - XCTAssertEqual(elementNode.name, tagNames[index].lowercased()) - XCTAssertEqual(thirdTextNode.text(), thirdText) - - guard elementNode.children.count == 1, - let secondTextNode = elementNode.children[0] as? TextNode else { - - XCTFail("Expected to find the secondary text node.") - return - } - - XCTAssertEqual(secondTextNode.text(), secondText) - } - } - - /// Test the conversion of double tags at the root level to `NSAttributedString`. - /// - /// Example: Hello - /// - func testDoubleTagToStringConversion() { - - let tagNames = [("bold", "italic"), - ("italic", "customTag"), - ("customTag", "div"), - ("div", "p"), - ("p", "a"), - ("a", "bold")] - - for (index, tagName) in tagNames.enumerated() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let text = "Hello" - let html = "<\(tagName.0)><\(tagName.1)>\(text)" - - let output = parser.convert(html) - - let rootNode = output.rootNode - - XCTAssertEqual(rootNode.name, RootNode.name) - XCTAssertEqual(rootNode.children.count, 1) - - guard let firstNode = rootNode.children[0] as? ElementNode else { - XCTFail("Expected to find the first node.") - return - } - - XCTAssertEqual(firstNode.parent, rootNode) - XCTAssertEqual(firstNode.name, tagNames[index].0.lowercased()) - XCTAssertEqual(firstNode.children.count, 1) - - guard let secondNode = firstNode.children[0] as? ElementNode else { - XCTFail("Expected to find the second node.") - return - } - - XCTAssertEqual(secondNode.parent, firstNode) - XCTAssertEqual(secondNode.name, tagNames[index].1.lowercased()) - XCTAssertEqual(secondNode.children.count, 1) - - guard let textNode = secondNode.children[0] as? TextNode else { - XCTFail("Expected to find the text node.") - return - } - - XCTAssertEqual(textNode.parent, secondNode) - } - } - - /// Test the conversion of double tags at different levels to `NSAttributedString`. - /// - /// Example: Hello world! - /// - func testDoubleTagAtDifferentLevelsToStringConversion() { - - let tagNames = [("bold", "italic"), - ("italic", "customTag"), - ("customTag", "div"), - ("div", "p"), - ("p", "a"), - ("a", "bold")] - - for (index, tagName) in tagNames.enumerated() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let firstText = "Hello " - let secondText = "world" - let thirdText = "!" - let html = "<\(tagName.0)>\(firstText)<\(tagName.1)>\(secondText)\(thirdText)" - - let output = parser.convert(html) - - let rootNode = output.rootNode - - XCTAssertEqual(rootNode.name, RootNode.name) - XCTAssertEqual(rootNode.children.count, 1) - - guard let firstNode = rootNode.children[0] as? ElementNode else { - XCTFail("Expected to find the first node.") - return - } - - XCTAssertEqual(firstNode.parent, rootNode) - XCTAssertEqual(firstNode.name, tagNames[index].0.lowercased()) - XCTAssertEqual(firstNode.children.count, 3) - - guard let firstTextNode = firstNode.children[0] as? TextNode else { - XCTFail("Expected to find the first text node.") - return - } - - XCTAssertEqual(firstTextNode.parent, firstNode) - XCTAssertEqual(firstTextNode.text(), firstText) - - guard let secondNode = firstNode.children[1] as? ElementNode else { - XCTFail("Expected to find the second node.") - return - } - - XCTAssertEqual(secondNode.parent, firstNode) - XCTAssertEqual(secondNode.name, tagNames[index].1.lowercased()) - XCTAssertEqual(secondNode.children.count, 1) - - guard let secondTextNode = secondNode.children[0] as? TextNode else { - XCTFail("Expected to find the second text node.") - return - } - - XCTAssertEqual(secondTextNode.parent, secondNode) - XCTAssertEqual(secondTextNode.text(), secondText) - - guard let thirdTextNode = firstNode.children[2] as? TextNode else { - XCTFail("Expected to find the third text node.") - return - } - - XCTAssertEqual(thirdTextNode.parent, firstNode) - XCTAssertEqual(thirdTextNode.text(), thirdText) - } - } - - /// Test the conversion of a single tag at root level, and double tags at child level to - /// `NSAttributedString`. - /// - /// Example: Hello world! - /// - func testSingleTagAtRootLevelAndDoubleChildTagsToStringConversion() { - - let tagNames = [("bold", "italic", "strong"), - ("italic", "strong", "customTag"), - ("strong", "customTag", "div"), - ("customTag", "div", "p"), - ("div", "p", "a"), - ("p", "a", "bold"), - ("a", "bold", "italic")] - - for (index, tagName) in tagNames.enumerated() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - - let firstText = "Hello " - let secondText = "world" - let thirdText = "!" - let html = "<\(tagName.0)>\(firstText)<\(tagName.1)><\(tagName.2)>\(secondText)\(thirdText)" - - let output = parser.convert(html) - - let rootNode = output.rootNode - - XCTAssertEqual(rootNode.name, RootNode.name) - XCTAssertEqual(rootNode.children.count, 1) - - guard let firstNode = rootNode.children[0] as? ElementNode else { - XCTFail("Expected to find the first node.") - return - } - - XCTAssertEqual(firstNode.parent, rootNode) - XCTAssertEqual(firstNode.name, tagNames[index].0.lowercased()) - XCTAssertEqual(firstNode.children.count, 3) - - guard let firstTextNode = firstNode.children[0] as? TextNode else { - XCTFail("Expected to find the first text node.") - return - } - - XCTAssertEqual(firstTextNode.parent, firstNode) - XCTAssertEqual(firstTextNode.text(), firstText) - - guard let secondNode = firstNode.children[1] as? ElementNode else { - XCTFail("Expected to find the second node.") - return - } - - XCTAssertEqual(secondNode.parent, firstNode) - XCTAssertEqual(secondNode.name, tagNames[index].1.lowercased()) - XCTAssertEqual(secondNode.children.count, 1) - - guard let thirdNode = secondNode.children[0] as? ElementNode else { - XCTFail("Expected to find the third node.") - return - } - - XCTAssertEqual(thirdNode.parent, secondNode) - XCTAssertEqual(thirdNode.name, tagNames[index].2.lowercased()) - XCTAssertEqual(thirdNode.children.count, 1) - - guard let secondTextNode = thirdNode.children[0] as? TextNode else { - XCTFail("Expected to find the second text node.") - return - } - - XCTAssertEqual(secondTextNode.parent, thirdNode) - XCTAssertEqual(secondTextNode.text(), secondText) - - guard let thirdTextNode = firstNode.children[2] as? TextNode else { - XCTFail("Expected to find the third text node.") - return - } - - XCTAssertEqual(thirdTextNode.parent, firstNode) - XCTAssertEqual(thirdTextNode.text(), thirdText) - } - } - - /// Test that text contained within script tags, parsed by libxml as CData, does not trigger a crash. - /// - /// Example: - /// - func testScriptTagWithCDataDoesNotTriggerACrash() { - let parser = HTMLToAttributedString(usingDefaultFontDescriptor: defaultFontDescriptor) - let html = "" - - XCTAssertNoThrow(parser.convert(html)) - } -} diff --git a/AztecTests/Converters/NSAttributedStringToNodesTests.swift b/AztecTests/NSAttributedString/Conversions/AttributedStringParserTests.swift similarity index 94% rename from AztecTests/Converters/NSAttributedStringToNodesTests.swift rename to AztecTests/NSAttributedString/Conversions/AttributedStringParserTests.swift index 2510c29a8..389532c29 100644 --- a/AztecTests/Converters/NSAttributedStringToNodesTests.swift +++ b/AztecTests/NSAttributedString/Conversions/AttributedStringParserTests.swift @@ -1,10 +1,7 @@ import XCTest @testable import Aztec - -// MARK: - NSAttributedStringToNodesTests -// -class NSAttributedStringToNodesTests: XCTestCase { +class AttributedStringParserTests: XCTestCase { /// Verifies that Bold Style gets effectively mapped. /// @@ -16,7 +13,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let attributes = BoldFormatter().apply(to: Constants.sampleAttributes) let string = NSAttributedString(string: "Bold?", attributes: attributes) - let rootNode = NSAttributedStringToNodes().convert(string) + let rootNode = AttributedStringParser().parse(string) XCTAssertEqual(rootNode.children.count, 1) guard let paragraph = rootNode.children.first as? ElementNode else { @@ -50,7 +47,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let attributes = ItalicFormatter().apply(to: Constants.sampleAttributes) let string = NSAttributedString(string: "Italics!", attributes: attributes) - let node = NSAttributedStringToNodes().convert(string) + let node = AttributedStringParser().parse(string) XCTAssertEqual(node.children.count, 1) guard let paragraph = node.children.first as? ElementNode else { @@ -84,7 +81,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let attributes = UnderlineFormatter().apply(to: Constants.sampleAttributes) let string = NSAttributedString(string: "Underlined!", attributes: attributes) - let node = NSAttributedStringToNodes().convert(string) + let node = AttributedStringParser().parse(string) XCTAssertEqual(node.children.count, 1) guard let paragraph = node.children.first as? ElementNode else { @@ -120,7 +117,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSAttributedString(string: "Strike!", attributes: attributes) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssertEqual(node.children.count, 1) guard let paragraph = node.children.first as? ElementNode else { @@ -157,7 +154,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSAttributedString(string: "Yo! Yose! Yosemite!", attributes: attributes) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssertEqual(node.children.count, 1) guard let paragraph = node.children.first as? ElementNode else { @@ -198,7 +195,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSMutableAttributedString(string: text, attributes: attributes) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) let list = node.children.first as? ElementNode @@ -239,7 +236,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSMutableAttributedString(string: text, attributes: attributes) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) let list = node.children.first as? ElementNode @@ -280,7 +277,7 @@ class NSAttributedStringToNodesTests: XCTestCase { testingString.insert(stringWithAttachment, at: 0) testingString.append(stringWithAttachment) - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssertEqual(node.children.count, 1) guard let paragraph = node.children.first as? ElementNode, @@ -326,7 +323,7 @@ class NSAttributedStringToNodesTests: XCTestCase { testingString.append(stringWithAttachment) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) guard let paragraphElement = node.children.first as? ElementNode else { XCTFail() @@ -375,7 +372,7 @@ class NSAttributedStringToNodesTests: XCTestCase { testingString.append(regularText) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 2) guard let headerNode = node.children[0] as? ElementNode else { @@ -428,7 +425,7 @@ class NSAttributedStringToNodesTests: XCTestCase { testingString.append(commentString) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) guard let paragraphNode = node.children.first as? ElementNode else { @@ -446,7 +443,7 @@ class NSAttributedStringToNodesTests: XCTestCase { return } - let reconvertedHTML = OutHTMLConverter().convert(htmlNode) + let reconvertedHTML = HTMLSerializer().serialize(htmlNode) XCTAssertEqual(reconvertedHTML, htmlAttachment.rawHTML) XCTAssertEqual(textNode.contents, textString.string) @@ -465,7 +462,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSAttributedString(string: "Hello\nWorld") // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssertEqual(node.children.count, 2) guard let paragraphElement1 = node.children[0] as? ElementNode else { @@ -506,7 +503,7 @@ class NSAttributedStringToNodesTests: XCTestCase { let testingString = NSAttributedString(string: "Hello\nWorld", attributes: headingStyle) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) guard node.children.count == 2 else { XCTFail() return @@ -547,7 +544,7 @@ class NSAttributedStringToNodesTests: XCTestCase { TextListFormatter(style: .ordered).applyAttributes(to: testingString, at: testingRange) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) guard let blockquoteElementNode = node.children.first as? ElementNode, @@ -604,7 +601,7 @@ class NSAttributedStringToNodesTests: XCTestCase { BlockquoteFormatter().applyAttributes(to: testingString, at: testingRange) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) guard let unorderedElementNode = node.children.first as? ElementNode, @@ -664,7 +661,7 @@ class NSAttributedStringToNodesTests: XCTestCase { HeaderFormatter().applyAttributes(to: testingString, at: testingRange) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) guard let unorderedElementNode = node.children.first as? ElementNode, @@ -723,7 +720,7 @@ class NSAttributedStringToNodesTests: XCTestCase { testingString.addAttribute(UnsupportedHTMLAttributeName, value: unsupportedHTML, range: testingString.rangeOfEntireString) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) let paragraphElement = node.children.first as? ElementNode @@ -751,7 +748,7 @@ class NSAttributedStringToNodesTests: XCTestCase { // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) let expectedNodes = [ 0: nil, @@ -797,7 +794,7 @@ class NSAttributedStringToNodesTests: XCTestCase { formatter.applyAttributes(to: testingString, at: range) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) let restoredSpanNode = node.children.first as? ElementNode @@ -826,7 +823,7 @@ class NSAttributedStringToNodesTests: XCTestCase { formatter.applyAttributes(to: testingString, at: range) // Convert + Verify - let node = NSAttributedStringToNodes().convert(testingString) + let node = AttributedStringParser().parse(testingString) XCTAssert(node.children.count == 1) let restoredDiv1Node = node.children.first as? ElementNode @@ -845,7 +842,7 @@ class NSAttributedStringToNodesTests: XCTestCase { // MARK: - Helpers // -private extension NSAttributedStringToNodesTests { +private extension AttributedStringParserTests { /// Constants /// diff --git a/AztecTests/Converters/HTMLNodeToNSAttributedStringTests.swift b/AztecTests/NSAttributedString/Conversions/AttributedStringSerializerTests.swift similarity index 87% rename from AztecTests/Converters/HTMLNodeToNSAttributedStringTests.swift rename to AztecTests/NSAttributedString/Conversions/AttributedStringSerializerTests.swift index 14a0a1c0a..637d21a98 100644 --- a/AztecTests/Converters/HTMLNodeToNSAttributedStringTests.swift +++ b/AztecTests/NSAttributedString/Conversions/AttributedStringSerializerTests.swift @@ -1,10 +1,7 @@ import XCTest @testable import Aztec - -// MARK: - HTMLNodeToNSAttributedStringTests -// -class HTMLNodeToNSAttributedStringTests: XCTestCase { +class AttributedStringSerializerTests: XCTestCase { /// Verifies that Nodes are preserved into the NSAttributedString instance, by means of the UnsupportedHTML /// attribute. @@ -106,11 +103,11 @@ class HTMLNodeToNSAttributedStringTests: XCTestCase { func testLineBreakTagWithinHTMLDivGetsProperlyEncodedAndDecoded() { let inHtml = "

Aztec, don't forget me!
" - let inNode = InHTMLConverter().convert(inHtml) + let inNode = HTMLParser().parse(inHtml) let attrString = attributedString(from: inNode) - let outNode = NSAttributedStringToNodes().convert(attrString) - let outHtml = OutHTMLConverter().convert(outNode) + let outNode = AttributedStringParser().parse(attrString) + let outHtml = HTMLSerializer().serialize(outNode) XCTAssertEqual(outHtml, inHtml) } @@ -123,11 +120,11 @@ class HTMLNodeToNSAttributedStringTests: XCTestCase { let inHtml = "
Aztec, don't forget me!
" let expectedHtml = "


Aztec, don't forget me!

" - let inNode = InHTMLConverter().convert(inHtml) + let inNode = HTMLParser().parse(inHtml) let attrString = attributedString(from: inNode) - let outNode = NSAttributedStringToNodes().convert(attrString) - let outHtml = OutHTMLConverter().convert(outNode) + let outNode = AttributedStringParser().parse(attrString) + let outHtml = HTMLSerializer().serialize(outNode) XCTAssertEqual(outHtml, expectedHtml) } @@ -145,11 +142,11 @@ class HTMLNodeToNSAttributedStringTests: XCTestCase { "

ThreeFourFive

" + "" - let inNode = InHTMLConverter().convert(inHtml) + let inNode = HTMLParser().parse(inHtml) let attrString = attributedString(from: inNode) - let outNode = NSAttributedStringToNodes().convert(attrString) - let outHtml = OutHTMLConverter().convert(outNode) + let outNode = AttributedStringParser().parse(attrString) + let outHtml = HTMLSerializer().serialize(outNode) XCTAssertEqual(outHtml, inHtml) } @@ -158,12 +155,12 @@ class HTMLNodeToNSAttributedStringTests: XCTestCase { // MARK: - Helpers // -extension HTMLNodeToNSAttributedStringTests { +extension AttributedStringSerializerTests { func attributedString(from node: Node) -> NSAttributedString { let descriptor = UIFont.systemFont(ofSize: 14).fontDescriptor - let converter = HTMLNodeToNSAttributedString(usingDefaultFontDescriptor: descriptor) + let serializer = AttributedStringSerializer(usingDefaultFontDescriptor: descriptor) - return converter.convert(node) + return serializer.serialize(node) } }