From 46072a09ccbe307b748dc87d9b93eb8eee24d3db Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 7 Nov 2016 21:50:45 +0100 Subject: [PATCH 01/75] Update html5lib-tests to latest commit as of 2016.11.07 Commit: 27724be8d27a1232a8809a55f9c37b69706cb03e --- Tests/html5lib-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/html5lib-tests b/Tests/html5lib-tests index c305da7..27724be 160000 --- a/Tests/html5lib-tests +++ b/Tests/html5lib-tests @@ -1 +1 @@ -Subproject commit c305da74fae50fb018870de7a042da36c1a93b65 +Subproject commit 27724be8d27a1232a8809a55f9c37b69706cb03e From 2fb871a7ff47b9ff89b39c4de1e1a61761a198cf Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 20 Nov 2016 18:36:55 +0100 Subject: [PATCH 02/75] Add implementation for the length property for HTML Nodes See: https://dom.spec.whatwg.org/#concept-node-length https://heycam.github.io/webidl/#dfn-code-unit --- Sources/HTMLComment.m | 5 +++++ Sources/HTMLDocumentType.m | 5 +++++ Sources/HTMLNode.m | 10 ++++++++++ Sources/HTMLText.m | 5 +++++ Sources/include/HTMLNode.h | 12 ++++++++++++ 5 files changed, 37 insertions(+) diff --git a/Sources/HTMLComment.m b/Sources/HTMLComment.m index c126999..170f025 100644 --- a/Sources/HTMLComment.m +++ b/Sources/HTMLComment.m @@ -35,6 +35,11 @@ self.data = textContent ?: @""; } +- (NSUInteger)length +{ + return self.data.length; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone diff --git a/Sources/HTMLDocumentType.m b/Sources/HTMLDocumentType.m index 8a4636c..c22be69 100644 --- a/Sources/HTMLDocumentType.m +++ b/Sources/HTMLDocumentType.m @@ -129,6 +129,11 @@ NS_INLINE BOOL nilOrEqual(id first, id second) { return HTMLQuirksModeNoQuirks; } +- (NSUInteger)length +{ + return 0; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index 83291d7..7e597ec 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -123,6 +123,11 @@ return nil; } +- (NSUInteger)length +{ + return self.childNodesCount; +} + #pragma mark - Cast - (HTMLElement *)asElement @@ -155,6 +160,11 @@ return self.childNodes.count; } +- (BOOL)isEmpty +{ + return self.length == 0; +} + - (HTMLNode *)childNodeAtIndex:(NSUInteger)index { return [self.childNodes objectAtIndex:index]; diff --git a/Sources/HTMLText.m b/Sources/HTMLText.m index 55daaae..a56ed51 100644 --- a/Sources/HTMLText.m +++ b/Sources/HTMLText.m @@ -42,6 +42,11 @@ [self.data appendString:string]; } +- (NSUInteger)length +{ + return self.data.length; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index da1a5c5..bc74b5a 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -137,6 +137,11 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) */ @property (nonatomic, copy) NSString *innerHTML; +/** + The length of the node as described in https://dom.spec.whatwg.org/#concept-node-length + */ +@property (nonatomic, assign) NSUInteger length; + /** @abstract Use concrete subclasses of the HTML Node. */ @@ -164,6 +169,13 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) */ - (NSUInteger)childNodesCount; +/** + Checks whether the node is empty as described in https://dom.spec.whatwg.org/#concept-node-length + + @return `YES` if the node is empty, `NO` otherwise. + */ +- (BOOL)isEmpty; + /** Returns the child node at a given index. From 9fd5d34244518e7ac1548440f1a1bc04dc9b1670 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 21 Nov 2016 01:17:48 +0100 Subject: [PATCH 03/75] Add HTML Range class stub --- HTMLKit.xcodeproj/project.pbxproj | 20 ++++++++++++++++++++ Sources/HTMLRange.h | 13 +++++++++++++ Sources/HTMLRange.m | 13 +++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 Sources/HTMLRange.h create mode 100644 Sources/HTMLRange.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 000f546..97202b7 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -277,6 +277,14 @@ 62857D901D39A47F008DC254 /* CSSCompoundSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; 628AF6301BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */; }; 62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; }; + 62D91C231DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; + 62D91C241DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; + 62D91C251DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; + 62D91C261DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; + 62D91C271DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; + 62D91C281DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; + 62D91C291DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; + 62D91C2A1DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; 62ECBEE11C0B69FD00AF847B /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -661,6 +669,8 @@ 62AE594819F9948A0043F069 /* HTMLCharacterToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterToken.m; sourceTree = ""; }; 62D8345719FB1AC4009205A9 /* HTML5LibTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTokenizerTest.h; sourceTree = ""; }; 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTokenizerTest.m; sourceTree = ""; }; + 62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLRange.h; sourceTree = ""; }; + 62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = ""; }; 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = ""; }; 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = ""; }; 62ECBF4D1C0B6C7600AF847B /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -792,6 +802,8 @@ 624717171B22333200C11912 /* HTMLNodeTraversal.m */, 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */, 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */, + 62D91C211DE218A500BEFADE /* HTMLRange.h */, + 62D91C221DE218A500BEFADE /* HTMLRange.m */, 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */, 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */, 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */, @@ -1081,6 +1093,7 @@ 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */, 62ECBEE31C0B69FD00AF847B /* HTMLTokenizer.h in Headers */, 62ECBEE41C0B69FD00AF847B /* HTMLTokenizerStates.h in Headers */, + 62D91C231DE218A500BEFADE /* HTMLRange.h in Headers */, 62ECBEE51C0B69FD00AF847B /* HTMLTokenizerCharacters.h in Headers */, 62ECBEE61C0B69FD00AF847B /* HTMLTokenizerEntities.h in Headers */, 625D0F031C2717DE00D7BEB0 /* HTMLNode+Private.h in Headers */, @@ -1146,6 +1159,7 @@ 62857CD61D3989C2008DC254 /* CSSSelectorParser.h in Headers */, 62857CAA1D398973008DC254 /* HTMLTreeWalker.h in Headers */, 62857CA31D398973008DC254 /* HTMLDocumentType.h in Headers */, + 62D91C261DE218A500BEFADE /* HTMLRange.h in Headers */, 62857C6B1D3988EE008DC254 /* HTMLKit.h in Headers */, 62857C701D398907008DC254 /* HTMLTokenizerCharacters.h in Headers */, 62857C6F1D398907008DC254 /* HTMLTokenizerStates.h in Headers */, @@ -1211,6 +1225,7 @@ 62857D841D39A472008DC254 /* CSSSelectorParser.h in Headers */, 62857D7F1D39A461008DC254 /* NSString+HTMLKit.h in Headers */, 62857D7E1D39A45B008DC254 /* HTMLNode+Private.h in Headers */, + 62D91C251DE218A500BEFADE /* HTMLRange.h in Headers */, 62857D701D39A44E008DC254 /* HTMLDocumentType.h in Headers */, 62857D861D39A476008DC254 /* CSSCodePoints.h in Headers */, 62857D8A1D39A47F008DC254 /* CSSTypeSelector.h in Headers */, @@ -1276,6 +1291,7 @@ 62ECBF9F1C0B6D3900AF847B /* HTMLParser.h in Headers */, 62ECBFA61C0B6D3A00AF847B /* HTMLDOM.h in Headers */, 62ECBFA71C0B6D3A00AF847B /* HTMLNode.h in Headers */, + 62D91C241DE218A500BEFADE /* HTMLRange.h in Headers */, 62ECBFA81C0B6D3A00AF847B /* HTMLDocument.h in Headers */, 62ECBFA91C0B6D3A00AF847B /* HTMLDocumentType.h in Headers */, 62ECBFAA1C0B6D3A00AF847B /* HTMLDocumentFragment.h in Headers */, @@ -1591,6 +1607,7 @@ 62ECBF211C0B6B7900AF847B /* HTMLCommentToken.m in Sources */, 62ECBF221C0B6B7900AF847B /* HTMLDOCTYPEToken.m in Sources */, 62ECBF231C0B6B7900AF847B /* HTMLParseErrorToken.m in Sources */, + 62D91C271DE218A500BEFADE /* HTMLRange.m in Sources */, 62ECBF241C0B6B7900AF847B /* HTMLTagToken.m in Sources */, 62ECBF251C0B6B7900AF847B /* HTMLEOFToken.m in Sources */, 62ECBF261C0B6B7900AF847B /* HTMLParser.m in Sources */, @@ -1673,6 +1690,7 @@ 62857CCB1D3989B8008DC254 /* CSSSelector.m in Sources */, 62857C8B1D39892D008DC254 /* HTMLParser.m in Sources */, 62857CC61D3989AF008DC254 /* CSSSelectors.m in Sources */, + 62D91C2A1DE218A500BEFADE /* HTMLRange.m in Sources */, 62857CD31D3989B8008DC254 /* CSSCompoundSelector.m in Sources */, 62857C7B1D398912008DC254 /* HTMLTokenizer.m in Sources */, 62857CB21D398992008DC254 /* HTMLDocument.m in Sources */, @@ -1725,6 +1743,7 @@ 62857D251D39A334008DC254 /* CSSSelector.m in Sources */, 62857D021D39A324008DC254 /* HTMLTokenizer.m in Sources */, 62857D201D39A334008DC254 /* CSSSelectors.m in Sources */, + 62D91C291DE218A500BEFADE /* HTMLRange.m in Sources */, 62857D2D1D39A334008DC254 /* CSSCompoundSelector.m in Sources */, 62857D061D39A324008DC254 /* HTMLCommentToken.m in Sources */, 62857D111D39A32A008DC254 /* HTMLDocumentType.m in Sources */, @@ -1807,6 +1826,7 @@ 62ECBF691C0B6D2A00AF847B /* HTMLCommentToken.m in Sources */, 62ECBF6A1C0B6D2A00AF847B /* HTMLDOCTYPEToken.m in Sources */, 62ECBF6B1C0B6D2A00AF847B /* HTMLParseErrorToken.m in Sources */, + 62D91C281DE218A500BEFADE /* HTMLRange.m in Sources */, 62ECBF6C1C0B6D2A00AF847B /* HTMLTagToken.m in Sources */, 62ECBF6D1C0B6D2A00AF847B /* HTMLEOFToken.m in Sources */, 62ECBF6E1C0B6D2A00AF847B /* HTMLParser.m in Sources */, diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h new file mode 100644 index 0000000..9cc2a0f --- /dev/null +++ b/Sources/HTMLRange.h @@ -0,0 +1,13 @@ +// +// HTMLRange.h +// HTMLKit +// +// Created by Iska on 20/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import + +@interface HTMLRange : NSObject + +@end diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m new file mode 100644 index 0000000..f403df6 --- /dev/null +++ b/Sources/HTMLRange.m @@ -0,0 +1,13 @@ +// +// HTMLRange.m +// HTMLKit +// +// Created by Iska on 20/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLRange.h" + +@implementation HTMLRange + +@end From a08fb84be93610ecd7851e16daeaeb1d175df74c Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 21 Nov 2016 01:19:31 +0100 Subject: [PATCH 04/75] Add properties to HTML Range interface See: https://dom.spec.whatwg.org/#range --- Sources/HTMLRange.h | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 9cc2a0f..39f7cc0 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -6,8 +6,47 @@ // Copyright © 2016 BrainCookie. All rights reserved. // -#import +#import "HTMLNode.h" +/** + A HTML Range, represents a sequence of content within a node tree. + Each range has a start and an end which are boundary points. + A boundary point is a tuple consisting of a node and a non-negative numeric offset. + + https://dom.spec.whatwg.org/#ranges + */ @interface HTMLRange : NSObject +/** + The node of the start boundary point. + */ +@property (nonatomic, readonly, strong) HTMLNode *startContainer; + +/** + The offset of the start boundary point. + */ +@property (nonatomic, readonly, assign) NSUInteger startOffset; + +/** + The node of the end boundary point. + */ +@property (nonatomic, readonly, strong) HTMLNode *endContainer; + +/** + The offset of the end boundary point. + */ +@property (nonatomic, readonly, assign) NSUInteger endOffset; + +/** + Checks whether the range is collapsed, i.e. if start is the same as end. + + @return `YES` if the range is collapsed, `NO` otherwise. + */ +@property (nonatomic, readonly, assign, getter=isCollapsed) BOOL collapsed; + +/** + The common container node that contains both start and end nodes. + */ +@property (nonatomic, readonly, weak) HTMLNode *commonAncestorContainer; + @end From c57117670f694e4e9f80f72593d9a0acd99e0cc0 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 21 Nov 2016 01:20:14 +0100 Subject: [PATCH 05/75] Add method declarations to initialize and define a HTML Range See: https://dom.spec.whatwg.org/#range --- Sources/HTMLRange.h | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 39f7cc0..0206bd2 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -49,4 +49,60 @@ */ @property (nonatomic, readonly, weak) HTMLNode *commonAncestorContainer; +/** + Intializes a new HTML Range isntance with the given boundaries. + + @param startNode The node of the start boundary. + @param startOffset The offset of the start boundary. + @param endNode The node of the end boundary. + @param endOffset The offset of the end boundary. + @return A new instance of HTML Range. + */ +- (instancetype)initWithStartNode:(HTMLNode *)startNode startOffset:(NSUInteger)startOffset + endNode:(HTMLNode *)endNode endOffset:(NSUInteger)endOffset; + +/** + Sets the start boundary. + + @param startNode The new node of the start boundary. + @param startOffset The new offset of the start boundary. + */ +- (void)setStartNode:(HTMLNode *)startNode startOffset:(NSUInteger)startOffset; + +/** + Sets the end boundary. + + @param startNode The new node of the end boundary. + @param startOffset The new offset of the end boundary. + */ +- (void)setEndNode:(HTMLNode *)endNode endOffset:(NSUInteger)endOffset; + +/** + Sets the start boundary before the given node. + + @param node The node before which the boundary will be set. + */ +- (void)setStartBeforeNode:(HTMLNode *)node; + +/** + Sets the start boundary after the given node. + + @param node The node after which the boundary will be set. + */ +- (void)setStartAfterNode:(HTMLNode *)node; + +/** + Sets the end boundary before the given node. + + @param node The node before which the boundary will be set. + */ +- (void)setEndBeforeNode:(HTMLNode *)node; + +/** + Sets the end boundary after the given node. + + @param node The node after which the boundary will be set. + */ +- (void)setEndAfterNode:(HTMLNode *)node; + @end From 14289f96e5d6df4ce9e747f054b01efa25bac518 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 21 Nov 2016 01:23:52 +0100 Subject: [PATCH 06/75] Add method declarations to collapse and select nodes in the HTML Range See: https://dom.spec.whatwg.org/#range --- Sources/HTMLRange.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 0206bd2..1a15245 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -105,4 +105,28 @@ */ - (void)setEndAfterNode:(HTMLNode *)node; +/** + Collapses this range to its start. + */ +- (void)collapseToStart; + +/** + Collapses this range to its end. + */ +- (void)collapseToEnd; + +/** + Selects the given node in the range. + + @param node The node to select + */ +- (void)selectNode:(HTMLNode *)node; + +/** + Selects the node's contents in the range. + + @param node The node to select the contents. + */ +- (void)selectNodeContents:(HTMLNode *)node; + @end From 394a1a53c4af397e14a0c1c87d70dcc882a23673 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:15:09 +0100 Subject: [PATCH 07/75] Add root-node property for HTML Node --- Sources/HTMLNode.m | 5 +++++ Sources/include/HTMLNode.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index 7e597ec..9237587 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -62,6 +62,11 @@ [self.childNodes.array makeObjectsPerformSelector:@selector(setOwnerDocument:) withObject:ownerDocument]; } +- (HTMLNode *)rootNode +{ + return _parentNode == nil ? self : _parentNode.rootNode; +} + - (void)setParentNode:(HTMLNode *)parentNode { _parentNode = parentNode; diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index bc74b5a..10a32e8 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -71,6 +71,11 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) */ @property (nonatomic, weak, readonly, nullable) HTMLDocument *ownerDocument; +/** + The root node of this node, if any. + */ +@property (nonatomic, weak, readonly, nullable) HTMLNode *rootNode; + /** The parent node of this node, if any. */ From ffc9e629f256e75db48f0f9f756c7638dc93a9cc Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:15:23 +0100 Subject: [PATCH 08/75] Add index property for HTML Node --- Sources/HTMLNode.m | 5 +++++ Sources/include/HTMLNode.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index 9237587..45ff5a5 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -123,6 +123,11 @@ return node.asElement; } +- (NSUInteger)index +{ + return [self.parentNode indexOfChildNode:self]; +} + - (NSString *)textContent { return nil; diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index 10a32e8..c0cfa16 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -127,6 +127,11 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) */ @property (nonatomic, strong, readonly, nullable) HTMLElement *nextSiblingElement; +/** + The index of this node. + */ +@property (nonatomic, readonly, assign) NSUInteger index; + /** The text content of this node. */ From 80299ad9e0b4e75ac4213b3d51234d0c2892a7b7 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:17:32 +0100 Subject: [PATCH 09/75] Change HTMLDocumentPosition to NS_OPTIONS instead of NS_ENUM Better interop with Swift --- Sources/include/HTMLNode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index c0cfa16..ab3fa5b 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -28,7 +28,7 @@ typedef NS_ENUM(short, HTMLNodeType) /** A node's position in the HTML document when compared with other nodes. */ -typedef NS_ENUM(unsigned short, HTMLDocumentPosition) +typedef NS_OPTIONS(unsigned short, HTMLDocumentPosition) { HTMLDocumentPositionEquivalent = 0x0, HTMLDocumentPositionDisconnected = 0x01, From 6ed0238a8925a7bdf67289e1804f9b4d5a4662d0 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:19:32 +0100 Subject: [PATCH 10/75] =?UTF-8?q?Add=20implementation=20for=20setting=20HT?= =?UTF-8?q?ML=20Range=E2=80=99s=20boundaries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLKitDOMExceptions.m | 2 + Sources/HTMLRange.h | 4 +- Sources/HTMLRange.m | 83 ++++++++++++++++++++++++++ Sources/include/HTMLKitDOMExceptions.h | 3 + 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLKitDOMExceptions.m b/Sources/HTMLKitDOMExceptions.m index 7a0d349..1a596a3 100644 --- a/Sources/HTMLKitDOMExceptions.m +++ b/Sources/HTMLKitDOMExceptions.m @@ -14,3 +14,5 @@ NSString * const HTMLKitNotFoundError = @"NotFoundError"; NSString * const HTMLKitNotSupportedError = @"NotSupportedError"; NSString * const HTMLKitSyntaxError = @"SyntaxError"; NSString * const HTMLKitInvalidCharacterError = @"InvalidCharacterError"; +NSString * const HTMLKitInvalidNodeTypeError = @"InvalidNodeTypeError"; +NSString * const HTMLKitIndexSizeError = @"IndexSizeError"; diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 1a15245..860a54d 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -67,7 +67,7 @@ @param startNode The new node of the start boundary. @param startOffset The new offset of the start boundary. */ -- (void)setStartNode:(HTMLNode *)startNode startOffset:(NSUInteger)startOffset; +- (void)setStartNode:(HTMLNode *)node startOffset:(NSUInteger)offset; /** Sets the end boundary. @@ -75,7 +75,7 @@ @param startNode The new node of the end boundary. @param startOffset The new offset of the end boundary. */ -- (void)setEndNode:(HTMLNode *)endNode endOffset:(NSUInteger)endOffset; +- (void)setEndNode:(HTMLNode *)node endOffset:(NSUInteger)offset; /** Sets the start boundary before the given node. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index f403df6..e7f2550 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -7,7 +7,90 @@ // #import "HTMLRange.h" +#import "HTMLKitDOMExceptions.h" @implementation HTMLRange + +#pragma mark - Boundaries + +NS_INLINE void CheckValidBoundaryNode(HTMLNode *node, NSString *cmd) +{ + if (node == nil || node.nodeType == HTMLNodeDocumentType) { + [NSException raise:HTMLKitNotFoundError + format:@"%@: Invalid Node Type Error, %@ is not a valid range boundary node.", + cmd, node]; + } +} + +NS_INLINE void CheckValidBoundaryOffset(HTMLNode *node, NSUInteger offset, NSString *cmd) +{ + if (node == nil || node.nodeType == HTMLNodeDocumentType) { + [NSException raise:HTMLKitIndexSizeError + format:@"%@: Index Size Error, invalid index %lu for range boundary node %@.", + cmd, (unsigned long)offset, node]; + } +} + +NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger startOffset, HTMLNode *endNode, NSUInteger endOffset) +{ + if (startNode == endNode) { + if (startOffset == endOffset) { + return NSOrderedSame; + } else if (startOffset < endOffset) { + return NSOrderedAscending; + } else { + return NSOrderedDescending; + } + } + + HTMLDocumentPosition position = [startNode compareDocumentPositionWithNode:endNode]; + if ((position & HTMLDocumentPositionFollowing) == HTMLDocumentPositionFollowing) { + // Check Spec + } + + if ([startNode containsNode:endNode]) { + HTMLNode *child = endNode; + while (child.parentNode != startNode) { + child = child.parentNode; + } + if ([child.parentNode indexOfChildNode:child] > startOffset) { + return NSOrderedDescending; + } + } + + return NSOrderedAscending; +} + +- (void)setStartNode:(HTMLNode *)node startOffset:(NSUInteger)offset +{ + CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryOffset(node, offset, NSStringFromSelector(_cmd)); + + if (self.rootNode != node.rootNode || + CompareBoundaries(node, offset, _endContainer, _endOffset) == NSOrderedDescending) { + _endContainer = node; + _endOffset = offset; + } + + _startContainer = node; + _startOffset = offset; +} + +- (void)setEndNode:(HTMLNode *)node endOffset:(NSUInteger)offset +{ + CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryOffset(node, offset, NSStringFromSelector(_cmd)); + + if (self.rootNode != node.rootNode || + CompareBoundaries(node, offset, _startContainer, _startOffset) == NSOrderedAscending) { + _startContainer = node; + _startOffset = offset; + } + + _endContainer = node; + _endOffset = offset; +} @end diff --git a/Sources/include/HTMLKitDOMExceptions.h b/Sources/include/HTMLKitDOMExceptions.h index 115b884..f11518c 100644 --- a/Sources/include/HTMLKitDOMExceptions.h +++ b/Sources/include/HTMLKitDOMExceptions.h @@ -14,3 +14,6 @@ extern NSString * const HTMLKitNotSupportedError; extern NSString * const HTMLKitSyntaxError; extern NSString * const HTMLKitInvalidCharacterError; + +extern NSString * const HTMLKitInvalidNodeTypeError; +extern NSString * const HTMLKitIndexSizeError; From 8391a0114736ecab81155b2740ca56e7db8415ad Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:23:00 +0100 Subject: [PATCH 11/75] =?UTF-8?q?Change=20HTML=20Range=E2=80=99s=20initial?= =?UTF-8?q?izer=20to=20accept=20one=20HTML=20Document=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to spec: “The Range() constructor, when invoked, must return a new range with (current global object’s associated Document, 0) as its start and end.” We don’t have a global object (window) with an associated document, thus we have to pass one instead. --- Sources/HTMLRange.h | 15 +++++++-------- Sources/HTMLRange.m | 13 +++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 860a54d..fe460e6 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -8,6 +8,9 @@ #import "HTMLNode.h" + +#pragma mark - DOM Range + /** A HTML Range, represents a sequence of content within a node tree. Each range has a start and an end which are boundary points. @@ -50,16 +53,12 @@ @property (nonatomic, readonly, weak) HTMLNode *commonAncestorContainer; /** - Intializes a new HTML Range isntance with the given boundaries. + Initializes a new range instance for the given document. - @param startNode The node of the start boundary. - @param startOffset The offset of the start boundary. - @param endNode The node of the end boundary. - @param endOffset The offset of the end boundary. - @return A new instance of HTML Range. + @param document The HTML doucment for which the range will be constructed. + @return A new HTML Range instance. */ -- (instancetype)initWithStartNode:(HTMLNode *)startNode startOffset:(NSUInteger)startOffset - endNode:(HTMLNode *)endNode endOffset:(NSUInteger)endOffset; +- (instancetype)initWithDowcument:(HTMLDocument *)document; /** Sets the start boundary. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index e7f2550..b7ab97c 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -7,10 +7,23 @@ // #import "HTMLRange.h" +#import "HTMLDocument.h" #import "HTMLKitDOMExceptions.h" @implementation HTMLRange +#pragma mark - Lifecycle + +- (instancetype)initWithDowcument:(HTMLDocument *)document +{ + self = [super init]; + if (self) { + [self setStartNode:document startOffset:0]; + [self setEndNode:document endOffset:0]; + } + return self; +} + #pragma mark - Boundaries From 733780091df526bf083c237f7b508d17c5fa3163 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:24:02 +0100 Subject: [PATCH 12/75] Add method declaration for comparing HTML Ranges --- Sources/HTMLRange.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index fe460e6..e17cc05 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -8,6 +8,15 @@ #import "HTMLNode.h" +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) +{ + HTMLRangeComparisonMethodStartToStart = 0, + HTMLRangeComparisonMethodStartToEnd = 1, + HTMLRangeComparisonMethodEndToEnd = 2, + HTMLRangeComparisonMethodEndToStart = 3 +}; #pragma mark - DOM Range @@ -128,4 +137,17 @@ */ - (void)selectNodeContents:(HTMLNode *)node; + +/** + Compares the boundary points of this range with the given source range. + + @param method The comparison method. + @param sourceRange The range to compare with. + @return `NSOrderedAscending` if ordered before, `NSOrderedSame` if ordered same, `NSOrderedDescending` otherwise. + + @see HTMLRangeComparisonMethod + */ +- (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange; @end + +NS_ASSUME_NONNULL_END From cfb1707fc4306b418f42c111dff517d8bfe7f259 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 01:25:04 +0100 Subject: [PATCH 13/75] Implement collapsed, common ancestor & root properties for HTML Range --- Sources/HTMLRange.m | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index b7ab97c..908d708 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -24,6 +24,26 @@ return self; } +#pragma mark - Properties + +- (BOOL)isCollapsed +{ + return _startContainer == _endContainer && _startOffset == _endOffset; +} + +- (HTMLNode *)commonAncestorContainer +{ + HTMLNode *container = _startContainer; + while (![container containsNode:_endContainer]) { + container = container.parentNode; + } + return container; +} + +- (HTMLNode *)rootNode +{ + return _startContainer.rootNode; +} #pragma mark - Boundaries From 8f0a6d133e688c7a4fb8e7963cd7d866ae4b7d62 Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 21:41:41 +0100 Subject: [PATCH 14/75] Finalize HTML Range methods for setting boundaries --- Sources/HTMLRange.h | 1 - Sources/HTMLRange.m | 55 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index e17cc05..7750cbd 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -137,7 +137,6 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (void)selectNodeContents:(HTMLNode *)node; - /** Compares the boundary points of this range with the given source range. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 908d708..b79e225 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -79,7 +79,11 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s HTMLDocumentPosition position = [startNode compareDocumentPositionWithNode:endNode]; if ((position & HTMLDocumentPositionFollowing) == HTMLDocumentPositionFollowing) { - // Check Spec + if (CompareBoundaries(endNode, endOffset, startNode, startOffset) == NSOrderedAscending) { + return NSOrderedDescending; + } else { + return NSOrderedAscending; + } } if ([startNode containsNode:endNode]) { @@ -126,4 +130,53 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s _endContainer = node; _endOffset = offset; } + +- (void)setStartBeforeNode:(HTMLNode *)node +{ + HTMLNode *parent = node.parentNode; + CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); + + [self setStartNode:parent startOffset:node.index]; +} + +- (void)setStartAfterNode:(HTMLNode *)node +{ + HTMLNode *parent = node.parentNode; + CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); + + [self setStartNode:parent startOffset:node.index + 1]; +} + +- (void)setEndBeforeNode:(HTMLNode *)node +{ + HTMLNode *parent = node.parentNode; + CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); + + [self setEndNode:parent endOffset:node.index]; +} + +- (void)setEndAfterNode:(HTMLNode *)node +{ + HTMLNode *parent = node.parentNode; + CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); + + [self setEndNode:parent endOffset:node.index + 1]; +} + +- (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange +{ + CheckValidDocument(self, sourceRange, NSStringFromSelector(_cmd)); + + switch (method) { + case HTMLRangeComparisonMethodStartToStart: + return CompareBoundaries(_startContainer, _startOffset, sourceRange.startContainer, sourceRange.startOffset); + case HTMLRangeComparisonMethodStartToEnd: + return CompareBoundaries(_endContainer, _endOffset, sourceRange.startContainer, sourceRange.startOffset); + case HTMLRangeComparisonMethodEndToEnd: + return CompareBoundaries(_endContainer, _endOffset, sourceRange.endContainer, sourceRange.endOffset); + case HTMLRangeComparisonMethodEndToStart: + return CompareBoundaries(_startContainer, _startOffset, sourceRange.endContainer, sourceRange.endOffset); + } +} + @end From 9bd9dfbf6b2da63a5118760dfc0ee74f25e0bd5b Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 21:42:15 +0100 Subject: [PATCH 15/75] Add methods to collapse a HTML Range --- Sources/HTMLRange.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index b79e225..847f9ef 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -163,6 +163,16 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s [self setEndNode:parent endOffset:node.index + 1]; } +- (void)collapseToStart +{ + [self setEndNode:_startContainer endOffset:_startOffset]; +} + +- (void)collapseToEnd +{ + [self setStartNode:_endContainer startOffset:_endOffset]; +} + - (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange { CheckValidDocument(self, sourceRange, NSStringFromSelector(_cmd)); From 49799f8bcd1b35e5c5af32ab96c75eb3b7f5854d Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 22 Nov 2016 21:42:45 +0100 Subject: [PATCH 16/75] Add methods to select a node and node contents in a HTML Range --- Sources/HTMLKitDOMExceptions.m | 1 + Sources/HTMLRange.m | 26 ++++++++++++++++++++++++++ Sources/include/HTMLKitDOMExceptions.h | 1 + 3 files changed, 28 insertions(+) diff --git a/Sources/HTMLKitDOMExceptions.m b/Sources/HTMLKitDOMExceptions.m index 1a596a3..5ea8311 100644 --- a/Sources/HTMLKitDOMExceptions.m +++ b/Sources/HTMLKitDOMExceptions.m @@ -16,3 +16,4 @@ NSString * const HTMLKitSyntaxError = @"SyntaxError"; NSString * const HTMLKitInvalidCharacterError = @"InvalidCharacterError"; NSString * const HTMLKitInvalidNodeTypeError = @"InvalidNodeTypeError"; NSString * const HTMLKitIndexSizeError = @"IndexSizeError"; +NSString * const HTMLKitWrongDocumentError = @"WrongDocumentError"; diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 847f9ef..ae90172 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -65,6 +65,15 @@ NS_INLINE void CheckValidBoundaryOffset(HTMLNode *node, NSUInteger offset, NSStr } } +NS_INLINE void CheckValidDocument(HTMLRange *lhs, HTMLRange *rhs, NSString *cmd) +{ + if (lhs.rootNode != rhs.rootNode) { + [NSException raise:HTMLKitWrongDocumentError + format:@"%@: Wrong Document Error, ranges %@ and %@ have different roots.", + cmd, lhs, rhs]; + } +} + NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger startOffset, HTMLNode *endNode, NSUInteger endOffset) { if (startNode == endNode) { @@ -173,6 +182,23 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s [self setStartNode:_endContainer startOffset:_endOffset]; } +- (void)selectNode:(HTMLNode *)node +{ + HTMLNode *parent = node.parentNode; + CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); + + [self setStartNode:parent startOffset:node.index]; + [self setEndNode:parent endOffset:node.index + 1]; +} + +- (void)selectNodeContents:(HTMLNode *)node +{ + CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); + + [self setStartNode:node startOffset:0]; + [self setEndNode:node endOffset:node.length]; +} + - (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange { CheckValidDocument(self, sourceRange, NSStringFromSelector(_cmd)); diff --git a/Sources/include/HTMLKitDOMExceptions.h b/Sources/include/HTMLKitDOMExceptions.h index f11518c..5b13fae 100644 --- a/Sources/include/HTMLKitDOMExceptions.h +++ b/Sources/include/HTMLKitDOMExceptions.h @@ -17,3 +17,4 @@ extern NSString * const HTMLKitInvalidCharacterError; extern NSString * const HTMLKitInvalidNodeTypeError; extern NSString * const HTMLKitIndexSizeError; +extern NSString * const HTMLKitWrongDocumentError; From fb2952062d1dabf742d2fca0e713b0c235857528 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 02:09:06 +0100 Subject: [PATCH 17/75] Add Character Data implementation as a base for text and comment nodes https://dom.spec.whatwg.org/#characterdata --- HTMLKit.xcodeproj/project.pbxproj | 30 ++++++++++++++++++ Sources/HTMLCharacterData+Private.h | 25 +++++++++++++++ Sources/HTMLCharacterData.h | 25 +++++++++++++++ Sources/HTMLCharacterData.m | 47 +++++++++++++++++++++++++++++ Sources/HTMLComment.m | 32 ++------------------ Sources/HTMLParser.m | 6 ++-- Sources/HTMLText.m | 32 ++------------------ Sources/include/HTMLComment.h | 7 ++--- Sources/include/HTMLText.h | 7 ++--- 9 files changed, 139 insertions(+), 72 deletions(-) create mode 100644 Sources/HTMLCharacterData+Private.h create mode 100644 Sources/HTMLCharacterData.h create mode 100644 Sources/HTMLCharacterData.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 97202b7..06c7aec 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -26,6 +26,14 @@ 624AC90F19FC702E00BD3C4A /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; 624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; }; + 624C777A1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 624C777B1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 624C777C1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 624C777D1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 624C777E1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; + 624C777F1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; + 624C77801DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; + 624C77811DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; 624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; }; 62567F501C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62567F511C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -42,6 +50,10 @@ 625EE4581CBAA41D00F2CC8E /* HTMLKitTestObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 625EE4561CBAA41D00F2CC8E /* HTMLKitTestObserver.m */; }; 625EE45B1CBB171300F2CC8E /* HTMLKitTestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */; }; 625EE45C1CBB171300F2CC8E /* HTMLKitTestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */; }; + 626679CF1DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626679D01DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626679D11DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626679D21DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 62857C6B1D3988EE008DC254 /* HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A14BC19C7829400AD0C32 /* HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62857C6C1D3988EE008DC254 /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62857C6D1D398907008DC254 /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -620,6 +632,8 @@ 624B37211B250BB50010BDDF /* CSSCodePoints.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CSSCodePoints.h; path = include/CSSCodePoints.h; sourceTree = ""; }; 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitStringCategoryTests.m; sourceTree = ""; }; 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitOrderedDictionaryTests.m; sourceTree = ""; }; + 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCharacterData.h; sourceTree = ""; }; + 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterData.m; sourceTree = ""; }; 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = ""; }; 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLDOMTokenList.h; path = include/HTMLDOMTokenList.h; sourceTree = ""; }; 62567F4F1C0CB5750025D458 /* HTMLDOMTokenList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDOMTokenList.m; sourceTree = ""; }; @@ -643,6 +657,7 @@ 625EE4591CBB171300F2CC8E /* HTMLKitTestUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLKitTestUtil.h; sourceTree = ""; }; 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTestUtil.m; sourceTree = ""; }; 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLKitErrorDomain.h; path = include/HTMLKitErrorDomain.h; sourceTree = ""; }; + 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLCharacterData+Private.h"; sourceTree = ""; }; 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLParserInsertionModes.h; path = include/HTMLParserInsertionModes.h; sourceTree = ""; }; 6279F87219E1808D00F12EE5 /* HTMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLElement.h; path = include/HTMLElement.h; sourceTree = ""; }; 6279F87319E1808D00F12EE5 /* HTMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLElement.m; sourceTree = ""; }; @@ -786,6 +801,8 @@ 623406E51ADB05AD004677A3 /* HTMLDocumentFragment.m */, 6279F87219E1808D00F12EE5 /* HTMLElement.h */, 6279F87319E1808D00F12EE5 /* HTMLElement.m */, + 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */, + 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */, 623857991A9E8934003A45D9 /* HTMLComment.h */, 6238579A1A9E8934003A45D9 /* HTMLComment.m */, 62362A3A1A9FA70400301989 /* HTMLText.h */, @@ -954,6 +971,7 @@ isa = PBXGroup; children = ( 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, + 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, ); name = Private; sourceTree = ""; @@ -1107,12 +1125,14 @@ 62ECBEED1C0B69FD00AF847B /* HTMLTagToken.h in Headers */, 62ECBEEE1C0B69FD00AF847B /* HTMLEOFToken.h in Headers */, 62567F501C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */, + 626679CF1DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, 62ECBEEF1C0B69FD00AF847B /* HTMLParser.h in Headers */, 62ECBEF01C0B69FD00AF847B /* HTMLStackOfOpenElements.h in Headers */, 62ECBEF11C0B69FD00AF847B /* HTMLListOfActiveFormattingElements.h in Headers */, 62ECBEF21C0B69FD00AF847B /* HTMLElementTypes.h in Headers */, 62ECBEF31C0B69FD00AF847B /* HTMLElementAdjustment.h in Headers */, 62ECBEF41C0B69FD00AF847B /* HTMLParserInsertionModes.h in Headers */, + 624C777A1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */, 62ECBEF51C0B69FD00AF847B /* HTMLMarker.h in Headers */, 62ECBEF61C0B69FE00AF847B /* HTMLDOM.h in Headers */, 62ECBEF71C0B69FE00AF847B /* HTMLNode.h in Headers */, @@ -1173,12 +1193,14 @@ 62857C731D398907008DC254 /* HTMLToken.h in Headers */, 62857CC51D3989AB008DC254 /* CSSStructuralPseudoSelectors.h in Headers */, 62857CDE1D3989CE008DC254 /* CSSPseudoFunctionSelector.h in Headers */, + 626679D21DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, 62857CAB1D398973008DC254 /* HTMLNodeFilter.h in Headers */, 62857CA61D398973008DC254 /* HTMLText.h in Headers */, 62857C751D398907008DC254 /* HTMLCommentToken.h in Headers */, 62857C891D398927008DC254 /* HTMLParserInsertionModes.h in Headers */, 62857CA81D398973008DC254 /* HTMLDOMTokenList.h in Headers */, 62857C851D398927008DC254 /* HTMLStackOfOpenElements.h in Headers */, + 624C777D1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */, 62857CDF1D3989CE008DC254 /* CSSCombinatorSelector.h in Headers */, 62857CA91D398973008DC254 /* HTMLNodeIterator.h in Headers */, 62857CAE1D398973008DC254 /* HTMLQuirksMode.h in Headers */, @@ -1239,12 +1261,14 @@ 62857D581D39A416008DC254 /* HTMLParser.h in Headers */, 62857D571D39A411008DC254 /* HTMLEOFToken.h in Headers */, 62857D8E1D39A47F008DC254 /* CSSPseudoFunctionSelector.h in Headers */, + 626679D11DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, 62857D511D39A411008DC254 /* HTMLToken.h in Headers */, 62857D531D39A411008DC254 /* HTMLCommentToken.h in Headers */, 62857D741D39A44E008DC254 /* HTMLText.h in Headers */, 62857D5D1D39A41D008DC254 /* HTMLParserInsertionModes.h in Headers */, 62857D591D39A41D008DC254 /* HTMLStackOfOpenElements.h in Headers */, 62857D781D39A44E008DC254 /* HTMLTreeWalker.h in Headers */, + 624C777C1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */, 62857D551D39A411008DC254 /* HTMLParseErrorToken.h in Headers */, 62857D541D39A411008DC254 /* HTMLDOCTYPEToken.h in Headers */, 62857D871D39A476008DC254 /* CSSInputStream.h in Headers */, @@ -1305,12 +1329,14 @@ 62567F511C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */, 62ECBFB31C0B6D3C00AF847B /* HTMLKitDOMExceptions.h in Headers */, 62ECBFB41C0B6D3D00AF847B /* HTMLNamespaces.h in Headers */, + 626679D01DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, 62ECBFB51C0B6D3D00AF847B /* HTMLQuirksMode.h in Headers */, 62ECBFB61C0B6D3D00AF847B /* NSString+HTMLKit.h in Headers */, 62ECBFB71C0B6D3D00AF847B /* NSCharacterSet+HTMLKit.h in Headers */, 62ECBFB81C0B6D3E00AF847B /* HTMLOrderedDictionary.h in Headers */, 62ECBFB91C0B6D3E00AF847B /* CSSSelectors.h in Headers */, 62ECBFBA1C0B6D3E00AF847B /* CSSStructuralPseudoSelectors.h in Headers */, + 624C777B1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */, 62ECBFBD1C0B6D3F00AF847B /* CSSSelectorParser.h in Headers */, 62ECBFBE1C0B6D4000AF847B /* CSSNthExpressionParser.h in Headers */, 62ECBFBF1C0B6D4000AF847B /* CSSSelector.h in Headers */, @@ -1645,6 +1671,7 @@ 62ECBF461C0B6B7900AF847B /* CSSCombinatorSelector.m in Sources */, 62ECBF471C0B6B7A00AF847B /* CSSCompoundSelector.m in Sources */, 62567F521C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */, + 624C777E1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1728,6 +1755,7 @@ 62857CD01D3989B8008DC254 /* CSSNthExpressionSelector.m in Sources */, 62857CB81D398992008DC254 /* HTMLDOMTokenList.m in Sources */, 62857C831D398912008DC254 /* HTMLEOFToken.m in Sources */, + 624C77811DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1781,6 +1809,7 @@ 62857D2A1D39A334008DC254 /* CSSNthExpressionSelector.m in Sources */, 62857D171D39A32A008DC254 /* HTMLDOMTokenList.m in Sources */, 62857D0A1D39A324008DC254 /* HTMLEOFToken.m in Sources */, + 624C77801DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1864,6 +1893,7 @@ 62ECBF8E1C0B6D2A00AF847B /* CSSCombinatorSelector.m in Sources */, 62ECBF8F1C0B6D2A00AF847B /* CSSCompoundSelector.m in Sources */, 62567F531C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */, + 624C777F1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/HTMLCharacterData+Private.h b/Sources/HTMLCharacterData+Private.h new file mode 100644 index 0000000..50a9463 --- /dev/null +++ b/Sources/HTMLCharacterData+Private.h @@ -0,0 +1,25 @@ +// +// HTMLCharacterData+Private.h +// HTMLKit +// +// Created by Iska on 26/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLCharacterData.h" +#import "HTMLNode.h" + +@interface HTMLCharacterData () + +/** + Designated initializer of the HTML CharacterData, which, however, should not be used directly. It is intended to be + called only by subclasses, i.e. HTMLText and HTMLComment. + + @param name The node's name. + @param type The node's type. + @param data The node's data string. + @return A new instance of a HTML CharacterData. + */ +- (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type data:(NSString *)data NS_DESIGNATED_INITIALIZER; + +@end diff --git a/Sources/HTMLCharacterData.h b/Sources/HTMLCharacterData.h new file mode 100644 index 0000000..7ca0e3a --- /dev/null +++ b/Sources/HTMLCharacterData.h @@ -0,0 +1,25 @@ +// +// HTMLCharacterData.h +// HTMLKit +// +// Created by Iska on 26/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLNode.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + A HTML CharacterData + + https://dom.spec.whatwg.org/#characterdata + */ +@interface HTMLCharacterData : HTMLNode + +/** @brief The associated mutable data string. */ +@property (nonatomic, copy, readonly) NSMutableString *data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLCharacterData.m b/Sources/HTMLCharacterData.m new file mode 100644 index 0000000..8f5eb44 --- /dev/null +++ b/Sources/HTMLCharacterData.m @@ -0,0 +1,47 @@ +// +// HTMLCharacterData.m +// HTMLKit +// +// Created by Iska on 26/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLCharacterData.h" +#import "HTMLNode+Private.h" + +@implementation HTMLCharacterData + +- (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type data:(NSString *)data +{ + self = [super initWithName:name type:type]; + if (self) { + _data = [[NSMutableString alloc] initWithString:data ?: @""]; + } + return self; +} + +- (NSString *)textContent +{ + return [_data copy]; +} + +- (void)setTextContent:(NSString *)textContent +{ + [_data setString:textContent ?: @""]; +} + +- (NSUInteger)length +{ + return _data.length; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone +{ + HTMLCharacterData *copy = [super copyWithZone:zone]; + copy->_data = self.data; + return copy; +} + +@end diff --git a/Sources/HTMLComment.m b/Sources/HTMLComment.m index 170f025..afebf89 100644 --- a/Sources/HTMLComment.m +++ b/Sources/HTMLComment.m @@ -7,7 +7,7 @@ // #import "HTMLComment.h" -#import "HTMLNode+Private.h" +#import "HTMLCharacterData+Private.h" @implementation HTMLComment @@ -18,35 +18,7 @@ - (instancetype)initWithData:(NSString *)data { - self = [super initWithName:@"#comment" type:HTMLNodeComment]; - if (self) { - self.data = data ?: @""; - } - return self; -} - -- (NSString *)textContent -{ - return self.data; -} - -- (void)setTextContent:(NSString *)textContent -{ - self.data = textContent ?: @""; -} - -- (NSUInteger)length -{ - return self.data.length; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - HTMLComment *copy = [super copyWithZone:zone]; - copy.data = self.data; - return copy; + return [super initWithName:@"#comment" type:HTMLNodeComment data:data]; } #pragma mark - Serialization diff --git a/Sources/HTMLParser.m b/Sources/HTMLParser.m index 230ad53..5311c1d 100644 --- a/Sources/HTMLParser.m +++ b/Sources/HTMLParser.m @@ -457,9 +457,11 @@ beforeChildNode:&child]; if (adjustedInsertionLocation.nodeType != HTMLNodeDocument) { if (child != nil && child.previousSibling.nodeType == HTMLNodeText) { - [(HTMLText *)child.previousSibling appendString:data]; + HTMLText *textNode = (HTMLText *)child.previousSibling; + [textNode.data appendString:data]; } else if (adjustedInsertionLocation.lastChild.nodeType == HTMLNodeText) { - [(HTMLText *)adjustedInsertionLocation.lastChild appendString:data]; + HTMLText *textNode = (HTMLText *)adjustedInsertionLocation.lastChild; + [textNode.data appendString:data]; } else { HTMLText *text = [[HTMLText alloc] initWithData:data]; [adjustedInsertionLocation insertNode:text beforeChildNode:child]; diff --git a/Sources/HTMLText.m b/Sources/HTMLText.m index a56ed51..ff504eb 100644 --- a/Sources/HTMLText.m +++ b/Sources/HTMLText.m @@ -9,7 +9,7 @@ #import "HTMLText.h" #import "HTMLElement.h" #import "NSString+HTMLKit.h" -#import "HTMLNode+Private.h" +#import "HTMLCharacterData+Private.h" @implementation HTMLText @@ -20,21 +20,7 @@ - (instancetype)initWithData:(NSString *)data { - self = [super initWithName:@"#text" type:HTMLNodeText]; - if (self) { - _data = [[NSMutableString alloc] initWithString:data ?: @""]; - } - return self; -} - -- (NSString *)textContent -{ - return [self.data copy]; -} - -- (void)setTextContent:(NSString *)textContent -{ - [self.data setString:textContent ?: @""]; + return [super initWithName:@"#text" type:HTMLNodeText data:data]; } - (void)appendString:(NSString *)string @@ -42,20 +28,6 @@ [self.data appendString:string]; } -- (NSUInteger)length -{ - return self.data.length; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone -{ - HTMLText *copy = [super copyWithZone:zone]; - copy.data = self.data; - return copy; -} - #pragma mark - Serialization - (NSString *)outerHTML diff --git a/Sources/include/HTMLComment.h b/Sources/include/HTMLComment.h index 41a378e..d9ab331 100644 --- a/Sources/include/HTMLComment.h +++ b/Sources/include/HTMLComment.h @@ -6,17 +6,14 @@ // Copyright (c) 2015 BrainCookie. All rights reserved. // -#import "HTMLNode.h" +#import "HTMLCharacterData.h" NS_ASSUME_NONNULL_BEGIN /** A HTML Comment node */ -@interface HTMLComment : HTMLNode - -/** @brief The comment string. */ -@property (nonatomic, copy) NSString *data; +@interface HTMLComment : HTMLCharacterData /** Initializes a new HTML comment node. diff --git a/Sources/include/HTMLText.h b/Sources/include/HTMLText.h index e97df7e..ce7b24b 100644 --- a/Sources/include/HTMLText.h +++ b/Sources/include/HTMLText.h @@ -6,17 +6,14 @@ // Copyright (c) 2015 BrainCookie. All rights reserved. // -#import "HTMLNode.h" +#import "HTMLCharacterData.h" NS_ASSUME_NONNULL_BEGIN /** A HTML Text node */ -@interface HTMLText : HTMLNode - -/** @brief The text string. */ -@property (nonatomic, copy) NSMutableString *data; +@interface HTMLText : HTMLCharacterData /** Initializes a new HTML text node. From c3c7c3431091e00303cd56c1c2d8c6100d8bfc50 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 02:10:10 +0100 Subject: [PATCH 18/75] Deprecate appendString: method in HTML Text node The data property is mutable and should be used instead --- Sources/include/HTMLText.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/include/HTMLText.h b/Sources/include/HTMLText.h index ce7b24b..e1343e7 100644 --- a/Sources/include/HTMLText.h +++ b/Sources/include/HTMLText.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @param string The string to append. */ -- (void)appendString:(NSString *)string; +- (void)appendString:(NSString *)string __attribute__((deprecated("Use the mutable data property instead."))); @end From 6fdc7ff85b9e16a079542b78c2d283978e6608cd Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 02:43:10 +0100 Subject: [PATCH 19/75] Refactor private HTML Document extensions into one separate category --- HTMLKit.xcodeproj/project.pbxproj | 10 ++++++++++ Sources/HTMLDocument+Private.h | 26 ++++++++++++++++++++++++++ Sources/HTMLNode.m | 7 +------ Sources/HTMLNodeIterator.m | 6 +----- Sources/HTMLParser.m | 5 +---- Sources/HTMLTemplate.m | 5 +---- 6 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 Sources/HTMLDocument+Private.h diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 06c7aec..d3de318 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -11,6 +11,10 @@ 62132E5D1C021FF200084175 /* css-tests in Resources */ = {isa = PBXBuildFile; fileRef = 62132E5B1C021FF200084175 /* css-tests */; }; 6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */; }; 6216ACFE1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */; }; + 621CC4911DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */; }; @@ -558,6 +562,7 @@ 62132E581C01F83200084175 /* CSSSelectorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorTest.m; sourceTree = ""; }; 62132E5B1C021FF200084175 /* css-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "css-tests"; sourceTree = ""; }; 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSExtensionSelectorsParsingTests.m; sourceTree = ""; }; + 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLDocument+Private.h"; sourceTree = ""; }; 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParserTests.m; sourceTree = ""; }; 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelectorTests.m; sourceTree = ""; }; 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLElementTypes.h; path = include/HTMLElementTypes.h; sourceTree = ""; }; @@ -970,6 +975,7 @@ 625D0F071C2717E400D7BEB0 /* Private */ = { isa = PBXGroup; children = ( + 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */, 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, ); @@ -1126,6 +1132,7 @@ 62ECBEEE1C0B69FD00AF847B /* HTMLEOFToken.h in Headers */, 62567F501C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */, 626679CF1DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, + 621CC4911DEA704000D1992A /* HTMLDocument+Private.h in Headers */, 62ECBEEF1C0B69FD00AF847B /* HTMLParser.h in Headers */, 62ECBEF01C0B69FD00AF847B /* HTMLStackOfOpenElements.h in Headers */, 62ECBEF11C0B69FD00AF847B /* HTMLListOfActiveFormattingElements.h in Headers */, @@ -1194,6 +1201,7 @@ 62857CC51D3989AB008DC254 /* CSSStructuralPseudoSelectors.h in Headers */, 62857CDE1D3989CE008DC254 /* CSSPseudoFunctionSelector.h in Headers */, 626679D21DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, + 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */, 62857CAB1D398973008DC254 /* HTMLNodeFilter.h in Headers */, 62857CA61D398973008DC254 /* HTMLText.h in Headers */, 62857C751D398907008DC254 /* HTMLCommentToken.h in Headers */, @@ -1262,6 +1270,7 @@ 62857D571D39A411008DC254 /* HTMLEOFToken.h in Headers */, 62857D8E1D39A47F008DC254 /* CSSPseudoFunctionSelector.h in Headers */, 626679D11DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, + 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */, 62857D511D39A411008DC254 /* HTMLToken.h in Headers */, 62857D531D39A411008DC254 /* HTMLCommentToken.h in Headers */, 62857D741D39A44E008DC254 /* HTMLText.h in Headers */, @@ -1330,6 +1339,7 @@ 62ECBFB31C0B6D3C00AF847B /* HTMLKitDOMExceptions.h in Headers */, 62ECBFB41C0B6D3D00AF847B /* HTMLNamespaces.h in Headers */, 626679D01DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */, + 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */, 62ECBFB51C0B6D3D00AF847B /* HTMLQuirksMode.h in Headers */, 62ECBFB61C0B6D3D00AF847B /* NSString+HTMLKit.h in Headers */, 62ECBFB71C0B6D3D00AF847B /* NSCharacterSet+HTMLKit.h in Headers */, diff --git a/Sources/HTMLDocument+Private.h b/Sources/HTMLDocument+Private.h new file mode 100644 index 0000000..c66c926 --- /dev/null +++ b/Sources/HTMLDocument+Private.h @@ -0,0 +1,26 @@ +// +// HTMLDocument+Private.h +// HTMLKit +// +// Created by Iska on 27/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLDocument.h" +#import "HTMLNode.h" +#import "HTMLNodeIterator.h" +#import "HTMLRange.h" + +@interface HTMLDocument () + +@property (nonatomic, assign) HTMLDocumentReadyState readyState; + +- (void)runRemovingStepsForNode:(HTMLNode *)oldNode + withOldParent:(HTMLNode *)oldParent + andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; + +- (void)attachNodeIterator:(HTMLNodeIterator *)iterator; +- (void)detachNodeIterator:(HTMLNodeIterator *)iterator; + + +@end diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index 45ff5a5..c2aecba 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -16,12 +16,7 @@ #import "HTMLKitDOMExceptions.h" #import "HTMLNodeFilter.h" #import "CSSSelector.h" - -@interface HTMLDocument (Private) -- (void)runRemovingStepsForNode:(HTMLNode *)oldNode - withOldParent:(HTMLNode *)oldParent - andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; -@end +#import "HTMLDocument+Private.h" @interface HTMLNode () { diff --git a/Sources/HTMLNodeIterator.m b/Sources/HTMLNodeIterator.m index 5e71387..7c0937e 100644 --- a/Sources/HTMLNodeIterator.m +++ b/Sources/HTMLNodeIterator.m @@ -11,6 +11,7 @@ #import "HTMLNode.h" #import "HTMLNodeFilter.h" #import "HTMLNodeTraversal.h" +#import "HTMLDocument+Private.h" typedef NS_ENUM(short, TraverseDirection) { @@ -18,11 +19,6 @@ typedef NS_ENUM(short, TraverseDirection) TraverseDirectionPrevious }; -@interface HTMLDocument (Private) -- (void)attachNodeIterator:(HTMLNodeIterator *)iterator; -- (void)detachNodeIterator:(HTMLNodeIterator *)iterator; -@end - @interface HTMLNodeIterator () { HTMLNode *_root; diff --git a/Sources/HTMLParser.m b/Sources/HTMLParser.m index 5311c1d..dd1714c 100644 --- a/Sources/HTMLParser.m +++ b/Sources/HTMLParser.m @@ -18,15 +18,12 @@ #import "HTMLMarker.h" #import "NSString+HTMLKit.h" #import "CSSSelectors.h" +#import "HTMLDocument+Private.h" @interface HTMLTokenizer (Private) @property (nonatomic, weak) HTMLParser *parser; @end -@interface HTMLDocument (Private) -@property (nonatomic, assign) HTMLDocumentReadyState readyState; -@end - @interface HTMLParser () { HTMLTokenizer *_tokenizer; diff --git a/Sources/HTMLTemplate.m b/Sources/HTMLTemplate.m index 9eebbc0..aa6fe59 100644 --- a/Sources/HTMLTemplate.m +++ b/Sources/HTMLTemplate.m @@ -8,10 +8,7 @@ #import "HTMLTemplate.h" #import "HTMLDocument.h" - -@interface HTMLNode (Private) -@property (nonatomic, weak) HTMLDocument *ownerDocument; -@end +#import "HTMLNode+Private.h" @implementation HTMLTemplate From 9df89043d3d7dc1e49ea552bfc70948a87fe45f5 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 03:12:58 +0100 Subject: [PATCH 20/75] Refactor all private extensions into own separate categories --- HTMLKit.xcodeproj/project.pbxproj | 20 +++++++++++++++++ Sources/HTMLCharacterData+Private.h | 3 +++ Sources/HTMLDocument+Private.h | 35 +++++++++++++++++++++++++++++ Sources/HTMLDocument.m | 7 +----- Sources/HTMLNodeIterator+Private.h | 28 +++++++++++++++++++++++ Sources/HTMLParser+Private.h | 23 +++++++++++++++++++ Sources/HTMLParser.m | 4 ---- Sources/HTMLTokenizer.m | 6 +---- Sources/include/HTMLTokenizer.h | 2 +- 9 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 Sources/HTMLNodeIterator+Private.h create mode 100644 Sources/HTMLParser+Private.h diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index d3de318..51701fb 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -15,6 +15,14 @@ 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; + 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; + 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; + 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; + 621CC4A51DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC4A61DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; }; + 621CC4A81DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */; }; @@ -563,6 +571,8 @@ 62132E5B1C021FF200084175 /* css-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "css-tests"; sourceTree = ""; }; 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSExtensionSelectorsParsingTests.m; sourceTree = ""; }; 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLDocument+Private.h"; sourceTree = ""; }; + 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLNodeIterator+Private.h"; sourceTree = ""; }; + 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLParser+Private.h"; sourceTree = ""; }; 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParserTests.m; sourceTree = ""; }; 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelectorTests.m; sourceTree = ""; }; 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLElementTypes.h; path = include/HTMLElementTypes.h; sourceTree = ""; }; @@ -978,6 +988,8 @@ 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */, 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, + 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */, + 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */, ); name = Private; sourceTree = ""; @@ -1143,6 +1155,7 @@ 62ECBEF51C0B69FD00AF847B /* HTMLMarker.h in Headers */, 62ECBEF61C0B69FE00AF847B /* HTMLDOM.h in Headers */, 62ECBEF71C0B69FE00AF847B /* HTMLNode.h in Headers */, + 621CC4A51DEA721A00D1992A /* HTMLParser+Private.h in Headers */, 62ECBEF81C0B69FE00AF847B /* HTMLDocument.h in Headers */, 62ECBEF91C0B69FE00AF847B /* HTMLDocumentType.h in Headers */, 62ECBEFA1C0B69FE00AF847B /* HTMLDocumentFragment.h in Headers */, @@ -1168,6 +1181,7 @@ 62ECBF0F1C0B6A0100AF847B /* CSSSelector.h in Headers */, 62ECBF101C0B6A0100AF847B /* CSSSelectorBlock.h in Headers */, 62ECBF111C0B6A0200AF847B /* CSSTypeSelector.h in Headers */, + 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBF121C0B6A0200AF847B /* CSSAttributeSelector.h in Headers */, 62ECBF131C0B6A0200AF847B /* CSSPseudoClassSelector.h in Headers */, 62ECBF141C0B6A0200AF847B /* CSSNthExpressionSelector.h in Headers */, @@ -1212,6 +1226,7 @@ 62857CDF1D3989CE008DC254 /* CSSCombinatorSelector.h in Headers */, 62857CA91D398973008DC254 /* HTMLNodeIterator.h in Headers */, 62857CAE1D398973008DC254 /* HTMLQuirksMode.h in Headers */, + 621CC4A81DEA721A00D1992A /* HTMLParser+Private.h in Headers */, 62857CAF1D398977008DC254 /* HTMLNodeTraversal.h in Headers */, 62857C771D398907008DC254 /* HTMLParseErrorToken.h in Headers */, 62857CDC1D3989CE008DC254 /* CSSPseudoClassSelector.h in Headers */, @@ -1237,6 +1252,7 @@ 62857CA11D398973008DC254 /* HTMLNode.h in Headers */, 62857CD41D3989BF008DC254 /* CSSCodePoints.h in Headers */, 62857C871D398927008DC254 /* HTMLElementTypes.h in Headers */, + 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62857C711D398907008DC254 /* HTMLTokenizerEntities.h in Headers */, 62857C6C1D3988EE008DC254 /* HTMLKitErrorDomain.h in Headers */, 62857CD51D3989BF008DC254 /* CSSInputStream.h in Headers */, @@ -1281,6 +1297,7 @@ 62857D551D39A411008DC254 /* HTMLParseErrorToken.h in Headers */, 62857D541D39A411008DC254 /* HTMLDOCTYPEToken.h in Headers */, 62857D871D39A476008DC254 /* CSSInputStream.h in Headers */, + 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */, 62857D8F1D39A47F008DC254 /* CSSCombinatorSelector.h in Headers */, 62857D5C1D39A41D008DC254 /* HTMLElementAdjustment.h in Headers */, 62857D891D39A47F008DC254 /* CSSSelectorBlock.h in Headers */, @@ -1306,6 +1323,7 @@ 62857D5B1D39A41D008DC254 /* HTMLElementTypes.h in Headers */, 62857D881D39A47F008DC254 /* CSSSelector.h in Headers */, 62857D4F1D39A40A008DC254 /* HTMLTokenizerEntities.h in Headers */, + 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62857D901D39A47F008DC254 /* CSSCompoundSelector.h in Headers */, 62857D4A1D39A3F4008DC254 /* HTMLKitErrorDomain.h in Headers */, 62857D7C1D39A452008DC254 /* HTMLQuirksMode.h in Headers */, @@ -1350,6 +1368,7 @@ 62ECBFBD1C0B6D3F00AF847B /* CSSSelectorParser.h in Headers */, 62ECBFBE1C0B6D4000AF847B /* CSSNthExpressionParser.h in Headers */, 62ECBFBF1C0B6D4000AF847B /* CSSSelector.h in Headers */, + 621CC4A61DEA721A00D1992A /* HTMLParser+Private.h in Headers */, 62ECBFC01C0B6D4000AF847B /* CSSSelectorBlock.h in Headers */, 62ECBFC11C0B6D4100AF847B /* CSSTypeSelector.h in Headers */, 62ECBFC21C0B6D4100AF847B /* CSSAttributeSelector.h in Headers */, @@ -1375,6 +1394,7 @@ 62ECBF9E1C0B6D3800AF847B /* HTMLEOFToken.h in Headers */, 62ECBFA01C0B6D3900AF847B /* HTMLStackOfOpenElements.h in Headers */, 62ECBFA11C0B6D3900AF847B /* HTMLListOfActiveFormattingElements.h in Headers */, + 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBFA21C0B6D3900AF847B /* HTMLElementTypes.h in Headers */, 62ECBFA31C0B6D3900AF847B /* HTMLElementAdjustment.h in Headers */, 62ECBFA41C0B6D3900AF847B /* HTMLParserInsertionModes.h in Headers */, diff --git a/Sources/HTMLCharacterData+Private.h b/Sources/HTMLCharacterData+Private.h index 50a9463..762a0d5 100644 --- a/Sources/HTMLCharacterData+Private.h +++ b/Sources/HTMLCharacterData+Private.h @@ -9,6 +9,9 @@ #import "HTMLCharacterData.h" #import "HTMLNode.h" +/** + Private HTML Character Data methods which are not intended for public API. + */ @interface HTMLCharacterData () /** diff --git a/Sources/HTMLDocument+Private.h b/Sources/HTMLDocument+Private.h index c66c926..1b30e5c 100644 --- a/Sources/HTMLDocument+Private.h +++ b/Sources/HTMLDocument+Private.h @@ -11,16 +11,51 @@ #import "HTMLNodeIterator.h" #import "HTMLRange.h" +/** + Private HTML Document methods which are not intended for public API. + */ @interface HTMLDocument () @property (nonatomic, assign) HTMLDocumentReadyState readyState; +/** + Runs the necessary steps after removing a node from the DOM. + + @param oldNode The old node that was removed. + @param oldParent The old parent of the node that was removed. + @param oldPreviousSibling The old previous sibling node of the node that was removed. + */ - (void)runRemovingStepsForNode:(HTMLNode *)oldNode withOldParent:(HTMLNode *)oldParent andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; +/** + Attaches a node iterator to this document. + + @param iterator The iterator to attach. + */ - (void)attachNodeIterator:(HTMLNodeIterator *)iterator; + +/** + Detaches a node interator from this document. + + @param iterator The iterator to detach. + */ - (void)detachNodeIterator:(HTMLNodeIterator *)iterator; +/** + Attaches a range to this document. + + @param range The range to attach. + */ +- (void)attachRange:(HTMLRange *)range; + +/** + Detaches a range from this document. + + @param range The range to detach. + */ +- (void)detachRange:(HTMLRange *)range; + @end diff --git a/Sources/HTMLDocument.m b/Sources/HTMLDocument.m index 120cfac..6fd7996 100644 --- a/Sources/HTMLDocument.m +++ b/Sources/HTMLDocument.m @@ -11,12 +11,7 @@ #import "HTMLNodeIterator.h" #import "HTMLKitDOMExceptions.h" #import "HTMLNode+Private.h" - -@interface HTMLNodeIterator (Private) -- (void)runRemovingStepsForNode:(HTMLNode *)oldNode - withOldParent:(HTMLNode *)oldParent - andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; -@end +#import "HTMLNodeIterator+Private.h" @interface HTMLDocument () { diff --git a/Sources/HTMLNodeIterator+Private.h b/Sources/HTMLNodeIterator+Private.h new file mode 100644 index 0000000..3714eac --- /dev/null +++ b/Sources/HTMLNodeIterator+Private.h @@ -0,0 +1,28 @@ +// +// HTMLNodeIterator+Private.h +// HTMLKit +// +// Created by Iska on 27/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLNodeIterator.h" +#import "HTMLNode.h" + +/** + Private HTML Node Iterator methods which are not intended for public API. + */ +@interface HTMLNodeIterator (Private) + +/** + Runs the necessary steps after removing a node from the DOM. + + @param oldNode The old node that was removed. + @param oldParent The old parent of the node that was removed. + @param oldPreviousSibling The old previous sibling node of the node that was removed. + */ +- (void)runRemovingStepsForNode:(HTMLNode *)oldNode + withOldParent:(HTMLNode *)oldParent + andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; + +@end diff --git a/Sources/HTMLParser+Private.h b/Sources/HTMLParser+Private.h new file mode 100644 index 0000000..35db646 --- /dev/null +++ b/Sources/HTMLParser+Private.h @@ -0,0 +1,23 @@ +// +// HTLMLParser+Private.h +// HTMLKit +// +// Created by Iska on 27/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLParser.h" +#import "HTMLElement.h" + +/** + Private HTML Parser properties & methods which are not intended for public API. + */ +@interface HTMLParser (Private) + +/** + The adjusted current node in the context of HTML parsing as described in: + https://html.spec.whatwg.org/#adjusted-current-node + */ +@property (nonatomic, strong, readonly) HTMLElement *adjustedCurrentNode; + +@end diff --git a/Sources/HTMLParser.m b/Sources/HTMLParser.m index dd1714c..15f85ab 100644 --- a/Sources/HTMLParser.m +++ b/Sources/HTMLParser.m @@ -20,10 +20,6 @@ #import "CSSSelectors.h" #import "HTMLDocument+Private.h" -@interface HTMLTokenizer (Private) -@property (nonatomic, weak) HTMLParser *parser; -@end - @interface HTMLParser () { HTMLTokenizer *_tokenizer; diff --git a/Sources/HTMLTokenizer.m b/Sources/HTMLTokenizer.m index 34068c2..705eb45 100644 --- a/Sources/HTMLTokenizer.m +++ b/Sources/HTMLTokenizer.m @@ -13,10 +13,7 @@ #import "HTMLTokenizerStates.h" #import "HTMLTokenizerCharacters.h" #import "HTMLTokenizerEntities.h" - -@interface HTMLParser (Private) -@property (nonatomic, strong, readonly) HTMLElement *adjustedCurrentNode; -@end +#import "HTMLParser+Private.h" @interface HTMLTokenizer () { @@ -45,7 +42,6 @@ BOOL _eof; } -@property (nonatomic, weak) HTMLParser *parser; @end @implementation HTMLTokenizer diff --git a/Sources/include/HTMLTokenizer.h b/Sources/include/HTMLTokenizer.h index 04a0673..0c37262 100644 --- a/Sources/include/HTMLTokenizer.h +++ b/Sources/include/HTMLTokenizer.h @@ -37,7 +37,7 @@ @see HTMLParser */ -@property (nonatomic, weak, readonly) HTMLParser *parser; +@property (nonatomic, weak) HTMLParser *parser; /** Initializes a new Tokenizer with the given string. From 0d95ba33d152d0472a1ea5637a95f3e1e75e3aec Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 03:13:21 +0100 Subject: [PATCH 21/75] Add HTML Document methods to attach and detach a range to the document --- Sources/HTMLDocument.m | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Sources/HTMLDocument.m b/Sources/HTMLDocument.m index 6fd7996..9c8f068 100644 --- a/Sources/HTMLDocument.m +++ b/Sources/HTMLDocument.m @@ -9,6 +9,7 @@ #import "HTMLDocument.h" #import "HTMLParser.h" #import "HTMLNodeIterator.h" +#import "HTMLRange.h" #import "HTMLKitDOMExceptions.h" #import "HTMLNode+Private.h" #import "HTMLNodeIterator+Private.h" @@ -17,6 +18,7 @@ { HTMLDocument *_inertTemplateDocument; NSMutableArray *_nodeIterators; + NSMutableArray *_ranges; } @property (nonatomic, assign) HTMLDocumentReadyState readyState; @end @@ -37,6 +39,7 @@ if (self) { _readyState = HTMLDocumentLoading; _nodeIterators = [NSMutableArray new]; + _ranges = [NSMutableArray new]; } return self; } @@ -149,6 +152,18 @@ } } +#pragma mark - Ranges + +- (void)attachRange:(HTMLRange *)range +{ + [_ranges addObject:range]; +} + +- (void)detachRange:(HTMLRange *)range +{ + [_ranges removeObject:range]; +} + #pragma mark - Mutation Algorithms - (HTMLNode *)adoptNode:(HTMLNode *)node From ef672e1dbb40f79cc1e93e7322b4987bd113a5aa Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 15:00:13 +0100 Subject: [PATCH 22/75] =?UTF-8?q?Add=20range=20attaching/detaching=20to=20?= =?UTF-8?q?the=20range=E2=80=99s=20lifecycle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index ae90172..d670a83 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -9,6 +9,13 @@ #import "HTMLRange.h" #import "HTMLDocument.h" #import "HTMLKitDOMExceptions.h" +#import "HTMLDocument+Private.h" + +@interface HTMLRange () +{ + HTMLDocument *_ownerDocument; +} +@end @implementation HTMLRange @@ -18,12 +25,19 @@ { self = [super init]; if (self) { + _ownerDocument = document; + [_ownerDocument attachRange:self]; [self setStartNode:document startOffset:0]; [self setEndNode:document endOffset:0]; } return self; } +- (void)dealloc +{ + [_ownerDocument detachRange:self]; +} + #pragma mark - Properties - (BOOL)isCollapsed From 6be1bd702f88b716ce29f38cd25e157945ae97eb Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 20:18:12 +0100 Subject: [PATCH 23/75] Add implementation for HTML Character Data methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The data property is longer exposed as a mutable string. Instead all manipulations must be performed via the provided API in order to ensure correct updates for the Document’s attached ranges. See: https://dom.spec.whatwg.org/#characterdata --- HTMLKit.xcodeproj/project.pbxproj | 10 ++++++ Sources/HTMLCharacterData.h | 10 ++++-- Sources/HTMLCharacterData.m | 55 +++++++++++++++++++++++++++++-- Sources/HTMLDocument+Private.h | 4 +++ Sources/HTMLDocument.m | 20 +++++++++-- Sources/HTMLParser.m | 4 +-- Sources/HTMLRange+Private.h | 17 ++++++++++ 7 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 Sources/HTMLRange+Private.h diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 51701fb..dc7ecb4 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -534,6 +534,10 @@ 62ECBFDE1C0B6E4400AF847B /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; 62ECBFDF1C0B6E4400AF847B /* html5lib-tests in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90419FBFE8A00BD3C4A /* html5lib-tests */; }; 62F658711BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */; }; + 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; + 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; + 62F7E5A41DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; + 62F7E5A51DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -710,6 +714,7 @@ 62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSNthExpressionParser.h; path = include/CSSNthExpressionParser.h; sourceTree = ""; }; 62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionParser.m; sourceTree = ""; }; 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNThExpressionSelectorTests.m; sourceTree = ""; }; + 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLRange+Private.h"; sourceTree = ""; }; 62F873E919E088C90062683C /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLParser.h; path = include/HTMLParser.h; sourceTree = ""; }; 62F873EA19E088C90062683C /* HTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParser.m; sourceTree = ""; }; 62FA04E11BCC360D009ABF98 /* CSSCombinatorSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSCombinatorSelector.h; path = include/CSSCombinatorSelector.h; sourceTree = ""; }; @@ -989,6 +994,7 @@ 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */, + 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */, 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */, ); name = Private; @@ -1124,6 +1130,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62ECBF181C0B6A1000AF847B /* HTMLKit.h in Headers */, 62ECBEE11C0B69FD00AF847B /* HTMLKitErrorDomain.h in Headers */, 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */, @@ -1195,6 +1202,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 62F7E5A51DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62857CBE1D398999008DC254 /* NSString+HTMLKit.h in Headers */, 62857CAC1D398973008DC254 /* HTMLKitDOMExceptions.h in Headers */, 62857CD61D3989C2008DC254 /* CSSSelectorParser.h in Headers */, @@ -1266,6 +1274,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 62F7E5A41DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62857D831D39A46D008DC254 /* CSSStructuralPseudoSelectors.h in Headers */, 62857D7D1D39A457008DC254 /* HTMLNodeTraversal.h in Headers */, 62857D841D39A472008DC254 /* CSSSelectorParser.h in Headers */, @@ -1337,6 +1346,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62ECBF901C0B6D3700AF847B /* HTMLKit.h in Headers */, 62ECBF911C0B6D3700AF847B /* HTMLKitErrorDomain.h in Headers */, 62ECBF9F1C0B6D3900AF847B /* HTMLParser.h in Headers */, diff --git a/Sources/HTMLCharacterData.h b/Sources/HTMLCharacterData.h index 7ca0e3a..1273401 100644 --- a/Sources/HTMLCharacterData.h +++ b/Sources/HTMLCharacterData.h @@ -17,8 +17,14 @@ NS_ASSUME_NONNULL_BEGIN */ @interface HTMLCharacterData : HTMLNode -/** @brief The associated mutable data string. */ -@property (nonatomic, copy, readonly) NSMutableString *data; +/** @brief The associated data string. */ +@property (nonatomic, copy, readonly) NSString *data; + +- (void)setData:(NSString *)data; +- (void)appendData:(NSString *)data; +- (void)insertData:(NSString *)data atOffset:(NSUInteger)offset; +- (void)deleteDataInRange:(NSRange)range; +- (void)replaceDataInRange:(NSRange)range withData:(NSString *)data; @end diff --git a/Sources/HTMLCharacterData.m b/Sources/HTMLCharacterData.m index 8f5eb44..86e4f90 100644 --- a/Sources/HTMLCharacterData.m +++ b/Sources/HTMLCharacterData.m @@ -8,8 +8,17 @@ #import "HTMLCharacterData.h" #import "HTMLNode+Private.h" +#import "HTMLDocument+Private.h" +#import "HTMLKitDOMExceptions.h" + +@interface HTMLCharacterData () +{ + NSMutableString *_data; +} +@end @implementation HTMLCharacterData +@synthesize data = _data; - (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type data:(NSString *)data { @@ -27,7 +36,7 @@ - (void)setTextContent:(NSString *)textContent { - [_data setString:textContent ?: @""]; + [self setData:textContent]; } - (NSUInteger)length @@ -35,12 +44,54 @@ return _data.length; } +#pragma mark - Data + +NS_INLINE void CheckValidOffset(HTMLCharacterData *node, NSUInteger offset, NSString *cmd) +{ + if (offset > node.length) { + [NSException raise:HTMLKitIndexSizeError + format:@"%@: Index Size Error, invalid index %lu for character data node %@.", + cmd, (unsigned long)offset, node]; + } +} + +- (void)setData:(NSString *)data +{ + [self replaceDataInRange:NSMakeRange(0, self.length) withData:data]; +} + +- (void)appendData:(NSString *)data +{ + [self replaceDataInRange:NSMakeRange(self.length, 0) withData:data]; +} + +- (void)insertData:(NSString *)data atOffset:(NSUInteger)offset +{ + [self replaceDataInRange:NSMakeRange(offset, 0) withData:data]; +} + +- (void)deleteDataInRange:(NSRange)range +{ + [self replaceDataInRange:range withData:@""]; +} + +- (void)replaceDataInRange:(NSRange)range withData:(NSString *)data +{ + CheckValidOffset(self, range.location, NSStringFromSelector(_cmd)); + + range.length = MIN(range.length, self.length - range.location); + + [_data replaceCharactersInRange:range withString:data]; + [self.ownerDocument didRemoveCharacterDataInNode:self atOffset:range.location withLength:range.length]; + [self.ownerDocument didAddCharacterDataToNode:self atOffset:range.location withLength:data.length]; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { HTMLCharacterData *copy = [super copyWithZone:zone]; - copy->_data = self.data; + copy->_data = _data; return copy; } diff --git a/Sources/HTMLDocument+Private.h b/Sources/HTMLDocument+Private.h index 1b30e5c..d14c723 100644 --- a/Sources/HTMLDocument+Private.h +++ b/Sources/HTMLDocument+Private.h @@ -8,6 +8,7 @@ #import "HTMLDocument.h" #import "HTMLNode.h" +#import "HTMLCharacterData.h" #import "HTMLNodeIterator.h" #import "HTMLRange.h" @@ -58,4 +59,7 @@ */ - (void)detachRange:(HTMLRange *)range; +- (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; +- (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; + @end diff --git a/Sources/HTMLDocument.m b/Sources/HTMLDocument.m index 9c8f068..8ce00da 100644 --- a/Sources/HTMLDocument.m +++ b/Sources/HTMLDocument.m @@ -10,9 +10,11 @@ #import "HTMLParser.h" #import "HTMLNodeIterator.h" #import "HTMLRange.h" +#import "HTMLCharacterData.h" #import "HTMLKitDOMExceptions.h" #import "HTMLNode+Private.h" #import "HTMLNodeIterator+Private.h" +#import "HTMLRange+Private.h" @interface HTMLDocument () { @@ -147,8 +149,8 @@ { for (HTMLNodeIterator *iterator in _nodeIterators) { [iterator runRemovingStepsForNode:oldNode - withOldParent:oldParent - andOldPreviousSibling:oldPreviousSibling]; + withOldParent:oldParent + andOldPreviousSibling:oldPreviousSibling]; } } @@ -164,6 +166,20 @@ [_ranges removeObject:range]; } +- (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length +{ + for (HTMLRange *range in _ranges) { + [range didRemoveCharacterDataInNode:node atOffset:offset withLength:length]; + } +} + +- (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length +{ + for (HTMLRange *range in _ranges) { + [range didAddCharacterDataToNode:node atOffset:offset withLength:length]; + } +} + #pragma mark - Mutation Algorithms - (HTMLNode *)adoptNode:(HTMLNode *)node diff --git a/Sources/HTMLParser.m b/Sources/HTMLParser.m index 15f85ab..aff3f97 100644 --- a/Sources/HTMLParser.m +++ b/Sources/HTMLParser.m @@ -451,10 +451,10 @@ if (adjustedInsertionLocation.nodeType != HTMLNodeDocument) { if (child != nil && child.previousSibling.nodeType == HTMLNodeText) { HTMLText *textNode = (HTMLText *)child.previousSibling; - [textNode.data appendString:data]; + [textNode appendData:data]; } else if (adjustedInsertionLocation.lastChild.nodeType == HTMLNodeText) { HTMLText *textNode = (HTMLText *)adjustedInsertionLocation.lastChild; - [textNode.data appendString:data]; + [textNode appendData:data]; } else { HTMLText *text = [[HTMLText alloc] initWithData:data]; [adjustedInsertionLocation insertNode:text beforeChildNode:child]; diff --git a/Sources/HTMLRange+Private.h b/Sources/HTMLRange+Private.h new file mode 100644 index 0000000..8d7e5d6 --- /dev/null +++ b/Sources/HTMLRange+Private.h @@ -0,0 +1,17 @@ +// +// HTMLRange+Private.h +// HTMLKit +// +// Created by Iska on 27/11/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLRange.h" +#import "HTMLCharacterData.h" + +@interface HTMLRange () + +- (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; +- (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; + +@end From e4b57f3333a9da01b823a0024291c64728c688b4 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 20:19:19 +0100 Subject: [PATCH 24/75] Update deprecation message in HTML Text node --- Sources/include/HTMLText.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/include/HTMLText.h b/Sources/include/HTMLText.h index e1343e7..8578c55 100644 --- a/Sources/include/HTMLText.h +++ b/Sources/include/HTMLText.h @@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @param string The string to append. */ -- (void)appendString:(NSString *)string __attribute__((deprecated("Use the mutable data property instead."))); +- (void)appendString:(NSString *)string __attribute__((deprecated("Use `appendData:` instead."))); @end From 5c2f6527a72dad6daf5c159f5d84cd186a471ed0 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 20:19:54 +0100 Subject: [PATCH 25/75] =?UTF-8?q?Add=20implementation=20for=20HTML=20Range?= =?UTF-8?q?=E2=80=99s=20contains-node=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.h | 9 +++++++++ Sources/HTMLRange.m | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 7750cbd..1f1302a 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -147,6 +147,15 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) @see HTMLRangeComparisonMethod */ - (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange; + +/** + Checks whether the given node is contained in this range. + + @param node The node to check. + @return `YES` if the node is contained in the range, `NO` otherwise. + */ +- (BOOL)containsNode:(HTMLNode *)node; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index d670a83..aef84cd 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -229,4 +229,23 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } +#pragma mark - Containment + +- (BOOL)containsNode:(HTMLNode *)node +{ + if (node.rootNode != self.rootNode) { + return NO; + } + + if (CompareBoundaries(node, 0, _startContainer, _startOffset) == NSOrderedDescending) { + return NO; + } + + if (CompareBoundaries(node, node.length, _endContainer, _endOffset) == NSOrderedAscending) { + return NO; + } + + return YES; +} + @end From 1f6f9d843e999850e82902631590d31e49517675 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 20:21:16 +0100 Subject: [PATCH 26/75] =?UTF-8?q?Add=20implementation=20for=20range?= =?UTF-8?q?=E2=80=99s=20update=20methods=20on=20character=20data=20mutatio?= =?UTF-8?q?ns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.m | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index aef84cd..f58ca01 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -248,4 +248,32 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s return YES; } +#pragma mark - Update Callbacks + +- (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length +{ + if (_startContainer == node && _startOffset > offset) { + if (_startOffset <= offset + length) { + _startOffset = offset; + } else { + _startOffset = _startOffset - length; + } + } else if (_endContainer == node && _endOffset > offset) { + if (_endOffset <= offset + length) { + _endOffset = offset; + } else { + _endOffset = _endOffset - length; + } + } +} + +- (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length +{ + if (_startContainer == node && _startOffset > offset) { + _startOffset = _startOffset + length; + } else if (_endContainer == node && _endOffset > offset) { + _endOffset = _endOffset + length; + } +} + @end From e60fe36e2518070658dacb1b9ed9d82e16de4e57 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 27 Nov 2016 20:22:21 +0100 Subject: [PATCH 27/75] Fix append-string method in HTML Text node --- Sources/HTMLText.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/HTMLText.m b/Sources/HTMLText.m index ff504eb..24e2728 100644 --- a/Sources/HTMLText.m +++ b/Sources/HTMLText.m @@ -25,7 +25,7 @@ - (void)appendString:(NSString *)string { - [self.data appendString:string]; + [self appendData:string]; } #pragma mark - Serialization From e4a0669cf2007fd4e49ef3779b794899e2312b20 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 28 Nov 2016 01:32:25 +0100 Subject: [PATCH 28/75] Fix travis badge on develop branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 004b57a..0783c74 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An Objective-C framework for your everyday HTML needs. -[![Build Status](https://img.shields.io/travis/iabudiab/HTMLKit/master.svg?style=flat)](https://travis-ci.org/iabudiab/HTMLKit) +[![Build Status](https://img.shields.io/travis/iabudiab/HTMLKit/develop.svg?style=flat)](https://travis-ci.org/iabudiab/HTMLKit) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/HTMLKit.svg?style=flat)](https://cocoapods.org/pods/HTMLKit) [![CocoaDocs](https://img.shields.io/cocoapods/metrics/doc-percent/HTMLKit.svg?style=flat)](http://cocoadocs.org/docsets/HTMLKit) From 4d132af99f3d71b5cf3b22df0ab9619467ed3f2b Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 29 Dec 2016 22:53:34 +0100 Subject: [PATCH 29/75] Update and reorganize private headers and modulemap --- HTMLKit.xcodeproj/project.pbxproj | 61 +++++++++++++++++++++---------- Sources/HTMLDOMUtils.h | 13 +++++++ Sources/HTMLDOMUtils.m | 13 +++++++ Sources/HTMLRange.m | 7 +--- Sources/include/HTMLDOM.h | 1 + Sources/module.modulemap | 55 ++++++++++++++++------------ 6 files changed, 102 insertions(+), 48 deletions(-) create mode 100644 Sources/HTMLDOMUtils.h create mode 100644 Sources/HTMLDOMUtils.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index dc7ecb4..eb16663 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -15,13 +15,13 @@ 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; - 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; - 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; - 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; }; + 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A51DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A61DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; }; + 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A81DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; @@ -66,6 +66,14 @@ 626679D01DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 626679D11DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 626679D21DEA3DAF004353E7 /* HTMLCharacterData+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626BE1E21DF3819500C49514 /* HTMLDOMUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626BE1E31DF3819500C49514 /* HTMLDOMUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626BE1E41DF3819500C49514 /* HTMLDOMUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626BE1E51DF3819500C49514 /* HTMLDOMUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 626BE1E61DF3819600C49514 /* HTMLDOMUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */; }; + 626BE1E71DF3819600C49514 /* HTMLDOMUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */; }; + 626BE1E81DF3819600C49514 /* HTMLDOMUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */; }; + 626BE1E91DF3819600C49514 /* HTMLDOMUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */; }; 62857C6B1D3988EE008DC254 /* HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A14BC19C7829400AD0C32 /* HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62857C6C1D3988EE008DC254 /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62857C6D1D398907008DC254 /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -301,14 +309,17 @@ 62857D901D39A47F008DC254 /* CSSCompoundSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; 628AF6301BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */; }; 62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; }; - 62D91C231DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; - 62D91C241DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; - 62D91C251DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; - 62D91C261DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; }; + 62D91C231DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 62D91C241DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 62D91C251DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 62D91C261DE218A500BEFADE /* HTMLRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 62D91C211DE218A500BEFADE /* HTMLRange.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62D91C271DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62D91C281DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62D91C291DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62D91C2A1DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; + 62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; + 62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; + 62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; 62ECBEE11C0B69FD00AF847B /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -534,10 +545,10 @@ 62ECBFDE1C0B6E4400AF847B /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; 62ECBFDF1C0B6E4400AF847B /* html5lib-tests in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90419FBFE8A00BD3C4A /* html5lib-tests */; }; 62F658711BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */; }; - 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; - 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; - 62F7E5A41DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; - 62F7E5A51DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; }; + 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62F7E5A41DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62F7E5A51DEB63F900DEF09B /* HTMLRange+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -677,6 +688,8 @@ 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTestUtil.m; sourceTree = ""; }; 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLKitErrorDomain.h; path = include/HTMLKitErrorDomain.h; sourceTree = ""; }; 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLCharacterData+Private.h"; sourceTree = ""; }; + 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDOMUtils.h; sourceTree = ""; }; + 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDOMUtils.m; sourceTree = ""; }; 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLParserInsertionModes.h; path = include/HTMLParserInsertionModes.h; sourceTree = ""; }; 6279F87219E1808D00F12EE5 /* HTMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLElement.h; path = include/HTMLElement.h; sourceTree = ""; }; 6279F87319E1808D00F12EE5 /* HTMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLElement.m; sourceTree = ""; }; @@ -835,8 +848,6 @@ 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */, 624717BA1B22009200B38302 /* HTMLTreeWalker.h */, 624717BB1B22009200B38302 /* HTMLTreeWalker.m */, - 624717161B22333200C11912 /* HTMLNodeTraversal.h */, - 624717171B22333200C11912 /* HTMLNodeTraversal.m */, 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */, 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */, 62D91C211DE218A500BEFADE /* HTMLRange.h */, @@ -996,6 +1007,10 @@ 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */, 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */, 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */, + 624717161B22333200C11912 /* HTMLNodeTraversal.h */, + 624717171B22333200C11912 /* HTMLNodeTraversal.m */, + 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */, + 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */, ); name = Private; sourceTree = ""; @@ -1130,7 +1145,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62ECBF181C0B6A1000AF847B /* HTMLKit.h in Headers */, 62ECBEE11C0B69FD00AF847B /* HTMLKitErrorDomain.h in Headers */, 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */, @@ -1146,6 +1160,7 @@ 62ECBEE91C0B69FD00AF847B /* HTMLCharacterToken.h in Headers */, 62ECBEEA1C0B69FD00AF847B /* HTMLCommentToken.h in Headers */, 62ECBEEB1C0B69FD00AF847B /* HTMLDOCTYPEToken.h in Headers */, + 626BE1E21DF3819500C49514 /* HTMLDOMUtils.h in Headers */, 62ECBEEC1C0B69FD00AF847B /* HTMLParseErrorToken.h in Headers */, 62ECBEED1C0B69FD00AF847B /* HTMLTagToken.h in Headers */, 62ECBEEE1C0B69FD00AF847B /* HTMLEOFToken.h in Headers */, @@ -1172,6 +1187,8 @@ 62ECBEFF1C0B69FE00AF847B /* HTMLNodeIterator.h in Headers */, 62ECBF001C0B69FF00AF847B /* HTMLTreeWalker.h in Headers */, 62ECBF011C0B69FF00AF847B /* HTMLNodeTraversal.h in Headers */, + 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, + 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBF021C0B69FF00AF847B /* HTMLNodeFilter.h in Headers */, 62ECBF031C0B69FF00AF847B /* HTMLKitDOMExceptions.h in Headers */, 62ECBF041C0B69FF00AF847B /* HTMLNamespaces.h in Headers */, @@ -1188,7 +1205,6 @@ 62ECBF0F1C0B6A0100AF847B /* CSSSelector.h in Headers */, 62ECBF101C0B6A0100AF847B /* CSSSelectorBlock.h in Headers */, 62ECBF111C0B6A0200AF847B /* CSSTypeSelector.h in Headers */, - 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBF121C0B6A0200AF847B /* CSSAttributeSelector.h in Headers */, 62ECBF131C0B6A0200AF847B /* CSSPseudoClassSelector.h in Headers */, 62ECBF141C0B6A0200AF847B /* CSSNthExpressionSelector.h in Headers */, @@ -1218,6 +1234,7 @@ 62857C841D398917008DC254 /* HTMLParser.h in Headers */, 62857CDB1D3989CE008DC254 /* CSSAttributeSelector.h in Headers */, 62857C791D398907008DC254 /* HTMLEOFToken.h in Headers */, + 626BE1E51DF3819500C49514 /* HTMLDOMUtils.h in Headers */, 62857CC41D3989A9008DC254 /* CSSSelectors.h in Headers */, 62857C731D398907008DC254 /* HTMLToken.h in Headers */, 62857CC51D3989AB008DC254 /* CSSStructuralPseudoSelectors.h in Headers */, @@ -1290,6 +1307,7 @@ 62857D4E1D39A40A008DC254 /* HTMLTokenizerCharacters.h in Headers */, 62857D4D1D39A40A008DC254 /* HTMLTokenizerStates.h in Headers */, 62857D501D39A411008DC254 /* HTMLTokens.h in Headers */, + 626BE1E41DF3819500C49514 /* HTMLDOMUtils.h in Headers */, 62857D7B1D39A452008DC254 /* HTMLNamespaces.h in Headers */, 62857D581D39A416008DC254 /* HTMLParser.h in Headers */, 62857D571D39A411008DC254 /* HTMLEOFToken.h in Headers */, @@ -1346,7 +1364,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 62ECBF901C0B6D3700AF847B /* HTMLKit.h in Headers */, 62ECBF911C0B6D3700AF847B /* HTMLKitErrorDomain.h in Headers */, 62ECBF9F1C0B6D3900AF847B /* HTMLParser.h in Headers */, @@ -1386,6 +1403,9 @@ 62ECBFC41C0B6D4200AF847B /* CSSNthExpressionSelector.h in Headers */, 62ECBFC51C0B6D4200AF847B /* CSSPseudoFunctionSelector.h in Headers */, 62ECBFC61C0B6D4300AF847B /* CSSCombinatorSelector.h in Headers */, + 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, + 626BE1E31DF3819500C49514 /* HTMLDOMUtils.h in Headers */, + 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 625D0F041C2717DE00D7BEB0 /* HTMLNode+Private.h in Headers */, 62ECBFC71C0B6D4300AF847B /* CSSCompoundSelector.h in Headers */, 62ECBFB11C0B6D3C00AF847B /* HTMLNodeTraversal.h in Headers */, @@ -1404,7 +1424,6 @@ 62ECBF9E1C0B6D3800AF847B /* HTMLEOFToken.h in Headers */, 62ECBFA01C0B6D3900AF847B /* HTMLStackOfOpenElements.h in Headers */, 62ECBFA11C0B6D3900AF847B /* HTMLListOfActiveFormattingElements.h in Headers */, - 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBFA21C0B6D3900AF847B /* HTMLElementTypes.h in Headers */, 62ECBFA31C0B6D3900AF847B /* HTMLElementAdjustment.h in Headers */, 62ECBFA41C0B6D3900AF847B /* HTMLParserInsertionModes.h in Headers */, @@ -1712,6 +1731,7 @@ 62ECBF471C0B6B7A00AF847B /* CSSCompoundSelector.m in Sources */, 62567F521C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */, 624C777E1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, + 626BE1E61DF3819600C49514 /* HTMLDOMUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1796,6 +1816,7 @@ 62857CB81D398992008DC254 /* HTMLDOMTokenList.m in Sources */, 62857C831D398912008DC254 /* HTMLEOFToken.m in Sources */, 624C77811DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, + 626BE1E91DF3819600C49514 /* HTMLDOMUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1850,6 +1871,7 @@ 62857D171D39A32A008DC254 /* HTMLDOMTokenList.m in Sources */, 62857D0A1D39A324008DC254 /* HTMLEOFToken.m in Sources */, 624C77801DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, + 626BE1E81DF3819600C49514 /* HTMLDOMUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1934,6 +1956,7 @@ 62ECBF8F1C0B6D2A00AF847B /* CSSCompoundSelector.m in Sources */, 62567F531C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */, 624C777F1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */, + 626BE1E71DF3819600C49514 /* HTMLDOMUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/HTMLDOMUtils.h b/Sources/HTMLDOMUtils.h new file mode 100644 index 0000000..fba89a6 --- /dev/null +++ b/Sources/HTMLDOMUtils.h @@ -0,0 +1,13 @@ +// +// HTMLDOMUtils.h +// HTMLKit +// +// Created by Iska on 03/12/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import + +@interface HTMLDOMUtils : NSObject + +@end diff --git a/Sources/HTMLDOMUtils.m b/Sources/HTMLDOMUtils.m new file mode 100644 index 0000000..7ab2d01 --- /dev/null +++ b/Sources/HTMLDOMUtils.m @@ -0,0 +1,13 @@ +// +// HTMLDOMUtils.m +// HTMLKit +// +// Created by Iska on 03/12/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import "HTMLDOMUtils.h" + +@implementation HTMLDOMUtils + +@end diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index f58ca01..8d1d77a 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -10,6 +10,7 @@ #import "HTMLDocument.h" #import "HTMLKitDOMExceptions.h" #import "HTMLDocument+Private.h" +#import "HTMLDOMUtils.h" @interface HTMLRange () { @@ -47,11 +48,7 @@ - (HTMLNode *)commonAncestorContainer { - HTMLNode *container = _startContainer; - while (![container containsNode:_endContainer]) { - container = container.parentNode; - } - return container; + return GetCommonAncestorContainer(_startContainer, _endContainer); } - (HTMLNode *)rootNode diff --git a/Sources/include/HTMLDOM.h b/Sources/include/HTMLDOM.h index 50eadbc..c269c14 100644 --- a/Sources/include/HTMLDOM.h +++ b/Sources/include/HTMLDOM.h @@ -14,6 +14,7 @@ #import "HTMLComment.h" #import "HTMLText.h" #import "HTMLTemplate.h" +#import "HTMLRange.h" #import "HTMLDOMTokenList.h" #import "HTMLNodeIterator.h" #import "HTMLTreeWalker.h" diff --git a/Sources/module.modulemap b/Sources/module.modulemap index 4172c3e..5f6af82 100644 --- a/Sources/module.modulemap +++ b/Sources/module.modulemap @@ -1,30 +1,37 @@ module HTMLKit { umbrella header "HTMLKit.h" - private header "CSSCodePoints.h" - private header "CSSInputStream.h" - private header "HTMLCharacterToken.h" - private header "HTMLCommentToken.h" - private header "HTMLDOCTYPEToken.h" - private header "HTMLElementAdjustment.h" - private header "HTMLElementTypes.h" - private header "HTMLEOFToken.h" - private header "HTMLInputStreamReader.h" - private header "HTMLListOfActiveFormattingElements.h" - private header "HTMLMarker.h" - private header "HTMLNode+Private.h" - private header "HTMLNodeTraversal.h" - private header "HTMLParseErrorToken.h" - private header "HTMLParserInsertionModes.h" - private header "HTMLStackOfOpenElements.h" - private header "HTMLTagToken.h" - private header "HTMLToken.h" - private header "HTMLTokenizer.h" - private header "HTMLTokenizerCharacters.h" - private header "HTMLTokenizerEntities.h" - private header "HTMLTokenizerStates.h" - private header "HTMLTokens.h" - module * { export * } export * + + explicit module Private { + header "CSSCodePoints.h" + header "CSSInputStream.h" + header "HTMLCharacterToken.h" + header "HTMLCommentToken.h" + header "HTMLDOCTYPEToken.h" + header "HTMLElementAdjustment.h" + header "HTMLElementTypes.h" + header "HTMLEOFToken.h" + header "HTMLInputStreamReader.h" + header "HTMLListOfActiveFormattingElements.h" + header "HTMLMarker.h" + header "HTMLNodeTraversal.h" + header "HTMLDOMUtils.h" + header "HTMLParseErrorToken.h" + header "HTMLParserInsertionModes.h" + header "HTMLStackOfOpenElements.h" + header "HTMLTagToken.h" + header "HTMLToken.h" + header "HTMLTokenizer.h" + header "HTMLTokenizerCharacters.h" + header "HTMLTokenizerEntities.h" + header "HTMLTokenizerStates.h" + header "HTMLTokens.h" + header "HTMLNode+Private.h" + header "HTMLCharacterData+Private.h" + header "HTMLRange+Private.h" + header "HTMLNodeIterator+Private.h" + header "HTMLParser+Private.h" + } } From fb04d49693df38f2e392e040d6e5eafc3e2487dd Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 29 Dec 2016 22:54:14 +0100 Subject: [PATCH 30/75] Add DOM method for computing a common ancestor of two nodes --- Sources/HTMLDOMUtils.h | 5 +++-- Sources/HTMLDOMUtils.m | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Sources/HTMLDOMUtils.h b/Sources/HTMLDOMUtils.h index fba89a6..2b62d59 100644 --- a/Sources/HTMLDOMUtils.h +++ b/Sources/HTMLDOMUtils.h @@ -7,7 +7,8 @@ // #import +#import "HTMLDOM.h" -@interface HTMLDOMUtils : NSObject +@class HTMLNode; -@end +extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB); diff --git a/Sources/HTMLDOMUtils.m b/Sources/HTMLDOMUtils.m index 7ab2d01..45a95ef 100644 --- a/Sources/HTMLDOMUtils.m +++ b/Sources/HTMLDOMUtils.m @@ -7,7 +7,17 @@ // #import "HTMLDOMUtils.h" +#import "HTMLNode.h" -@implementation HTMLDOMUtils +extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB) +{ + for (HTMLNode *parentA = nodeA; parentA != nil; parentA = parentA.parentNode) { + for (HTMLNode *parentB = nodeB; parentB != nil; parentB = parentB.parentNode) { + if (parentA == parentB) { + return parentA; + } + } + } -@end + return nil; +} From 6da3f7bd49cd4d8aeabff4148b75fd5024432ec3 Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 29 Dec 2016 22:54:39 +0100 Subject: [PATCH 31/75] =?UTF-8?q?Mark=20HTML=20Range=E2=80=99s=20default?= =?UTF-8?q?=20initializer=20as=20unavailable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 1f1302a..b3b7870 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -61,6 +61,11 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ @property (nonatomic, readonly, weak) HTMLNode *commonAncestorContainer; +/** + @abstract A range is always associated with a HTML Document. Use `initWithDocument:` initializer instead. + */ +- (instancetype)init NS_UNAVAILABLE; + /** Initializes a new range instance for the given document. From 3898ae243c5ddfae1c88dd62b00d940cadc229e4 Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 29 Dec 2016 22:54:59 +0100 Subject: [PATCH 32/75] Add HTML Range tests class and setup --- HTMLKit.xcodeproj/project.pbxproj | 5 ++ Tests/HTMLRangeTests.m | 95 +++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 Tests/HTMLRangeTests.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index eb16663..998a40f 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -719,6 +719,7 @@ 62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLRange.h; sourceTree = ""; }; 62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = ""; }; 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = ""; }; + 62EC0A841E158BD80007786B /* HTMLRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRangeTests.m; sourceTree = ""; }; 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = ""; }; 62ECBF4D1C0B6C7600AF847B /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 62ECBF561C0B6C7600AF847B /* HTMLKitTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HTMLKitTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -879,6 +880,7 @@ 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */, 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */, 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */, + 62EC0A841E158BD80007786B /* HTMLRangeTests.m */, ); name = DOM; sourceTree = ""; @@ -1739,6 +1741,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */, 6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */, 62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */, 6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, @@ -1879,6 +1882,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */, 62857D3B1D39A345008DC254 /* CSSSelectorTest.m in Sources */, 62857D421D39A345008DC254 /* CSSCombinatorSelectorTests.m in Sources */, 62857D3C1D39A345008DC254 /* CSSSelectorParserTests.m in Sources */, @@ -1964,6 +1968,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */, 6216ACFE1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */, 62ECBFCA1C0B6E2E00AF847B /* HTML5LibTokenizerTest.m in Sources */, 62ECBFCB1C0B6E2E00AF847B /* HTMLKitTokenizerTests.m in Sources */, diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m new file mode 100644 index 0000000..0681aa3 --- /dev/null +++ b/Tests/HTMLRangeTests.m @@ -0,0 +1,95 @@ +// +// HTMLRangeTests.m +// HTMLKit +// +// Created by Iska on 29/12/16. +// Copyright © 2016 BrainCookie. All rights reserved. +// + +#import +#import "HTMLDOM.h" +#import "HTMLNode+Private.h" +#import "HTMLRange+Private.h" + +@interface HTMLRangeTests : XCTestCase +{ + HTMLDocument *_document; + HTMLElement *_a; + HTMLElement *_b; + HTMLElement *_c; + HTMLElement *_d; + HTMLElement *_e; + HTMLElement *_f; + HTMLText *_firstText; + HTMLText *_secondText; + HTMLText *_thirdText; + HTMLComment *_firstComment; + HTMLComment *_secondComment; +} +@end + +@implementation HTMLRangeTests + +- (void)setUp +{ + [super setUp]; + [self setupDocument]; +} + +- (void)setupDocument +{ + // Tree structure: + // #a + // | + // +----------+----------+ + // | | + // "This is text" #b + // | + // +----+--------------+ + // | | + // #c + // | + // +-----------------+----------+ + // | | | + // "Another text" #d #e + // | + // +-----------+----------------------+ + // | | | + // #f "Third text" + + + _a = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"a"}]; + _b = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"b"}]; + _c = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"c"}]; + _d = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"d"}]; + _e = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"e"}]; + _f = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"f"}]; + + _firstText = [[HTMLText alloc] initWithData:@"This is text"]; + _secondText = [[HTMLText alloc] initWithData:@"Another text"]; + _thirdText = [[HTMLText alloc] initWithData:@"Third text"]; + + _firstComment = [[HTMLComment alloc] initWithData:@"This is a comment"]; + _secondComment = [[HTMLComment alloc] initWithData:@"Another comment"]; + + [_a appendNodes:@[_firstText, _b]]; + [_b appendNodes:@[_c, _firstComment]]; + [_c appendNodes:@[_secondText, _d, _e]]; + [_e appendNodes:@[_f, _thirdText, _secondComment]]; + + _document = [HTMLDocument documentWithString:@""]; + [_document.body appendNodes:@[_a]]; +} + +- (void)testInitRange +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + XCTAssertEqual(range.startContainer, _document); + XCTAssertEqual(range.startOffset, 0); + + XCTAssertEqual(range.endContainer, _document); + XCTAssertEqual(range.endOffset, 0); +} + +@end From 7506ed8caeb1dbbdc0321feb4c77d38f46ccf980 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 03:07:33 +0100 Subject: [PATCH 33/75] =?UTF-8?q?Refactor=20method=20to=20get=20a=20node?= =?UTF-8?q?=E2=80=99s=20ancestor=20chain=20into=20the=20utils=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLDOMUtils.h | 1 + Sources/HTMLDOMUtils.m | 9 +++++++++ Sources/HTMLNode.m | 12 +++--------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Sources/HTMLDOMUtils.h b/Sources/HTMLDOMUtils.h index 2b62d59..b792197 100644 --- a/Sources/HTMLDOMUtils.h +++ b/Sources/HTMLDOMUtils.h @@ -12,3 +12,4 @@ @class HTMLNode; extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB); +extern NSArray * GetAncestorNodes(HTMLNode *node); diff --git a/Sources/HTMLDOMUtils.m b/Sources/HTMLDOMUtils.m index 45a95ef..efc2d82 100644 --- a/Sources/HTMLDOMUtils.m +++ b/Sources/HTMLDOMUtils.m @@ -21,3 +21,12 @@ extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB) return nil; } + +extern NSArray * GetAncestorNodes(HTMLNode *node) +{ + NSMutableArray *ancestors = [NSMutableArray array]; + for (HTMLNode *it = node; it; it = it.parentNode) { + [ancestors addObject:it]; + } + return ancestors; +} diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index c2aecba..9ba3bd3 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -17,6 +17,7 @@ #import "HTMLNodeFilter.h" #import "CSSSelector.h" #import "HTMLDocument+Private.h" +#import "HTMLDOMUtils.h" @interface HTMLNode () { @@ -343,16 +344,9 @@ return HTMLDocumentPositionEquivalent; } - NSArray * (^ ancestorNodes) (HTMLNode *) = ^ NSArray * (HTMLNode *node) { - NSMutableArray *ancestors = [NSMutableArray array]; - for (HTMLNode *node = self; node; node = node.parentNode) { - [ancestors addObject:node]; - } - return ancestors; - }; - NSArray *ancestors1 = ancestorNodes(self); - NSArray *ancestors2 = ancestorNodes(otherNode); + NSArray *ancestors1 = GetAncestorNodes(self); + NSArray *ancestors2 = GetAncestorNodes(otherNode); if (ancestors1.lastObject != ancestors2.lastObject) { return HTMLDocumentPositionDisconnected | From 15acfa06f60d0e8237e2c553fc6738a02a39c948 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 03:07:59 +0100 Subject: [PATCH 34/75] =?UTF-8?q?Fix=20HTML=20Node=E2=80=99s=20method=20to?= =?UTF-8?q?=20compare=20document=20positions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLNode.m | 29 +++++++++++++++++++---------- Tests/HTMLKitNodesTests.m | 29 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index 9ba3bd3..d188bb0 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -344,34 +344,43 @@ return HTMLDocumentPositionEquivalent; } + if (self.ownerDocument != otherNode.ownerDocument) { + return (HTMLDocumentPositionDisconnected | HTMLDocumentPositionImplementationSpecific | + self.hash < otherNode.hash ? HTMLDocumentPositionPreceding : HTMLDocumentPositionFollowing); + } NSArray *ancestors1 = GetAncestorNodes(self); NSArray *ancestors2 = GetAncestorNodes(otherNode); if (ancestors1.lastObject != ancestors2.lastObject) { - return HTMLDocumentPositionDisconnected | - HTMLDocumentPositionImplementationSpecific | - HTMLDocumentPositionFollowing; + return (HTMLDocumentPositionDisconnected | HTMLDocumentPositionImplementationSpecific | + self.hash < otherNode.hash ? HTMLDocumentPositionPreceding : HTMLDocumentPositionFollowing); } - for (NSUInteger i = MIN(ancestors1.count - 1, ancestors2.count - 1); i; --i) { - HTMLNode *child1 = ancestors1[i]; - HTMLNode *child2 = ancestors2[i]; + NSUInteger index1 = ancestors1.count; + NSUInteger index2 = ancestors2.count; + + for (NSUInteger i = MIN(index1, index2); i; --i) { + index1 -= 1; + index2 -= 1; + + HTMLNode *child1 = ancestors1[index1]; + HTMLNode *child2 = ancestors2[index2]; if (child1 != child2) { for (HTMLNode *sibling = child1.nextSibling; sibling; sibling = sibling.nextSibling) { if (sibling == child2) { - return HTMLDocumentPositionFollowing; + return HTMLDocumentPositionPreceding; } } - return HTMLDocumentPositionPreceding; + return HTMLDocumentPositionFollowing; } } if (ancestors1.count < ancestors2.count) { - return HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing; - } else { return HTMLDocumentPositionContains | HTMLDocumentPositionPreceding; + } else { + return HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing; } } diff --git a/Tests/HTMLKitNodesTests.m b/Tests/HTMLKitNodesTests.m index 7193ecb..8e994dd 100644 --- a/Tests/HTMLKitNodesTests.m +++ b/Tests/HTMLKitNodesTests.m @@ -483,4 +483,33 @@ XCTAssertEqualObjects([element childNodeAtIndex:1].asElement.tagName, @"p"); } +- (void)testCompareDocumentPosition +{ + HTMLDocument *document = [HTMLDocument documentWithString:@"

