Files
HTMLKit/Sources/HTMLRange.m
T
iska 8391a01147 Change HTML Range’s initializer to accept one HTML Document argument
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.
2016-11-22 01:23:17 +01:00

110 lines
2.7 KiB
Objective-C

//
// HTMLRange.m
// HTMLKit
//
// Created by Iska on 20/11/16.
// Copyright © 2016 BrainCookie. All rights reserved.
//
#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
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