Add methods to check Doctype validity and its quirks mode
This commit is contained in:
@@ -8,13 +8,7 @@
|
||||
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLDocumentType.h"
|
||||
|
||||
typedef NS_ENUM(short, HTMLQuirksMode)
|
||||
{
|
||||
HTMLQuirksModeNoQuirks,
|
||||
HTMLQuirksModeQuirks,
|
||||
HTMLQuirksModeLimitedQuirks
|
||||
};
|
||||
#import "HTMLQuirksMode.h"
|
||||
|
||||
@interface HTMLDocument : HTMLNode
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLQuirksMode.h"
|
||||
|
||||
@interface HTMLDocumentType : HTMLNode
|
||||
|
||||
@@ -18,4 +19,7 @@
|
||||
publicIdentifier:(NSString *)publicIdentifier
|
||||
systemIdentifier:(NSString *)systemIdentifier;
|
||||
|
||||
- (BOOL)isValid;
|
||||
- (HTMLQuirksMode)quirksMode;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
#import "HTMLDocumentType.h"
|
||||
|
||||
NS_INLINE BOOL nilOrEqual(id first, id second) {
|
||||
return (first == nil) || ([first isEqual:second]);
|
||||
}
|
||||
|
||||
@implementation HTMLDocumentType
|
||||
|
||||
- (instancetype)initWithName:(NSString *)name
|
||||
@@ -22,6 +26,86 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
if (![self.name isEqualToString:@"html"]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ([_publicIdentifier isEqualToString:@"-//W3C//DTD HTML 4.0//EN"] &&
|
||||
nilOrEqual(_systemIdentifier, @"http://www.w3.org/TR/REC-html40/strict.dtd")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([_publicIdentifier isEqualToString:@"-//W3C//DTD HTML 4.01//EN"] &&
|
||||
nilOrEqual(_systemIdentifier, @"http://www.w3.org/TR/html4/strict.dtd")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([_publicIdentifier isEqualToString:@"-//W3C//DTD XHTML 1.0 Strict//EN"] &&
|
||||
nilOrEqual(_systemIdentifier, @"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([_publicIdentifier isEqualToString:@"-//W3C//DTD XHTML 1.1//EN"] &&
|
||||
nilOrEqual(_systemIdentifier, @"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (_publicIdentifier != nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (_systemIdentifier && ![_systemIdentifier isEqualToString:@"about:legacy-compat"]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (HTMLQuirksMode)quirksMode
|
||||
{
|
||||
if (![self.name isEqualToString:@"html"]) {
|
||||
return HTMLQuirksModeQuirks;
|
||||
}
|
||||
|
||||
if (isEqualCaseInsensitive(_publicIdentifier, @"-//W3O//DTD W3 HTML Strict 3.0//EN//") ||
|
||||
isEqualCaseInsensitive(_publicIdentifier, @"-/W3C/DTD HTML 4.0 Transitional/EN") ||
|
||||
isEqualCaseInsensitive(_publicIdentifier, @"HTML")) {
|
||||
return HTMLQuirksModeQuirks;
|
||||
}
|
||||
|
||||
if (isEqualCaseInsensitive(_systemIdentifier, @"http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")) {
|
||||
return HTMLQuirksModeQuirks;
|
||||
}
|
||||
|
||||
if (QuirksModePrefixMatch(_publicIdentifier)) {
|
||||
return HTMLQuirksModeQuirks;
|
||||
}
|
||||
|
||||
if (_systemIdentifier == nil) {
|
||||
if (hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD HTML 4.01 Frameset//") ||
|
||||
hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD HTML 4.01 Transitional//")) {
|
||||
return HTMLQuirksModeQuirks;
|
||||
}
|
||||
}
|
||||
|
||||
#warning Check "iframe srcdoc"
|
||||
if (hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD XHTML 1.0 Frameset//") ||
|
||||
hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD XHTML 1.0 Transitional//")) {
|
||||
return HTMLQuirksModeLimitedQuirks;
|
||||
}
|
||||
|
||||
if (_systemIdentifier != nil) {
|
||||
if (hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD HTML 4.01 Frameset//") ||
|
||||
hasPrefixCaseInsensitive(_publicIdentifier, @"-//W3C//DTD HTML 4.01 Transitional//")) {
|
||||
return HTMLQuirksModeLimitedQuirks;
|
||||
}
|
||||
}
|
||||
|
||||
return HTMLQuirksModeNoQuirks;
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// HTMLQuirksMode.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/02/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
typedef NS_ENUM(short, HTMLQuirksMode)
|
||||
{
|
||||
HTMLQuirksModeNoQuirks,
|
||||
HTMLQuirksModeQuirks,
|
||||
HTMLQuirksModeLimitedQuirks
|
||||
};
|
||||
|
||||
#define QUIRKS_MODE_PREFIXES \
|
||||
QUIRKS_ENTRY( "+//Silmaril//dtd html Pro v0r11 19970101//" ) \
|
||||
QUIRKS_ENTRY( "-//AS//DTD HTML 3.0 asWedit + extensions//" ) \
|
||||
QUIRKS_ENTRY( "-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0 Level 1//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0 Level 2//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0 Strict Level 1//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0 Strict Level 2//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0 Strict//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.0//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 2.1E//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 3.0//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 3.2 Final//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 3.2//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML 3//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Level 0//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Level 1//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Level 2//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Level 3//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Strict Level 0//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Strict Level 1//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Strict Level 2//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Strict Level 3//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML Strict//" ) \
|
||||
QUIRKS_ENTRY( "-//IETF//DTD HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//Metrius//DTD Metrius Presentational//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 2.0 HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 2.0 Tables//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 3.0 HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//Microsoft//DTD Internet Explorer 3.0 Tables//" ) \
|
||||
QUIRKS_ENTRY( "-//Netscape Comm. Corp.//DTD HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//Netscape Comm. Corp.//DTD Strict HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//O'Reilly and Associates//DTD HTML 2.0//" ) \
|
||||
QUIRKS_ENTRY( "-//O'Reilly and Associates//DTD HTML Extended 1.0//" ) \
|
||||
QUIRKS_ENTRY( "-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//" ) \
|
||||
QUIRKS_ENTRY( "-//SQ//DTD HTML 2.0 HoTMetaL + extensions//" ) \
|
||||
QUIRKS_ENTRY( "-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//" ) \
|
||||
QUIRKS_ENTRY( "-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//" ) \
|
||||
QUIRKS_ENTRY( "-//Spyglass//DTD HTML 2.0 Extended//" ) \
|
||||
QUIRKS_ENTRY( "-//Sun Microsystems Corp.//DTD HotJava HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//Sun Microsystems Corp.//DTD HotJava Strict HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 3 1995-03-24//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 3.2 Draft//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 3.2 Final//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 3.2//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 3.2S Draft//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 4.0 Frameset//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML 4.0 Transitional//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML Experimental 19960712//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD HTML Experimental 970421//" ) \
|
||||
QUIRKS_ENTRY( "-//W3C//DTD W3 HTML//" ) \
|
||||
QUIRKS_ENTRY( "-//W3O//DTD W3 HTML 3.0//" ) \
|
||||
QUIRKS_ENTRY( "-//WebTechs//DTD Mozilla HTML 2.0//" ) \
|
||||
QUIRKS_ENTRY( "-//WebTechs//DTD Mozilla HTML//" )
|
||||
|
||||
static NSString * HTMLQuirksModePrefixes[] = {
|
||||
#define QUIRKS_ENTRY( prefix ) @prefix,
|
||||
QUIRKS_MODE_PREFIXES
|
||||
#undef QUIRKS_ENTRY
|
||||
};
|
||||
|
||||
NS_INLINE BOOL isEqualCaseInsensitive(NSString *first, NSString *second) {
|
||||
return [first caseInsensitiveCompare:second] == NSOrderedSame;
|
||||
}
|
||||
|
||||
NS_INLINE BOOL hasPrefixCaseInsensitive(NSString *string, NSString *prefix) {
|
||||
NSRange reange = [string rangeOfString:prefix
|
||||
options:NSAnchoredSearch|NSCaseInsensitiveSearch];
|
||||
return reange.location != NSNotFound;
|
||||
}
|
||||
|
||||
NS_INLINE BOOL QuirksModePrefixMatch(NSString *publicIdentifier)
|
||||
{
|
||||
for (int i = 0; i < sizeof(HTMLQuirksModePrefixes) / sizeof(HTMLQuirksModePrefixes[0]); i++) {
|
||||
if (hasPrefixCaseInsensitive(publicIdentifier, HTMLQuirksModePrefixes[i])) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
Reference in New Issue
Block a user