hello

"]; + + HTMLNode *outerDiv = document.body.firstChild; + HTMLNode *paragraph = document.body.firstChild.firstChild; + HTMLNode *anchor = [[document.body.firstChild childNodeAtIndex:1] childNodeAtIndex:0]; + HTMLNode *image = [[document.body.firstChild childNodeAtIndex:1] childNodeAtIndex:1]; + + XCTAssertTrue([paragraph compareDocumentPositionWithNode:paragraph] == HTMLDocumentPositionEquivalent); + + HTMLElement *element = [HTMLElement new]; + XCTAssertTrue([paragraph compareDocumentPositionWithNode:element] == + (HTMLDocumentPositionDisconnected | HTMLDocumentPositionImplementationSpecific | + paragraph.hash < element.hash ? HTMLDocumentPositionPreceding: HTMLDocumentPositionFollowing)); + + XCTAssertTrue([paragraph compareDocumentPositionWithNode:image] == HTMLDocumentPositionPreceding); + XCTAssertTrue([anchor compareDocumentPositionWithNode:image] == HTMLDocumentPositionPreceding); + XCTAssertTrue([image compareDocumentPositionWithNode:anchor] == HTMLDocumentPositionFollowing); + + XCTAssertTrue([outerDiv compareDocumentPositionWithNode:paragraph] == (HTMLDocumentPositionContains | HTMLDocumentPositionPreceding)); + XCTAssertTrue([outerDiv compareDocumentPositionWithNode:anchor] == (HTMLDocumentPositionContains | HTMLDocumentPositionPreceding)); + XCTAssertTrue([outerDiv compareDocumentPositionWithNode:image] == (HTMLDocumentPositionContains | HTMLDocumentPositionPreceding)); + + XCTAssertTrue([paragraph compareDocumentPositionWithNode:outerDiv] == (HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing)); + XCTAssertTrue([anchor compareDocumentPositionWithNode:outerDiv] == (HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing)); + XCTAssertTrue([image compareDocumentPositionWithNode:outerDiv] == (HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing)); +} + @end From b7b29d2af57697b1ef834d5aa13f74d99d470f46 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 03:21:17 +0100 Subject: [PATCH 35/75] Fix HTML Range boundary validations --- Sources/HTMLRange.m | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 8d1d77a..503d5bb 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -58,10 +58,19 @@ #pragma mark - Boundaries -NS_INLINE void CheckValidBoundaryNode(HTMLNode *node, NSString *cmd) +NS_INLINE void CheckValidBoundaryNode(HTMLDocument *document, HTMLNode *node, NSString *cmd) +{ + if (node.ownerDocument != document) { + [NSException raise:HTMLKitWrongDocumentError + format:@"%@: Invalid Node Error, %@ is not in the same document.", + cmd, node]; + } +} + +NS_INLINE void CheckValidBoundaryNodeType(HTMLNode *node, NSString *cmd) { if (node == nil || node.nodeType == HTMLNodeDocumentType) { - [NSException raise:HTMLKitNotFoundError + [NSException raise:HTMLKitInvalidNodeTypeError format:@"%@: Invalid Node Type Error, %@ is not a valid range boundary node.", cmd, node]; } @@ -69,7 +78,7 @@ NS_INLINE void CheckValidBoundaryNode(HTMLNode *node, NSString *cmd) NS_INLINE void CheckValidBoundaryOffset(HTMLNode *node, NSUInteger offset, NSString *cmd) { - if (node == nil || node.nodeType == HTMLNodeDocumentType) { + if (node.length < offset) { [NSException raise:HTMLKitIndexSizeError format:@"%@: Index Size Error, invalid index %lu for range boundary node %@.", cmd, (unsigned long)offset, node]; @@ -80,7 +89,7 @@ NS_INLINE void CheckValidDocument(HTMLRange *lhs, HTMLRange *rhs, NSString *cmd) { if (lhs.rootNode != rhs.rootNode) { [NSException raise:HTMLKitWrongDocumentError - format:@"%@: Wrong Document Error, ranges %@ and %@ have different roots.", + format:@"%@: Wrong Document Error, ranges %@ and %@ are not in the same document.", cmd, lhs, rhs]; } } @@ -106,7 +115,7 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } - if ([startNode containsNode:endNode]) { + if ((position & HTMLDocumentPositionContains) == HTMLDocumentPositionContains) { HTMLNode *child = endNode; while (child.parentNode != startNode) { child = child.parentNode; @@ -121,7 +130,9 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s - (void)setStartNode:(HTMLNode *)node startOffset:(NSUInteger)offset { - CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); + CheckValidBoundaryNode(_ownerDocument, node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryNodeType(node, NSStringFromSelector(_cmd)); CheckValidBoundaryOffset(node, offset, NSStringFromSelector(_cmd)); @@ -137,7 +148,9 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s - (void)setEndNode:(HTMLNode *)node endOffset:(NSUInteger)offset { - CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); + CheckValidBoundaryNode(_ownerDocument, node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryNodeType(node, NSStringFromSelector(_cmd)); CheckValidBoundaryOffset(node, offset, NSStringFromSelector(_cmd)); @@ -154,32 +167,24 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s - (void)setStartBeforeNode:(HTMLNode *)node { HTMLNode *parent = node.parentNode; - CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); - [self setStartNode:parent startOffset:node.index]; } - (void)setStartAfterNode:(HTMLNode *)node { HTMLNode *parent = node.parentNode; - CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); - [self setStartNode:parent startOffset:node.index + 1]; } - (void)setEndBeforeNode:(HTMLNode *)node { HTMLNode *parent = node.parentNode; - CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); - [self setEndNode:parent endOffset:node.index]; } - (void)setEndAfterNode:(HTMLNode *)node { HTMLNode *parent = node.parentNode; - CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); - [self setEndNode:parent endOffset:node.index + 1]; } @@ -196,16 +201,12 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s - (void)selectNode:(HTMLNode *)node { HTMLNode *parent = node.parentNode; - CheckValidBoundaryNode(parent, NSStringFromSelector(_cmd)); - [self setStartNode:parent startOffset:node.index]; [self setEndNode:parent endOffset:node.index + 1]; } - (void)selectNodeContents:(HTMLNode *)node { - CheckValidBoundaryNode(node, NSStringFromSelector(_cmd)); - [self setStartNode:node startOffset:0]; [self setEndNode:node endOffset:node.length]; } From de6c215550672f54c0423ce947c77830fd3a98d6 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 21:54:58 +0100 Subject: [PATCH 36/75] =?UTF-8?q?Fix=20check=20in=20range=E2=80=99s=20comp?= =?UTF-8?q?are-boundaries=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 503d5bb..d9bc135 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -120,7 +120,7 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s while (child.parentNode != startNode) { child = child.parentNode; } - if ([child.parentNode indexOfChildNode:child] > startOffset) { + if (child.index < startOffset) { return NSOrderedDescending; } } From 734c1851377f9d62337955557a7dad2936750235 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 21:55:36 +0100 Subject: [PATCH 37/75] Add HTML Range tests for boundaries logic --- Tests/HTMLRangeTests.m | 576 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 535 insertions(+), 41 deletions(-) diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 0681aa3..5385c34 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -14,15 +14,14 @@ @interface HTMLRangeTests : XCTestCase { HTMLDocument *_document; - HTMLElement *_a; - HTMLElement *_b; - HTMLElement *_c; - HTMLElement *_d; - HTMLElement *_e; - HTMLElement *_f; + HTMLElement *_h1; + HTMLElement *_p; + HTMLElement *_div1; + HTMLElement *_div2; + HTMLText *_title; + HTMLText *_paragraphText; HTMLText *_firstText; HTMLText *_secondText; - HTMLText *_thirdText; HTMLComment *_firstComment; HTMLComment *_secondComment; } @@ -38,47 +37,45 @@ - (void)setupDocument { - // Tree structure: - // #a - // | - // +----------+----------+ - // | | - // "This is text" #b - // | - // +----+--------------+ - // | | - // #c - // | - // +-----------------+----------+ - // | | | - // "Another text" #d #e - // | - // +-----------+----------------------+ - // | | | - // #f "Third text" + // HTML:

