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