-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathHTMLDocument.m
129 lines (106 loc) · 3.45 KB
/
HTMLDocument.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// HTMLDocument.m
//
// Public domain. https://github.com/nolanw/HTMLReader
#import "HTMLDocument+Private.h"
#import "HTMLParser.h"
NS_ASSUME_NONNULL_BEGIN
@implementation HTMLDocument
+ (instancetype)documentWithData:(NSData *)data contentTypeHeader:(NSString * __nullable)contentType
{
NSParameterAssert(data);
HTMLParser *parser = ParserWithDataAndContentType(data, contentType);
return parser.document;
}
- (instancetype)initWithData:(NSData *)data contentTypeHeader:(NSString * __nullable)contentType
{
NSParameterAssert(data);
return [self.class documentWithData:data contentTypeHeader:contentType];
}
+ (instancetype)documentWithString:(NSString *)string
{
NSParameterAssert(string);
HTMLStringEncoding defaultEncoding = (HTMLStringEncoding){
.encoding = NSUTF8StringEncoding,
.confidence = Tentative
};
HTMLParser *parser = [[HTMLParser alloc] initWithString:string encoding:defaultEncoding context:nil];
return parser.document;
}
- (instancetype)initWithString:(NSString *)string
{
NSParameterAssert(string);
return [self.class documentWithString:string];
}
- (instancetype)init
{
if (!(self = [super init])) {
return nil;
}
_parsedStringEncoding = NSUTF8StringEncoding;
return self;
}
- (HTMLDocumentType * __nullable)documentType
{
return FirstNodeOfType(self.children, [HTMLDocumentType class]);
}
- (void)setDocumentType:(HTMLDocumentType * __nullable)documentType
{
HTMLDocumentType *oldDocumentType = self.documentType;
NSMutableOrderedSet *children = [self mutableChildren];
if (oldDocumentType && documentType) {
NSUInteger i = [children indexOfObject:oldDocumentType];
[children replaceObjectAtIndex:i withObject:(HTMLDocumentType * __nonnull)documentType];
} else if (documentType) {
HTMLElement *rootElement = self.rootElement;
if (rootElement) {
[children insertObject:(HTMLDocumentType * __nonnull)documentType atIndex:[children indexOfObject:rootElement]];
} else {
[children addObject:(HTMLDocumentType * __nonnull)documentType];
}
} else if (oldDocumentType) {
[children removeObject:oldDocumentType];
}
}
- (void)setParsedStringEncoding:(NSStringEncoding)parsedStringEncoding
{
_parsedStringEncoding = parsedStringEncoding;
}
- (HTMLElement * __nullable)rootElement
{
return FirstNodeOfType(self.children, [HTMLElement class]);
}
- (void)setRootElement:(HTMLElement * __nullable)rootElement
{
HTMLElement *oldRootElement = self.rootElement;
NSMutableOrderedSet *children = [self mutableChildren];
if (oldRootElement && rootElement) {
[children replaceObjectAtIndex:[children indexOfObject:oldRootElement] withObject:(HTMLElement * __nonnull)rootElement];
} else if (rootElement) {
[children addObject:(HTMLElement * __nonnull)rootElement];
} else if (oldRootElement) {
[children removeObject:oldRootElement];
}
}
- (HTMLElement * __nullable)bodyElement
{
for (id child in self.rootElement.children) {
if ([child isKindOfClass:[HTMLElement class]]) {
HTMLElement *elem = child;
if ([elem.tagName isEqualToString:@"body"]) {
return elem;
}
}
}
return nil;
}
static id FirstNodeOfType(id <NSFastEnumeration> collection, Class type)
{
for (id node in collection) {
if ([node isKindOfClass:type]) {
return node;
}
}
return nil;
}
@end
NS_ASSUME_NONNULL_END