Title

Hello

First textSecond text
<--Second comment-->
+ // DOM: + // + // | + // +------------+-----------+ + // | | | + //

+ // | | | + // "Title" "Hello" | + // | + // +--------+----------+ + // | | + //
+ // | + // +-----------------+-----------------+ + // | | | + // "First text" "Second text" + _h1 = [[HTMLElement alloc] initWithTagName:@"h1" attributes:@{@"id": @"h1"}]; + _p = [[HTMLElement alloc] initWithTagName:@"p" attributes:@{@"id": @"p"}]; - _a = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"a"}]; - _b = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"b"}]; - _c = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"c"}]; - _d = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"d"}]; - _e = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"e"}]; - _f = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"f"}]; + _div1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"div1"}]; + _div2 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"div2"}]; - _firstText = [[HTMLText alloc] initWithData:@"This is text"]; - _secondText = [[HTMLText alloc] initWithData:@"Another text"]; - _thirdText = [[HTMLText alloc] initWithData:@"Third text"]; + _title = [[HTMLText alloc] initWithData:@"Title"]; + _paragraphText = [[HTMLText alloc] initWithData:@"Hello"]; + _firstText = [[HTMLText alloc] initWithData:@"First text"]; + _secondText = [[HTMLText alloc] initWithData:@"Second text"]; - _firstComment = [[HTMLComment alloc] initWithData:@"This is a comment"]; - _secondComment = [[HTMLComment alloc] initWithData:@"Another comment"]; + _firstComment = [[HTMLComment alloc] initWithData:@"First comment"]; + _secondComment = [[HTMLComment alloc] initWithData:@"Second comment"]; - [_a appendNodes:@[_firstText, _b]]; - [_b appendNodes:@[_c, _firstComment]]; - [_c appendNodes:@[_secondText, _d, _e]]; - [_e appendNodes:@[_f, _thirdText, _secondComment]]; + [_h1 appendNode:_title]; + [_p appendNode:_paragraphText]; + [_div1 appendNodes:@[_div2, _secondComment]]; + [_div2 appendNodes:@[_firstText, _firstComment, _secondText]]; _document = [HTMLDocument documentWithString:@""]; - [_document.body appendNodes:@[_a]]; + [_document.body appendNodes:@[_h1, _p, _div1]]; } - (void)testInitRange @@ -92,4 +89,501 @@ XCTAssertEqual(range.endOffset, 0); } +- (void)testSetStartBoundary +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + XCTAssertThrows([range setStartNode:[HTMLElement new] startOffset:0], @"Cannot set boundary to a node outside of the range's document"); + XCTAssertThrows([range setStartNode:[HTMLDocumentType new] startOffset:0], @"DOCTYPE as range boundary is invalid"); + XCTAssertThrows([range setStartNode:_firstText startOffset:_firstText.length + 1], @"Offset is outside the boundary node"); + + //

Title

Hello

First textSecond text
+ // | + // collapsed range + + [range setStartNode:_paragraphText startOffset:4]; + XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqual(range.startOffset, 4); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |______________| + // s e + + [range setStartNode:_title startOffset:2]; + XCTAssertEqual(range.startContainer, _title); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); +} + +- (void)testSetEndBoundary +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + XCTAssertThrows([range setEndNode:[HTMLDocumentType new] endOffset: 0], @"DOCTYPE as range boundary is invalid"); + XCTAssertThrows([range setEndNode:_firstText endOffset:_firstText.length + 1], @"Offset is outside the boundary node"); + + // ....

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setEndNode:_title endOffset:4]; + XCTAssertEqual(range.startContainer, _document); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _title); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |_| + // s e + + [range setStartNode:_title startOffset:3]; + XCTAssertEqual(range.startContainer, _title); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _title); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // | + // collapsed range + + [range setEndNode:_title endOffset:0]; + XCTAssertEqual(range.startContainer, _title); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _title); + XCTAssertEqual(range.endOffset, 0); +} + +- (void)testSetStartBeforeNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (p, 0)->|_____| + // s e + + [range setStartBeforeNode:_paragraphText]; + + XCTAssertEqual(range.startContainer, _p); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (body, 1)->|_____| + // s e + + [range setStartBeforeNode:_p]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ //(body, 0)->|__________________| + // s e + + [range setStartBeforeNode:_h1]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // (div1, 0)->|________________________________| + // s e + + [range setStartBeforeNode:_div2]; + + XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 0); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // (body, 2)->|_____________________________________| + // s e + + [range setStartBeforeNode:_div1]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 0); +} + +- (void)testSetStartAfterNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (p, 1)->| + // collapsed range + + [range setStartAfterNode:_paragraphText]; + + XCTAssertEqual(range.startContainer, _p); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _p); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (body, 2)->| + // collapsed range + + [range setStartAfterNode:_p]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 2); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (body, 1)->|_____| + // s e + + [range setStartAfterNode:_h1]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // (div1, 1)->| + // collapsed range + + [range setStartAfterNode:_div2]; + + XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // (_div2, 1)->|___________________| + // s e + + [range setStartAfterNode:_firstText]; + + XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 0); +} + +- (void)testSetEndBeforeNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (p, 0)->| + // collapsed range + + [range setEndBeforeNode:_paragraphText]; + + XCTAssertEqual(range.startContainer, _p); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _p); + XCTAssertEqual(range.endOffset, 0); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (body, 1)->| + // collapsed range + + [range setEndBeforeNode:_p]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ //(body, 0)->| + // collapsed range + + [range setEndBeforeNode:_h1]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 0); + + //

Title

Hello

First textSecond text
+ // |_____________________________| + // s e + + [range setStartNode:_firstText startOffset:0]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // |__________|<-(div2, 1) + // s e + + [range setEndBeforeNode:_firstComment]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |______________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:2]; + + //

Title

Hello

First textSecond text
+ // |___________________|<-(div1, 2) + // s e + + [range setEndBeforeNode:_secondText]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, _firstText.length); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 2); +} + +- (void)testSetEndAfterNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // |____|<-(p, 1) + // s e + + [range setEndAfterNode:_paragraphText]; + + XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _p); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // |_______________|<-(body, 2) + // s e + + [range setEndAfterNode:_p]; + + XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 2); + + //

Title

Hello

First textSecond text
+ // |___| + // s e + + [range setStartNode:_paragraphText startOffset:0]; + [range setEndNode:_paragraphText endOffset:4]; + + //

Title

Hello

First textSecond text
+ // (body, 1)->| + // collapsed range + + [range setEndAfterNode:_h1]; + + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // |______________________________________|<-(div1, 1) + // s e + + [range setEndAfterNode:_div2]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, _firstText.length); + XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
+ // |____________________| + // s e + + [range setStartNode:_firstText startOffset:_firstText.length]; + [range setEndNode:_secondText endOffset:0]; + + //

Title

Hello

First textSecond text
+ // |__________________|<-(div2, 2) + // s e + + [range setEndAfterNode:_firstComment]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, _firstText.length); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 2); +} + +- (void)testIsCollapsed +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + XCTAssertTrue(range.isCollapsed); + + [range setEndNode:_title endOffset:1]; + XCTAssertFalse(range.isCollapsed); + + [range setStartNode:_title startOffset:1]; + XCTAssertTrue(range.isCollapsed); +} + +- (void)testCollapseToStart +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |______________| + // s e + + [range setStartNode:_title startOffset:2]; + [range setEndNode:_paragraphText endOffset:4]; + [range collapseToStart]; + + XCTAssertEqual(range.startContainer, _title); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqual(range.endContainer, _title); + XCTAssertEqual(range.endOffset, 2); + XCTAssertTrue(range.isCollapsed); +} + +- (void)testCollapseToEnd +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |______________| + // s e + + [range setStartNode:_title startOffset:2]; + [range setEndNode:_paragraphText endOffset:4]; + [range collapseToEnd]; + + XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqual(range.startOffset, 4); + XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqual(range.endOffset, 4); + XCTAssertTrue(range.isCollapsed); +} + @end From bdacc629eb2fe4799c337e76a187f7af143b31d3 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 22:08:23 +0100 Subject: [PATCH 38/75] Add HTML Range tests for node selecting --- Tests/HTMLRangeTests.m | 111 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 5385c34..762bbaf 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -586,4 +586,115 @@ XCTAssertTrue(range.isCollapsed); } +- (void)testSelectNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------- + [range selectNode:_firstText]; + XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // -------------------- + [range selectNode:_firstComment]; + XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 2); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------------------------------------------------------------------------------- + [range selectNode:_div1]; + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range selectNode:_div2]; + XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqual(range.endOffset, 1); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // -------------------- + [range selectNode:_secondComment]; + XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqual(range.startOffset, 1); + XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqual(range.endOffset, 2); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // -------------- + [range selectNode:_h1]; + XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqual(range.endOffset, 1); +} + +- (void)testSelectNodeContents +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------- + [range selectNodeContents:_firstText]; + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, _firstText.length); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------- + [range selectNodeContents:_firstComment]; + XCTAssertEqual(range.startContainer, _firstComment); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstComment); + XCTAssertEqual(range.endOffset, _firstComment.length); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------------------------------------------------------------------ + [range selectNodeContents:_div1]; + XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqual(range.endOffset, 2); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------------------------------------- + [range selectNodeContents:_div2]; + XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // -------------- + [range selectNodeContents:_secondComment]; + XCTAssertEqual(range.startContainer, _secondComment); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondComment); + XCTAssertEqual(range.endOffset, _secondComment.length); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----- + [range selectNodeContents:_h1]; + XCTAssertEqual(range.startContainer, _h1); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _h1); + XCTAssertEqual(range.endOffset, 1); +} + +- (void)testCompareBoundaries +{ + +} + @end From dfd01b1908c3486593757eed4e044ad5bf80ad47 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 22:11:14 +0100 Subject: [PATCH 39/75] Update Xcode image and SDK versions in travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 095d84f..495f1c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8 +osx_image: xcode8.2 branches: except: @@ -17,10 +17,10 @@ env: - MACOS_FRAMEWORK_SCHEME=HTMLKit-macOS - WATCHOS_FRAMEWORK_SCHEME="HTMLKit-watchOS" - TVOS_FRAMEWORK_SCHEME="HTMLKit-tvOS" - - IOS_SDK=iphonesimulator10.0 + - IOS_SDK=iphonesimulator10.2 - MACOS_SDK=macosx10.12 - - WATCHOS_SDK=watchsimulator3.0 - - TVOS_SDK=appletvsimulator10.0 + - WATCHOS_SDK=watchsimulator3.1 + - TVOS_SDK=appletvsimulator10.1 matrix: - DESTINATION="arch=x86_64" SIMULATOR="" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" - DESTINATION="OS=9.0,name=iPhone 6" SIMULATOR="iPhone 6 (9.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" From 78b3069a252f0b8b90766cc17a7d5bc2772dbace Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 22:54:05 +0100 Subject: [PATCH 40/75] Fix watchOS and iOS destinations in travis.yml --- .travis.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 495f1c9..134832c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,16 +22,16 @@ env: - WATCHOS_SDK=watchsimulator3.1 - TVOS_SDK=appletvsimulator10.1 matrix: - - DESTINATION="arch=x86_64" SIMULATOR="" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" - - DESTINATION="OS=9.0,name=iPhone 6" SIMULATOR="iPhone 6 (9.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=9.1,name=iPhone 6 Plus" SIMULATOR="iPhone 6 Plus (9.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=9.2,name=iPhone 6S" SIMULATOR="iPhone 6S (9.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=9.3,name=iPhone 6S Plus" SIMULATOR="iPhone 6S Plus (9.3)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=10.0,name=iPhone 7 Plus" SIMULATOR="iPhone 7 Plus (10.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=2.0,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (2.2)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" - - DESTINATION="OS=3.0,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (3.0)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" - - DESTINATION="OS=9.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (9.2)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK" - - DESTINATION="OS=10.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (10.0)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK" + - DESTINATION="arch=x86_64" SIMULATOR="" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK" + - DESTINATION="OS=9.0,name=iPhone 6" SIMULATOR="iPhone 6 (9.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=9.1,name=iPhone 6 Plus" SIMULATOR="iPhone 6 Plus (9.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=9.2,name=iPhone 6S" SIMULATOR="iPhone 6S (9.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=9.3,name=iPhone 6S Plus" SIMULATOR="iPhone 6S Plus (9.3)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=10.2,name=iPhone 7 Plus" SIMULATOR="iPhone 7 Plus (10.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (2.2)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" + - DESTINATION="OS=3.1,name=Apple Watch Series 2 - 42mm" SIMULATOR="Apple Watch Series 2 - 42mm (3.1)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" + - DESTINATION="OS=9.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (9.2)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK" + - DESTINATION="OS=10.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (10.0)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK" script: - set -o pipefail From 3f74fcaa7bc153c6ab05f707c1ecf15a483e99cb Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 30 Dec 2016 23:35:00 +0100 Subject: [PATCH 41/75] =?UTF-8?q?Use=20the=20=E2=80=9CiPhone=207=20Plus=20?= =?UTF-8?q?10.1=E2=80=9D=20destination=20in=20travis.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that the Xcode8.2 image in travis contains multiple (2) “iPhone 7 Plus 10.2” destinations See build log: https://travis-ci.org/iabudiab/HTMLKit/jobs/187795560 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 134832c..1d24de1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ env: - DESTINATION="OS=9.1,name=iPhone 6 Plus" SIMULATOR="iPhone 6 Plus (9.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - DESTINATION="OS=9.2,name=iPhone 6S" SIMULATOR="iPhone 6S (9.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - DESTINATION="OS=9.3,name=iPhone 6S Plus" SIMULATOR="iPhone 6S Plus (9.3)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - - DESTINATION="OS=10.2,name=iPhone 7 Plus" SIMULATOR="iPhone 7 Plus (10.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" + - DESTINATION="OS=10.1,name=iPhone 7 Plus" SIMULATOR="iPhone 7 Plus (10.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (2.2)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" - DESTINATION="OS=3.1,name=Apple Watch Series 2 - 42mm" SIMULATOR="Apple Watch Series 2 - 42mm (3.1)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK" - DESTINATION="OS=9.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (9.2)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK" From 0319536a6ca3d6d2089d0872129387b321db1938 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 31 Dec 2016 00:34:54 +0100 Subject: [PATCH 42/75] Add HTML Range tests for boundary comparison --- Sources/HTMLRange.h | 12 ++++++-- Tests/HTMLRangeTests.m | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index b3b7870..6fd2b05 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -10,6 +10,14 @@ NS_ASSUME_NONNULL_BEGIN +/** + The comparison method of range boundaries + + - HTMLRangeComparisonMethodStartToStart: Compares the start boundary-point of sourceRange to the start boundary-point of this range. + - HTMLRangeComparisonMethodStartToEnd: Compares the start boundary-point of sourceRange to the end boundary-point of this range. + - HTMLRangeComparisonMethodEndToEnd: Compares the end boundary-point of sourceRange to the end boundary-point of this range. + - HTMLRangeComparisonMethodEndToStart: Compares the end boundary-point of sourceRange to the start boundary-point of this range. + */ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) { HTMLRangeComparisonMethodStartToStart = 0, @@ -143,10 +151,10 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) - (void)selectNodeContents:(HTMLNode *)node; /** - Compares the boundary points of this range with the given source range. + Compares the boundary points of the given range with this range. @param method The comparison method. - @param sourceRange The range to compare with. + @param sourceRange The source range for comparison. @return `NSOrderedAscending` if ordered before, `NSOrderedSame` if ordered same, `NSOrderedDescending` otherwise. @see HTMLRangeComparisonMethod diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 762bbaf..85e8710 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -694,7 +694,74 @@ - (void)testCompareBoundaries { + HTMLRange *range1 = [[HTMLRange alloc] initWithDowcument:_document]; + HTMLRange *range2 = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------- + [range1 selectNode:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------- + [range2 selectNode:_secondText]; + + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToStart sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToEnd sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToEnd sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------- + [range1 selectNode:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // -------------------- + [range2 selectNode:_firstComment]; + + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToStart sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToEnd sourceRange:range2] == NSOrderedSame); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToEnd sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------- + [range1 selectNode:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range2 selectNode:_div2]; + + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToStart sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToEnd sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToEnd sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------- + [range1 selectNode:_secondText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range2 selectNode:_div2]; + + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToStart sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToEnd sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToEnd sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------------------------------------------------------------------------------- + [range1 selectNode:_div1]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range2 selectNode:_div2]; + + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToStart sourceRange:range2] == NSOrderedAscending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodStartToEnd sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToEnd sourceRange:range2] == NSOrderedDescending); + XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); } @end From 9795172c9c0daf08b8e20485011ba3837cb5c83e Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 31 Dec 2016 03:11:49 +0100 Subject: [PATCH 43/75] Add implementation and tests for Range comparison and intersection methods --- Sources/HTMLRange.h | 26 ++++++++-- Sources/HTMLRange.m | 41 +++++++++++++--- Tests/HTMLRangeTests.m | 106 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 11 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 6fd2b05..c4e067b 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -162,12 +162,30 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) - (NSComparisonResult)compareBoundaryPoints:(HTMLRangeComparisonMethod)method sourceRange:(HTMLRange *)sourceRange; /** - Checks whether the given node is contained in this range. + Compares the given point (reference node, offset) with this range. - @param node The node to check. - @return `YES` if the node is contained in the range, `NO` otherwise. + @param node The node to compare with this range. + @param offset The offset inside the reference node. + @return `NSOrderedAscending`, `NSOrderedSame`, or `NSOrderedDescending` depending on whether the node is before, the same as, or after this range. */ -- (BOOL)containsNode:(HTMLNode *)node; +- (NSComparisonResult)comparePoint:(HTMLNode *)node offset:(NSUInteger)offset; + +/** + Checks if the given point (reference node, offset) is in this range. + + @param node The node to compare with this range. + @param offset The offset inside the reference node. + @return `YES` if the given point is in this range, `NO` otherwise. + */ +- (BOOL)containsPoint:(HTMLNode *)node offset:(NSUInteger)offset; + +/** + Checks if the given node intersects this range. + + @param node The node to compare with this range. + @return `YES` if the given node intersects the range, `NO` otherwise. + */ +- (BOOL)intersectsNode:(HTMLNode *)node; @end diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index d9bc135..57188e6 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -229,21 +229,48 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s #pragma mark - Containment -- (BOOL)containsNode:(HTMLNode *)node +- (NSComparisonResult)comparePoint:(HTMLNode *)node offset:(NSUInteger)offset { - if (node.rootNode != self.rootNode) { + CheckValidBoundaryNode(_ownerDocument, node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryNodeType(node, NSStringFromSelector(_cmd)); + + CheckValidBoundaryOffset(node, offset, NSStringFromSelector(_cmd)); + + if (CompareBoundaries(node, offset, _startContainer, _startOffset) == NSOrderedAscending) { + return NSOrderedAscending; + } + + if (CompareBoundaries(node, offset, _endContainer, _endOffset) == NSOrderedDescending) { + return NSOrderedDescending; + } + + return NSOrderedSame; +} + +- (BOOL)containsPoint:(HTMLNode *)node offset:(NSUInteger)offset +{ + return [self comparePoint:node offset:offset] == NSOrderedSame; +} + +- (BOOL)intersectsNode:(HTMLNode *)node +{ + if (self.rootNode != node.rootNode) { return NO; } - if (CompareBoundaries(node, 0, _startContainer, _startOffset) == NSOrderedDescending) { - return NO; + HTMLNode *parent = node.parentNode; + if (parent == nil) { + return YES; } - if (CompareBoundaries(node, node.length, _endContainer, _endOffset) == NSOrderedAscending) { - return NO; + NSUInteger offset = node.index; + if (CompareBoundaries(parent, offset, _endContainer, _endOffset) == NSOrderedAscending && + CompareBoundaries(parent, offset + 1, _startContainer, _startOffset) == NSOrderedDescending) { + return YES; } - return YES; + return NO; } #pragma mark - Update Callbacks diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 85e8710..c6664c4 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -764,4 +764,110 @@ XCTAssertTrue([range1 compareBoundaryPoints:HTMLRangeComparisonMethodEndToStart sourceRange:range2] == NSOrderedAscending); } +- (void)testContainmentAndComparisons +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + /*********** Compare ***********/ + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range selectNode:_div2]; + XCTAssertTrue([range comparePoint:_div1 offset:0] == NSOrderedSame); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------------------------------------- + [range selectNodeContents:_div2]; + XCTAssertTrue([range comparePoint:_div1 offset:0] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----- + [range selectNodeContents:_p]; + XCTAssertTrue([range comparePoint:_div1 offset:0] == NSOrderedDescending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range comparePoint:_document.body offset:0] == NSOrderedAscending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range comparePoint:_document.body offset:1] == NSOrderedSame); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range comparePoint:_document.body offset:2] == NSOrderedSame); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range comparePoint:_document.body offset:3] == NSOrderedDescending); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------- + [range selectNodeContents:_firstComment]; + XCTAssertTrue([range comparePoint:_firstComment offset:0] == NSOrderedSame); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------- + [range selectNodeContents:_firstComment]; + XCTAssertTrue([range comparePoint:_firstComment offset:3] == NSOrderedSame); + + /*********** Contains ***********/ + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ---------------------------------------------------- + [range selectNode:_div2]; + XCTAssertTrue([range containsPoint:_div1 offset:0]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range containsPoint:_document.body offset:1]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertTrue([range containsPoint:_document.body offset:2]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------- + [range selectNodeContents:_firstComment]; + XCTAssertTrue([range containsPoint:_firstComment offset:3]); +} + +- (void)testIntersections +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + XCTAssertFalse([range intersectsNode:[HTMLText new]]); + XCTAssertTrue([range intersectsNode:_document]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ------------ + [range selectNode:_p]; + XCTAssertFalse([range intersectsNode:_h1]); + XCTAssertTrue([range intersectsNode:_p]); + XCTAssertFalse([range intersectsNode:_div1]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ----------------- + [range selectNode:_p]; + [range setEndAfterNode:_div1]; + XCTAssertFalse([range intersectsNode:_h1]); + XCTAssertTrue([range intersectsNode:_p]); + XCTAssertTrue([range intersectsNode:_div1]); + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // --------------------------- + [range selectNode:_firstComment]; + [range setEndAfterNode:_secondText]; + XCTAssertTrue([range intersectsNode:_div2]); + XCTAssertFalse([range intersectsNode:_firstText]); + XCTAssertTrue([range intersectsNode:_firstComment]); + XCTAssertTrue([range intersectsNode:_secondText]); +} + @end From ea17eeef9dc45e3aeea2a7ae34df2a6841471758 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 31 Dec 2016 16:26:06 +0100 Subject: [PATCH 44/75] Fix copy methods for CharacterData and DocumentType nodes --- Sources/HTMLCharacterData.m | 2 +- Sources/HTMLDocumentType.m | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/HTMLCharacterData.m b/Sources/HTMLCharacterData.m index 86e4f90..0891f64 100644 --- a/Sources/HTMLCharacterData.m +++ b/Sources/HTMLCharacterData.m @@ -91,7 +91,7 @@ NS_INLINE void CheckValidOffset(HTMLCharacterData *node, NSUInteger offset, NSSt - (id)copyWithZone:(NSZone *)zone { HTMLCharacterData *copy = [super copyWithZone:zone]; - copy->_data = _data; + copy->_data = [_data mutableCopy]; return copy; } diff --git a/Sources/HTMLDocumentType.m b/Sources/HTMLDocumentType.m index c22be69..0bff20c 100644 --- a/Sources/HTMLDocumentType.m +++ b/Sources/HTMLDocumentType.m @@ -139,8 +139,8 @@ NS_INLINE BOOL nilOrEqual(id first, id second) { - (id)copyWithZone:(NSZone *)zone { HTMLDocumentType *copy = [super copyWithZone:zone]; - copy->_publicIdentifier = self.publicIdentifier; - copy->_systemIdentifier = self.systemIdentifier; + copy->_publicIdentifier = [_publicIdentifier copy]; + copy->_systemIdentifier = [_systemIdentifier copy]; return copy; } From c2948021993e6a471cdf7b20518786c7bcba1ee6 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 2 Jan 2017 00:39:55 +0100 Subject: [PATCH 45/75] Add HTML Range tests for character data mutation callbacks --- Sources/HTMLRange.m | 6 ++- Tests/HTMLRangeTests.m | 97 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 57188e6..0e963df 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -283,7 +283,8 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } else { _startOffset = _startOffset - length; } - } else if (_endContainer == node && _endOffset > offset) { + } + if (_endContainer == node && _endOffset > offset) { if (_endOffset <= offset + length) { _endOffset = offset; } else { @@ -296,7 +297,8 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s { if (_startContainer == node && _startOffset > offset) { _startOffset = _startOffset + length; - } else if (_endContainer == node && _endOffset > offset) { + } + if (_endContainer == node && _endOffset > offset) { _endOffset = _endOffset + length; } } diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index c6664c4..978e098 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -870,4 +870,101 @@ XCTAssertTrue([range intersectsNode:_secondText]); } +- (void)testThatCharacterDataMutationsUpdateRangeCorrectly +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |________| + [range selectNodeContents:_firstText]; + + //

Title

Hello

First text New TextSecond text
<--Second comment-->
+ // |________| + [_firstText appendData:@" New Text"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 10); + + //

Title

Hello

New TextSecond text
<--Second comment-->
+ // |______| + [_firstText replaceDataInRange:NSMakeRange(0, 5) withData:@"New"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 8); + + //

Title

Hello

New TextSecond text
<--Second comment-->
+ // | + [_firstText setData:@"New Text"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 0); + + //

Title

Hello

New TextSecond text
<--Second comment-->
+ // |______| + [range selectNodeContents:_firstText]; + + //

Title

Hello

NewTextSecond text
<--Second comment-->
+ // |_____| + [_firstText deleteDataInRange:NSMakeRange(3, 1)]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 7); + + //

Title

Hello

NewNewTextSecond text
<--Second comment-->
+ // |________| + [_firstText insertData:@"New" atOffset:3]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 10); + + //

Title

Hello

NewNewTextSecond text
<--Second comment-->
+ // |_____| + [range setStartNode:_firstText startOffset:3]; + + //

Title

Hello

PrefixNewNewTextSecond text
<--Second comment-->
+ // |_____| + [_firstText insertData:@"Prefix" atOffset:0]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 9); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 16); + + //

Title

Hello

PrefixNewTextSecond text
<--Second comment-->
+ // |_____| + [_firstText deleteDataInRange:NSMakeRange(6, 3)]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 6); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 13); + + //

Title

Hello

PreABCDTextSecond text
<--Second comment-->
+ // |______| + [_firstText replaceDataInRange:NSMakeRange(3, 6) withData:@"ABCD"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 11); + + //

Title

Hello

Pre TextSecond text
<--Second comment-->
+ // |___| + [_firstText replaceDataInRange:NSMakeRange(3, 4) withData:@" "]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 8); +} @end From 1042571c57f5495bde940ac36fbead1e714ee400 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 2 Jan 2017 01:04:00 +0100 Subject: [PATCH 46/75] Add Range tests for character data callbacks with different boundaries --- Tests/HTMLRangeTests.m | 117 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 978e098..12834a2 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -887,7 +887,7 @@ XCTAssertEqual(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 10); - //

Title

Hello

New TextSecond text
<--Second comment-->
+ //

Title

Hello

New text New TextSecond text
<--Second comment-->
// |______| [_firstText replaceDataInRange:NSMakeRange(0, 5) withData:@"New"]; @@ -967,4 +967,119 @@ XCTAssertEqual(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 8); } + +- (void)testThatCharacterDataMutationsUpdateRangeCorrectly_DifferentBoundaries +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |___________________________| + [range setStartNode:_firstText startOffset:5]; + [range setEndNode:_secondText endOffset:3]; + + //

Title

Hello

First text New TextSecond text
<--Second comment-->
+ // |____________________________________| + [_firstText appendData:@" New Text"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 5); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

New text New TextSecond text
<--Second comment-->
+ // |______________________________________| + [_firstText replaceDataInRange:NSMakeRange(0, 5) withData:@"New"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

New TextSecond text
<--Second comment-->
+ // |_____________________________| + [_firstText setData:@"New Text"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + + //

Title

Hello

NewTextSecond text
<--Second comment-->
+ // |____________________________| + [_firstText deleteDataInRange:NSMakeRange(3, 1)]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

NewNewTextSecond text
<--Second comment-->
+ // |_______________________________| + [_firstText insertData:@"New" atOffset:3]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

NewNewTextSecond text
<--Second comment-->
+ // |____________________________| + [range setStartNode:_firstText startOffset:3]; + + //

Title

Hello

PrefixNewNewTextSecond text
<--Second comment-->
+ // |____________________________| + [_firstText insertData:@"Prefix" atOffset:0]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 9); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

PrefixNewTextSecond text
<--Second comment-->
+ // |____________________________| + [_firstText deleteDataInRange:NSMakeRange(6, 3)]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 6); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

PreABCDTextSecond text
<--Second comment-->
+ // |_____________________________| + [_firstText replaceDataInRange:NSMakeRange(3, 6) withData:@"ABCD"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

Pre TextSecond text
<--Second comment-->
+ // |__________________________| + [_firstText replaceDataInRange:NSMakeRange(3, 4) withData:@" "]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); + + //

Title

Hello

Pre TextPrefixSecond text
<--Second comment-->
+ // |________________________________| + [_secondText insertData:@"Prefix" atOffset:0]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 9); + + //

Title

Hello

Pre TextPrefixSecond text
<--Second comment-->
+ // |___________________| + [_firstComment setData:@"X"]; + + XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 3); + XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 9); +} + @end From b66f5264bac1fee2f1369a16bf9ce30d0599d3a8 Mon Sep 17 00:00:00 2001 From: iska Date: Wed, 4 Jan 2017 03:49:05 +0100 Subject: [PATCH 47/75] Rename some test classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Drop the “Kit” from class names --- HTMLKit.xcodeproj/project.pbxproj | 96 +++++++++---------- ...kenListTests.m => HTMLDOMTokenListTests.m} | 0 ...sTests.m => HTMLMutationAlgorithmsTests.m} | 0 ...teratorTests.m => HTMLNodeIteratorTests.m} | 0 .../{HTMLKitNodesTests.m => HTMLNodesTests.m} | 0 ...ryTests.m => HTMLOrderedDictionaryTests.m} | 0 ...egoryTests.m => HTMLStringCategoryTests.m} | 0 7 files changed, 48 insertions(+), 48 deletions(-) rename Tests/{HTMLKitDOMTokenListTests.m => HTMLDOMTokenListTests.m} (100%) rename Tests/{HTMLKitMutationAlgorithmsTests.m => HTMLMutationAlgorithmsTests.m} (100%) rename Tests/{HTMLKitNodeIteratorTests.m => HTMLNodeIteratorTests.m} (100%) rename Tests/{HTMLKitNodesTests.m => HTMLNodesTests.m} (100%) rename Tests/{HTMLKitOrderedDictionaryTests.m => HTMLOrderedDictionaryTests.m} (100%) rename Tests/{HTMLKitStringCategoryTests.m => HTMLStringCategoryTests.m} (100%) diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 998a40f..0b01a68 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */; }; - 623916C81AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; }; + 623916C81AC7209E0066B4FE /* HTMLNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLNodeIteratorTests.m */; }; 6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */; }; 6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; }; 623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; }; @@ -36,8 +36,8 @@ 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; }; 624AC90519FBFE9A00BD3C4A /* html5lib-tests in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90419FBFE8A00BD3C4A /* html5lib-tests */; }; 624AC90F19FC702E00BD3C4A /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; - 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; - 624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; }; + 624B9FB31AE0313300646C4C /* HTMLStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */; }; + 624B9FB61AE0391400646C4C /* HTMLOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */; }; 624C777A1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 624C777B1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 624C777C1DE9D05E00DD6DFA /* HTMLCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -46,13 +46,13 @@ 624C777F1DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; 624C77801DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; 624C77811DE9D05E00DD6DFA /* HTMLCharacterData.m in Sources */ = {isa = PBXBuildFile; fileRef = 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */; }; - 624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; }; + 624FC37B1AE591D80015DDF9 /* HTMLNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */; }; 62567F501C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62567F511C0CB5750025D458 /* HTMLDOMTokenList.h in Headers */ = {isa = PBXBuildFile; fileRef = 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62567F521C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F4F1C0CB5750025D458 /* HTMLDOMTokenList.m */; }; 62567F531C0CB5750025D458 /* HTMLDOMTokenList.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F4F1C0CB5750025D458 /* HTMLDOMTokenList.m */; }; - 62567F561C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m */; }; - 62567F571C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m */; }; + 62567F561C0CC3AE0025D458 /* HTMLDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLDOMTokenListTests.m */; }; + 62567F571C0CC3AE0025D458 /* HTMLDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLDOMTokenListTests.m */; }; 625A14B019C7829400AD0C32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AF19C7829400AD0C32 /* Cocoa.framework */; }; 625A14C519C7829400AD0C32 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14C419C7829400AD0C32 /* XCTest.framework */; }; 625A14C919C7829400AD0C32 /* HTMLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AC19C7829400AD0C32 /* HTMLKit.framework */; }; @@ -229,13 +229,13 @@ 62857D311D39A33C008DC254 /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; }; 62857D321D39A33C008DC254 /* HTMLKitTreeConstructionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */; }; 62857D331D39A33C008DC254 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; }; - 62857D341D39A33F008DC254 /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; }; + 62857D341D39A33F008DC254 /* HTMLNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLNodeIteratorTests.m */; }; 62857D351D39A33F008DC254 /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; }; - 62857D361D39A33F008DC254 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; }; - 62857D371D39A33F008DC254 /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; - 62857D381D39A342008DC254 /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; - 62857D391D39A342008DC254 /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; }; - 62857D3A1D39A342008DC254 /* HTMLKitDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m */; }; + 62857D361D39A33F008DC254 /* HTMLNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */; }; + 62857D371D39A33F008DC254 /* HTMLMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */; }; + 62857D381D39A342008DC254 /* HTMLStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */; }; + 62857D391D39A342008DC254 /* HTMLOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */; }; + 62857D3A1D39A342008DC254 /* HTMLDOMTokenListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62567F551C0CC3AE0025D458 /* HTMLDOMTokenListTests.m */; }; 62857D3B1D39A345008DC254 /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; }; 62857D3C1D39A345008DC254 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 62857D3D1D39A345008DC254 /* CSSExtensionSelectorsParsingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */; }; @@ -320,7 +320,7 @@ 62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; 62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; 62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; - 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; + 62EC7AE71AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */; }; 62ECBEE11C0B69FD00AF847B /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62ECBEE21C0B69FD00AF847B /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; settings = {ATTRIBUTES = (Private, ); }; }; 62ECBEE31C0B69FD00AF847B /* HTMLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -528,12 +528,12 @@ 62ECBFCD1C0B6E2E00AF847B /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; }; 62ECBFCE1C0B6E2E00AF847B /* HTMLKitTreeConstructionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */; }; 62ECBFCF1C0B6E2E00AF847B /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; }; - 62ECBFD01C0B6E2E00AF847B /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; }; + 62ECBFD01C0B6E2E00AF847B /* HTMLNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLNodeIteratorTests.m */; }; 62ECBFD11C0B6E2E00AF847B /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; }; - 62ECBFD21C0B6E2E00AF847B /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; }; - 62ECBFD31C0B6E2E00AF847B /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; - 62ECBFD41C0B6E2E00AF847B /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; - 62ECBFD51C0B6E2E00AF847B /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; }; + 62ECBFD21C0B6E2E00AF847B /* HTMLNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */; }; + 62ECBFD31C0B6E2E00AF847B /* HTMLMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */; }; + 62ECBFD41C0B6E2E00AF847B /* HTMLStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */; }; + 62ECBFD51C0B6E2E00AF847B /* HTMLOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */; }; 62ECBFD61C0B6E2E00AF847B /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; }; 62ECBFD71C0B6E2E00AF847B /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; 62ECBFD81C0B6E2E00AF847B /* CSSNthExpressionsParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */; }; @@ -625,7 +625,7 @@ 6238579A1A9E8934003A45D9 /* HTMLComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLComment.m; sourceTree = ""; }; 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLKitDOMExceptions.h; path = include/HTMLKitDOMExceptions.h; sourceTree = ""; }; 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitDOMExceptions.m; sourceTree = ""; }; - 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodeIteratorTests.m; sourceTree = ""; }; + 623916C61AC7209E0066B4FE /* HTMLNodeIteratorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeIteratorTests.m; sourceTree = ""; }; 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTreeConstructionTests.m; sourceTree = ""; }; 6239755C1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTreeConstructionTest.h; sourceTree = ""; }; 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTreeConstructionTest.m; sourceTree = ""; }; @@ -660,14 +660,14 @@ 624B371C1B24E9BA0010BDDF /* CSSInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSInputStream.h; path = include/CSSInputStream.h; sourceTree = ""; }; 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSInputStream.m; sourceTree = ""; }; 624B37211B250BB50010BDDF /* CSSCodePoints.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CSSCodePoints.h; path = include/CSSCodePoints.h; sourceTree = ""; }; - 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitStringCategoryTests.m; sourceTree = ""; }; - 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitOrderedDictionaryTests.m; sourceTree = ""; }; + 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLStringCategoryTests.m; sourceTree = ""; }; + 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLOrderedDictionaryTests.m; sourceTree = ""; }; 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCharacterData.h; sourceTree = ""; }; 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterData.m; sourceTree = ""; }; - 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = ""; }; + 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodesTests.m; sourceTree = ""; }; 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLDOMTokenList.h; path = include/HTMLDOMTokenList.h; sourceTree = ""; }; 62567F4F1C0CB5750025D458 /* HTMLDOMTokenList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDOMTokenList.m; sourceTree = ""; }; - 62567F551C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitDOMTokenListTests.m; sourceTree = ""; }; + 62567F551C0CC3AE0025D458 /* HTMLDOMTokenListTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDOMTokenListTests.m; sourceTree = ""; }; 625A14AC19C7829400AD0C32 /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 625A14AF19C7829400AD0C32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 625A14B219C7829400AD0C32 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -720,7 +720,7 @@ 62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = ""; }; 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = ""; }; 62EC0A841E158BD80007786B /* HTMLRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRangeTests.m; sourceTree = ""; }; - 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = ""; }; + 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLMutationAlgorithmsTests.m; sourceTree = ""; }; 62ECBF4D1C0B6C7600AF847B /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 62ECBF561C0B6C7600AF847B /* HTMLKitTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HTMLKitTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerEntities.h; path = include/HTMLTokenizerEntities.h; sourceTree = ""; }; @@ -876,10 +876,10 @@ 624B9FB71AE072CB00646C4C /* DOM */ = { isa = PBXGroup; children = ( - 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */, + 623916C61AC7209E0066B4FE /* HTMLNodeIteratorTests.m */, 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */, - 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */, - 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */, + 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */, + 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */, 62EC0A841E158BD80007786B /* HTMLRangeTests.m */, ); name = DOM; @@ -888,7 +888,7 @@ 624B9FB81AE072D500646C4C /* Categories */ = { isa = PBXGroup; children = ( - 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */, + 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */, ); name = Categories; sourceTree = ""; @@ -896,8 +896,8 @@ 624E1A2D1B1D1C8A00E66AAC /* Structures */ = { isa = PBXGroup; children = ( - 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */, - 62567F551C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m */, + 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */, + 62567F551C0CC3AE0025D458 /* HTMLDOMTokenListTests.m */, ); name = Structures; sourceTree = ""; @@ -1749,18 +1749,18 @@ 623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */, 625EE4571CBAA41D00F2CC8E /* HTMLKitTestObserver.m in Sources */, 6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */, - 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 62EC7AE71AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m in Sources */, 624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */, - 624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */, + 624B9FB61AE0391400646C4C /* HTMLOrderedDictionaryTests.m in Sources */, 624AB3181B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */, 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */, - 62567F561C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m in Sources */, + 62567F561C0CC3AE0025D458 /* HTMLDOMTokenListTests.m in Sources */, 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */, - 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */, - 623916C81AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */, + 624B9FB31AE0313300646C4C /* HTMLStringCategoryTests.m in Sources */, + 623916C81AC7209E0066B4FE /* HTMLNodeIteratorTests.m in Sources */, 62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */, 6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */, - 624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */, + 624FC37B1AE591D80015DDF9 /* HTMLNodesTests.m in Sources */, 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */, 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */, 625EE45B1CBB171300F2CC8E /* HTMLKitTestUtil.m in Sources */, @@ -1889,19 +1889,19 @@ 62857D301D39A339008DC254 /* HTMLKitTokenizerPerformance.m in Sources */, 62857D321D39A33C008DC254 /* HTMLKitTreeConstructionTests.m in Sources */, 62857D431D39A34B008DC254 /* HTMLKitTestObserver.m in Sources */, - 62857D371D39A33F008DC254 /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 62857D371D39A33F008DC254 /* HTMLMutationAlgorithmsTests.m in Sources */, 62857D3E1D39A345008DC254 /* CSSNthExpressionsParserTests.m in Sources */, 62857D3F1D39A345008DC254 /* CSSTypeSelectorTests.m in Sources */, - 62857D361D39A33F008DC254 /* HTMLKitNodesTests.m in Sources */, - 62857D3A1D39A342008DC254 /* HTMLKitDOMTokenListTests.m in Sources */, + 62857D361D39A33F008DC254 /* HTMLNodesTests.m in Sources */, + 62857D3A1D39A342008DC254 /* HTMLDOMTokenListTests.m in Sources */, 62857D3D1D39A345008DC254 /* CSSExtensionSelectorsParsingTests.m in Sources */, 62857D401D39A345008DC254 /* CSSAttributeSelectorTests.m in Sources */, 62857D311D39A33C008DC254 /* HTML5LibTreeConstructionTest.m in Sources */, - 62857D391D39A342008DC254 /* HTMLKitOrderedDictionaryTests.m in Sources */, + 62857D391D39A342008DC254 /* HTMLOrderedDictionaryTests.m in Sources */, 62857D411D39A345008DC254 /* CSSNThExpressionSelectorTests.m in Sources */, - 62857D381D39A342008DC254 /* HTMLKitStringCategoryTests.m in Sources */, + 62857D381D39A342008DC254 /* HTMLStringCategoryTests.m in Sources */, 62857D331D39A33C008DC254 /* HTMLKitParserPerformance.m in Sources */, - 62857D341D39A33F008DC254 /* HTMLKitNodeIteratorTests.m in Sources */, + 62857D341D39A33F008DC254 /* HTMLNodeIteratorTests.m in Sources */, 62857D2E1D39A339008DC254 /* HTML5LibTokenizerTest.m in Sources */, 62857D351D39A33F008DC254 /* HTMLTreeWalkerTests.m in Sources */, 62857D441D39A34D008DC254 /* HTMLKitTestUtil.m in Sources */, @@ -1977,13 +1977,13 @@ 625EE4581CBAA41D00F2CC8E /* HTMLKitTestObserver.m in Sources */, 62ECBFCE1C0B6E2E00AF847B /* HTMLKitTreeConstructionTests.m in Sources */, 62ECBFCF1C0B6E2E00AF847B /* HTMLKitParserPerformance.m in Sources */, - 62ECBFD01C0B6E2E00AF847B /* HTMLKitNodeIteratorTests.m in Sources */, + 62ECBFD01C0B6E2E00AF847B /* HTMLNodeIteratorTests.m in Sources */, 62ECBFD11C0B6E2E00AF847B /* HTMLTreeWalkerTests.m in Sources */, - 62ECBFD21C0B6E2E00AF847B /* HTMLKitNodesTests.m in Sources */, - 62ECBFD31C0B6E2E00AF847B /* HTMLKitMutationAlgorithmsTests.m in Sources */, - 62567F571C0CC3AE0025D458 /* HTMLKitDOMTokenListTests.m in Sources */, - 62ECBFD41C0B6E2E00AF847B /* HTMLKitStringCategoryTests.m in Sources */, - 62ECBFD51C0B6E2E00AF847B /* HTMLKitOrderedDictionaryTests.m in Sources */, + 62ECBFD21C0B6E2E00AF847B /* HTMLNodesTests.m in Sources */, + 62ECBFD31C0B6E2E00AF847B /* HTMLMutationAlgorithmsTests.m in Sources */, + 62567F571C0CC3AE0025D458 /* HTMLDOMTokenListTests.m in Sources */, + 62ECBFD41C0B6E2E00AF847B /* HTMLStringCategoryTests.m in Sources */, + 62ECBFD51C0B6E2E00AF847B /* HTMLOrderedDictionaryTests.m in Sources */, 62ECBFD61C0B6E2E00AF847B /* CSSSelectorTest.m in Sources */, 62ECBFD71C0B6E2E00AF847B /* CSSSelectorParserTests.m in Sources */, 62ECBFD81C0B6E2E00AF847B /* CSSNthExpressionsParserTests.m in Sources */, diff --git a/Tests/HTMLKitDOMTokenListTests.m b/Tests/HTMLDOMTokenListTests.m similarity index 100% rename from Tests/HTMLKitDOMTokenListTests.m rename to Tests/HTMLDOMTokenListTests.m diff --git a/Tests/HTMLKitMutationAlgorithmsTests.m b/Tests/HTMLMutationAlgorithmsTests.m similarity index 100% rename from Tests/HTMLKitMutationAlgorithmsTests.m rename to Tests/HTMLMutationAlgorithmsTests.m diff --git a/Tests/HTMLKitNodeIteratorTests.m b/Tests/HTMLNodeIteratorTests.m similarity index 100% rename from Tests/HTMLKitNodeIteratorTests.m rename to Tests/HTMLNodeIteratorTests.m diff --git a/Tests/HTMLKitNodesTests.m b/Tests/HTMLNodesTests.m similarity index 100% rename from Tests/HTMLKitNodesTests.m rename to Tests/HTMLNodesTests.m diff --git a/Tests/HTMLKitOrderedDictionaryTests.m b/Tests/HTMLOrderedDictionaryTests.m similarity index 100% rename from Tests/HTMLKitOrderedDictionaryTests.m rename to Tests/HTMLOrderedDictionaryTests.m diff --git a/Tests/HTMLKitStringCategoryTests.m b/Tests/HTMLStringCategoryTests.m similarity index 100% rename from Tests/HTMLKitStringCategoryTests.m rename to Tests/HTMLStringCategoryTests.m From 12fc9726025f6cf454e5534fa6e97c36d0ba2173 Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 5 Jan 2017 02:43:07 +0100 Subject: [PATCH 48/75] Add HTML Range handling for mutation callback on node removal See: https://dom.spec.whatwg.org/#concept-node-remove --- Sources/HTMLDocument.m | 30 +++++++++++++++++++----------- Sources/HTMLRange+Private.h | 26 ++++++++++++++++++++++++++ Sources/HTMLRange.m | 21 +++++++++++++++++++++ 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/Sources/HTMLDocument.m b/Sources/HTMLDocument.m index 8ce00da..bc544bd 100644 --- a/Sources/HTMLDocument.m +++ b/Sources/HTMLDocument.m @@ -143,17 +143,6 @@ [_nodeIterators removeObject:iterator]; } -- (void)runRemovingStepsForNode:(HTMLNode *)oldNode - withOldParent:(HTMLNode *)oldParent - andOldPreviousSibling:(HTMLNode *)oldPreviousSibling -{ - for (HTMLNodeIterator *iterator in _nodeIterators) { - [iterator runRemovingStepsForNode:oldNode - withOldParent:oldParent - andOldPreviousSibling:oldPreviousSibling]; - } -} - #pragma mark - Ranges - (void)attachRange:(HTMLRange *)range @@ -180,6 +169,25 @@ } } +#pragma mark - Mutation Callback + +- (void)runRemovingStepsForNode:(HTMLNode *)oldNode + withOldParent:(HTMLNode *)oldParent + andOldPreviousSibling:(HTMLNode *)oldPreviousSibling +{ + for (HTMLRange *range in _ranges) { + [range runRemovingStepsForNode:oldNode + withOldParent:oldParent + andOldPreviousSibling:oldPreviousSibling]; + } + + for (HTMLNodeIterator *iterator in _nodeIterators) { + [iterator runRemovingStepsForNode:oldNode + withOldParent:oldParent + andOldPreviousSibling:oldPreviousSibling]; + } +} + #pragma mark - Mutation Algorithms - (HTMLNode *)adoptNode:(HTMLNode *)node diff --git a/Sources/HTMLRange+Private.h b/Sources/HTMLRange+Private.h index 8d7e5d6..57f83c4 100644 --- a/Sources/HTMLRange+Private.h +++ b/Sources/HTMLRange+Private.h @@ -11,7 +11,33 @@ @interface HTMLRange () +/** + Runs the necessary steps after removing data from a character data node that may be a range's boundary. + + @param node The character data node. + @param offset The offset at which the data was removed. + @param length The length of the data that was removed. + */ - (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; + +/** + Runs the necessary steps after adding data to a character data node that may be a range's boundary. + + @param node The character data node. + @param offset The offset at which the data was added. + @param length The length of the data that was added. + */ - (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; +/** + Runs the necessary steps after removing a node from the DOM. + + @param oldNode The old node that was removed. + @param oldParent The old parent of the node that was removed. +@param oldPreviousSibling The old previous sibling node of the node that was removed. + */ +- (void)runRemovingStepsForNode:(HTMLNode *)oldNode + withOldParent:(HTMLNode *)oldParent + andOldPreviousSibling:(HTMLNode *)oldPreviousSibling; + @end diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 0e963df..1617584 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -303,4 +303,25 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } +- (void)runRemovingStepsForNode:(HTMLNode *)oldNode withOldParent:(HTMLNode *)oldParent andOldPreviousSibling:(HTMLNode *)oldPreviousSibling +{ + NSUInteger oldIndex = oldPreviousSibling.index + 1; + + if ([_startContainer containsNode:oldNode]) { + [self setStartNode:oldNode startOffset:oldIndex]; + } + + if ([_endContainer containsNode:oldNode]) { + [self setEndNode:oldNode endOffset:oldIndex]; + } + + if (_startContainer == oldParent && _startOffset > oldIndex) { + _startOffset -= 1; + } + + if (_endContainer == oldParent && _endOffset > oldIndex) { + _endOffset -= 1; + } +} + @end From 8602ad5a7ba07e8a3f2e7981047db6f77ca1a90b Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 5 Jan 2017 02:44:05 +0100 Subject: [PATCH 49/75] =?UTF-8?q?Add=20extended=20documentation=20for=20No?= =?UTF-8?q?de=E2=80=99s=20containsNode=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be deprecated and replaced with isInclusiveAncestor in a later release. --- Sources/include/HTMLNode.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index ab3fa5b..5e94f2e 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -340,7 +340,8 @@ typedef NS_OPTIONS(unsigned short, HTMLDocumentPosition) - (BOOL)isDescendantOfNode:(HTMLNode *)node; /** - Checks whether this node contains the given node. + Checks whether this node contains the given node. This performs an `invlusive ancestor` check, i.e. it returns `YES` + if the given node is the same object as this node. @param node The node to check. @return `YES` if this node contains the given node, `NO` otherwsie. From 07c72f65d9037dc3292a9d4e829a2007c84c103a Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 08:07:47 +0100 Subject: [PATCH 50/75] Add HTML Range methods for contained nodes --- Sources/HTMLRange.m | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 1617584..15f30c7 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -273,6 +273,34 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s return NO; } +- (BOOL)containsNode:(HTMLNode *)node +{ + return CompareBoundaries(_startContainer, _startOffset, node, 0) == NSOrderedAscending && + CompareBoundaries(_endContainer, _endOffset, node, node.length) == NSOrderedDescending; +} + +- (BOOL)partiallyContainsNode:(HTMLNode *)node +{ + return [GetAncestorNodes(_startContainer) containsObject:node] || [GetAncestorNodes(_endContainer) containsObject:node]; +} + +- (NSArray *)containedNodes +{ + HTMLNode *commonAncestor = self.commonAncestorContainer; + + NSMutableArray *containedNodes = [NSMutableArray array]; + [commonAncestor.childNodes enumerateObjectsUsingBlock:^(HTMLNode * _Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) { + if (node.nodeType == HTMLNodeDocumentType) { + [NSException raise:HTMLKitHierarchyRequestError format:@"Hierarchy Request Error, encountered a DOCTYPE contained in range: %@", self]; + } + if ([self containsNode:node]) { + [containedNodes addObject:node]; + } + }]; + + return containedNodes; +} + #pragma mark - Update Callbacks - (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length From 0ac49f2a0fa22fb1a856a8fe1e80120a76096f9e Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 08:09:26 +0100 Subject: [PATCH 51/75] =?UTF-8?q?Add=20implementation=20for=20HTML=20Range?= =?UTF-8?q?=E2=80=99s=20delete=20contents=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HTMLKit.xcodeproj/project.pbxproj | 8 +- Sources/HTMLRange.h | 4 + Sources/HTMLRange.m | 58 +++++++ Tests/HTMLRangeTests.m | 252 ++++++++++++++++++++++++++++++ 4 files changed, 318 insertions(+), 4 deletions(-) diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 0b01a68..4439f3b 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -974,6 +974,10 @@ 625A14CA19C7829400AD0C32 /* Tests */ = { isa = PBXGroup; children = ( + 625EE4551CBAA41D00F2CC8E /* HTMLKitTestObserver.h */, + 625EE4561CBAA41D00F2CC8E /* HTMLKitTestObserver.m */, + 625EE4591CBB171300F2CC8E /* HTMLKitTestUtil.h */, + 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */, 6236738C1AC0CD2400FF89B3 /* Tokenizer */, 623975581AC362A5007E26F1 /* Tree Construction */, 624B9FB71AE072CB00646C4C /* DOM */, @@ -981,10 +985,6 @@ 624E1A2D1B1D1C8A00E66AAC /* Structures */, 62FF516C1C0A430A009BFDFE /* Selectors */, 625A14CB19C7829400AD0C32 /* Supporting Files */, - 625EE4551CBAA41D00F2CC8E /* HTMLKitTestObserver.h */, - 625EE4561CBAA41D00F2CC8E /* HTMLKitTestObserver.m */, - 625EE4591CBB171300F2CC8E /* HTMLKitTestUtil.h */, - 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */, ); path = Tests; sourceTree = ""; diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index c4e067b..5b34213 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -187,6 +187,10 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (BOOL)intersectsNode:(HTMLNode *)node; +/** + Deletes the contents represented by this range from the associated document. + */ +- (void)deleteContents; @end NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 15f30c7..5cc63e2 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -11,6 +11,7 @@ #import "HTMLKitDOMExceptions.h" #import "HTMLDocument+Private.h" #import "HTMLDOMUtils.h" +#import "HTMLNodeTraversal.h" @interface HTMLRange () { @@ -352,4 +353,61 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } + +- (void)deleteContents +{ + if (self.isCollapsed) { + return; + } + + if (_startContainer == _endContainer && [_startContainer isKindOfClass:[HTMLCharacterData class]]) { + [(HTMLCharacterData *)_startContainer deleteDataInRange:NSMakeRange(_startOffset, _endOffset - _startOffset)]; + return; + } + + HTMLNode *commonAncestor = self.commonAncestorContainer; + + NSMutableArray *containedNodes = [NSMutableArray array]; + + HTMLNode *node = FollowingNode(_startContainer, commonAncestor); + while (node) { + if ([self containsNode:node]) { + [containedNodes addObject:node]; + node = FollowingNodeSkippingChildren(node, commonAncestor); + } else { + node = FollowingNode(node, commonAncestor); + } + } + + HTMLNode *newNode = _startContainer; + NSUInteger newOffset = _startOffset; + + if (![_startContainer containsNode:_endContainer]) { + HTMLNode *referenceNode = _startContainer; + while (referenceNode.parentNode) { + if ([referenceNode.parentNode containsNode:_endContainer]) { + newNode = referenceNode.parentNode; + newOffset = referenceNode.index + 1; + break; + } + referenceNode = referenceNode.parentNode; + } + } + + if ([_startContainer isKindOfClass:[HTMLCharacterData class]]) { + [(HTMLCharacterData *)_startContainer deleteDataInRange:NSMakeRange(_startOffset, _startContainer.length - _startOffset)]; + } + + for (HTMLNode *node in containedNodes) { + [node removeFromParentNode]; + } + + if ([_endContainer isKindOfClass:[HTMLCharacterData class]]) { + [(HTMLCharacterData *)_endContainer deleteDataInRange:NSMakeRange(0, _endOffset)]; + } + + [self setStartNode:newNode startOffset:newOffset]; + [self setEndNode:newNode endOffset:newOffset]; +} + @end diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 12834a2..1184c45 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -7,10 +7,14 @@ // #import + #import "HTMLDOM.h" #import "HTMLNode+Private.h" #import "HTMLRange+Private.h" +#define BodyOf(doc) doc.body.innerHTML +#define InnerHTML(str) [HTMLDocument documentWithString:str].body.innerHTML + @interface HTMLRangeTests : XCTestCase { HTMLDocument *_document; @@ -29,6 +33,8 @@ @implementation HTMLRangeTests +#pragma mark - Setup + - (void)setUp { [super setUp]; @@ -78,6 +84,8 @@ [_document.body appendNodes:@[_h1, _p, _div1]]; } +#pragma mark - Tests + - (void)testInitRange { HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; @@ -1082,4 +1090,248 @@ XCTAssertEqual(range.endOffset, 9); } +#pragma mark - Editing + +- (HTMLDocument *)editingDocument +{ + //
+ //
+ //

This is a text

+ //

Hello

+ //
+ //

World

+ //
+ //

Another text

+ //
+ //
+ //
+ // | + // +---------------+---------------+ + // | | | + //

+ // | | | + // +--------+-------+ "World"

+ // | | | + //

+-----+-----+ + // | | | | + // +-------+-------+ "Hello" "Another" + // | | | + // "This " " text" | + // | "Text" + // "is a" + // + // + return [HTMLDocument documentWithString: + @"

" + @"

This is a text

Hello

" + @"

World

" + @"

Another text

" + @"
"]; +} + +- (void)testDeleteContents_SameTextNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#P1"].firstChild; + [range setEndNode:end endOffset:4]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

T is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_SameTextNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNode:node]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 2); +} + +- (void)testDeleteContents_SameTextNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNodeContents:node]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 3); + XCTAssertEqual([document querySelector:@"#P1"].firstChild.nodeType, HTMLNodeText); +} + +- (void)testDeleteContents_DifferentTextNodesOfSingleParent +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:2]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thiext

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_DifferentTextNodesOfDifferentParents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P2"].lastChild; + [range setEndNode:end endOffset:4]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thi

o

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P4"].firstChild; + [range setEndNode:end endOffset:2]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thi

" + @"

other text

" + @"
")); +} + +- (void)testDeleteContents_SameContainerNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"]; + [range setEndNode:end endOffset:2]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_SameContainerNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNode:node]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_SameContainerNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNodeContents:node]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_StartContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P2"].firstChild; + [range setEndNode:end endOffset:2]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

llo

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testDeleteContents_EndContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#D1"]; + [range setEndNode:end endOffset:1]; + [range deleteContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

T

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + @end From e48ccf42cac2b1ba261b3e564c4d4abc8aa060d1 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 09:31:37 +0100 Subject: [PATCH 52/75] Add HTML Node deep clone implementation --- Sources/HTMLNode.m | 15 +++++++++++++++ Sources/include/HTMLNode.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index d188bb0..e1c74c3 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -668,6 +668,21 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin #endif +#pragma mark - Clone + +- (instancetype)cloneNodeDeep:(BOOL)deep +{ + HTMLNode *copy = [self copy]; + + if (deep) { + for (HTMLNode *child in self.childNodes) { + [copy appendNode:[child cloneNodeDeep:YES]]; + } + } + + return copy; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone diff --git a/Sources/include/HTMLNode.h b/Sources/include/HTMLNode.h index 5e94f2e..c9ca332 100644 --- a/Sources/include/HTMLNode.h +++ b/Sources/include/HTMLNode.h @@ -186,6 +186,14 @@ typedef NS_OPTIONS(unsigned short, HTMLDocumentPosition) */ - (BOOL)isEmpty; +/** + Clones this node. + + @param deep If `YES` then also clones child nodes. Otherwise a shallow clone is returned, which behaves the same as `copy`. + @return A clone of this node. + */ +- (instancetype)cloneNodeDeep:(BOOL)deep; + /** Returns the child node at a given index. From 395ce5e981402b4f22dccdb2e06bc4c70803699a Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 09:32:15 +0100 Subject: [PATCH 53/75] Add HTML Range initializer that accepts start and end boundaries --- Sources/HTMLRange.h | 14 ++++++++++++++ Sources/HTMLRange.m | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 5b34213..8e0fc95 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -82,6 +82,20 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (instancetype)initWithDowcument:(HTMLDocument *)document; +/** + Initializes a new range instance for the given document and boundaries. + + @param document The HTML doucment for which the range will be constructed. + @param startContainer The node for the start boundary + @param startOffset The offset of the start boundary + @param endContainer The node for the end boundary + @param endOffset The offset of the end boundary + @return A new HTML Range instance. + */ +- (instancetype)initWithDowcument:(HTMLDocument *)document + startContainer:(HTMLNode *)startContainer startOffset:(NSUInteger)startOffset + endContainer:(HTMLNode *)endContainer endOffset:(NSUInteger)endOffset; + /** Sets the start boundary. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 5cc63e2..d60a56d 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -24,13 +24,20 @@ #pragma mark - Lifecycle - (instancetype)initWithDowcument:(HTMLDocument *)document +{ + return [self initWithDowcument:document startContainer:document startOffset:0 endContainer:document endOffset:0]; +} + +- (instancetype)initWithDowcument:(HTMLDocument *)document + startContainer:(HTMLNode *)startContainer startOffset:(NSUInteger)startOffset + endContainer:(HTMLNode *)endContainer endOffset:(NSUInteger)endOffset { self = [super init]; if (self) { _ownerDocument = document; [_ownerDocument attachRange:self]; - [self setStartNode:document startOffset:0]; - [self setEndNode:document endOffset:0]; + [self setStartNode:startContainer startOffset:startOffset]; + [self setEndNode:endContainer endOffset:endOffset]; } return self; } From 51c94d49bdca309ac818f1dbc7ad35c7a83f543a Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 09:33:15 +0100 Subject: [PATCH 54/75] =?UTF-8?q?Add=20implementation=20for=20HTML=20Range?= =?UTF-8?q?=E2=80=99s=20clone=20contents=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.h | 9 +++ Sources/HTMLRange.m | 90 ++++++++++++++++++++++- Tests/HTMLRangeTests.m | 159 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 3 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 8e0fc95..8def393 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -7,6 +7,7 @@ // #import "HTMLNode.h" +#import "HTMLDocumentFragment.h" NS_ASSUME_NONNULL_BEGIN @@ -205,6 +206,14 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) Deletes the contents represented by this range from the associated document. */ - (void)deleteContents; + +/** + Clones the contents represented by this range in the associated document. + + @return A document fragment with the cloned contents. + */ +- (HTMLDocumentFragment *)cloneContents; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index d60a56d..aba478e 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -292,10 +292,8 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s return [GetAncestorNodes(_startContainer) containsObject:node] || [GetAncestorNodes(_endContainer) containsObject:node]; } -- (NSArray *)containedNodes +- (NSArray *)containedNodes:(HTMLNode *)commonAncestor { - HTMLNode *commonAncestor = self.commonAncestorContainer; - NSMutableArray *containedNodes = [NSMutableArray array]; [commonAncestor.childNodes enumerateObjectsUsingBlock:^(HTMLNode * _Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) { if (node.nodeType == HTMLNodeDocumentType) { @@ -360,6 +358,19 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } +#pragma mark - Mutations + +NS_INLINE HTMLNode * GetHighestPartiallyContainedChild(HTMLNode *node, HTMLNode *root) +{ + if (node == root) { + return nil; + } + + while (node.parentNode != root) { + node = node.parentNode; + } + return node; +} - (void)deleteContents { @@ -417,4 +428,77 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s [self setEndNode:newNode endOffset:newOffset]; } +- (HTMLDocumentFragment *)extractContents +{ + return nil; +} + +NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger start, NSUInteger length) +{ + HTMLCharacterData *clone = (HTMLCharacterData *)[node cloneNodeDeep:NO]; + [clone setData:[clone.data substringWithRange:NSMakeRange(start, length)]]; + return clone; +} + +- (HTMLDocumentFragment *)cloneContents +{ + HTMLDocumentFragment *fragment = [[HTMLDocumentFragment alloc] initWithDocument:_ownerDocument]; + + // Nothing todo + if (self.isCollapsed) { + return fragment; + } + + // Same character data container, handle that and return + if (_startContainer == _endContainer && [_startContainer isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _endOffset - _startOffset); + [fragment appendNode:clone]; + return fragment; + } + + HTMLNode *commonAncestor = self.commonAncestorContainer; + HTMLNode *firstPartiallyContainedChild = GetHighestPartiallyContainedChild(_startContainer, commonAncestor); + HTMLNode *lastPartiallyContainedChild = GetHighestPartiallyContainedChild(_endContainer, commonAncestor); + NSArray *containedNodes = [self containedNodes:commonAncestor]; + + if ([firstPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _startContainer.length - _startOffset); + [fragment appendNode:clone]; + } else if (firstPartiallyContainedChild != nil) { + HTMLNode *clone = [firstPartiallyContainedChild copy]; + [fragment appendNode:clone]; + + HTMLRange *subRange = [[HTMLRange alloc] initWithDowcument:_ownerDocument + startContainer:_startContainer + startOffset:_startOffset + endContainer:firstPartiallyContainedChild + endOffset:firstPartiallyContainedChild.length]; + HTMLDocumentFragment *subFragment = [subRange cloneContents]; + [clone appendNode:subFragment]; + } + + for (HTMLNode *node in containedNodes) { + HTMLNode *clone = [node cloneNodeDeep:YES]; + [fragment appendNode:clone]; + } + + if ([lastPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_endContainer, 0, _endOffset); + [fragment appendNode:clone]; + } else if (lastPartiallyContainedChild != nil) { + HTMLNode *clone = [lastPartiallyContainedChild copy]; + [fragment appendNode:clone]; + + HTMLRange *subRange = [[HTMLRange alloc] initWithDowcument:_ownerDocument + startContainer:lastPartiallyContainedChild + startOffset:0 + endContainer:_endContainer + endOffset:_endOffset]; + HTMLDocumentFragment *subFragment = [subRange cloneContents]; + [clone appendNode:subFragment]; + } + + return fragment; +} + @end diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 1184c45..c8de9b1 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -14,6 +14,7 @@ #define BodyOf(doc) doc.body.innerHTML #define InnerHTML(str) [HTMLDocument documentWithString:str].body.innerHTML +#define DoubleQuote(str) [str stringByReplacingOccurrencesOfString:@"'" withString:@"\""] @interface HTMLRangeTests : XCTestCase { @@ -1129,6 +1130,8 @@ @"
"]; } +#pragma mark - Delete Contents + - (void)testDeleteContents_SameTextNode { HTMLDocument *document = self.editingDocument; @@ -1334,4 +1337,160 @@ @"
")); } +#pragma mark - Clone Contents + +- (void)testCloneContents_SameTextNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#P1"].firstChild; + [range setEndNode:end endOffset:4]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, @"his"); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testCloneContents_SameTextNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNode:node]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, @"This "); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testCloneContents_SameTextNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNodeContents:node]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, @"This "); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testCloneContents_DifferentTextNodesOfSingleParent +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, @"s is a t"); +} + +- (void)testCloneContents_DifferentTextNodesOfDifferentParents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P2"].lastChild; + [range setEndNode:end endOffset:4]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

s is a text

Hell

")); +} + +- (void)testCloneContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P4"].firstChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

s is a text

Hello

" + @"

World

" + @"

An

")); +} + +- (void)testCloneContents_SameContainerNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"]; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, @"This is a"); +} + +- (void)testCloneContents_SameContainerNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNode:node]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

This is a text

")); +} + +- (void)testCloneContents_SameContainerNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNodeContents:node]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text")); +} + +- (void)testCloneContents_StartContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P2"].firstChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

This is a text

He

")); +} + +- (void)testCloneContents_EndContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#D1"]; + [range setEndNode:end endOffset:1]; + HTMLDocumentFragment *fragment = [range cloneContents]; + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

his is a text

")); +} + @end From f1b1f523b8a9d8b42b1abe5d49dce1064ab81471 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 09:44:03 +0100 Subject: [PATCH 55/75] =?UTF-8?q?Add=20implementation=20for=20HTML=20Range?= =?UTF-8?q?=E2=80=99s=20extract=20contents=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/HTMLRange.h | 7 ++ Sources/HTMLRange.m | 100 +++++++++++++++-- Tests/HTMLRangeTests.m | 237 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 334 insertions(+), 10 deletions(-) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 8def393..eebbec8 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -207,6 +207,13 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (void)deleteContents; +/** + Extracts the contents represented by this range from the associated document. + + @return A document fragment with the extracted contents. + */ +- (HTMLDocumentFragment *)extractContents; + /** Clones the contents represented by this range in the associated document. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index aba478e..76b18d2 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -372,6 +372,19 @@ NS_INLINE HTMLNode * GetHighestPartiallyContainedChild(HTMLNode *node, HTMLNode return node; } +NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger start, NSUInteger length, BOOL delete) +{ + HTMLCharacterData *clone = (HTMLCharacterData *)[node cloneNodeDeep:NO]; + NSRange range = NSMakeRange(start, length); + [clone setData:[clone.data substringWithRange:range]]; + + if (delete) { + [(HTMLCharacterData *)node deleteDataInRange:range]; + } + + return clone; +} + - (void)deleteContents { if (self.isCollapsed) { @@ -430,14 +443,81 @@ NS_INLINE HTMLNode * GetHighestPartiallyContainedChild(HTMLNode *node, HTMLNode - (HTMLDocumentFragment *)extractContents { - return nil; -} + HTMLDocumentFragment *fragment = [[HTMLDocumentFragment alloc] initWithDocument:_ownerDocument]; -NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger start, NSUInteger length) -{ - HTMLCharacterData *clone = (HTMLCharacterData *)[node cloneNodeDeep:NO]; - [clone setData:[clone.data substringWithRange:NSMakeRange(start, length)]]; - return clone; + // Nothing todo + if (self.isCollapsed) { + return fragment; + } + + // Same character data container, handle that and return + if (_startContainer == _endContainer && [_startContainer isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _endOffset - _startOffset, YES); + [fragment appendNode:clone]; + + return fragment; + } + + HTMLNode *commonAncestor = self.commonAncestorContainer; + HTMLNode *firstPartiallyContainedChild = GetHighestPartiallyContainedChild(_startContainer, commonAncestor); + HTMLNode *lastPartiallyContainedChild = GetHighestPartiallyContainedChild(_endContainer, commonAncestor); + NSArray *containedNodes = [self containedNodes:commonAncestor]; + + HTMLNode *newNode = _startContainer; + NSUInteger newOffset = _startOffset; + + if (![_startContainer containsNode:_endContainer]) { + HTMLNode *referenceNode = _startContainer; + while (referenceNode.parentNode) { + if ([referenceNode.parentNode containsNode:_endContainer]) { + newNode = referenceNode.parentNode; + newOffset = referenceNode.index + 1; + break; + } + referenceNode = referenceNode.parentNode; + } + } + + if ([firstPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _startContainer.length - _startOffset, YES); + [fragment appendNode:clone]; + } else if (firstPartiallyContainedChild != nil) { + HTMLNode *clone = [firstPartiallyContainedChild copy]; + [fragment appendNode:clone]; + + HTMLRange *subRange = [[HTMLRange alloc] initWithDowcument:_ownerDocument + startContainer:_startContainer + startOffset:_startOffset + endContainer:firstPartiallyContainedChild + endOffset:firstPartiallyContainedChild.length]; + HTMLDocumentFragment *subFragment = [subRange extractContents]; + [clone appendNode:subFragment]; + } + + for (HTMLNode *node in containedNodes) { + [fragment appendNode:node]; + } + + if ([lastPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { + HTMLCharacterData *clone = CloneCharachterData(_endContainer, 0, _endOffset, YES); + [fragment appendNode:clone]; + } else if (lastPartiallyContainedChild != nil) { + HTMLNode *clone = [lastPartiallyContainedChild copy]; + [fragment appendNode:clone]; + + HTMLRange *subRange = [[HTMLRange alloc] initWithDowcument:_ownerDocument + startContainer:lastPartiallyContainedChild + startOffset:0 + endContainer:_endContainer + endOffset:_endOffset]; + HTMLDocumentFragment *subFragment = [subRange extractContents]; + [clone appendNode:subFragment]; + } + + [self setStartNode:newNode startOffset:newOffset]; + [self setEndNode:newNode endOffset:newOffset]; + + return fragment; } - (HTMLDocumentFragment *)cloneContents @@ -451,7 +531,7 @@ NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger sta // Same character data container, handle that and return if (_startContainer == _endContainer && [_startContainer isKindOfClass:[HTMLCharacterData class]]) { - HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _endOffset - _startOffset); + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _endOffset - _startOffset, NO); [fragment appendNode:clone]; return fragment; } @@ -462,7 +542,7 @@ NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger sta NSArray *containedNodes = [self containedNodes:commonAncestor]; if ([firstPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { - HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _startContainer.length - _startOffset); + HTMLCharacterData *clone = CloneCharachterData(_startContainer, _startOffset, _startContainer.length - _startOffset, NO); [fragment appendNode:clone]; } else if (firstPartiallyContainedChild != nil) { HTMLNode *clone = [firstPartiallyContainedChild copy]; @@ -483,7 +563,7 @@ NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger sta } if ([lastPartiallyContainedChild isKindOfClass:[HTMLCharacterData class]]) { - HTMLCharacterData *clone = CloneCharachterData(_endContainer, 0, _endOffset); + HTMLCharacterData *clone = CloneCharachterData(_endContainer, 0, _endOffset, NO); [fragment appendNode:clone]; } else if (lastPartiallyContainedChild != nil) { HTMLNode *clone = [lastPartiallyContainedChild copy]; diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index c8de9b1..d47278f 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -1493,4 +1493,241 @@ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

his is a text

")); } +#pragma mark - Extract Contents + +- (void)testExtractContents_SameTextNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#P1"].firstChild; + [range setEndNode:end endOffset:4]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

T is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, @"his"); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testExtractContents_SameTextNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNode:node]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 2); + + XCTAssertEqualObjects(fragment.innerHTML, @"This "); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testExtractContents_SameTextNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"].firstChild; + [range selectNodeContents:node]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 3); + XCTAssertEqual([document querySelector:@"#P1"].firstChild.nodeType, HTMLNodeText); + + XCTAssertEqualObjects(fragment.innerHTML, @"This "); + XCTAssertEqual(fragment.childNodesCount, 1); + XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText); +} + +- (void)testExtractContents_DifferentTextNodesOfSingleParent +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thiext

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, @"s is a t"); +} + +- (void)testExtractContents_DifferentTextNodesOfDifferentParents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P2"].lastChild; + [range setEndNode:end endOffset:4]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thi

o

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

s is a text

Hell

")); +} + +- (void)testExtractContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:3]; + HTMLNode *end = [document querySelector:@"#P4"].firstChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Thi

" + @"

other text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

s is a text

Hello

" + @"

World

" + @"

An

")); +} + +- (void)testExtractContents_SameContainerNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"]; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

text

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, @"This is a"); +} + +- (void)testExtractContents_SameContainerNode_Selected +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNode:node]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

This is a text

")); +} + +- (void)testExtractContents_SameContainerNode_SelectedContents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *node = [document querySelector:@"#P1"]; + [range selectNodeContents:node]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text")); +} + +- (void)testExtractContents_StartContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P2"].firstChild; + [range setEndNode:end endOffset:2]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

llo

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

This is a text

He

")); +} + +- (void)testExtractContents_EndContainerIsCommonRoot +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#D1"]; + [range setEndNode:end endOffset:1]; + HTMLDocumentFragment *fragment = [range extractContents]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

T

Hello

" + @"

World

" + @"

Another text

" + @"
")); + + XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

his is a text

")); +} + @end From c7edbd3e1404c68de7e1952ddd3e54f2b8b82f0c Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 22:35:53 +0100 Subject: [PATCH 56/75] Add HTML Document and Range methods for Text splitting callbacks --- Sources/HTMLDocument+Private.h | 34 ++++++++++++++++++++++++++++++++++ Sources/HTMLDocument.m | 15 +++++++++++++++ Sources/HTMLRange+Private.h | 18 ++++++++++++++++++ Sources/HTMLRange.m | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) diff --git a/Sources/HTMLDocument+Private.h b/Sources/HTMLDocument+Private.h index d14c723..7678b9f 100644 --- a/Sources/HTMLDocument+Private.h +++ b/Sources/HTMLDocument+Private.h @@ -11,6 +11,7 @@ #import "HTMLCharacterData.h" #import "HTMLNodeIterator.h" #import "HTMLRange.h" +#import "HTMLText.h" /** Private HTML Document methods which are not intended for public API. @@ -59,7 +60,40 @@ */ - (void)detachRange:(HTMLRange *)range; +/** + Callback on removing text from a CharacterData node. + + @param node The CharacterData node. + @param offset The offset at which the data was removed. + @param length The length of the data that was removed. + */ - (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; + +/** + Callback on adding text from a CharacterData node. + + @param node The CharacterData node. + @param offset The offset at which the data was added. + @param length The length of the data that was added. + */ - (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; +/** + Callback on inserting a new text node when an old text node is split. + + @param newNode The new text node after splitting. + @param parent The parent where newNode was inserted. + @param node The old text node that was split. + @param offset The offset of splitting. + */ +- (void)didInsertNewTextNode:(HTMLText *)newNode intoParent:(HTMLNode *)parent afterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset; + +/** + Callback for clamping current ranges whose end boundary is after the text node upon splitting it. + + @param node The text node that was split. + @param offset The offset of splitting + */ +- (void)clampRangesAfterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset; + @end diff --git a/Sources/HTMLDocument.m b/Sources/HTMLDocument.m index bc544bd..0d34a78 100644 --- a/Sources/HTMLDocument.m +++ b/Sources/HTMLDocument.m @@ -11,6 +11,7 @@ #import "HTMLNodeIterator.h" #import "HTMLRange.h" #import "HTMLCharacterData.h" +#import "HTMLText.h" #import "HTMLKitDOMExceptions.h" #import "HTMLNode+Private.h" #import "HTMLNodeIterator+Private.h" @@ -169,6 +170,20 @@ } } +- (void)didInsertNewTextNode:(HTMLText *)newNode intoParent:(HTMLNode *)parent afterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset +{ + for (HTMLRange *range in _ranges) { + [range didInsertNewTextNode:newNode intoParent:parent afterSplittingTextNode:node atOffset:offset]; + } +} + +- (void)clampRangesAfterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset +{ + for (HTMLRange *range in _ranges) { + [range clampRangesAfterSplittingTextNode:node atOffset:offset]; + } +} + #pragma mark - Mutation Callback - (void)runRemovingStepsForNode:(HTMLNode *)oldNode diff --git a/Sources/HTMLRange+Private.h b/Sources/HTMLRange+Private.h index 57f83c4..e745578 100644 --- a/Sources/HTMLRange+Private.h +++ b/Sources/HTMLRange+Private.h @@ -29,6 +29,24 @@ */ - (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length; +/** + Runs the necessary steps after inserting a new text node when an old text node is split. + + @param newNode The new text node after splitting. + @param parent The parent where newNode was inserted. + @param node The old text node that was split. + @param offset The offset of splitting. + */ +- (void)didInsertNewTextNode:(HTMLText *)newNode intoParent:(HTMLNode *)parent afterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset; + +/** + Runs the necessary steps to clamp the range whose end boundary is after the text node upon splitting it. + + @param node The text node that was split. + @param offset The offset of splitting + */ +- (void)clampRangesAfterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset; + /** Runs the necessary steps after removing a node from the DOM. diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 76b18d2..0b5a922 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -337,6 +337,38 @@ NS_INLINE NSComparisonResult CompareBoundaries(HTMLNode *startNode, NSUInteger s } } +- (void)didInsertNewTextNode:(HTMLText *)newNode intoParent:(HTMLNode *)parent afterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset +{ + if (_startContainer == node && _startOffset > offset) { + _startContainer = newNode; + _startOffset -= offset; + } + + if (_endContainer == node && _endOffset > offset) { + _endContainer = newNode; + _endOffset -= offset; + } + + if (_startContainer == parent && _startOffset == node.index + 1) { + _startOffset += 1; + } + + if (_endContainer == parent && _endOffset == node.index + 1) { + _endOffset += 1; + } +} + +- (void)clampRangesAfterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset +{ + if (_startContainer == node && _startOffset > offset) { + _startOffset = offset; + } + + if (_endContainer == node && _endOffset > offset) { + _endOffset = offset; + } +} + - (void)runRemovingStepsForNode:(HTMLNode *)oldNode withOldParent:(HTMLNode *)oldParent andOldPreviousSibling:(HTMLNode *)oldPreviousSibling { NSUInteger oldIndex = oldPreviousSibling.index + 1; From fe46b106b204e588a58bd292a8cda06a205f2cae Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 22:36:47 +0100 Subject: [PATCH 57/75] Add implementation for HTML Text splitting --- Sources/HTMLText.m | 38 ++++++++++++++++++++++++++++++++++++++ Sources/include/HTMLText.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/Sources/HTMLText.m b/Sources/HTMLText.m index 24e2728..605a924 100644 --- a/Sources/HTMLText.m +++ b/Sources/HTMLText.m @@ -10,6 +10,8 @@ #import "HTMLElement.h" #import "NSString+HTMLKit.h" #import "HTMLCharacterData+Private.h" +#import "HTMLKitDOMExceptions.h" +#import "HTMLDocument+Private.h" @implementation HTMLText @@ -28,6 +30,42 @@ [self appendData:string]; } +NS_INLINE void CheckValidOffset(HTMLNode *node, NSUInteger offset, NSString *cmd) +{ + if (offset > node.length) { + [NSException raise:HTMLKitIndexSizeError + format:@"%@: Index Size Error, invalid offset %lu for splitting text node %@.", + cmd, (unsigned long)offset, node]; + } +} + +- (HTMLNode *)splitTextAtOffset:(NSUInteger)offset +{ + CheckValidOffset(self, offset, NSStringFromSelector(_cmd)); + + NSUInteger length = self.length; + NSUInteger count = length - offset; + NSRange range = NSMakeRange(offset, count); + + NSString *newData = [self.data substringWithRange:range]; + HTMLText *newNode = [[HTMLText alloc] initWithData:newData]; + [self.ownerDocument adoptNode:newNode]; + + HTMLNode *parent = self.parentNode; + if (parent != nil) { + [parent insertNode:newNode beforeChildNode:self.nextSibling]; + [self.ownerDocument didInsertNewTextNode:newNode intoParent:parent afterSplittingTextNode:self atOffset:offset]; + } + + [self deleteDataInRange:range]; + + if (parent != nil) { + [self.ownerDocument clampRangesAfterSplittingTextNode:self atOffset:offset]; + } + + return newNode; +} + #pragma mark - Serialization - (NSString *)outerHTML diff --git a/Sources/include/HTMLText.h b/Sources/include/HTMLText.h index 8578c55..872550d 100644 --- a/Sources/include/HTMLText.h +++ b/Sources/include/HTMLText.h @@ -30,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)appendString:(NSString *)string __attribute__((deprecated("Use `appendData:` instead."))); +- (HTMLNode *)splitTextAtOffset:(NSUInteger)offset; + @end NS_ASSUME_NONNULL_END From 925848404bdefaae430738dc68a50a1f54111688 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 8 Jan 2017 22:38:41 +0100 Subject: [PATCH 58/75] Add implementation for HTML Range surround and insert node --- Sources/HTMLKitDOMExceptions.m | 1 + Sources/HTMLRange.h | 19 +++++ Sources/HTMLRange.m | 97 ++++++++++++++++++++++++++ Sources/include/HTMLKitDOMExceptions.h | 1 + 4 files changed, 118 insertions(+) diff --git a/Sources/HTMLKitDOMExceptions.m b/Sources/HTMLKitDOMExceptions.m index 5ea8311..d568734 100644 --- a/Sources/HTMLKitDOMExceptions.m +++ b/Sources/HTMLKitDOMExceptions.m @@ -17,3 +17,4 @@ NSString * const HTMLKitInvalidCharacterError = @"InvalidCharacterError"; NSString * const HTMLKitInvalidNodeTypeError = @"InvalidNodeTypeError"; NSString * const HTMLKitIndexSizeError = @"IndexSizeError"; NSString * const HTMLKitWrongDocumentError = @"WrongDocumentError"; +NSString * const HTMLKitInvalidStateError = @"InvalidStateError"; diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index eebbec8..44e90ec 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -221,6 +221,25 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (HTMLDocumentFragment *)cloneContents; +/** + Inserts the given node at the start of this range. + + If the node is being added to a text node, then the text node is split at the insertion point and the given node + is inserted between the resulting text nodes. + + @param node The node to insert. + */ +- (void)insertNode:(HTMLNode *)node; + +/** + Surrounds the contents of this range with the given node. + + The range's boundaries will placed around the given node, i.e. start is before and end is after newParent. + + @param newParent The new parent node which will surround the range. + */ +- (void)surroundContents:(HTMLNode *)newParent; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 0b5a922..b1cf9b7 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -613,4 +613,101 @@ NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger sta return fragment; } +#pragma mark - Insertion & Surround + +NS_INLINE void CheckValidInsertionNode(HTMLNode *startContainer, HTMLNode *node, NSString *cmd) +{ + if (startContainer == node || startContainer.nodeType == HTMLNodeComment || + (startContainer.nodeType == HTMLNodeText && startContainer.parentNode == nil)) { + [NSException raise:HTMLKitHierarchyRequestError + format:@"%@: Hierarchy Request Error, cannot insert node into range: %@", cmd, node]; + } +} + +- (void)insertNode:(HTMLNode *)node +{ + CheckValidInsertionNode(_startContainer, node, NSStringFromSelector(_cmd)); + + HTMLNode *referenceNode = nil; + + if (_startContainer.nodeType == HTMLNodeText) { + referenceNode = _startContainer; + } else { + referenceNode = [_startContainer childNodeAtIndex:_startOffset]; + } + + HTMLNode *parent = _startContainer; + if (referenceNode != nil) { + parent = referenceNode.parentNode; + } + + if (_startContainer.nodeType == HTMLNodeText) { + referenceNode = [(HTMLText *)_startContainer splitTextAtOffset:_startOffset]; + } + + if (node == referenceNode) { + referenceNode = referenceNode.nextSibling; + } + + [node removeFromParentNode]; + + NSUInteger newOffset = referenceNode ? referenceNode.index : parent.length; + newOffset += (node.nodeType == HTMLNodeDocumentFragment) ? node.length : 1; + + [parent insertNode:node beforeChildNode:referenceNode]; + + if (self.isCollapsed) { + [self setEndNode:parent endOffset:newOffset]; + } +} + +NS_INLINE void CheckValidSurroundState(HTMLRange *range, NSString *cmd) +{ + for (HTMLNode *node in GetAncestorNodes(range.startContainer)) { + if ([node containsNode:range.endContainer]) { + return; + } + + if (node.nodeType != HTMLNodeText) { + [NSException raise:HTMLKitInvalidStateError + format:@"%@: Invalid State Error, cannot surround range with a partially-contaied non-text node.", cmd]; + } + }; + + for (HTMLNode *node in GetAncestorNodes(range.endContainer)) { + if ([node containsNode:range.startContainer]) { + return; + } + + if (node.nodeType != HTMLNodeText) { + [NSException raise:HTMLKitInvalidNodeTypeError + format:@"%@: Invalid State Error, cannot surround range with a partially-contaied non-text node.", cmd]; + } + }; +} + +NS_INLINE void CheckValidSurroundNodeType(HTMLNode *node, NSString *cmd) +{ + if (node == nil || node.nodeType == HTMLNodeDocumentType || node.nodeType == HTMLNodeDocument || + node.nodeType == HTMLNodeDocumentFragment) { + [NSException raise:HTMLKitInvalidNodeTypeError + format:@"%@: Invalid Node Type Error, %@ is not a valid new parent for a range.", + cmd, node]; + } +} + +- (void)surroundContents:(HTMLNode *)newParent +{ + CheckValidSurroundState(self, NSStringFromSelector(_cmd)); + + CheckValidSurroundNodeType(newParent, NSStringFromSelector(_cmd)); + + HTMLDocumentFragment *fragment = [self extractContents]; + [newParent removeAllChildNodes]; + + [self insertNode:newParent]; + [newParent appendNode:fragment]; + [self selectNode:newParent]; +} + @end diff --git a/Sources/include/HTMLKitDOMExceptions.h b/Sources/include/HTMLKitDOMExceptions.h index 5b13fae..4e357cc 100644 --- a/Sources/include/HTMLKitDOMExceptions.h +++ b/Sources/include/HTMLKitDOMExceptions.h @@ -18,3 +18,4 @@ extern NSString * const HTMLKitInvalidCharacterError; extern NSString * const HTMLKitInvalidNodeTypeError; extern NSString * const HTMLKitIndexSizeError; extern NSString * const HTMLKitWrongDocumentError; +extern NSString * const HTMLKitInvalidStateError; From 1e5517f4035085e3f71688483ff97151a1d7826d Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 10 Jan 2017 17:55:26 +0100 Subject: [PATCH 59/75] Fix return type of split-text method in HTML Text --- Sources/HTMLText.m | 2 +- Sources/include/HTMLText.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/HTMLText.m b/Sources/HTMLText.m index 605a924..76e94d3 100644 --- a/Sources/HTMLText.m +++ b/Sources/HTMLText.m @@ -39,7 +39,7 @@ NS_INLINE void CheckValidOffset(HTMLNode *node, NSUInteger offset, NSString *cmd } } -- (HTMLNode *)splitTextAtOffset:(NSUInteger)offset +- (HTMLText *)splitTextAtOffset:(NSUInteger)offset { CheckValidOffset(self, offset, NSStringFromSelector(_cmd)); diff --git a/Sources/include/HTMLText.h b/Sources/include/HTMLText.h index 872550d..4e8c6d6 100644 --- a/Sources/include/HTMLText.h +++ b/Sources/include/HTMLText.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)appendString:(NSString *)string __attribute__((deprecated("Use `appendData:` instead."))); -- (HTMLNode *)splitTextAtOffset:(NSUInteger)offset; +- (HTMLText *)splitTextAtOffset:(NSUInteger)offset; @end From bc94f91c6ec7a2a8bc41a1900e6e99011f54783b Mon Sep 17 00:00:00 2001 From: iska Date: Tue, 10 Jan 2017 17:55:39 +0100 Subject: [PATCH 60/75] Add HTML Character Data & Text tests --- HTMLKit.xcodeproj/project.pbxproj | 8 +++ Tests/HTMLCharacterDataTests.m | 100 ++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 Tests/HTMLCharacterDataTests.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 4439f3b..f1bfc2c 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -317,6 +317,9 @@ 62D91C281DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62D91C291DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; 62D91C2A1DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; }; + 62E0BA971E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; }; + 62E0BA981E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; }; + 62E0BA991E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; }; 62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; 62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; 62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; }; @@ -718,6 +721,7 @@ 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTokenizerTest.m; sourceTree = ""; }; 62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLRange.h; sourceTree = ""; }; 62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = ""; }; + 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterDataTests.m; sourceTree = ""; }; 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = ""; }; 62EC0A841E158BD80007786B /* HTMLRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRangeTests.m; sourceTree = ""; }; 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLMutationAlgorithmsTests.m; sourceTree = ""; }; @@ -881,6 +885,7 @@ 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */, 62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */, 62EC0A841E158BD80007786B /* HTMLRangeTests.m */, + 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */, ); name = DOM; sourceTree = ""; @@ -1742,6 +1747,7 @@ buildActionMask = 2147483647; files = ( 62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */, + 62E0BA971E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */, 6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */, 62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */, 6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, @@ -1883,6 +1889,7 @@ buildActionMask = 2147483647; files = ( 62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */, + 62E0BA991E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */, 62857D3B1D39A345008DC254 /* CSSSelectorTest.m in Sources */, 62857D421D39A345008DC254 /* CSSCombinatorSelectorTests.m in Sources */, 62857D3C1D39A345008DC254 /* CSSSelectorParserTests.m in Sources */, @@ -1969,6 +1976,7 @@ buildActionMask = 2147483647; files = ( 62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */, + 62E0BA981E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */, 6216ACFE1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */, 62ECBFCA1C0B6E2E00AF847B /* HTML5LibTokenizerTest.m in Sources */, 62ECBFCB1C0B6E2E00AF847B /* HTMLKitTokenizerTests.m in Sources */, diff --git a/Tests/HTMLCharacterDataTests.m b/Tests/HTMLCharacterDataTests.m new file mode 100644 index 0000000..9d66891 --- /dev/null +++ b/Tests/HTMLCharacterDataTests.m @@ -0,0 +1,100 @@ +// +// HTMLCharacterDataTests.m +// HTMLKit +// +// Created by Iska on 10/01/17. +// Copyright © 2017 BrainCookie. All rights reserved. +// + +#import +#import "HTMLElement.h" +#import "HTMLCharacterData.h" +#import "HTMLText.h" + +@interface HTMLCharacterDataTests : XCTestCase + +@end + +@implementation HTMLCharacterDataTests + +- (void)testSetData +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + + [text setData:@"New text"]; + XCTAssertEqualObjects(text.data, @"New text"); +} + +- (void)testAppendData +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + + [text appendData:@"New text"]; + XCTAssertEqualObjects(text.data, @"This is a textNew text"); +} + +- (void)testReplaceData +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + + [text replaceDataInRange:NSMakeRange(0, 5) withData:@"New text "]; + XCTAssertEqualObjects(text.data, @"New text is a text"); + + [text replaceDataInRange:NSMakeRange(4, 4) withData:@"data"]; + XCTAssertEqualObjects(text.data, @"New data is a text"); +} + +- (void)testDeleteData +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + + [text deleteDataInRange:NSMakeRange(5, 3)]; + XCTAssertEqualObjects(text.data, @"This a text"); + + [text deleteDataInRange:NSMakeRange(0, text.data.length)]; + XCTAssertEqualObjects(text.data, @""); +} + +- (void)testInsertData +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + + [text insertData:@"New " atOffset:10]; + XCTAssertEqualObjects(text.data, @"This is a New text"); + + [text insertData:@"Prefix " atOffset:0]; + XCTAssertEqualObjects(text.data, @"Prefix This is a New text"); +} + +- (void)testSplitText_Invalid +{ + HTMLText *text = [[HTMLText alloc] initWithData:@"text"]; + XCTAssertThrows([text splitTextAtOffset:5]); +} + +- (void)testSplitText +{ + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"]; + [div appendNode:text]; + + HTMLText *newText = [text splitTextAtOffset:7]; + XCTAssertEqualObjects(newText.data, @" a text"); + + XCTAssertEqual(div.childNodesCount, 2); + XCTAssertEqualObjects(div.firstChild.textContent, @"This is"); + XCTAssertEqualObjects(div.lastChild.textContent, @" a text"); + + [div appendNode:[[HTMLElement alloc] initWithTagName:@"p"]]; + + newText = [newText splitTextAtOffset:0]; + XCTAssertEqualObjects(newText.data, @" a text"); + + XCTAssertEqual(div.childNodesCount, 4); + XCTAssertEqualObjects([div childNodeAtIndex:0].textContent, @"This is"); + XCTAssertEqualObjects([div childNodeAtIndex:1].textContent, @""); + XCTAssertEqualObjects([div childNodeAtIndex:2].textContent, @" a text"); + XCTAssertEqual([div childNodeAtIndex:3].nodeType, HTMLNodeElement); +} + +@end From f53ce3464d786a05a1cf2a9216da4cac879f4b8b Mon Sep 17 00:00:00 2001 From: iska Date: Wed, 11 Jan 2017 18:29:30 +0100 Subject: [PATCH 61/75] Add HTML Range tests for node surround and insertion --- Tests/HTMLRangeTests.m | 219 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index d47278f..51bfd8a 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -1730,4 +1730,223 @@ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"

his is a text

")); } +#pragma mark - Insertion & Surround + +- (void)testInsertNode_InvalidNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + XCTAssertThrows([range insertNode:start]); + + HTMLComment *comment = [[HTMLComment alloc] initWithData:@"data"]; + [[document querySelector:@"#D1"] appendNode: comment]; + [range setStartNode:comment startOffset:2]; + + XCTAssertThrows([range insertNode:end]); +} + +- (void)testInsertNode_TextNodeStart_Begin +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + [div appendNodes:@[ + [[HTMLText alloc] initWithData:@"TEXT"], + [[HTMLElement alloc] initWithTagName:@"a"]]]; + + [range insertNode:div]; + + XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@"
" + @"

TEXT
This is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testInsertNode_TextNodeStart_Middle +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + [div appendNodes:@[ + [[HTMLText alloc] initWithData:@"TEXT"], + [[HTMLElement alloc] initWithTagName:@"a"]]]; + + [range insertNode:div]; + + XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@"
" + @"

Th

TEXT
is is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testInsertNode_NonTextNodeStart_Begin +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + [div appendNodes:@[ + [[HTMLText alloc] initWithData:@"TEXT"], + [[HTMLElement alloc] initWithTagName:@"a"]]]; + + [range insertNode:div]; + + XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@"
" + @"

TEXT
This is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testInsertNode_NonTextNodeStart_Middle +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + [div appendNodes:@[ + [[HTMLText alloc] initWithData:@"TEXT"], + [[HTMLElement alloc] initWithTagName:@"a"]]]; + + [range insertNode:div]; + + XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@"
" + @"

This is a

TEXT
text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testInsertNode_NonTextNodeStart_DifferentParents +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:1]; + HTMLNode *end = [document querySelector:@"#P3"].firstChild; + [range setEndNode:end endOffset:4]; + + HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"]; + [div appendNodes:@[ + [[HTMLText alloc] initWithData:@"TEXT"], + [[HTMLElement alloc] initWithTagName:@"a"]]]; + + [range insertNode:div]; + + XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@"
" + @"

This is a text

TEXT

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testSurroundContents_InvalidNode +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:5]; + + XCTAssertThrows([range surroundContents:[HTMLDocumentType new]]); + XCTAssertThrows([range surroundContents:[HTMLDocument new]]); + XCTAssertThrows([range surroundContents:[[HTMLDocumentFragment alloc] initWithDocument:document]]); +} + +- (void)testSurroundContents_PartiallySelectedAncestors +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P3"].lastChild; + [range setEndNode:end endOffset:3]; + + HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"]; + XCTAssertThrows([range surroundContents:span]); + + start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#D2"]; + [range setEndNode:end endOffset:1]; + + XCTAssertThrows([range surroundContents:span]); +} + +- (void)testSurroundContents_TextNodes +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:3]; + + HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"]; + [range surroundContents:span]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

This is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + +- (void)testSurroundContents_NonTextNodes +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + HTMLNode *end = [document querySelector:@"#P1"]; + [range setEndNode:end endOffset:2]; + + HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"]; + [range surroundContents:span]; + + XCTAssertEqualObjects(BodyOf(document), InnerHTML( + @"
" + @"

This is a text

Hello

" + @"

World

" + @"

Another text

" + @"
")); +} + @end From a38d1e648437c63774b11c8282b90ed7bd033611 Mon Sep 17 00:00:00 2001 From: iska Date: Wed, 11 Jan 2017 19:17:54 +0100 Subject: [PATCH 62/75] Add HTML CharacterData method for substring data --- Sources/HTMLCharacterData.h | 1 + Sources/HTMLCharacterData.m | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Sources/HTMLCharacterData.h b/Sources/HTMLCharacterData.h index 1273401..302d2c5 100644 --- a/Sources/HTMLCharacterData.h +++ b/Sources/HTMLCharacterData.h @@ -25,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)insertData:(NSString *)data atOffset:(NSUInteger)offset; - (void)deleteDataInRange:(NSRange)range; - (void)replaceDataInRange:(NSRange)range withData:(NSString *)data; +- (NSString *)substringDataWithRange:(NSRange)range; @end diff --git a/Sources/HTMLCharacterData.m b/Sources/HTMLCharacterData.m index 0891f64..68a7e19 100644 --- a/Sources/HTMLCharacterData.m +++ b/Sources/HTMLCharacterData.m @@ -86,6 +86,11 @@ NS_INLINE void CheckValidOffset(HTMLCharacterData *node, NSUInteger offset, NSSt [self.ownerDocument didAddCharacterDataToNode:self atOffset:range.location withLength:data.length]; } +- (NSString *)substringDataWithRange:(NSRange)range +{ + return [_data substringWithRange:range]; +} + #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone From bdaddc093888359dd35330a7d34479629f3469ba Mon Sep 17 00:00:00 2001 From: iska Date: Wed, 11 Jan 2017 22:38:53 +0100 Subject: [PATCH 63/75] Add travis_retry in travis.yml to fix build issues So this happened: https://github.com/travis-ci/travis-ci/issues/6422 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d24de1..313ee3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ script: - xcodebuild -showsdks - SIMULATOR_ID=$(xcrun instruments -s devices | grep -io "$SIMULATOR \[.*\]" | grep -o "\[.*\]" | sed "s/^\[\(.*\)\]$/\1/") - open -b com.apple.iphonesimulator --args -CurrentDeviceUDID $SIMULATOR_ID - - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean build | xcpretty -c + - travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean build | xcpretty -c - if [ "$SDK" != "$WATCHOS_SDK" ]; then - xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c; + travis_retry xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c; fi From 472d59546a8ce145b78ee5ecee9f32685c4d9d20 Mon Sep 17 00:00:00 2001 From: iska Date: Wed, 11 Jan 2017 22:48:51 +0100 Subject: [PATCH 64/75] Add HTML Range stringifier and description https://dom.spec.whatwg.org/#dom-range-stringifier --- Sources/HTMLRange.h | 7 +++++++ Sources/HTMLRange.m | 40 ++++++++++++++++++++++++++++++++++++++ Tests/HTMLRangeTests.m | 44 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/Sources/HTMLRange.h b/Sources/HTMLRange.h index 44e90ec..a35c468 100644 --- a/Sources/HTMLRange.h +++ b/Sources/HTMLRange.h @@ -240,6 +240,13 @@ typedef NS_ENUM(unsigned short, HTMLRangeComparisonMethod) */ - (void)surroundContents:(HTMLNode *)newParent; +/** + The stringifier of the range. + + @return The text contents of the range. + */ +- (NSString *)textContent; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index b1cf9b7..57c2ade 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -710,4 +710,44 @@ NS_INLINE void CheckValidSurroundNodeType(HTMLNode *node, NSString *cmd) [self selectNode:newParent]; } +#pragma mark - Description & Stringifier + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p (%@, %lu), (%@, %lu)>", self.class, self, + _startContainer, (unsigned long)_startOffset, + _endContainer, (unsigned long)_endOffset]; +} + +- (NSString *)textContent +{ + HTMLNode *lastNode = nil; + if ([_endContainer isKindOfClass:[HTMLCharacterData class]]) { + lastNode = FollowingNodeSkippingChildren(_endContainer, _ownerDocument); + } else if (_endContainer.childNodesCount > _endOffset) { + lastNode = [_endContainer childNodeAtIndex:_endOffset]; + } else { + lastNode = FollowingNodeSkippingChildren(_endContainer, _ownerDocument); + } + + NSMutableString *content = [NSMutableString string]; + for (HTMLNode *node = _startContainer; node != lastNode; node = FollowingNode(node, _ownerDocument)) { + if (node.nodeType == HTMLNodeText) { + HTMLText *text = (HTMLText *)node; + + if (node == _startContainer) { + NSString *string = [text substringDataWithRange:NSMakeRange(_startOffset, _startContainer.length - _startOffset)]; + [content appendString:string]; + } else if (node == _endContainer) { + NSString *string = [text substringDataWithRange:NSMakeRange(0, _endOffset)]; + [content appendString:string]; + } else { + [content appendString:text.data]; + } + } + } + + return content; +} + @end diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 51bfd8a..7c657fc 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -1949,4 +1949,48 @@ @"
")); } +#pragma mark - Stringifier + +- (void)testRangeStringifier +{ + HTMLDocument *document = self.editingDocument; + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document]; + + HTMLNode *start = [document querySelector:@"#P1"].firstChild; + [range setStartNode:start startOffset:2]; + HTMLNode *end = [document querySelector:@"#P1"].lastChild; + [range setEndNode:end endOffset:3]; + XCTAssertEqualObjects([range textContent], @"is is a te"); + + start = [document querySelector:@"#P1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#P1"]; + [range setEndNode:end endOffset:2]; + XCTAssertEqualObjects([range textContent], @"This is a"); + + start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#D1"]; + [range setEndNode:end endOffset:1]; + XCTAssertEqualObjects([range textContent], @"This is a text"); + + start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#D1"]; + [range setEndNode:end endOffset:2]; + XCTAssertEqualObjects([range textContent], @"This is a textHello"); + + start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#D2"]; + [range setEndNode:end endOffset:0]; + XCTAssertEqualObjects([range textContent], @"This is a textHelloWorld"); + + start = [document querySelector:@"#D1"]; + [range setStartNode:start startOffset:0]; + end = [document querySelector:@"#D2"]; + [range setEndNode:end endOffset:1]; + XCTAssertEqualObjects([range textContent], @"This is a textHelloWorldAnother text"); +} + @end From 718e43ff9c3e36d97e0bdbbf3382634bac87bd2b Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 13 Jan 2017 18:23:56 +0100 Subject: [PATCH 65/75] Add HTML Range tests for Text split callbacks --- Sources/HTMLRange.m | 2 +- Tests/HTMLRangeTests.m | 105 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/Sources/HTMLRange.m b/Sources/HTMLRange.m index 57c2ade..e2b9454 100644 --- a/Sources/HTMLRange.m +++ b/Sources/HTMLRange.m @@ -406,7 +406,7 @@ NS_INLINE HTMLNode * GetHighestPartiallyContainedChild(HTMLNode *node, HTMLNode NS_INLINE HTMLCharacterData * CloneCharachterData(HTMLNode *node, NSUInteger start, NSUInteger length, BOOL delete) { - HTMLCharacterData *clone = (HTMLCharacterData *)[node cloneNodeDeep:NO]; + HTMLCharacterData *clone = (HTMLCharacterData *)[node copy]; NSRange range = NSMakeRange(start, length); [clone setData:[clone.data substringWithRange:range]]; diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index 7c657fc..bf70ca5 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -1091,6 +1091,111 @@ XCTAssertEqual(range.endOffset, 9); } +- (void)testThatTextSplitUpdateRangeCorrectly_BeforeStartTextNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |________| + [range selectNodeContents:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ^________| + HTMLText *split = [_firstText splitTextAtOffset:0]; + + XCTAssertEqualObjects(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqualObjects(range.endContainer, split); + XCTAssertEqual(range.endOffset, 10); +} + +- (void)testThatTextSplitUpdateRangeCorrectly_AfterEndTextNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |________| + [range selectNodeContents:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |________^ + [_firstText splitTextAtOffset:_firstText.length]; + + XCTAssertEqualObjects(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqualObjects(range.endContainer, _firstText); + XCTAssertEqual(range.endOffset, 10); +} + +- (void)testThatTextSplitUpdateRangeCorrectly_MidleSameTextNode +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |________| + [range selectNodeContents:_firstText]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |____^___| + HTMLText *split = [_firstText splitTextAtOffset:6]; + + XCTAssertEqualObjects(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 0); + XCTAssertEqualObjects(range.endContainer, split); + XCTAssertEqual(range.endOffset, 4); +} + +- (void)testThatTextSplitUpdateRangeCorrectly_MidleDifferentTextNodes +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |______________________________| + [range setStartNode:_firstText startOffset:2]; + [range setEndNode:_secondText endOffset:3]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |____^__________________________| + [_firstText splitTextAtOffset:6]; + + XCTAssertEqualObjects(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 2); + XCTAssertEqualObjects(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); +} + +- (void)testThatTextSplitUpdateRangeCorrectly_BeforeStartDifferentTextNodes +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |______________________________| + [range setStartNode:_firstText startOffset:6]; + [range setEndNode:_secondText endOffset:3]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // ^ |__________________________| + HTMLText *split = [_firstText splitTextAtOffset:2]; + + XCTAssertEqualObjects(range.startContainer, split); + XCTAssertEqual(range.startOffset, 4); + XCTAssertEqualObjects(range.endContainer, _secondText); + XCTAssertEqual(range.endOffset, 3); +} + +- (void)testThatTextSplitUpdateRangeCorrectly_BeforeEndDifferentTextNodes +{ + HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |_______________________________| + [range setStartNode:_firstText startOffset:6]; + [range setEndNode:_secondText endOffset:4]; + + //

Title

Hello

First textSecond text
<--Second comment-->
+ // |_____________________________^_| + HTMLText *split = [_secondText splitTextAtOffset:2]; + + XCTAssertEqualObjects(range.startContainer, _firstText); + XCTAssertEqual(range.startOffset, 6); + XCTAssertEqualObjects(range.endContainer, split); + XCTAssertEqual(range.endOffset, 2); +} + #pragma mark - Editing - (HTMLDocument *)editingDocument From 542bc26ff9b38c8d792093633daf676db3fc615e Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 13 Jan 2017 18:28:29 +0100 Subject: [PATCH 66/75] Use AssertEqualObjects instead of AssertEqual in range tests Better error message on failures. --- Tests/HTMLRangeTests.m | 240 ++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/Tests/HTMLRangeTests.m b/Tests/HTMLRangeTests.m index bf70ca5..48e5fe0 100644 --- a/Tests/HTMLRangeTests.m +++ b/Tests/HTMLRangeTests.m @@ -91,10 +91,10 @@ { HTMLRange *range = [[HTMLRange alloc] initWithDowcument:_document]; - XCTAssertEqual(range.startContainer, _document); + XCTAssertEqualObjects(range.startContainer, _document); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _document); + XCTAssertEqualObjects(range.endContainer, _document); XCTAssertEqual(range.endOffset, 0); } @@ -111,9 +111,9 @@ // collapsed range [range setStartNode:_paragraphText startOffset:4]; - XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqualObjects(range.startContainer, _paragraphText); XCTAssertEqual(range.startOffset, 4); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -121,9 +121,9 @@ // s e [range setStartNode:_title startOffset:2]; - XCTAssertEqual(range.startContainer, _title); + XCTAssertEqualObjects(range.startContainer, _title); XCTAssertEqual(range.startOffset, 2); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); } @@ -139,9 +139,9 @@ // s e [range setEndNode:_title endOffset:4]; - XCTAssertEqual(range.startContainer, _document); + XCTAssertEqualObjects(range.startContainer, _document); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _title); + XCTAssertEqualObjects(range.endContainer, _title); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -149,9 +149,9 @@ // s e [range setStartNode:_title startOffset:3]; - XCTAssertEqual(range.startContainer, _title); + XCTAssertEqualObjects(range.startContainer, _title); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _title); + XCTAssertEqualObjects(range.endContainer, _title); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -159,9 +159,9 @@ // collapsed range [range setEndNode:_title endOffset:0]; - XCTAssertEqual(range.startContainer, _title); + XCTAssertEqualObjects(range.startContainer, _title); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _title); + XCTAssertEqualObjects(range.endContainer, _title); XCTAssertEqual(range.endOffset, 0); } @@ -182,9 +182,9 @@ [range setStartBeforeNode:_paragraphText]; - XCTAssertEqual(range.startContainer, _p); + XCTAssertEqualObjects(range.startContainer, _p); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -200,9 +200,9 @@ [range setStartBeforeNode:_p]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -218,9 +218,9 @@ [range setStartBeforeNode:_h1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -236,9 +236,9 @@ [range setStartBeforeNode:_div2]; - XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqualObjects(range.startContainer, _div1); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 0); //

Title

Hello

First textSecond text
@@ -254,9 +254,9 @@ [range setStartBeforeNode:_div1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 2); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 0); } @@ -277,9 +277,9 @@ [range setStartAfterNode:_paragraphText]; - XCTAssertEqual(range.startContainer, _p); + XCTAssertEqualObjects(range.startContainer, _p); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _p); + XCTAssertEqualObjects(range.endContainer, _p); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -295,9 +295,9 @@ [range setStartAfterNode:_p]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 2); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 2); //

Title

Hello

First textSecond text
@@ -313,9 +313,9 @@ [range setStartAfterNode:_h1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); //

Title

Hello

First textSecond text
@@ -331,9 +331,9 @@ [range setStartAfterNode:_div2]; - XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqualObjects(range.startContainer, _div1); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqualObjects(range.endContainer, _div1); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -349,9 +349,9 @@ [range setStartAfterNode:_firstText]; - XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqualObjects(range.startContainer, _div2); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 0); } @@ -372,9 +372,9 @@ [range setEndBeforeNode:_paragraphText]; - XCTAssertEqual(range.startContainer, _p); + XCTAssertEqualObjects(range.startContainer, _p); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _p); + XCTAssertEqualObjects(range.endContainer, _p); XCTAssertEqual(range.endOffset, 0); //

Title

Hello

First textSecond text
@@ -390,9 +390,9 @@ [range setEndBeforeNode:_p]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -408,9 +408,9 @@ [range setEndBeforeNode:_h1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 0); //

Title

Hello

First textSecond text
@@ -426,9 +426,9 @@ [range setEndBeforeNode:_firstComment]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -444,9 +444,9 @@ [range setEndBeforeNode:_secondText]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, _firstText.length); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 2); } @@ -467,9 +467,9 @@ [range setEndAfterNode:_paragraphText]; - XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqualObjects(range.startContainer, _paragraphText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _p); + XCTAssertEqualObjects(range.endContainer, _p); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -485,9 +485,9 @@ [range setEndAfterNode:_p]; - XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqualObjects(range.startContainer, _paragraphText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 2); //

Title

Hello

First textSecond text
@@ -503,9 +503,9 @@ [range setEndAfterNode:_h1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -521,9 +521,9 @@ [range setEndAfterNode:_div2]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, _firstText.length); - XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqualObjects(range.endContainer, _div1); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
@@ -539,9 +539,9 @@ [range setEndAfterNode:_firstComment]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, _firstText.length); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 2); } @@ -569,9 +569,9 @@ [range setEndNode:_paragraphText endOffset:4]; [range collapseToStart]; - XCTAssertEqual(range.startContainer, _title); + XCTAssertEqualObjects(range.startContainer, _title); XCTAssertEqual(range.startOffset, 2); - XCTAssertEqual(range.endContainer, _title); + XCTAssertEqualObjects(range.endContainer, _title); XCTAssertEqual(range.endOffset, 2); XCTAssertTrue(range.isCollapsed); } @@ -588,9 +588,9 @@ [range setEndNode:_paragraphText endOffset:4]; [range collapseToEnd]; - XCTAssertEqual(range.startContainer, _paragraphText); + XCTAssertEqualObjects(range.startContainer, _paragraphText); XCTAssertEqual(range.startOffset, 4); - XCTAssertEqual(range.endContainer, _paragraphText); + XCTAssertEqualObjects(range.endContainer, _paragraphText); XCTAssertEqual(range.endOffset, 4); XCTAssertTrue(range.isCollapsed); } @@ -602,49 +602,49 @@ //

Title

Hello

First textSecond text
<--Second comment-->
// ---------- [range selectNode:_firstText]; - XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqualObjects(range.startContainer, _div2); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
<--Second comment-->
// -------------------- [range selectNode:_firstComment]; - XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqualObjects(range.startContainer, _div2); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 2); //

Title

Hello

First textSecond text
<--Second comment-->
// ----------------------------------------------------------------------------------- [range selectNode:_div1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 2); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

First textSecond text
<--Second comment-->
// ---------------------------------------------------- [range selectNode:_div2]; - XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqualObjects(range.startContainer, _div1); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqualObjects(range.endContainer, _div1); XCTAssertEqual(range.endOffset, 1); //

Title

Hello

First textSecond text
<--Second comment-->
// -------------------- [range selectNode:_secondComment]; - XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqualObjects(range.startContainer, _div1); XCTAssertEqual(range.startOffset, 1); - XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqualObjects(range.endContainer, _div1); XCTAssertEqual(range.endOffset, 2); //

Title

Hello

First textSecond text
<--Second comment-->
// -------------- [range selectNode:_h1]; - XCTAssertEqual(range.startContainer, _document.body); + XCTAssertEqualObjects(range.startContainer, _document.body); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _document.body); + XCTAssertEqualObjects(range.endContainer, _document.body); XCTAssertEqual(range.endOffset, 1); } @@ -655,49 +655,49 @@ //

Title

Hello

First textSecond text
<--Second comment-->
// ---------- [range selectNodeContents:_firstText]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, _firstText.length); //

Title

Hello

First textSecond text
<--Second comment-->
// ------------- [range selectNodeContents:_firstComment]; - XCTAssertEqual(range.startContainer, _firstComment); + XCTAssertEqualObjects(range.startContainer, _firstComment); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstComment); + XCTAssertEqualObjects(range.endContainer, _firstComment); XCTAssertEqual(range.endOffset, _firstComment.length); //

Title

Hello

First textSecond text
<--Second comment-->
// ------------------------------------------------------------------------ [range selectNodeContents:_div1]; - XCTAssertEqual(range.startContainer, _div1); + XCTAssertEqualObjects(range.startContainer, _div1); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _div1); + XCTAssertEqualObjects(range.endContainer, _div1); XCTAssertEqual(range.endOffset, 2); //

Title

Hello

First textSecond text
<--Second comment-->
// ----------------------------------------- [range selectNodeContents:_div2]; - XCTAssertEqual(range.startContainer, _div2); + XCTAssertEqualObjects(range.startContainer, _div2); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _div2); + XCTAssertEqualObjects(range.endContainer, _div2); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

First textSecond text
<--Second comment-->
// -------------- [range selectNodeContents:_secondComment]; - XCTAssertEqual(range.startContainer, _secondComment); + XCTAssertEqualObjects(range.startContainer, _secondComment); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondComment); + XCTAssertEqualObjects(range.endContainer, _secondComment); XCTAssertEqual(range.endOffset, _secondComment.length); //

Title

Hello

First textSecond text
<--Second comment-->
// ----- [range selectNodeContents:_h1]; - XCTAssertEqual(range.startContainer, _h1); + XCTAssertEqualObjects(range.startContainer, _h1); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _h1); + XCTAssertEqualObjects(range.endContainer, _h1); XCTAssertEqual(range.endOffset, 1); } @@ -891,27 +891,27 @@ // |________| [_firstText appendData:@" New Text"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 10); //

Title

Hello

New text New TextSecond text
<--Second comment-->
// |______| [_firstText replaceDataInRange:NSMakeRange(0, 5) withData:@"New"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 8); //

Title

Hello

New TextSecond text
<--Second comment-->
// | [_firstText setData:@"New Text"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 0); //

Title

Hello

New TextSecond text
<--Second comment-->
@@ -922,18 +922,18 @@ // |_____| [_firstText deleteDataInRange:NSMakeRange(3, 1)]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 7); //

Title

Hello

NewNewTextSecond text
<--Second comment-->
// |________| [_firstText insertData:@"New" atOffset:3]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 10); //

Title

Hello

NewNewTextSecond text
<--Second comment-->
@@ -944,36 +944,36 @@ // |_____| [_firstText insertData:@"Prefix" atOffset:0]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 9); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 16); //

Title

Hello

PrefixNewTextSecond text
<--Second comment-->
// |_____| [_firstText deleteDataInRange:NSMakeRange(6, 3)]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 6); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 13); //

Title

Hello

PreABCDTextSecond text
<--Second comment-->
// |______| [_firstText replaceDataInRange:NSMakeRange(3, 6) withData:@"ABCD"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 11); //

Title

Hello

Pre TextSecond text
<--Second comment-->
// |___| [_firstText replaceDataInRange:NSMakeRange(3, 4) withData:@" "]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _firstText); + XCTAssertEqualObjects(range.endContainer, _firstText); XCTAssertEqual(range.endOffset, 8); } @@ -990,27 +990,27 @@ // |____________________________________| [_firstText appendData:@" New Text"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 5); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

New text New TextSecond text
<--Second comment-->
// |______________________________________| [_firstText replaceDataInRange:NSMakeRange(0, 5) withData:@"New"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

New TextSecond text
<--Second comment-->
// |_____________________________| [_firstText setData:@"New Text"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); @@ -1018,18 +1018,18 @@ // |____________________________| [_firstText deleteDataInRange:NSMakeRange(3, 1)]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

NewNewTextSecond text
<--Second comment-->
// |_______________________________| [_firstText insertData:@"New" atOffset:3]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 0); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

NewNewTextSecond text
<--Second comment-->
@@ -1040,54 +1040,54 @@ // |____________________________| [_firstText insertData:@"Prefix" atOffset:0]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 9); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

PrefixNewTextSecond text
<--Second comment-->
// |____________________________| [_firstText deleteDataInRange:NSMakeRange(6, 3)]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 6); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

PreABCDTextSecond text
<--Second comment-->
// |_____________________________| [_firstText replaceDataInRange:NSMakeRange(3, 6) withData:@"ABCD"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

Pre TextSecond text
<--Second comment-->
// |__________________________| [_firstText replaceDataInRange:NSMakeRange(3, 4) withData:@" "]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 3); //

Title

Hello

Pre TextPrefixSecond text
<--Second comment-->
// |________________________________| [_secondText insertData:@"Prefix" atOffset:0]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 9); //

Title

Hello

Pre TextPrefixSecond text
<--Second comment-->
// |___________________| [_firstComment setData:@"X"]; - XCTAssertEqual(range.startContainer, _firstText); + XCTAssertEqualObjects(range.startContainer, _firstText); XCTAssertEqual(range.startOffset, 3); - XCTAssertEqual(range.endContainer, _secondText); + XCTAssertEqualObjects(range.endContainer, _secondText); XCTAssertEqual(range.endOffset, 9); } From ea63b38379ce856d5d352cfc3a801bea4b099a09 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 13 Jan 2017 19:35:09 +0100 Subject: [PATCH 67/75] Update html5lib-tests to latest commit as of 2017-01-13 Commit: 50568b5664d6b034b752310603b2b664d045ad0f This commit references a PR adding tests --- Tests/html5lib-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/html5lib-tests b/Tests/html5lib-tests index 27724be..50568b5 160000 --- a/Tests/html5lib-tests +++ b/Tests/html5lib-tests @@ -1 +1 @@ -Subproject commit 27724be8d27a1232a8809a55f9c37b69706cb03e +Subproject commit 50568b5664d6b034b752310603b2b664d045ad0f From e5237a68c4f65342916034f4a59fddc99da5953c Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:22:10 +0100 Subject: [PATCH 68/75] Update project headers and targets --- HTMLKit.xcodeproj/project.pbxproj | 40 +++++++++++-------- .../xcschemes/HTMLKit-macOS.xcscheme | 3 +- .../xcschemes/HTMLKit-tvOS.xcscheme | 3 +- .../xcschemes/HTMLKit-watchOS.xcscheme | 3 +- .../{ => include}/HTMLCharacterData+Private.h | 0 Sources/{ => include}/HTMLCharacterData.h | 0 Sources/include/HTMLDOM.h | 1 + Sources/{ => include}/HTMLDOMUtils.h | 0 Sources/{ => include}/HTMLDocument+Private.h | 0 .../{ => include}/HTMLNodeIterator+Private.h | 0 Sources/{ => include}/HTMLParser+Private.h | 0 Sources/{ => include}/HTMLRange+Private.h | 0 Sources/{ => include}/HTMLRange.h | 0 13 files changed, 30 insertions(+), 20 deletions(-) rename Sources/{ => include}/HTMLCharacterData+Private.h (100%) rename Sources/{ => include}/HTMLCharacterData.h (100%) rename Sources/{ => include}/HTMLDOMUtils.h (100%) rename Sources/{ => include}/HTMLDocument+Private.h (100%) rename Sources/{ => include}/HTMLNodeIterator+Private.h (100%) rename Sources/{ => include}/HTMLParser+Private.h (100%) rename Sources/{ => include}/HTMLRange+Private.h (100%) rename Sources/{ => include}/HTMLRange.h (100%) diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index f1bfc2c..1b56eba 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 62056C4F1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62056C501E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62056C511E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 62056C521E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; }; 62132E5D1C021FF200084175 /* css-tests in Resources */ = {isa = PBXBuildFile; fileRef = 62132E5B1C021FF200084175 /* css-tests */; }; 6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */; }; @@ -15,10 +19,8 @@ 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49C1DEA71D800D1992A /* HTMLNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 621CC49E1DEA71D800D1992A /* HTMLNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A51DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A61DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -579,6 +581,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLNodeIterator+Private.h"; path = "include/HTMLNodeIterator+Private.h"; sourceTree = "<group>"; }; 62079BE71AF56F1E00D3B402 /* CSSSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSSelector.h; path = include/CSSSelector.h; sourceTree = "<group>"; }; 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSCompoundSelector.h; path = include/CSSCompoundSelector.h; sourceTree = "<group>"; }; 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCompoundSelector.m; sourceTree = "<group>"; }; @@ -588,9 +591,9 @@ 62132E581C01F83200084175 /* CSSSelectorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorTest.m; sourceTree = "<group>"; }; 62132E5B1C021FF200084175 /* css-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "css-tests"; sourceTree = "<group>"; }; 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSExtensionSelectorsParsingTests.m; sourceTree = "<group>"; }; - 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLDocument+Private.h"; sourceTree = "<group>"; }; - 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLNodeIterator+Private.h"; sourceTree = "<group>"; }; - 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLParser+Private.h"; sourceTree = "<group>"; }; + 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLDocument+Private.h"; path = "include/HTMLDocument+Private.h"; sourceTree = "<group>"; }; + 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLNode+Private.h"; path = "include/HTMLNode+Private.h"; sourceTree = "<group>"; }; + 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLParser+Private.h"; path = "include/HTMLParser+Private.h"; sourceTree = "<group>"; }; 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParserTests.m; sourceTree = "<group>"; }; 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelectorTests.m; sourceTree = "<group>"; }; 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLElementTypes.h; path = include/HTMLElementTypes.h; sourceTree = "<group>"; }; @@ -665,7 +668,7 @@ 624B37211B250BB50010BDDF /* CSSCodePoints.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CSSCodePoints.h; path = include/CSSCodePoints.h; sourceTree = "<group>"; }; 624B9FB11AE0313300646C4C /* HTMLStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLStringCategoryTests.m; sourceTree = "<group>"; }; 624B9FB41AE0391400646C4C /* HTMLOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLOrderedDictionaryTests.m; sourceTree = "<group>"; }; - 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCharacterData.h; sourceTree = "<group>"; }; + 624C77781DE9D05E00DD6DFA /* HTMLCharacterData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLCharacterData.h; path = include/HTMLCharacterData.h; sourceTree = "<group>"; }; 624C77791DE9D05E00DD6DFA /* HTMLCharacterData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterData.m; sourceTree = "<group>"; }; 624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodesTests.m; sourceTree = "<group>"; }; 62567F4E1C0CB5750025D458 /* HTMLDOMTokenList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLDOMTokenList.h; path = include/HTMLDOMTokenList.h; sourceTree = "<group>"; }; @@ -690,8 +693,8 @@ 625EE4591CBB171300F2CC8E /* HTMLKitTestUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLKitTestUtil.h; sourceTree = "<group>"; }; 625EE45A1CBB171300F2CC8E /* HTMLKitTestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTestUtil.m; sourceTree = "<group>"; }; 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLKitErrorDomain.h; path = include/HTMLKitErrorDomain.h; sourceTree = "<group>"; }; - 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLCharacterData+Private.h"; sourceTree = "<group>"; }; - 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDOMUtils.h; sourceTree = "<group>"; }; + 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLCharacterData+Private.h"; path = "include/HTMLCharacterData+Private.h"; sourceTree = "<group>"; }; + 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLDOMUtils.h; path = include/HTMLDOMUtils.h; sourceTree = "<group>"; }; 626BE1E11DF3819500C49514 /* HTMLDOMUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDOMUtils.m; sourceTree = "<group>"; }; 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLParserInsertionModes.h; path = include/HTMLParserInsertionModes.h; sourceTree = "<group>"; }; 6279F87219E1808D00F12EE5 /* HTMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLElement.h; path = include/HTMLElement.h; sourceTree = "<group>"; }; @@ -719,7 +722,7 @@ 62AE594819F9948A0043F069 /* HTMLCharacterToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterToken.m; sourceTree = "<group>"; }; 62D8345719FB1AC4009205A9 /* HTML5LibTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTokenizerTest.h; sourceTree = "<group>"; }; 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTokenizerTest.m; sourceTree = "<group>"; }; - 62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLRange.h; sourceTree = "<group>"; }; + 62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLRange.h; path = include/HTMLRange.h; sourceTree = "<group>"; }; 62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = "<group>"; }; 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterDataTests.m; sourceTree = "<group>"; }; 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = "<group>"; }; @@ -732,7 +735,7 @@ 62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSNthExpressionParser.h; path = include/CSSNthExpressionParser.h; sourceTree = "<group>"; }; 62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionParser.m; sourceTree = "<group>"; }; 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNThExpressionSelectorTests.m; sourceTree = "<group>"; }; - 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HTMLRange+Private.h"; sourceTree = "<group>"; }; + 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLRange+Private.h"; path = "include/HTMLRange+Private.h"; sourceTree = "<group>"; }; 62F873E919E088C90062683C /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTMLParser.h; path = include/HTMLParser.h; sourceTree = "<group>"; }; 62F873EA19E088C90062683C /* HTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParser.m; sourceTree = "<group>"; }; 62FA04E11BCC360D009ABF98 /* CSSCombinatorSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSCombinatorSelector.h; path = include/CSSCombinatorSelector.h; sourceTree = "<group>"; }; @@ -1011,9 +1014,10 @@ 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */, 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, - 621CC4991DEA71D800D1992A /* HTMLNodeIterator+Private.h */, + 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */, 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */, 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */, + 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */, 624717161B22333200C11912 /* HTMLNodeTraversal.h */, 624717171B22333200C11912 /* HTMLNodeTraversal.m */, 626BE1E01DF3819500C49514 /* HTMLDOMUtils.h */, @@ -1195,7 +1199,6 @@ 62ECBF001C0B69FF00AF847B /* HTMLTreeWalker.h in Headers */, 62ECBF011C0B69FF00AF847B /* HTMLNodeTraversal.h in Headers */, 62F7E5A21DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, - 621CC49B1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62ECBF021C0B69FF00AF847B /* HTMLNodeFilter.h in Headers */, 62ECBF031C0B69FF00AF847B /* HTMLKitDOMExceptions.h in Headers */, 62ECBF041C0B69FF00AF847B /* HTMLNamespaces.h in Headers */, @@ -1213,6 +1216,7 @@ 62ECBF101C0B6A0100AF847B /* CSSSelectorBlock.h in Headers */, 62ECBF111C0B6A0200AF847B /* CSSTypeSelector.h in Headers */, 62ECBF121C0B6A0200AF847B /* CSSAttributeSelector.h in Headers */, + 62056C4F1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */, 62ECBF131C0B6A0200AF847B /* CSSPseudoClassSelector.h in Headers */, 62ECBF141C0B6A0200AF847B /* CSSNthExpressionSelector.h in Headers */, 62ECBF151C0B6A0200AF847B /* CSSPseudoFunctionSelector.h in Headers */, @@ -1284,8 +1288,9 @@ 62857CA11D398973008DC254 /* HTMLNode.h in Headers */, 62857CD41D3989BF008DC254 /* CSSCodePoints.h in Headers */, 62857C871D398927008DC254 /* HTMLElementTypes.h in Headers */, - 621CC49E1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, + 621CC49E1DEA71D800D1992A /* HTMLNode+Private.h in Headers */, 62857C711D398907008DC254 /* HTMLTokenizerEntities.h in Headers */, + 62056C521E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */, 62857C6C1D3988EE008DC254 /* HTMLKitErrorDomain.h in Headers */, 62857CD51D3989BF008DC254 /* CSSInputStream.h in Headers */, 62857C741D398907008DC254 /* HTMLCharacterToken.h in Headers */, @@ -1357,8 +1362,8 @@ 62857D5B1D39A41D008DC254 /* HTMLElementTypes.h in Headers */, 62857D881D39A47F008DC254 /* CSSSelector.h in Headers */, 62857D4F1D39A40A008DC254 /* HTMLTokenizerEntities.h in Headers */, - 621CC49D1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, 62857D901D39A47F008DC254 /* CSSCompoundSelector.h in Headers */, + 62056C511E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */, 62857D4A1D39A3F4008DC254 /* HTMLKitErrorDomain.h in Headers */, 62857D7C1D39A452008DC254 /* HTMLQuirksMode.h in Headers */, 62857D791D39A44E008DC254 /* HTMLNodeFilter.h in Headers */, @@ -1412,7 +1417,7 @@ 62ECBFC61C0B6D4300AF847B /* CSSCombinatorSelector.h in Headers */, 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 626BE1E31DF3819500C49514 /* HTMLDOMUtils.h in Headers */, - 621CC49C1DEA71D800D1992A /* HTMLNodeIterator+Private.h in Headers */, + 621CC49C1DEA71D800D1992A /* HTMLNode+Private.h in Headers */, 625D0F041C2717DE00D7BEB0 /* HTMLNode+Private.h in Headers */, 62ECBFC71C0B6D4300AF847B /* CSSCompoundSelector.h in Headers */, 62ECBFB11C0B6D3C00AF847B /* HTMLNodeTraversal.h in Headers */, @@ -1432,6 +1437,7 @@ 62ECBFA01C0B6D3900AF847B /* HTMLStackOfOpenElements.h in Headers */, 62ECBFA11C0B6D3900AF847B /* HTMLListOfActiveFormattingElements.h in Headers */, 62ECBFA21C0B6D3900AF847B /* HTMLElementTypes.h in Headers */, + 62056C501E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */, 62ECBFA31C0B6D3900AF847B /* HTMLElementAdjustment.h in Headers */, 62ECBFA41C0B6D3900AF847B /* HTMLParserInsertionModes.h in Headers */, 62ECBFA51C0B6D3900AF847B /* HTMLMarker.h in Headers */, diff --git a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-macOS.xcscheme b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-macOS.xcscheme index a7178bb..e115eb8 100644 --- a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-macOS.xcscheme +++ b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-macOS.xcscheme @@ -26,7 +26,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> <Testables> <TestableReference skipped = "NO"> diff --git a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-tvOS.xcscheme b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-tvOS.xcscheme index 883c1b3..fc392c9 100644 --- a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-tvOS.xcscheme +++ b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-tvOS.xcscheme @@ -26,7 +26,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> <Testables> <TestableReference skipped = "NO"> diff --git a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-watchOS.xcscheme b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-watchOS.xcscheme index 2c81d4b..1fe0add 100644 --- a/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-watchOS.xcscheme +++ b/HTMLKit.xcodeproj/xcshareddata/xcschemes/HTMLKit-watchOS.xcscheme @@ -26,7 +26,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> <Testables> </Testables> <AdditionalOptions> diff --git a/Sources/HTMLCharacterData+Private.h b/Sources/include/HTMLCharacterData+Private.h similarity index 100% rename from Sources/HTMLCharacterData+Private.h rename to Sources/include/HTMLCharacterData+Private.h diff --git a/Sources/HTMLCharacterData.h b/Sources/include/HTMLCharacterData.h similarity index 100% rename from Sources/HTMLCharacterData.h rename to Sources/include/HTMLCharacterData.h diff --git a/Sources/include/HTMLDOM.h b/Sources/include/HTMLDOM.h index c269c14..567062b 100644 --- a/Sources/include/HTMLDOM.h +++ b/Sources/include/HTMLDOM.h @@ -11,6 +11,7 @@ #import "HTMLDocumentType.h" #import "HTMLDocumentFragment.h" #import "HTMLElement.h" +#import "HTMLCharacterData.h" #import "HTMLComment.h" #import "HTMLText.h" #import "HTMLTemplate.h" diff --git a/Sources/HTMLDOMUtils.h b/Sources/include/HTMLDOMUtils.h similarity index 100% rename from Sources/HTMLDOMUtils.h rename to Sources/include/HTMLDOMUtils.h diff --git a/Sources/HTMLDocument+Private.h b/Sources/include/HTMLDocument+Private.h similarity index 100% rename from Sources/HTMLDocument+Private.h rename to Sources/include/HTMLDocument+Private.h diff --git a/Sources/HTMLNodeIterator+Private.h b/Sources/include/HTMLNodeIterator+Private.h similarity index 100% rename from Sources/HTMLNodeIterator+Private.h rename to Sources/include/HTMLNodeIterator+Private.h diff --git a/Sources/HTMLParser+Private.h b/Sources/include/HTMLParser+Private.h similarity index 100% rename from Sources/HTMLParser+Private.h rename to Sources/include/HTMLParser+Private.h diff --git a/Sources/HTMLRange+Private.h b/Sources/include/HTMLRange+Private.h similarity index 100% rename from Sources/HTMLRange+Private.h rename to Sources/include/HTMLRange+Private.h diff --git a/Sources/HTMLRange.h b/Sources/include/HTMLRange.h similarity index 100% rename from Sources/HTMLRange.h rename to Sources/include/HTMLRange.h From 65666a13c07d24047c2fdf27b442f9e116d9982e Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:46:28 +0100 Subject: [PATCH 69/75] Remove redundant header file from private group --- HTMLKit.xcodeproj/project.pbxproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 1b56eba..fcd465f 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -19,8 +19,6 @@ 621CC4921DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4931DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4941DEA704000D1992A /* HTMLDocument+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49C1DEA71D800D1992A /* HTMLNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 621CC49E1DEA71D800D1992A /* HTMLNode+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A51DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A61DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 621CC4A71DEA721A00D1992A /* HTMLParser+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -592,7 +590,6 @@ 62132E5B1C021FF200084175 /* css-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "css-tests"; sourceTree = "<group>"; }; 6216ACFC1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSExtensionSelectorsParsingTests.m; sourceTree = "<group>"; }; 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLDocument+Private.h"; path = "include/HTMLDocument+Private.h"; sourceTree = "<group>"; }; - 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLNode+Private.h"; path = "include/HTMLNode+Private.h"; sourceTree = "<group>"; }; 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "HTMLParser+Private.h"; path = "include/HTMLParser+Private.h"; sourceTree = "<group>"; }; 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParserTests.m; sourceTree = "<group>"; }; 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelectorTests.m; sourceTree = "<group>"; }; @@ -1014,7 +1011,6 @@ 621CC48F1DEA704000D1992A /* HTMLDocument+Private.h */, 625D0F011C2717DE00D7BEB0 /* HTMLNode+Private.h */, 626679CD1DEA3DAF004353E7 /* HTMLCharacterData+Private.h */, - 621CC4991DEA71D800D1992A /* HTMLNode+Private.h */, 62F7E5A01DEB63F900DEF09B /* HTMLRange+Private.h */, 621CC4A31DEA721A00D1992A /* HTMLParser+Private.h */, 62056C4E1E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h */, @@ -1288,7 +1284,6 @@ 62857CA11D398973008DC254 /* HTMLNode.h in Headers */, 62857CD41D3989BF008DC254 /* CSSCodePoints.h in Headers */, 62857C871D398927008DC254 /* HTMLElementTypes.h in Headers */, - 621CC49E1DEA71D800D1992A /* HTMLNode+Private.h in Headers */, 62857C711D398907008DC254 /* HTMLTokenizerEntities.h in Headers */, 62056C521E2AD9FB009A4EE0 /* HTMLNodeIterator+Private.h in Headers */, 62857C6C1D3988EE008DC254 /* HTMLKitErrorDomain.h in Headers */, @@ -1417,7 +1412,6 @@ 62ECBFC61C0B6D4300AF847B /* CSSCombinatorSelector.h in Headers */, 62F7E5A31DEB63F900DEF09B /* HTMLRange+Private.h in Headers */, 626BE1E31DF3819500C49514 /* HTMLDOMUtils.h in Headers */, - 621CC49C1DEA71D800D1992A /* HTMLNode+Private.h in Headers */, 625D0F041C2717DE00D7BEB0 /* HTMLNode+Private.h in Headers */, 62ECBFC71C0B6D4300AF847B /* CSSCompoundSelector.h in Headers */, 62ECBFB11C0B6D3C00AF847B /* HTMLNodeTraversal.h in Headers */, From 28ecfb0278513d5dd956295012dbc1eb94d4114f Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:53:42 +0100 Subject: [PATCH 70/75] Update headers in module map --- Sources/module.modulemap | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/module.modulemap b/Sources/module.modulemap index 5f6af82..6eca8e6 100644 --- a/Sources/module.modulemap +++ b/Sources/module.modulemap @@ -16,8 +16,6 @@ module HTMLKit { header "HTMLInputStreamReader.h" header "HTMLListOfActiveFormattingElements.h" header "HTMLMarker.h" - header "HTMLNodeTraversal.h" - header "HTMLDOMUtils.h" header "HTMLParseErrorToken.h" header "HTMLParserInsertionModes.h" header "HTMLStackOfOpenElements.h" @@ -29,9 +27,12 @@ module HTMLKit { header "HTMLTokenizerStates.h" header "HTMLTokens.h" header "HTMLNode+Private.h" + header "HTMLDocument+Private.h" header "HTMLCharacterData+Private.h" header "HTMLRange+Private.h" header "HTMLNodeIterator+Private.h" header "HTMLParser+Private.h" + header "HTMLNodeTraversal.h" + header "HTMLDOMUtils.h" } } From 1919992b0ea574c9f6d137876c3b26fe3b5a0f9f Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:51:47 +0100 Subject: [PATCH 71/75] Update podspec for 1.1.0 --- HTMLKit.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HTMLKit.podspec b/HTMLKit.podspec index 8025949..13c58c1 100644 --- a/HTMLKit.podspec +++ b/HTMLKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "HTMLKit" - s.version = "1.0.0" + s.version = "1.1.0" s.summary = "HTMLKit, an Objective-C framework for your everyday HTML needs." s.license = "MIT" s.homepage = "https://github.com/iabudiab/HTMLKit" @@ -16,7 +16,7 @@ Pod::Spec.new do |s| s.source_files = "Sources", "Sources/**/*.{h,m}" s.private_header_files = [ - 'Sources/**/*{HTMLToken,HTMLTokens,HTMLTagToken,HTMLCharacterToken,HTMLCommentToken,HTMLDOCTYPEToken,HTMLEOFToken,HTMLTokenizer,HTMLTokenizerCharacters,HTMLTokenizerEntities,HTMLTokenizerStates,HTMLElementAdjustment,HTMLElementTypes,HTMLInputStreamReader,HTMLListOfActiveFormattingElements,HTMLNodeTraversal,HTMLParseErrorToken,HTMLParserInsertionModes,HTMLStackOfOpenElements,HTMLNode+Private,HTMLMarker,CSSCodePoints,CSSInputStream}.h' + 'Sources/**/*{HTMLToken,HTMLTokens,HTMLTagToken,HTMLCharacterToken,HTMLCommentToken,HTMLDOCTYPEToken,HTMLEOFToken,HTMLTokenizer,HTMLTokenizerCharacters,HTMLTokenizerEntities,HTMLTokenizerStates,HTMLElementAdjustment,HTMLElementTypes,HTMLInputStreamReader,HTMLListOfActiveFormattingElements,HTMLParseErrorToken,HTMLParserInsertionModes,HTMLStackOfOpenElements,HTMLMarker,HTMLNode+Private,HTMLDocument+Private,HTMLCharacterData+Private,HTMLRange+Private,HTMLParser+Private,HTMLNodeIterator+Private,HTMLNodeTraversal,HTMLDOMUtils,CSSCodePoints,CSSInputStream}.h' ] s.requires_arc = true From 46e36e9c24d7361dd6dbefdf5c701a8f7789803e Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:41:24 +0100 Subject: [PATCH 72/75] Update jazzy.yaml for 1.1.0 --- .jazzy.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 9fab102..115f74d 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -1,5 +1,5 @@ module: HTMLKit -module_version: 1.0.0 +module_version: 1.1.0 author: Iskandar Abudiab author_url: https://twitter.com/iabudiab github_url: https://github.com/iabudiab/HTMLKit @@ -27,10 +27,12 @@ custom_categories: - HTMLDocumentType - HTMLDocumentFragment - HTMLDocumentPosition + - HTMLCharacterData - HTMLText - HTMLComment - HTMLTemplate - HTMLDOMTokenList + - HTMLRange - name: Iteration & Filtering children: From 1a5238863ad095c6177643d426cf246acb6bc725 Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:39:25 +0100 Subject: [PATCH 73/75] Add Changelog entry for HTMLKit 1.1.0 --- CHANGELOG.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e8cb29..37ffbba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Change Log +## [1.1.0](https://github.com/iabudiab/HTMLKit/releases/tag/1.1.0) + +Released on 2017.01.14 + +### Added + +- `DOM Ranges` implementation ([spec](https://dom.spec.whatwg.org/#ranges)) +- `HTMLChatacterData` as base class for `HTMLText` & `HTMLComment` + - `HTMLText` and `HTMLComment` no longer extend `HTMLNode` directly +- `splitText` implementation for `HTMLText` nodes +- `index` property for `HTMLNode` +- `cloneNodeDeep` method for `HTMLNode` + +### Deprecated + +- `appendString` method in `HTMLText` in favor of `appendData` from the supperclass `HTMLCharacterData` + + ## [1.0.0](https://github.com/iabudiab/HTMLKit/releases/tag/1.0.0) Released on 2016.09.28 @@ -61,7 +79,6 @@ This release passes all tokenizer and tree construction html5lib-tests as of 201 - `<isindex>` is completely removed from the spec now, therefore it is dropped from the implementation - `Tokenizer` and `Tree-Construction` tests are now generated dynamically - Test failures are collected by a `XCTestObservation` for better reporting - - `<isindex>` is completely removed from the spec now, therefore it is dropped from the implementation - `Tokenizer` and `Tree-Construction` tests are now generated dynamically - Test failures are collected by a `XCTestObservation` for better reporting From c727ce6643b10cdacdcab35b290cf6f738268f85 Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:59:56 +0100 Subject: [PATCH 74/75] Update README.md --- README.md | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0783c74..fdf1e55 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,12 @@ An Objective-C framework for your everyday HTML needs. [![Platform](https://img.shields.io/cocoapods/p/HTMLKit.svg?style=flat)](http://cocoadocs.org/docsets/HTMLKit) [![License MIT](https://img.shields.io/badge/license-MIT-4481C7.svg?style=flat)](https://opensource.org/licenses/MIT) +- [Quick Overview](#overview) +- [Installation](#installation) +- [Parsing](#parsing) +- [The DOM](#the-dom) +- [CSS3 Selectors](#css3-selectors) + # Quick Overview HTMLKit is a [WHATWG specification](https://html.spec.whatwg.org/multipage/)-compliant framework for parsing and serializing HTML documents and document fragments for iOS and OSX. HTMLKit parses real-world HTML the same way modern web browsers would. @@ -33,7 +39,7 @@ Check out the playground! # Installation -### Carthage +## Carthage [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. @@ -56,7 +62,7 @@ Then run the following command to build the framework and drag the built `HTMLKi $ carthage update ``` -### CocoaPods +## CocoaPods [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. @@ -72,7 +78,7 @@ To add `HTMLKit` as a dependency into your project using CocoaPods just add the use_frameworks! target 'MyTarget' do - pod 'HTMLKit', '~> 0.9' + pod 'HTMLKit', '~> 1.1' end ``` @@ -82,14 +88,14 @@ Then, run the following command: $ pod install ``` -### Swift Package Manager +## Swift Package Manager [Swift Package Manager](https://github.com/apple/swift-package-manager) is the package manager for the Swift programming language. Add `HTMLKit` to your `Package.swift` dependecies: ```swift -.Package(url: "https://github.com/iabudiab/HTMLKit", majorVersion: 0, minor: 9) +.Package(url: "https://github.com/iabudiab/HTMLKit", majorVersion: 1) ``` Then run: @@ -98,7 +104,7 @@ Then run: $ swift build ``` -### Manually +## Manually 1- Add `HTMLKit` as git submodule @@ -110,9 +116,9 @@ $ git submodule add https://github.com/iabudiab/HTMLKit.git 3- In the General panel of your target add `HTMLKit.framework` under the `Embedded Binaries` -# Features +# Parsing -# Parsing Documents +## Parsing Documents Given some HTML content, you can parse it either via the `HTMLParser` or instatiate a `HTMLDocument` directly: @@ -127,7 +133,7 @@ HTMLDocument *document = [parser parseDocument]; HTMLDocument *document = [HTMLDocument documentWithString:htmlString]; ``` -# Parsing Fragments +## Parsing Fragments You can also prase HTML content as a document fragment with a specified context element: @@ -150,7 +156,7 @@ nodes = [parser parseFragmentWithContextElement:bodyContext]; # The DOM -Here are some of the things you can do: +The DOM tree can be manipulated in several ways, here are just a few: * Create new elements and assign attributes @@ -174,7 +180,7 @@ NSArray *nodes = @[ [body appendNodes:nodes]; ``` -* Enumerate child elements and perform DOM manipulation +* Enumerate child elements and perform DOM editing ```objective-c [body enumerateChildElementsUsingBlock:^(HTMLElement *element, NSUInteger idx, BOOL *stop) { @@ -194,6 +200,12 @@ NSArray *nodes = @[ [body.lastChild removeFromParentNode]; ``` +* Manipulate the HTML directly + +```objective-c +greenDiv.innerHTML = @"<ul><li>item 1<li>item 2"; +``` + * Navigate to child and sibling nodes ```objective-c @@ -201,12 +213,6 @@ HTMLNode *firstChild = body.firstChild; HTMLNode *greenDiv = firstChild.nextSibling; ``` -* Manipulate the HTML directly - -```objective-c -greenDiv.innerHTML = @"<ul><li>item 1<li>item 2"; -``` - * Iterate the DOM tree with custom filters ```objective-c @@ -222,6 +228,17 @@ for (HTMLElement *element in [body nodeIteratorWithShowOptions:HTMLNodeFilterSho } ``` +* Create and manipulate DOM Ranges + +```objective-c +HTMLDocument *document = [HTMLDocument documentWithString:@"<div><h1>HTMLKit</h1><p id='foo'>Hello there!</p></div>"]; +HTMLRange *range = [[HTMLRange alloc] initWithDocument:document]; + +HTMLNode *paragraph = [document querySelector:@"#foo"]; +[range selectNode:paragraph]; +[range extractContents]; +``` + # CSS3 Selectors All CSS3 Selectors are supported except for the pseudo-elements (`::first-line`, `::first-letter`, ...etc.). You can use them the way you always have: From 049d7b71489a410b8fe69408d1f6cc6857774ea6 Mon Sep 17 00:00:00 2001 From: iska <iska.gp@gmail.com> Date: Sat, 14 Jan 2017 23:40:31 +0100 Subject: [PATCH 75/75] Bump HTMLKit version to 1.1.0 --- Sources/HTMLKit-Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/HTMLKit-Info.plist b/Sources/HTMLKit-Info.plist index ecef4c7..7fde877 100644 --- a/Sources/HTMLKit-Info.plist +++ b/Sources/HTMLKit-Info.plist @@ -17,7 +17,7 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>1.0.0</string> + <string>1.1.0</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key>