diff --git a/.gitignore b/.gitignore index bd9f093..b0f2379 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -# OS X -.DS_Store - # Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated build/ +DerivedData + +## Various settings *.pbxuser !default.pbxuser *.mode1v3 @@ -12,13 +16,28 @@ build/ *.perspectivev3 !default.perspectivev3 xcuserdata + +## Other *.xccheckout -profile *.moved-aside -DerivedData +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific *.hmap *.ipa # CocoaPods -Pods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +Pods/ +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +Carthage/Checkouts + +Carthage/Build \ No newline at end of file diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 1ea6aea..27284ab 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -7,49 +7,51 @@ objects = { /* Begin PBXBuildFile section */ - 623406E11ADB04F9004677A3 /* HTMLTemplate.h in Headers */ = {isa = PBXBuildFile; fileRef = 623406DF1ADB04F9004677A3 /* HTMLTemplate.h */; }; + 620C877C1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */; }; + 620C877D1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */; }; + 620C877E1BD4519A00FB3EEE /* CSSPseudoFunctionSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62ACB8DC1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.m */; }; + 620C877F1BD4519A00FB3EEE /* CSSPseudoFunctionSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62ACB8DC1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.m */; }; + 620EE94A1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620EE9481BC46F2A0028ED34 /* CSSPseudoClassSelector.m */; }; + 620EE94B1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620EE9481BC46F2A0028ED34 /* CSSPseudoClassSelector.m */; }; + 62132E591C01F83200084175 /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; }; + 62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62132E581C01F83200084175 /* CSSSelectorTest.m */; }; + 62132E5C1C021FF200084175 /* css-tests in Resources */ = {isa = PBXBuildFile; fileRef = 62132E5B1C021FF200084175 /* css-tests */; }; + 62132E5D1C021FF200084175 /* css-tests in Resources */ = {isa = PBXBuildFile; fileRef = 62132E5B1C021FF200084175 /* css-tests */; }; + 621FBE5A1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; + 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */; }; + 621FBE5D1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; + 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */; }; + 622BF5821BBF2FD700363583 /* CSSSelectorParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 622BF5801BBF2FD700363583 /* CSSSelectorParser.m */; }; + 622BF5831BBF2FD700363583 /* CSSSelectorParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 622BF5801BBF2FD700363583 /* CSSSelectorParser.m */; }; 623406E21ADB04F9004677A3 /* HTMLTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 623406E01ADB04F9004677A3 /* HTMLTemplate.m */; }; 623406E31ADB04F9004677A3 /* HTMLTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 623406E01ADB04F9004677A3 /* HTMLTemplate.m */; }; - 623406E61ADB05AD004677A3 /* HTMLDocumentFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = 623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */; }; 623406E71ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 623406E51ADB05AD004677A3 /* HTMLDocumentFragment.m */; }; 623406E81ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = 623406E51ADB05AD004677A3 /* HTMLDocumentFragment.m */; }; - 623424881AB467B200726190 /* HTMLOrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 623424861AB467B200726190 /* HTMLOrderedDictionary.h */; }; 623424891AB467B200726190 /* HTMLOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 623424871AB467B200726190 /* HTMLOrderedDictionary.m */; }; 6234248A1AB467B200726190 /* HTMLOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 623424871AB467B200726190 /* HTMLOrderedDictionary.m */; }; - 6234584E1A9D2FA4009BD491 /* HTMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234584C1A9D2FA4009BD491 /* HTMLNode.h */; }; 6234584F1A9D2FA4009BD491 /* HTMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234584D1A9D2FA4009BD491 /* HTMLNode.m */; }; 623458501A9D2FA4009BD491 /* HTMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234584D1A9D2FA4009BD491 /* HTMLNode.m */; }; - 6234BEEE1AABBF1400DEB15F /* HTMLStackOfOpenElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234BEEC1AABBF1400DEB15F /* HTMLStackOfOpenElements.h */; }; 6234BEEF1AABBF1400DEB15F /* HTMLStackOfOpenElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234BEED1AABBF1400DEB15F /* HTMLStackOfOpenElements.m */; }; 6234BEF01AABBF1400DEB15F /* HTMLStackOfOpenElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234BEED1AABBF1400DEB15F /* HTMLStackOfOpenElements.m */; }; 6234CF571ABF892400B6077D /* libHTMLKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14DE19C7834000AD0C32 /* libHTMLKit.a */; }; - 6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6235CE991AA509430026937B /* NSString+HTMLKit.h */; }; 6235CE9C1AA509430026937B /* NSString+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */; }; 6235CE9D1AA509430026937B /* NSString+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */; }; - 6235CEA01AA5170A0026937B /* HTMLMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6235CE9E1AA5170A0026937B /* HTMLMarker.h */; }; 6235CEA11AA5170A0026937B /* HTMLMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9F1AA5170A0026937B /* HTMLMarker.m */; }; 6235CEA21AA5170A0026937B /* HTMLMarker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9F1AA5170A0026937B /* HTMLMarker.m */; }; - 62362A3C1A9FA70400301989 /* HTMLText.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3A1A9FA70400301989 /* HTMLText.h */; }; 62362A3D1A9FA70400301989 /* HTMLText.m in Sources */ = {isa = PBXBuildFile; fileRef = 62362A3B1A9FA70400301989 /* HTMLText.m */; }; 62362A3E1A9FA70400301989 /* HTMLText.m in Sources */ = {isa = PBXBuildFile; fileRef = 62362A3B1A9FA70400301989 /* HTMLText.m */; }; - 62363C3D1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */; }; 62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */; }; 62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */; }; 6236738E1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */; }; 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */; }; - 6238039F1AB63A8C008A53D0 /* HTMLEOFToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238039D1AB63A8C008A53D0 /* HTMLEOFToken.h */; }; 623803A01AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238039E1AB63A8C008A53D0 /* HTMLEOFToken.m */; }; 623803A11AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238039E1AB63A8C008A53D0 /* HTMLEOFToken.m */; }; - 623857911A9E772B003A45D9 /* HTMLDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238578F1A9E772B003A45D9 /* HTMLDocument.h */; }; 623857921A9E772B003A45D9 /* HTMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 623857901A9E772B003A45D9 /* HTMLDocument.m */; }; 623857931A9E772B003A45D9 /* HTMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 623857901A9E772B003A45D9 /* HTMLDocument.m */; }; - 623857961A9E8606003A45D9 /* HTMLDocumentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 623857941A9E8606003A45D9 /* HTMLDocumentType.h */; }; 623857971A9E8606003A45D9 /* HTMLDocumentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 623857951A9E8606003A45D9 /* HTMLDocumentType.m */; }; 623857981A9E8606003A45D9 /* HTMLDocumentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 623857951A9E8606003A45D9 /* HTMLDocumentType.m */; }; - 6238579B1A9E8934003A45D9 /* HTMLComment.h in Headers */ = {isa = PBXBuildFile; fileRef = 623857991A9E8934003A45D9 /* HTMLComment.h */; }; 6238579C1A9E8934003A45D9 /* HTMLComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238579A1A9E8934003A45D9 /* HTMLComment.m */; }; 6238579D1A9E8934003A45D9 /* HTMLComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238579A1A9E8934003A45D9 /* HTMLComment.m */; }; - 6238C9851AB8D6330006512E /* HTMLKitDOMExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */; }; 6238C9861AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */; }; 6238C9871AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */; }; 623916C71AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; }; @@ -60,33 +62,38 @@ 6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; }; 623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; }; 623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; }; - 624493A619CCC54100BCDDF4 /* HTMLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */; }; 624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; }; 624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; }; - 624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */; }; 624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; }; 624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; }; - 624717181B22333200C11912 /* HTMLNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717161B22333200C11912 /* HTMLNodeTraversal.h */; }; 624717191B22333200C11912 /* HTMLNodeTraversal.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717171B22333200C11912 /* HTMLNodeTraversal.m */; }; 6247171A1B22333200C11912 /* HTMLNodeTraversal.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717171B22333200C11912 /* HTMLNodeTraversal.m */; }; 6247171C1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; }; 6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; }; 624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */; }; 624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */; }; - 624717BC1B22009200B38302 /* HTMLTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717BA1B22009200B38302 /* HTMLTreeWalker.h */; }; 624717BD1B22009200B38302 /* HTMLTreeWalker.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717BB1B22009200B38302 /* HTMLTreeWalker.m */; }; 624717BE1B22009200B38302 /* HTMLTreeWalker.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717BB1B22009200B38302 /* HTMLTreeWalker.m */; }; - 6247A9431B152F4F00CCF25C /* HTMLNodeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */; }; 6247A9441B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */; }; 6247A9451B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */; }; - 6247A9471B152F8C00CCF25C /* HTMLNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */; }; - 624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */; }; + 624AB3171B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */; }; + 624AB3181B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */; }; + 624AB31A1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */; }; + 624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */; }; 624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; }; 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; }; 624AC90519FBFE9A00BD3C4A /* html5lib-tests in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90419FBFE8A00BD3C4A /* html5lib-tests */; }; 624AC90619FBFEA000BD3C4A /* html5lib-tests in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90419FBFE8A00BD3C4A /* html5lib-tests */; }; 624AC90E19FC702E00BD3C4A /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; 624AC90F19FC702E00BD3C4A /* HTML Standard.html in Resources */ = {isa = PBXBuildFile; fileRef = 624AC90D19FC702E00BD3C4A /* HTML Standard.html */; }; + 624B28B91B03DA820048D328 /* CSSTypeSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28B71B03DA820048D328 /* CSSTypeSelector.m */; }; + 624B28BA1B03DA820048D328 /* CSSTypeSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28B71B03DA820048D328 /* CSSTypeSelector.m */; }; + 624B28C01B0413200048D328 /* CSSAttributeSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28BE1B0413200048D328 /* CSSAttributeSelector.m */; }; + 624B28C11B0413200048D328 /* CSSAttributeSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28BE1B0413200048D328 /* CSSAttributeSelector.m */; }; + 624B28C51B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */; }; + 624B28C61B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */; }; + 624B371F1B24E9BA0010BDDF /* CSSInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */; }; + 624B37201B24E9BA0010BDDF /* CSSInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */; }; 624B9FB21AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; }; 624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; }; @@ -95,7 +102,6 @@ 624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; }; 625A14B019C7829400AD0C32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AF19C7829400AD0C32 /* Cocoa.framework */; }; 625A14BA19C7829400AD0C32 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 625A14B819C7829400AD0C32 /* InfoPlist.strings */; }; - 625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A14BD19C7829400AD0C32 /* HTMLKit.m */; }; 625A14C519C7829400AD0C32 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14C419C7829400AD0C32 /* XCTest.framework */; }; 625A14C619C7829400AD0C32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AF19C7829400AD0C32 /* Cocoa.framework */; }; 625A14C919C7829400AD0C32 /* HTMLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AC19C7829400AD0C32 /* HTMLKit.framework */; }; @@ -103,48 +109,102 @@ 625A14E019C7834100AD0C32 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14DF19C7834100AD0C32 /* Foundation.framework */; }; 625A14ED19C7834100AD0C32 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14C419C7829400AD0C32 /* XCTest.framework */; }; 625A14EE19C7834100AD0C32 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14DF19C7834100AD0C32 /* Foundation.framework */; }; - 625A150219C783DE00AD0C32 /* HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A14BD19C7829400AD0C32 /* HTMLKit.m */; }; 625A150319C783E200AD0C32 /* HTMLKit.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 625A14BC19C7829400AD0C32 /* HTMLKit.h */; }; - 625A150419C783EB00AD0C32 /* HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A14BC19C7829400AD0C32 /* HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 625A150819C78ABA00AD0C32 /* HTMLInputStreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */; }; 625A150919C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A150719C78ABA00AD0C32 /* HTMLInputStreamReader.m */; }; 625A150A19C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A150719C78ABA00AD0C32 /* HTMLInputStreamReader.m */; }; - 6279F87419E1808D00F12EE5 /* HTMLElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 6279F87219E1808D00F12EE5 /* HTMLElement.h */; }; + 626652F91C03D7AC00C3F121 /* HTMLKitErrorDomain.h in Headers */ = {isa = PBXBuildFile; fileRef = 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6279F87519E1808D00F12EE5 /* HTMLElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 6279F87319E1808D00F12EE5 /* HTMLElement.m */; }; 6279F87619E1808D00F12EE5 /* HTMLElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 6279F87319E1808D00F12EE5 /* HTMLElement.m */; }; - 62AE593519F97D880043F069 /* HTMLParseErrorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593319F97D880043F069 /* HTMLParseErrorToken.h */; }; + 628AF62F1BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */; }; + 628AF6301BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */; }; + 628AF6341BC9A63D00496128 /* CSSNthExpressionSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF6321BC9A63D00496128 /* CSSNthExpressionSelector.m */; }; + 628AF6351BC9A63D00496128 /* CSSNthExpressionSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF6321BC9A63D00496128 /* CSSNthExpressionSelector.m */; }; + 628AF63F1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF63D1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m */; }; + 628AF6401BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 628AF63D1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m */; }; + 629AA0EA1BDD9C2900D5CC98 /* HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 625A14BC19C7829400AD0C32 /* HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0EB1BDD9C2900D5CC98 /* HTMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F873E919E088C90062683C /* HTMLParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0EC1BDD9C2900D5CC98 /* HTMLDOM.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3F1A9FDE8A00301989 /* HTMLDOM.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0ED1BDD9C2900D5CC98 /* HTMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234584C1A9D2FA4009BD491 /* HTMLNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0EE1BDD9C2900D5CC98 /* HTMLDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238578F1A9E772B003A45D9 /* HTMLDocument.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0EF1BDD9C2900D5CC98 /* HTMLDocumentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 623857941A9E8606003A45D9 /* HTMLDocumentType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F01BDD9C2900D5CC98 /* HTMLDocumentFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = 623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F11BDD9C2900D5CC98 /* HTMLElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 6279F87219E1808D00F12EE5 /* HTMLElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F21BDD9C2900D5CC98 /* HTMLComment.h in Headers */ = {isa = PBXBuildFile; fileRef = 623857991A9E8934003A45D9 /* HTMLComment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F31BDD9C2900D5CC98 /* HTMLText.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3A1A9FA70400301989 /* HTMLText.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F41BDD9C2A00D5CC98 /* HTMLTemplate.h in Headers */ = {isa = PBXBuildFile; fileRef = 623406DF1ADB04F9004677A3 /* HTMLTemplate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F51BDD9C2A00D5CC98 /* HTMLNodeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F61BDD9C2A00D5CC98 /* HTMLTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717BA1B22009200B38302 /* HTMLTreeWalker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F71BDD9C2A00D5CC98 /* HTMLNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717161B22333200C11912 /* HTMLNodeTraversal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F81BDD9C2A00D5CC98 /* HTMLNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0F91BDD9C2A00D5CC98 /* HTMLKitDOMExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FA1BDD9C2A00D5CC98 /* HTMLNamespaces.h in Headers */ = {isa = PBXBuildFile; fileRef = 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FB1BDD9C2A00D5CC98 /* HTMLQuirksMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FC1BDD9C2A00D5CC98 /* NSString+HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6235CE991AA509430026937B /* NSString+HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FD1BDD9C2A00D5CC98 /* NSCharacterSet+HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B28C21B04190D0048D328 /* NSCharacterSet+HTMLKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FE1BDD9C2A00D5CC98 /* HTMLOrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 623424861AB467B200726190 /* HTMLOrderedDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA0FF1BDD9C2A00D5CC98 /* CSSSelectors.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AB3151B04EA4200F3830D /* CSSSelectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1001BDD9C2A00D5CC98 /* CSSSelectorParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 622BF57F1BBF2FD700363583 /* CSSSelectorParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1011BDD9C2A00D5CC98 /* CSSSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 62079BE71AF56F1E00D3B402 /* CSSSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1021BDD9C2B00D5CC98 /* CSSSelectorBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 62FA98061BD5A7E200A2AF86 /* CSSSelectorBlock.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1031BDD9C2B00D5CC98 /* CSSTypeSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B28B61B03DA820048D328 /* CSSTypeSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1041BDD9C2B00D5CC98 /* CSSAttributeSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B28BD1B0413200048D328 /* CSSAttributeSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1051BDD9C2B00D5CC98 /* CSSPseudoClassSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 620EE9471BC46F2A0028ED34 /* CSSPseudoClassSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1061BDD9C2B00D5CC98 /* CSSStructuralPseudoSelectors.h in Headers */ = {isa = PBXBuildFile; fileRef = 628AF63C1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1071BDD9C2B00D5CC98 /* CSSNthExpressionSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 628AF6311BC9A63D00496128 /* CSSNthExpressionSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1081BDD9C2B00D5CC98 /* CSSPseudoFunctionSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 62ACB8DB1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA1091BDD9C2B00D5CC98 /* CSSCombinatorSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 62FA04E11BCC360D009ABF98 /* CSSCombinatorSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA10A1BDD9C2B00D5CC98 /* CSSCompoundSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 629AA10B1BDD9C5200D5CC98 /* HTMLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */; }; + 629AA10C1BDD9C5200D5CC98 /* HTMLTokenizerStates.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */; }; + 629AA10D1BDD9C5300D5CC98 /* HTMLTokenizerCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */; }; + 629AA10E1BDD9C5300D5CC98 /* HTMLTokenizerEntities.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */; }; + 629AA10F1BDD9C5300D5CC98 /* HTMLTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */; }; + 629AA1101BDD9C5300D5CC98 /* HTMLToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */; }; + 629AA1111BDD9C5300D5CC98 /* HTMLCharacterToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE594719F9948A0043F069 /* HTMLCharacterToken.h */; }; + 629AA1121BDD9C5300D5CC98 /* HTMLCommentToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE594219F992F30043F069 /* HTMLCommentToken.h */; }; + 629AA1131BDD9C5300D5CC98 /* HTMLDOCTYPEToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593819F97E1C0043F069 /* HTMLDOCTYPEToken.h */; }; + 629AA1141BDD9C5400D5CC98 /* HTMLParseErrorToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593319F97D880043F069 /* HTMLParseErrorToken.h */; }; + 629AA1151BDD9C5400D5CC98 /* HTMLTagToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593D19F9907C0043F069 /* HTMLTagToken.h */; }; + 629AA1161BDD9C5400D5CC98 /* HTMLEOFToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238039D1AB63A8C008A53D0 /* HTMLEOFToken.h */; }; + 629AA1171BDD9C5400D5CC98 /* HTMLStackOfOpenElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234BEEC1AABBF1400DEB15F /* HTMLStackOfOpenElements.h */; }; + 629AA1181BDD9C5400D5CC98 /* HTMLListOfActiveFormattingElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */; }; + 629AA1191BDD9C5400D5CC98 /* HTMLElementTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */; }; + 629AA11A1BDD9C5400D5CC98 /* HTMLElementAdjustment.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */; }; + 629AA11B1BDD9C5500D5CC98 /* HTMLParserInsertionModes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */; }; + 629AA11C1BDD9C5500D5CC98 /* HTMLMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6235CE9E1AA5170A0026937B /* HTMLMarker.h */; }; + 629AA11D1BDD9C5500D5CC98 /* CSSCodePoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B37211B250BB50010BDDF /* CSSCodePoints.h */; }; + 629AA11E1BDD9C5500D5CC98 /* CSSInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B371C1B24E9BA0010BDDF /* CSSInputStream.h */; }; + 629AA11F1BDD9C5E00D5CC98 /* CSSNthExpressionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62AE593619F97D880043F069 /* HTMLParseErrorToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593419F97D880043F069 /* HTMLParseErrorToken.m */; }; 62AE593719F97D880043F069 /* HTMLParseErrorToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593419F97D880043F069 /* HTMLParseErrorToken.m */; }; - 62AE593A19F97E1C0043F069 /* HTMLDOCTYPEToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593819F97E1C0043F069 /* HTMLDOCTYPEToken.h */; }; 62AE593B19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593919F97E1C0043F069 /* HTMLDOCTYPEToken.m */; }; 62AE593C19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593919F97E1C0043F069 /* HTMLDOCTYPEToken.m */; }; - 62AE593F19F9907C0043F069 /* HTMLTagToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE593D19F9907C0043F069 /* HTMLTagToken.h */; }; 62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593E19F9907C0043F069 /* HTMLTagToken.m */; }; 62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE593E19F9907C0043F069 /* HTMLTagToken.m */; }; - 62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE594219F992F30043F069 /* HTMLCommentToken.h */; }; 62AE594519F992F30043F069 /* HTMLCommentToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594319F992F30043F069 /* HTMLCommentToken.m */; }; 62AE594619F992F30043F069 /* HTMLCommentToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594319F992F30043F069 /* HTMLCommentToken.m */; }; - 62AE594919F9948A0043F069 /* HTMLCharacterToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE594719F9948A0043F069 /* HTMLCharacterToken.h */; }; 62AE594A19F9948A0043F069 /* HTMLCharacterToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594819F9948A0043F069 /* HTMLCharacterToken.m */; }; 62AE594B19F9948A0043F069 /* HTMLCharacterToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594819F9948A0043F069 /* HTMLCharacterToken.m */; }; 62D8345919FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; }; 62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; }; - 62D89DB01AE7080300B6243D /* HTMLDOM.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3F1A9FDE8A00301989 /* HTMLDOM.h */; }; - 62D89DB11AE7081600B6243D /* HTMLTokenizerStates.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */; }; - 62D89DB21AE7081600B6243D /* HTMLTokenizerCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */; }; - 62D89DB31AE7081600B6243D /* HTMLNamespaces.h in Headers */ = {isa = PBXBuildFile; fileRef = 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */; }; - 62D89DB41AE7081600B6243D /* HTMLElementTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */; }; - 62D89DB51AE7081600B6243D /* HTMLElementAdjustment.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */; }; - 62D89DB61AE7081600B6243D /* HTMLParserInsertionModes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */; }; - 62D89DB71AE7081600B6243D /* HTMLQuirksMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */; }; 62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; }; - 62F31FDD19E9DCCF007F0657 /* HTMLTokenizerEntities.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */; }; 62F31FDE19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; }; 62F31FDF19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; }; - 62F873EB19E088C90062683C /* HTMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F873E919E088C90062683C /* HTMLParser.h */; }; + 62F501661BC9576B0069F47B /* CSSNthExpressionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */; }; + 62F501671BC9576B0069F47B /* CSSNthExpressionParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */; }; + 62F658701BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */; }; + 62F658711BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */; }; 62F873EC19E088C90062683C /* HTMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F873EA19E088C90062683C /* HTMLParser.m */; }; 62F873ED19E088C90062683C /* HTMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F873EA19E088C90062683C /* HTMLParser.m */; }; + 62FA04E41BCC360D009ABF98 /* CSSCombinatorSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA04E21BCC360D009ABF98 /* CSSCombinatorSelector.m */; }; + 62FA04E51BCC360D009ABF98 /* CSSCombinatorSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA04E21BCC360D009ABF98 /* CSSCombinatorSelector.m */; }; + 62FA98041BD57B6200A2AF86 /* CSSSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA98031BD57B6200A2AF86 /* CSSSelectors.m */; }; + 62FA98051BD57B6200A2AF86 /* CSSSelectors.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA98031BD57B6200A2AF86 /* CSSSelectors.m */; }; + 62FA98091BD5A7E200A2AF86 /* CSSSelectorBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA98071BD5A7E200A2AF86 /* CSSSelectorBlock.m */; }; + 62FA980A1BD5A7E200A2AF86 /* CSSSelectorBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FA98071BD5A7E200A2AF86 /* CSSSelectorBlock.m */; }; + 62FC60461BD0519B0042BBE7 /* CSSSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FC60451BD0519B0042BBE7 /* CSSSelector.m */; }; + 62FC60471BD0519B0042BBE7 /* CSSSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FC60451BD0519B0042BBE7 /* CSSSelector.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -178,7 +238,19 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 62079BE71AF56F1E00D3B402 /* CSSSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelector.h; sourceTree = ""; }; + 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSCompoundSelector.h; sourceTree = ""; }; + 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCompoundSelector.m; sourceTree = ""; }; + 620EE9471BC46F2A0028ED34 /* CSSPseudoClassSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPseudoClassSelector.h; sourceTree = ""; }; + 620EE9481BC46F2A0028ED34 /* CSSPseudoClassSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSPseudoClassSelector.m; sourceTree = ""; }; + 62132E571C01F83200084175 /* CSSSelectorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorTest.h; sourceTree = ""; }; + 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 = ""; }; + 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; path = HTMLElementTypes.h; sourceTree = ""; }; + 622BF57F1BBF2FD700363583 /* CSSSelectorParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorParser.h; sourceTree = ""; }; + 622BF5801BBF2FD700363583 /* CSSSelectorParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParser.m; sourceTree = ""; }; 623406DF1ADB04F9004677A3 /* HTMLTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTemplate.h; sourceTree = ""; }; 623406E01ADB04F9004677A3 /* HTMLTemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTemplate.m; sourceTree = ""; }; 623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDocumentFragment.h; sourceTree = ""; }; @@ -230,10 +302,22 @@ 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeIterator.h; sourceTree = ""; }; 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeIterator.m; sourceTree = ""; }; 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeFilter.h; sourceTree = ""; }; + 624AB3151B04EA4200F3830D /* CSSSelectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSSelectors.h; sourceTree = ""; }; + 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTypeSelectorTests.m; sourceTree = ""; }; + 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSAttributeSelectorTests.m; sourceTree = ""; }; 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokens.h; sourceTree = ""; }; 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTokenizerTests.m; sourceTree = ""; }; 624AC90419FBFE8A00BD3C4A /* html5lib-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "html5lib-tests"; sourceTree = ""; }; 624AC90D19FC702E00BD3C4A /* HTML Standard.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "HTML Standard.html"; sourceTree = ""; }; + 624B28B61B03DA820048D328 /* CSSTypeSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSTypeSelector.h; sourceTree = ""; }; + 624B28B71B03DA820048D328 /* CSSTypeSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTypeSelector.m; sourceTree = ""; }; + 624B28BD1B0413200048D328 /* CSSAttributeSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSAttributeSelector.h; sourceTree = ""; }; + 624B28BE1B0413200048D328 /* CSSAttributeSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSAttributeSelector.m; sourceTree = ""; }; + 624B28C21B04190D0048D328 /* NSCharacterSet+HTMLKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCharacterSet+HTMLKit.h"; sourceTree = ""; }; + 624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSCharacterSet+HTMLKit.m"; sourceTree = ""; }; + 624B371C1B24E9BA0010BDDF /* CSSInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 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; path = 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 = ""; }; 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = ""; }; @@ -246,7 +330,6 @@ 625A14B919C7829400AD0C32 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 625A14BB19C7829400AD0C32 /* HTMLKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HTMLKit-Prefix.pch"; sourceTree = ""; }; 625A14BC19C7829400AD0C32 /* HTMLKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLKit.h; sourceTree = ""; }; - 625A14BD19C7829400AD0C32 /* HTMLKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTMLKit.m; sourceTree = ""; }; 625A14C319C7829400AD0C32 /* HTMLKitFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTMLKitFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 625A14C419C7829400AD0C32 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 625A14CC19C7829400AD0C32 /* HTMLKitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HTMLKitTests-Info.plist"; sourceTree = ""; }; @@ -256,10 +339,18 @@ 625A14EC19C7834100AD0C32 /* HTMLKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTMLKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 625A150619C78ABA00AD0C32 /* HTMLInputStreamReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLInputStreamReader.h; sourceTree = ""; }; 625A150719C78ABA00AD0C32 /* HTMLInputStreamReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLInputStreamReader.m; sourceTree = ""; }; + 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLKitErrorDomain.h; sourceTree = ""; }; 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLParserInsertionModes.h; sourceTree = ""; }; 6279F87219E1808D00F12EE5 /* HTMLElement.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = HTMLElement.h; sourceTree = ""; }; 6279F87319E1808D00F12EE5 /* HTMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLElement.m; sourceTree = ""; }; + 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionsParserTests.m; sourceTree = ""; }; + 628AF6311BC9A63D00496128 /* CSSNthExpressionSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSNthExpressionSelector.h; sourceTree = ""; }; + 628AF6321BC9A63D00496128 /* CSSNthExpressionSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionSelector.m; sourceTree = ""; }; + 628AF63C1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSStructuralPseudoSelectors.h; sourceTree = ""; }; + 628AF63D1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSStructuralPseudoSelectors.m; sourceTree = ""; }; 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLNamespaces.h; sourceTree = ""; }; + 62ACB8DB1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPseudoFunctionSelector.h; sourceTree = ""; }; + 62ACB8DC1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSPseudoFunctionSelector.m; sourceTree = ""; }; 62AE593319F97D880043F069 /* HTMLParseErrorToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParseErrorToken.h; sourceTree = ""; }; 62AE593419F97D880043F069 /* HTMLParseErrorToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParseErrorToken.m; sourceTree = ""; }; 62AE593819F97E1C0043F069 /* HTMLDOCTYPEToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDOCTYPEToken.h; sourceTree = ""; }; @@ -276,8 +367,17 @@ 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = ""; }; 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerEntities.h; sourceTree = ""; }; 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizerEntities.m; sourceTree = ""; }; + 62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 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 = ""; }; 62F873E919E088C90062683C /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 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; path = CSSCombinatorSelector.h; sourceTree = ""; }; + 62FA04E21BCC360D009ABF98 /* CSSCombinatorSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelector.m; sourceTree = ""; }; + 62FA98031BD57B6200A2AF86 /* CSSSelectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectors.m; sourceTree = ""; }; + 62FA98061BD5A7E200A2AF86 /* CSSSelectorBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorBlock.h; sourceTree = ""; }; + 62FA98071BD5A7E200A2AF86 /* CSSSelectorBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorBlock.m; sourceTree = ""; }; + 62FC60451BD0519B0042BBE7 /* CSSSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelector.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -320,6 +420,42 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 62079BE61AF5656600D3B402 /* Selectors */ = { + isa = PBXGroup; + children = ( + 624AB3151B04EA4200F3830D /* CSSSelectors.h */, + 62FA98031BD57B6200A2AF86 /* CSSSelectors.m */, + 624B37211B250BB50010BDDF /* CSSCodePoints.h */, + 624B371C1B24E9BA0010BDDF /* CSSInputStream.h */, + 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */, + 622BF57F1BBF2FD700363583 /* CSSSelectorParser.h */, + 622BF5801BBF2FD700363583 /* CSSSelectorParser.m */, + 62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */, + 62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */, + 62079BE71AF56F1E00D3B402 /* CSSSelector.h */, + 62FC60451BD0519B0042BBE7 /* CSSSelector.m */, + 62FA98061BD5A7E200A2AF86 /* CSSSelectorBlock.h */, + 62FA98071BD5A7E200A2AF86 /* CSSSelectorBlock.m */, + 624B28B61B03DA820048D328 /* CSSTypeSelector.h */, + 624B28B71B03DA820048D328 /* CSSTypeSelector.m */, + 624B28BD1B0413200048D328 /* CSSAttributeSelector.h */, + 624B28BE1B0413200048D328 /* CSSAttributeSelector.m */, + 620EE9471BC46F2A0028ED34 /* CSSPseudoClassSelector.h */, + 620EE9481BC46F2A0028ED34 /* CSSPseudoClassSelector.m */, + 628AF63C1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.h */, + 628AF63D1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m */, + 628AF6311BC9A63D00496128 /* CSSNthExpressionSelector.h */, + 628AF6321BC9A63D00496128 /* CSSNthExpressionSelector.m */, + 62ACB8DB1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.h */, + 62ACB8DC1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.m */, + 62FA04E11BCC360D009ABF98 /* CSSCombinatorSelector.h */, + 62FA04E21BCC360D009ABF98 /* CSSCombinatorSelector.m */, + 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */, + 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */, + ); + name = Selectors; + sourceTree = ""; + }; 6236738C1AC0CD2400FF89B3 /* Tokenizer */ = { isa = PBXGroup; children = ( @@ -451,12 +587,13 @@ isa = PBXGroup; children = ( 625A14BC19C7829400AD0C32 /* HTMLKit.h */, - 625A14BD19C7829400AD0C32 /* HTMLKit.m */, + 626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */, 62AE593219F97CCA0043F069 /* Tokenizing */, 628E16EC1ADAE71700B15A06 /* Parsing */, 623719441AA1472B002E03C8 /* DOM */, 628E16ED1ADAE73700B15A06 /* Categories */, 628E16EE1ADAE75300B15A06 /* Structures */, + 62079BE61AF5656600D3B402 /* Selectors */, 625A14B619C7829400AD0C32 /* Supporting Files */, ); name = "Source Code"; @@ -482,6 +619,14 @@ 624B9FB81AE072D500646C4C /* Categories */, 624E1A2D1B1D1C8A00E66AAC /* Structures */, 625A14CB19C7829400AD0C32 /* Supporting Files */, + 62132E571C01F83200084175 /* CSSSelectorTest.h */, + 62132E581C01F83200084175 /* CSSSelectorTest.m */, + 621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */, + 628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */, + 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */, + 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */, + 62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */, + 621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */, ); name = Tests; path = HTMLKitTests; @@ -490,6 +635,7 @@ 625A14CB19C7829400AD0C32 /* Supporting Files */ = { isa = PBXGroup; children = ( + 62132E5B1C021FF200084175 /* css-tests */, 624AC90D19FC702E00BD3C4A /* HTML Standard.html */, 624AC90419FBFE8A00BD3C4A /* html5lib-tests */, 625A14CC19C7829400AD0C32 /* HTMLKitTests-Info.plist */, @@ -521,6 +667,8 @@ children = ( 6235CE991AA509430026937B /* NSString+HTMLKit.h */, 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */, + 624B28C21B04190D0048D328 /* NSCharacterSet+HTMLKit.h */, + 624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */, ); name = Categories; sourceTree = ""; @@ -571,45 +719,61 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 624717181B22333200C11912 /* HTMLNodeTraversal.h in Headers */, - 6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */, - 62D89DB11AE7081600B6243D /* HTMLTokenizerStates.h in Headers */, - 62D89DB21AE7081600B6243D /* HTMLTokenizerCharacters.h in Headers */, - 62D89DB31AE7081600B6243D /* HTMLNamespaces.h in Headers */, - 62D89DB41AE7081600B6243D /* HTMLElementTypes.h in Headers */, - 62D89DB51AE7081600B6243D /* HTMLElementAdjustment.h in Headers */, - 62D89DB61AE7081600B6243D /* HTMLParserInsertionModes.h in Headers */, - 62D89DB71AE7081600B6243D /* HTMLQuirksMode.h in Headers */, - 62D89DB01AE7080300B6243D /* HTMLDOM.h in Headers */, - 62F873EB19E088C90062683C /* HTMLParser.h in Headers */, - 624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */, - 62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */, - 624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */, - 6235CEA01AA5170A0026937B /* HTMLMarker.h in Headers */, - 62F31FDD19E9DCCF007F0657 /* HTMLTokenizerEntities.h in Headers */, - 623406E11ADB04F9004677A3 /* HTMLTemplate.h in Headers */, - 6234BEEE1AABBF1400DEB15F /* HTMLStackOfOpenElements.h in Headers */, - 6238C9851AB8D6330006512E /* HTMLKitDOMExceptions.h in Headers */, - 6238039F1AB63A8C008A53D0 /* HTMLEOFToken.h in Headers */, - 6279F87419E1808D00F12EE5 /* HTMLElement.h in Headers */, - 62AE593F19F9907C0043F069 /* HTMLTagToken.h in Headers */, - 623857911A9E772B003A45D9 /* HTMLDocument.h in Headers */, - 624493A619CCC54100BCDDF4 /* HTMLTokenizer.h in Headers */, - 62AE593A19F97E1C0043F069 /* HTMLDOCTYPEToken.h in Headers */, - 6247A9471B152F8C00CCF25C /* HTMLNodeFilter.h in Headers */, - 623424881AB467B200726190 /* HTMLOrderedDictionary.h in Headers */, - 6247A9431B152F4F00CCF25C /* HTMLNodeIterator.h in Headers */, - 625A150419C783EB00AD0C32 /* HTMLKit.h in Headers */, - 625A150819C78ABA00AD0C32 /* HTMLInputStreamReader.h in Headers */, - 6238579B1A9E8934003A45D9 /* HTMLComment.h in Headers */, - 62AE593519F97D880043F069 /* HTMLParseErrorToken.h in Headers */, - 62AE594919F9948A0043F069 /* HTMLCharacterToken.h in Headers */, - 623857961A9E8606003A45D9 /* HTMLDocumentType.h in Headers */, - 623406E61ADB05AD004677A3 /* HTMLDocumentFragment.h in Headers */, - 62363C3D1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h in Headers */, - 624717BC1B22009200B38302 /* HTMLTreeWalker.h in Headers */, - 62362A3C1A9FA70400301989 /* HTMLText.h in Headers */, - 6234584E1A9D2FA4009BD491 /* HTMLNode.h in Headers */, + 629AA0EA1BDD9C2900D5CC98 /* HTMLKit.h in Headers */, + 626652F91C03D7AC00C3F121 /* HTMLKitErrorDomain.h in Headers */, + 629AA0EB1BDD9C2900D5CC98 /* HTMLParser.h in Headers */, + 629AA0EC1BDD9C2900D5CC98 /* HTMLDOM.h in Headers */, + 629AA0ED1BDD9C2900D5CC98 /* HTMLNode.h in Headers */, + 629AA0EE1BDD9C2900D5CC98 /* HTMLDocument.h in Headers */, + 629AA0EF1BDD9C2900D5CC98 /* HTMLDocumentType.h in Headers */, + 629AA0F01BDD9C2900D5CC98 /* HTMLDocumentFragment.h in Headers */, + 629AA0F11BDD9C2900D5CC98 /* HTMLElement.h in Headers */, + 629AA0F21BDD9C2900D5CC98 /* HTMLComment.h in Headers */, + 629AA0F31BDD9C2900D5CC98 /* HTMLText.h in Headers */, + 629AA0F41BDD9C2A00D5CC98 /* HTMLTemplate.h in Headers */, + 629AA0F51BDD9C2A00D5CC98 /* HTMLNodeIterator.h in Headers */, + 629AA0F61BDD9C2A00D5CC98 /* HTMLTreeWalker.h in Headers */, + 629AA0F71BDD9C2A00D5CC98 /* HTMLNodeTraversal.h in Headers */, + 629AA0F81BDD9C2A00D5CC98 /* HTMLNodeFilter.h in Headers */, + 629AA0F91BDD9C2A00D5CC98 /* HTMLKitDOMExceptions.h in Headers */, + 629AA0FA1BDD9C2A00D5CC98 /* HTMLNamespaces.h in Headers */, + 629AA0FB1BDD9C2A00D5CC98 /* HTMLQuirksMode.h in Headers */, + 629AA0FC1BDD9C2A00D5CC98 /* NSString+HTMLKit.h in Headers */, + 629AA0FD1BDD9C2A00D5CC98 /* NSCharacterSet+HTMLKit.h in Headers */, + 629AA0FE1BDD9C2A00D5CC98 /* HTMLOrderedDictionary.h in Headers */, + 629AA0FF1BDD9C2A00D5CC98 /* CSSSelectors.h in Headers */, + 629AA1001BDD9C2A00D5CC98 /* CSSSelectorParser.h in Headers */, + 629AA11F1BDD9C5E00D5CC98 /* CSSNthExpressionParser.h in Headers */, + 629AA1011BDD9C2A00D5CC98 /* CSSSelector.h in Headers */, + 629AA1021BDD9C2B00D5CC98 /* CSSSelectorBlock.h in Headers */, + 629AA1031BDD9C2B00D5CC98 /* CSSTypeSelector.h in Headers */, + 629AA1041BDD9C2B00D5CC98 /* CSSAttributeSelector.h in Headers */, + 629AA1051BDD9C2B00D5CC98 /* CSSPseudoClassSelector.h in Headers */, + 629AA1061BDD9C2B00D5CC98 /* CSSStructuralPseudoSelectors.h in Headers */, + 629AA1071BDD9C2B00D5CC98 /* CSSNthExpressionSelector.h in Headers */, + 629AA1081BDD9C2B00D5CC98 /* CSSPseudoFunctionSelector.h in Headers */, + 629AA1091BDD9C2B00D5CC98 /* CSSCombinatorSelector.h in Headers */, + 629AA10A1BDD9C2B00D5CC98 /* CSSCompoundSelector.h in Headers */, + 629AA10B1BDD9C5200D5CC98 /* HTMLTokenizer.h in Headers */, + 629AA10C1BDD9C5200D5CC98 /* HTMLTokenizerStates.h in Headers */, + 629AA10D1BDD9C5300D5CC98 /* HTMLTokenizerCharacters.h in Headers */, + 629AA10E1BDD9C5300D5CC98 /* HTMLTokenizerEntities.h in Headers */, + 629AA10F1BDD9C5300D5CC98 /* HTMLTokens.h in Headers */, + 629AA1101BDD9C5300D5CC98 /* HTMLToken.h in Headers */, + 629AA1111BDD9C5300D5CC98 /* HTMLCharacterToken.h in Headers */, + 629AA1121BDD9C5300D5CC98 /* HTMLCommentToken.h in Headers */, + 629AA1131BDD9C5300D5CC98 /* HTMLDOCTYPEToken.h in Headers */, + 629AA1141BDD9C5400D5CC98 /* HTMLParseErrorToken.h in Headers */, + 629AA1151BDD9C5400D5CC98 /* HTMLTagToken.h in Headers */, + 629AA1161BDD9C5400D5CC98 /* HTMLEOFToken.h in Headers */, + 629AA1171BDD9C5400D5CC98 /* HTMLStackOfOpenElements.h in Headers */, + 629AA1181BDD9C5400D5CC98 /* HTMLListOfActiveFormattingElements.h in Headers */, + 629AA1191BDD9C5400D5CC98 /* HTMLElementTypes.h in Headers */, + 629AA11A1BDD9C5400D5CC98 /* HTMLElementAdjustment.h in Headers */, + 629AA11B1BDD9C5500D5CC98 /* HTMLParserInsertionModes.h in Headers */, + 629AA11C1BDD9C5500D5CC98 /* HTMLMarker.h in Headers */, + 629AA11D1BDD9C5500D5CC98 /* CSSCodePoints.h in Headers */, + 629AA11E1BDD9C5500D5CC98 /* CSSInputStream.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -693,7 +857,7 @@ 625A14A319C7829400AD0C32 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = BrainCookie; TargetAttributes = { 625A14C219C7829400AD0C32 = { @@ -739,6 +903,7 @@ files = ( 624AC90F19FC702E00BD3C4A /* HTML Standard.html in Resources */, 624AC90519FBFE9A00BD3C4A /* html5lib-tests in Resources */, + 62132E5D1C021FF200084175 /* css-tests in Resources */, 625A14CF19C7829400AD0C32 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -747,6 +912,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62132E5C1C021FF200084175 /* css-tests in Resources */, 624AC90619FBFEA000BD3C4A /* html5lib-tests in Resources */, 624AC90E19FC702E00BD3C4A /* HTML Standard.html in Resources */, ); @@ -759,34 +925,48 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62F501671BC9576B0069F47B /* CSSNthExpressionParser.m in Sources */, 62362A3E1A9FA70400301989 /* HTMLText.m in Sources */, + 622BF5831BBF2FD700363583 /* CSSSelectorParser.m in Sources */, 6235CE9D1AA509430026937B /* NSString+HTMLKit.m in Sources */, 6247A9451B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */, 6238579D1A9E8934003A45D9 /* HTMLComment.m in Sources */, 6234BEF01AABBF1400DEB15F /* HTMLStackOfOpenElements.m in Sources */, 624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */, 6235CEA21AA5170A0026937B /* HTMLMarker.m in Sources */, + 62FA98051BD57B6200A2AF86 /* CSSSelectors.m in Sources */, 6234248A1AB467B200726190 /* HTMLOrderedDictionary.m in Sources */, 624717BE1B22009200B38302 /* HTMLTreeWalker.m in Sources */, 62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */, + 624B37201B24E9BA0010BDDF /* CSSInputStream.m in Sources */, 62AE594619F992F30043F069 /* HTMLCommentToken.m in Sources */, 62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */, 62AE593C19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */, 623406E31ADB04F9004677A3 /* HTMLTemplate.m in Sources */, + 62FA04E51BCC360D009ABF98 /* CSSCombinatorSelector.m in Sources */, 6238C9871AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */, + 62FA980A1BD5A7E200A2AF86 /* CSSSelectorBlock.m in Sources */, + 628AF6401BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m in Sources */, 6247171A1B22333200C11912 /* HTMLNodeTraversal.m in Sources */, 62F873ED19E088C90062683C /* HTMLParser.m in Sources */, 623803A11AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */, + 624B28C61B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */, 6279F87619E1808D00F12EE5 /* HTMLElement.m in Sources */, + 620C877D1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */, 625A150A19C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */, + 628AF6351BC9A63D00496128 /* CSSNthExpressionSelector.m in Sources */, 623857931A9E772B003A45D9 /* HTMLDocument.m in Sources */, 623406E81ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */, 624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */, + 620EE94B1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */, 624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */, - 625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */, + 624B28BA1B03DA820048D328 /* CSSTypeSelector.m in Sources */, + 62FC60471BD0519B0042BBE7 /* CSSSelector.m in Sources */, 623857981A9E8606003A45D9 /* HTMLDocumentType.m in Sources */, + 620C877F1BD4519A00FB3EEE /* CSSPseudoFunctionSelector.m in Sources */, 62AE594B19F9948A0043F069 /* HTMLCharacterToken.m in Sources */, 623458501A9D2FA4009BD491 /* HTMLNode.m in Sources */, + 624B28C11B0413200048D328 /* CSSAttributeSelector.m in Sources */, 62F31FDF19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */, 62AE593719F97D880043F069 /* HTMLParseErrorToken.m in Sources */, ); @@ -796,11 +976,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */, 6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, + 62F658711BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */, 623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */, 6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */, 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */, 624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */, + 624AB3181B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */, 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */, 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */, 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */, @@ -808,6 +992,9 @@ 62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */, 6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */, 624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */, + 621FBE5B1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */, + 621FBE5E1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */, + 628AF6301BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -816,6 +1003,7 @@ buildActionMask = 2147483647; files = ( 62362A3D1A9FA70400301989 /* HTMLText.m in Sources */, + 622BF5821BBF2FD700363583 /* CSSSelectorParser.m in Sources */, 6235CE9C1AA509430026937B /* NSString+HTMLKit.m in Sources */, 6247A9441B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */, 6238579C1A9E8934003A45D9 /* HTMLComment.m in Sources */, @@ -823,26 +1011,39 @@ 624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */, 6235CEA11AA5170A0026937B /* HTMLMarker.m in Sources */, 623424891AB467B200726190 /* HTMLOrderedDictionary.m in Sources */, + 62FA98041BD57B6200A2AF86 /* CSSSelectors.m in Sources */, 624717BD1B22009200B38302 /* HTMLTreeWalker.m in Sources */, 62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */, + 62F501661BC9576B0069F47B /* CSSNthExpressionParser.m in Sources */, + 624B371F1B24E9BA0010BDDF /* CSSInputStream.m in Sources */, 62AE594519F992F30043F069 /* HTMLCommentToken.m in Sources */, 62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */, 62AE593B19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */, 623406E21ADB04F9004677A3 /* HTMLTemplate.m in Sources */, + 62FA04E41BCC360D009ABF98 /* CSSCombinatorSelector.m in Sources */, + 628AF63F1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m in Sources */, + 62FA98091BD5A7E200A2AF86 /* CSSSelectorBlock.m in Sources */, 6238C9861AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */, 624717191B22333200C11912 /* HTMLNodeTraversal.m in Sources */, 62F873EC19E088C90062683C /* HTMLParser.m in Sources */, 623803A01AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */, + 624B28C51B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */, 6279F87519E1808D00F12EE5 /* HTMLElement.m in Sources */, + 620C877C1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */, 625A150919C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */, 623857921A9E772B003A45D9 /* HTMLDocument.m in Sources */, 623406E71ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */, 624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */, + 620EE94A1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */, 624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */, - 625A150219C783DE00AD0C32 /* HTMLKit.m in Sources */, + 624B28B91B03DA820048D328 /* CSSTypeSelector.m in Sources */, 623857971A9E8606003A45D9 /* HTMLDocumentType.m in Sources */, + 62FC60461BD0519B0042BBE7 /* CSSSelector.m in Sources */, 62AE594A19F9948A0043F069 /* HTMLCharacterToken.m in Sources */, + 620C877E1BD4519A00FB3EEE /* CSSPseudoFunctionSelector.m in Sources */, 6234584F1A9D2FA4009BD491 /* HTMLNode.m in Sources */, + 624B28C01B0413200048D328 /* CSSAttributeSelector.m in Sources */, + 628AF6341BC9A63D00496128 /* CSSNthExpressionSelector.m in Sources */, 62F31FDE19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */, 62AE593619F97D880043F069 /* HTMLParseErrorToken.m in Sources */, ); @@ -852,11 +1053,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62132E591C01F83200084175 /* CSSSelectorTest.m in Sources */, 6239755A1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, + 62F658701BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m in Sources */, 623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */, 6247171C1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */, 62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 624AB31A1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */, 624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */, + 624AB3171B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */, 6236738E1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */, 624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */, 624B9FB21AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */, @@ -864,6 +1069,9 @@ 62D8345919FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */, 6239755E1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */, 624FC37A1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */, + 621FBE5A1BDAD68700BC9555 /* CSSSelectorParserTests.m in Sources */, + 621FBE5D1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m in Sources */, + 628AF62F1BC99A6C00496128 /* CSSNthExpressionsParserTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -919,6 +1127,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -976,12 +1185,14 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; INFOPLIST_FILE = "HTMLKit/HTMLKit-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = HTMLKit; WRAPPER_EXTENSION = framework; }; @@ -991,12 +1202,14 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; INFOPLIST_FILE = "HTMLKit/HTMLKit-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = HTMLKit; WRAPPER_EXTENSION = framework; }; @@ -1018,6 +1231,7 @@ "$(inherited)", ); INFOPLIST_FILE = "HTMLKitTests/HTMLKitTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -1036,6 +1250,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; INFOPLIST_FILE = "HTMLKitTests/HTMLKitTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -1045,6 +1260,7 @@ 625A14FD19C7834100AD0C32 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEFINES_MODULE = YES; DSTROOT = /tmp/HTMLKit.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; @@ -1063,6 +1279,7 @@ 625A14FE19C7834100AD0C32 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEFINES_MODULE = YES; DSTROOT = /tmp/HTMLKit.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; @@ -1091,6 +1308,8 @@ ); INFOPLIST_FILE = "HTMLKitTests/HTMLKitTests-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.1; + OTHER_LDFLAGS = " -ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; TEST_HOST = "$(BUNDLE_LOADER)"; @@ -1110,6 +1329,8 @@ GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch"; INFOPLIST_FILE = "HTMLKitTests/HTMLKitTests-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.1; + OTHER_LDFLAGS = " -ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.braincookie.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; TEST_HOST = "$(BUNDLE_LOADER)"; diff --git a/HTMLKit.xcworkspace/contents.xcworkspacedata b/HTMLKit.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..da024c6 --- /dev/null +++ b/HTMLKit.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/HTMLKit/CSSAttributeSelector.h b/HTMLKit/CSSAttributeSelector.h new file mode 100644 index 0000000..d1ba040 --- /dev/null +++ b/HTMLKit/CSSAttributeSelector.h @@ -0,0 +1,30 @@ +// +// CSSAttributeSelector.h +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSAttributeSelector : CSSSelector + +@property (nonatomic, assign) CSSAttributeSelectorType type; +@property (nonatomic, strong, readonly) NSString *name; +@property (nonatomic, strong, readonly) NSString *value; + ++ (instancetype)classSelector:(NSString *)className; ++ (instancetype)idSelector:(NSString *)elementId; ++ (instancetype)hasAttributeSelector:(NSString *)attributeName; + +- (instancetype)initWithType:(CSSAttributeSelectorType)type + attributeName:(NSString *)name + attrbiuteValue:(NSString *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSAttributeSelector.m b/HTMLKit/CSSAttributeSelector.m new file mode 100644 index 0000000..b8d49f7 --- /dev/null +++ b/HTMLKit/CSSAttributeSelector.m @@ -0,0 +1,111 @@ +// +// CSSAttributeSelector.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "CSSAttributeSelector.h" +#import "HTMLElement.h" +#import "NSCharacterSet+HTMLKit.h" + +@interface CSSAttributeSelector () +{ + CSSAttributeSelectorType _type; + NSString *_name; + NSString *_value; +} +@end + +@implementation CSSAttributeSelector + ++ (instancetype)classSelector:(NSString *)className +{ + return [[self alloc] initWithType:CSSAttributeSelectorIncludes attributeName:@"class" attrbiuteValue:className]; +} + ++ (instancetype)idSelector:(NSString *)elementId +{ + return [[self alloc] initWithType:CSSAttributeSelectorExactMatch attributeName:@"id" attrbiuteValue:elementId]; +} + ++ (instancetype)hasAttributeSelector:(NSString *)attributeName +{ + return [[self alloc] initWithType:CSSAttributeSelectorExists attributeName:attributeName attrbiuteValue:@""]; +} + +- (instancetype)initWithType:(CSSAttributeSelectorType)type + attributeName:(NSString *)name + attrbiuteValue:(NSString *)value +{ + self = [super init]; + if (self) { + self.type = type; + _name = [name copy]; + _value = value ? [value copy]: @""; + } + return self; +} + +- (BOOL)acceptElement:(HTMLElement *)element +{ + switch (_type) { + case CSSAttributeSelectorExists: + { + return !!element[_name]; + } + case CSSAttributeSelectorExactMatch: + { + return [element[_name] isEqualToString:_value]; + } + case CSSAttributeSelectorIncludes: + { + NSArray *components = [element[_name] componentsSeparatedByCharactersInSet:[NSCharacterSet HTMLWhitespaceCharacterSet]]; + return [components containsObject:_value]; + } + case CSSAttributeSelectorBegins: + { + return [element[_name] hasPrefix:_value]; + } + case CSSAttributeSelectorEnds: + { + return [element[_name] hasSuffix:_value]; + } + case CSSAttributeSelectorContains: + { + return [element[_name] containsString:_value]; + } + case CSSAttributeSelectorHyphen: + { + return [element[_name] isEqualToString:_value] || [element[_name] hasPrefix:[_value stringByAppendingString:@"-"]]; + } + case CSSAttributeSelectorNot: + { + return ![element[_name] isEqualToString:_value]; + } + default: + return NO; + } +} + +#pragma mark - Description + +- (NSString *)debugDescription +{ + if (self.type == CSSAttributeSelectorExists) { + return [NSString stringWithFormat:@"[%@]", self.name]; + } + + NSString *matcher = @{@(CSSAttributeSelectorExactMatch): @"=", + @(CSSAttributeSelectorIncludes): @"~=", + @(CSSAttributeSelectorBegins): @"^=", + @(CSSAttributeSelectorEnds): @"$=", + @(CSSAttributeSelectorContains): @"*=", + @(CSSAttributeSelectorHyphen): @"|=", + @(CSSAttributeSelectorNot): @"!="}[@(self.type)]; + + return [NSString stringWithFormat:@"[%@%@'%@']", self.name, matcher, self.value]; +} + +@end diff --git a/HTMLKit/CSSCodePoints.h b/HTMLKit/CSSCodePoints.h new file mode 100644 index 0000000..0d1a0fc --- /dev/null +++ b/HTMLKit/CSSCodePoints.h @@ -0,0 +1,140 @@ +// +// CSSTokenizer CODEPOINTs.h +// HTMLKit +// +// Created by Iska on 08/06/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#define CODEPOINTS \ + CODEPOINT( CONTROL, 0x0080 ) \ + CODEPOINT( CHARACTER_TABULATION, 0x0009 ) \ + CODEPOINT( LINE_FEED, 0x000A ) \ + CODEPOINT( SPACE, 0x0020 ) \ + CODEPOINT( QUOTATION_MARK, 0x0022 ) \ + CODEPOINT( NUMBER_SIGN, 0x0023 ) \ + CODEPOINT( DOLLAR_SIGN, 0x0024 ) \ + CODEPOINT( APOSTROPHE, 0x0027 ) \ + CODEPOINT( LEFT_PARENTHESIS, 0x0028 ) \ + CODEPOINT( RIGHT_PARENTHESIS, 0x0029 ) \ + CODEPOINT( ASTERIX, 0x002A ) \ + CODEPOINT( PLUS_SIGN, 0x002B ) \ + CODEPOINT( COMMA, 0x002C ) \ + CODEPOINT( HYPHEN_MINUS, 0x002D ) \ + CODEPOINT( FULL_STOP, 0x002E ) \ + CODEPOINT( DIGIT_ZERO, 0x0030 ) \ + CODEPOINT( DIGIT_NINE, 0x0039 ) \ + CODEPOINT( COLON, 0x003A ) \ + CODEPOINT( EQUALS_SIGN, 0x003D ) \ + CODEPOINT( GREATER_THAN_SIGN, 0x003E ) \ + CODEPOINT( LATIN_CAPITAL_LETTER_A, 0x0041 ) \ + CODEPOINT( LATIN_CAPITAL_LETTER_F, 0x0046 ) \ + CODEPOINT( LATIN_CAPITAL_LETTER_Z, 0x005A ) \ + CODEPOINT( LEFT_SQUARE_BRACKET, 0x005B ) \ + CODEPOINT( REVERSE_SOLIDUS, 0x005C ) \ + CODEPOINT( RIGHT_SQUARE_BRACKET, 0x005D ) \ + CODEPOINT( CIRCUMFLEX_ACCENT, 0x005E ) \ + CODEPOINT( LOW_LINE, 0x005F ) \ + CODEPOINT( LATIN_SMALL_LETTER_A, 0x0061 ) \ + CODEPOINT( LATIN_SMALL_LETTER_F, 0x0066 ) \ + CODEPOINT( LATIN_SMALL_LETTER_Z, 0x007A ) \ + CODEPOINT( VERTICAL_LINE, 0x007C ) \ + CODEPOINT( TILDE, 0x007E ) \ + CODEPOINT( REPLACEMENT_CHARACTER, 0xFFFD ) + +#define CODEPOINT( name, value ) static UniChar const name = value; +CODEPOINTS +#undef CODEPOINT + +NS_INLINE BOOL isWhitespace(UTF32Char codePoint) +{ + return (codePoint == CHARACTER_TABULATION || + codePoint == LINE_FEED || + codePoint == SPACE); +} + +NS_INLINE BOOL isCombinator(UTF32Char codePoint) +{ + return (codePoint == SPACE || + codePoint == PLUS_SIGN || + codePoint == COMMA || + codePoint == GREATER_THAN_SIGN || + codePoint == TILDE); +} + +NS_INLINE BOOL isDigit(UTF32Char codePoint) +{ + return codePoint >= DIGIT_ZERO && codePoint <= DIGIT_NINE; +} + +NS_INLINE BOOL isHexDigit(UTF32Char codePoint) +{ + return ((codePoint >= DIGIT_ZERO && codePoint <= DIGIT_NINE) || + (codePoint >= LATIN_CAPITAL_LETTER_A && codePoint <= LATIN_CAPITAL_LETTER_F) || + (codePoint >= LATIN_SMALL_LETTER_A && codePoint <= LATIN_SMALL_LETTER_F)); +} + +NS_INLINE BOOL isQuote(UTF32Char codePoint) +{ + return codePoint == QUOTATION_MARK || codePoint == APOSTROPHE; +} + +NS_INLINE BOOL isNewLine(UTF32Char codePoint) +{ + return codePoint == LINE_FEED; +} + +NS_INLINE BOOL isNameStart(UTF32Char codePoint) +{ + return ((codePoint >= LATIN_CAPITAL_LETTER_A && codePoint <= LATIN_CAPITAL_LETTER_Z) || + (codePoint >= LATIN_SMALL_LETTER_A && codePoint <= LATIN_SMALL_LETTER_Z) || + codePoint >= CONTROL || + codePoint == LOW_LINE); +} + +NS_INLINE BOOL isName(UTF32Char codePoint) +{ + return isNameStart(codePoint) || isDigit(codePoint) || codePoint == HYPHEN_MINUS; +} + +NS_INLINE BOOL isValidEscape(UTF32Char first, UTF32Char second) +{ + if (first != REVERSE_SOLIDUS || isNewLine(second)) { + return false; + } + + return YES; +} + +NS_INLINE BOOL isValidEscapedCodePoint(UTF32Char codePoint) +{ + return (codePoint != 0 && + !(codePoint >= 0xD800 && codePoint <= 0x0DFFF) && + codePoint <= 0x10FFFF); +} + +NS_INLINE BOOL isValidIdentifierStart(UTF32Char first, UTF32Char second, UTF32Char third) +{ + if (first == HYPHEN_MINUS) { + if (isNameStart(second) || + second == HYPHEN_MINUS || + isValidEscape(second, third)) { + return YES; + } else { + return NO; + } + } else if (isNameStart(first)) { + return YES; + } else if (first == REVERSE_SOLIDUS) { + return isValidEscape(first, second); + } else { + return NO; + } +} + +NS_INLINE void AppendCodePoint(CFMutableStringRef string, UTF32Char codePoint) +{ + UniChar pair[2]; + Boolean isPair = CFStringGetSurrogatePairForLongCharacter(codePoint, pair); + CFStringAppendCharacters(string, pair, isPair ? 2 : 1); +} diff --git a/HTMLKit/CSSCombinatorSelector.h b/HTMLKit/CSSCombinatorSelector.h new file mode 100644 index 0000000..b227736 --- /dev/null +++ b/HTMLKit/CSSCombinatorSelector.h @@ -0,0 +1,22 @@ +// +// CSSCombinatorSelector.h +// HTMLKit +// +// Created by Iska on 12/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSCombinatorSelector : CSSSelector + ++ (instancetype)childOfElementCombinator:(CSSSelector *)selector; ++ (instancetype)descendantOfElementCombinator:(CSSSelector *)selector; ++ (instancetype)adjacentSiblingCombinator:(CSSSelector *)selector; ++ (instancetype)generalSiblingCombinator:(CSSSelector *)selector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSCombinatorSelector.m b/HTMLKit/CSSCombinatorSelector.m new file mode 100644 index 0000000..847ae7f --- /dev/null +++ b/HTMLKit/CSSCombinatorSelector.m @@ -0,0 +1,154 @@ +// +// CSSCombinatorSelector.m +// HTMLKit +// +// Created by Iska on 12/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSCombinatorSelector.h" +#import "HTMLElement.h" + +#pragma mark - Declarations + +@interface CSSChildOfElementCombinatorSelector : CSSCombinatorSelector +@end + +@interface CSSDecendantOfElementCombinatorSelector : CSSCombinatorSelector +@end + +@interface CSSAdjacentSiblingCombinatorSelector : CSSCombinatorSelector +@end + +@interface CSSGeneralSiblingCombinatorSelector : CSSCombinatorSelector +@end + +#pragma mark - Base Combinator + +@interface CSSCombinatorSelector () +{ + CSSSelector *_selector; +} +@property (nonatomic, strong, readonly) CSSSelector *selector; +@end + +@implementation CSSCombinatorSelector +@synthesize selector = _selector; + ++ (instancetype)childOfElementCombinator:(CSSSelector *)selector +{ + return [[CSSChildOfElementCombinatorSelector alloc] initWithSelector:selector]; +} + ++ (instancetype)descendantOfElementCombinator:(CSSSelector *)selector +{ + return [[CSSDecendantOfElementCombinatorSelector alloc] initWithSelector:selector]; +} + ++ (instancetype)adjacentSiblingCombinator:(CSSSelector *)selector +{ + return [[CSSAdjacentSiblingCombinatorSelector alloc] initWithSelector:selector]; +} + ++ (instancetype)generalSiblingCombinator:(CSSSelector *)selector +{ + return [[CSSGeneralSiblingCombinatorSelector alloc] initWithSelector:selector]; +} + +- (instancetype)initWithSelector:(CSSSelector *)selector +{ + self = [super init]; + if (self) { + _selector = selector; + } + return self; +} + +@end + +#pragma mark - Child OfElement Combinator + +@implementation CSSChildOfElementCombinatorSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + HTMLElement *parent = element.parentElement; + return parent != nil && [self.selector acceptElement:parent]; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@"%@ > ", self.selector.debugDescription]; +} + +@end + +#pragma mark - Decendant Of Element Combinator + +@implementation CSSDecendantOfElementCombinatorSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + HTMLElement *parent = element.parentElement; + + while (parent != nil) { + if ([self.selector acceptElement:parent]) { + return YES; + } + parent = parent.parentElement; + } + + return NO; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@"%@ ", self.selector.debugDescription]; +} + +@end + +#pragma mark - Adjacent Sibling Combinator + +@implementation CSSAdjacentSiblingCombinatorSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + HTMLNode *previous = element.previousSiblingElement; + if (previous == nil || previous.nodeType != HTMLNodeElement) { + return NO; + } + return [self.selector acceptElement:previous.asElement]; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@"%@ + ", self.selector.debugDescription]; +} + +@end + +#pragma mark - General Sibling Combinator + +@implementation CSSGeneralSiblingCombinatorSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + HTMLNode *previous = element.previousSiblingElement; + + while (previous != nil && previous.nodeType == HTMLNodeElement) { + if ([self.selector acceptElement:previous.asElement]) { + return YES; + } + previous = previous.previousSiblingElement; + } + + return NO; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@"%@ ~ ", self.selector.debugDescription]; +} + +@end diff --git a/HTMLKit/CSSCompoundSelector.h b/HTMLKit/CSSCompoundSelector.h new file mode 100644 index 0000000..00873d3 --- /dev/null +++ b/HTMLKit/CSSCompoundSelector.h @@ -0,0 +1,22 @@ +// +// CSSCompoundSelector.h +// HTMLKit +// +// Created by Iska on 18/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSCompoundSelector : CSSSelector + ++ (instancetype)andSelector:(NSArray *)selectors; ++ (instancetype)orSelector:(NSArray *)selectors; + +- (void)addSelector:(CSSSelector *)selector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSCompoundSelector.m b/HTMLKit/CSSCompoundSelector.m new file mode 100644 index 0000000..712d55f --- /dev/null +++ b/HTMLKit/CSSCompoundSelector.m @@ -0,0 +1,99 @@ +// +// CSSCompoundSelector.m +// HTMLKit +// +// Created by Iska on 18/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSCompoundSelector.h" + +#pragma mark - Declarations + +@interface CSSAndCompoundSelector : CSSCompoundSelector +@end + +@interface CSSOrCompoundSelector : CSSCompoundSelector +@end + +#pragma mark - Base Combinator + +@interface CSSCompoundSelector () +{ + NSMutableArray *_selectors; +} +@property (nonatomic, strong, readonly) NSArray *selectors; +@end + +@implementation CSSCompoundSelector +@synthesize selectors = _selectors; + ++ (instancetype)andSelector:(NSArray *)selectors +{ + return [[CSSAndCompoundSelector alloc] initWithSelectors:selectors]; +} + ++ (instancetype)orSelector:(NSArray *)selectors +{ + return [[CSSOrCompoundSelector alloc] initWithSelectors:selectors]; +} + +- (instancetype)initWithSelectors:(NSArray *)selectors +{ + self = [super init]; + if (self) { + _selectors = [[NSMutableArray alloc] initWithArray:selectors]; + } + return self; +} + +- (void)addSelector:(CSSSelector *)selector +{ + [_selectors addObject:selector]; +} + +@end + +#pragma mark - And Compound Selector + +@implementation CSSAndCompoundSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + for (CSSSelector *selector in self.selectors) { + if (![selector acceptElement:element]) { + return NO; + } + } + return YES; +} + +- (NSString *)debugDescription +{ + NSArray *descriptions = [self.selectors valueForKey:@"debugDescription"]; + return [descriptions componentsJoinedByString:@""]; +} + +@end + +#pragma mark - Or Compound Selector + +@implementation CSSOrCompoundSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + for (CSSSelector *selector in self.selectors) { + if ([selector acceptElement:element]) { + return YES; + } + } + return NO; +} + +- (NSString *)debugDescription +{ + NSArray *descriptions = [self.selectors valueForKey:@"debugDescription"]; + return [descriptions componentsJoinedByString:@","]; +} + +@end diff --git a/HTMLKit/CSSInputStream.h b/HTMLKit/CSSInputStream.h new file mode 100644 index 0000000..3bf9c1e --- /dev/null +++ b/HTMLKit/CSSInputStream.h @@ -0,0 +1,20 @@ +// +// CSSInputStream.h +// HTMLKit +// +// Created by Iska on 07/06/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "HTMLInputStreamReader.h" + +@interface CSSInputStream : HTMLInputStreamReader + +- (void)consumeWhitespace; +- (NSString *)consumeIdentifier; +- (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint; +- (UTF32Char)consumeEscapedCodePoint; +- (NSString *)consumeCombinator; + +@end diff --git a/HTMLKit/CSSInputStream.m b/HTMLKit/CSSInputStream.m new file mode 100644 index 0000000..f9336be --- /dev/null +++ b/HTMLKit/CSSInputStream.m @@ -0,0 +1,128 @@ +// +// CSSInputStream.m +// HTMLKit +// +// Created by Iska on 07/06/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "CSSInputStream.h" +#import "CSSCodePoints.h" + +@interface HTMLInputStreamReader () +- (void)emitParseError:(NSString *)reason; +@end + +@implementation CSSInputStream + +- (void)consumeWhitespace +{ + while (isWhitespace(self.nextInputCharacter)) { + [self consumeNextInputCharacter]; + } +} + +- (NSString *)consumeIdentifier +{ + CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0); + + if (!isValidIdentifierStart([self inputCharacterPointAtOffset:0], + [self inputCharacterPointAtOffset:1], + [self inputCharacterPointAtOffset:2])) { + return nil; + } + + while (YES) { + UTF32Char codePoint = [self consumeNextInputCharacter]; + if (codePoint == EOF) { + break; + } else if (isName(codePoint)) { + AppendCodePoint(value, codePoint); + } else if (isValidEscape(codePoint, [self inputCharacterPointAtOffset:1])) { + UTF32Char escapedCodePoint = [self consumeEscapedCodePoint]; + AppendCodePoint(value, escapedCodePoint); + } else { + [self reconsumeCurrentInputCharacter]; + break; + } + } + + return (__bridge NSString *)(CFStringGetLength(value) > 0 ? value : nil); +} + +- (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint +{ + CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0); + + while (YES) { + UTF32Char codePoint = [self consumeNextInputCharacter]; + if (codePoint == endingCodePoint) { + break; + } + + switch (codePoint) { + case EOF: + break; + case LINE_FEED: + [self emitParseError:@"New-line character (0x000A) in CSS attribute value"]; + [self reconsumeCurrentInputCharacter]; + break; + case REVERSE_SOLIDUS: + { + UTF32Char next = self.nextInputCharacter; + if (next == EOF) { + continue; + } else if (next == LINE_FEED) { + [self consumeNextInputCharacter]; + } else { + UTF32Char escapedCodePoint = [self consumeNextInputCharacter]; + AppendCodePoint(value, escapedCodePoint); + } + } + default: + AppendCodePoint(value, codePoint); + break; + } + } + + return (__bridge NSString *)(CFStringGetLength(value) > 0 ? value : nil); +} + +- (UTF32Char)consumeEscapedCodePoint +{ + UTF32Char codePoint = [self consumeNextInputCharacter]; + + if (isHexDigit(codePoint)) { + CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 6); + AppendCodePoint(hexString, codePoint); + + while (isHexDigit(self.nextInputCharacter) && CFStringGetLength(hexString) <= 6) { + UniChar codePoint = [self consumeNextInputCharacter]; + CFStringAppendCharacters(hexString, &codePoint, 1); + } + + if (isWhitespace(self.nextInputCharacter)) { + [self consumeNextInputCharacter]; + } + + NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexString)]; + UTF32Char number; + [scanner scanHexInt:&number]; + + return isValidEscapedCodePoint(number) ? number : REPLACEMENT_CHARACTER; + } else if (codePoint == EOF) { + return REPLACEMENT_CHARACTER; + } + + return codePoint; +} + +- (NSString *)consumeCombinator +{ + NSString *combinator = [self consumeCharactersInString:@" >+~"]; + combinator = [combinator stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + return combinator; +} + +@end diff --git a/HTMLKit/CSSNthExpressionParser.h b/HTMLKit/CSSNthExpressionParser.h new file mode 100644 index 0000000..e484bab --- /dev/null +++ b/HTMLKit/CSSNthExpressionParser.h @@ -0,0 +1,16 @@ +// +// CSSNthExpression.h +// HTMLKit +// +// Created by Iska on 10/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" + +@interface CSSNthExpressionParser : NSObject + ++ (CSSNthExpression)parseExpression:(NSString *)expression; + +@end diff --git a/HTMLKit/CSSNthExpressionParser.m b/HTMLKit/CSSNthExpressionParser.m new file mode 100644 index 0000000..392acb4 --- /dev/null +++ b/HTMLKit/CSSNthExpressionParser.m @@ -0,0 +1,50 @@ +// +// CSSNthExpression.m +// HTMLKit +// +// Created by Iska on 10/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSNthExpressionParser.h" +#import "CSSCodePoints.h" +#import "NSString+HTMLKit.h" +#import "NSCharacterSet+HTMLKit.h" + +@implementation CSSNthExpressionParser + ++ (CSSNthExpression)parseExpression:(NSString *)expression +{ + NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet]; + + NSString *string = [expression.lowercaseString copy]; + string = [[string stringByTrimmingCharactersInSet:whitespace] copy]; + + if ([string isEqualToStringIgnoringCase:@"odd"]) { + return CSSNthExpressionOdd; + } else if ([string isEqualToStringIgnoringCase:@"even"]) { + return CSSNthExpressionEven; + } + + NSCharacterSet *set = [[NSCharacterSet CSSNthExpressionCharacterSet] invertedSet]; + if ([string rangeOfCharacterFromSet:set].location != NSNotFound) { + return CSSNthExpressionMake(0, 0); + } + NSArray *parts = [string componentsSeparatedByString:@"n"]; + + if (parts.count == 1) { + NSInteger b = [parts[0] integerValue]; + return CSSNthExpressionMake(0, b); + } else if (parts.count == 2) { + NSInteger a = [parts[0] integerValue]; + if (a == 0) { + a = [parts[0] isEqualToString:@"-"] ? -1 : 1; + } + NSInteger b = [parts[1] integerValue]; + return CSSNthExpressionMake(a, b); + } else { + return CSSNthExpressionMake(0, 0); + } +} + +@end diff --git a/HTMLKit/CSSNthExpressionSelector.h b/HTMLKit/CSSNthExpressionSelector.h new file mode 100644 index 0000000..f8ddccf --- /dev/null +++ b/HTMLKit/CSSNthExpressionSelector.h @@ -0,0 +1,25 @@ +// +// CSSNthExpressionSelector.h +// HTMLKit +// +// Created by Iska on 10/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSNthExpressionSelector : CSSSelector + +@property (nonatomic, strong, readonly) NSString *className; +@property (nonatomic, assign, readonly) CSSNthExpression expression; + ++ (instancetype)nthChildSelector:(CSSNthExpression)expression; ++ (instancetype)nthLastChildSelector:(CSSNthExpression)expression; ++ (instancetype)nthOfTypeSelector:(CSSNthExpression)expression; ++ (instancetype)nthLastOfTypeSelector:(CSSNthExpression)expression; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSNthExpressionSelector.m b/HTMLKit/CSSNthExpressionSelector.m new file mode 100644 index 0000000..0ef6e5e --- /dev/null +++ b/HTMLKit/CSSNthExpressionSelector.m @@ -0,0 +1,130 @@ +// +// CSSNthExpressionSelector.m +// HTMLKit +// +// Created by Iska on 10/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSNthExpressionSelector.h" +#import "HTMLElement.h" + +#pragma mark - Nth-Expression + +const CSSNthExpression CSSNthExpressionOdd = (CSSNthExpression) { + .an = 2, .b = 1 +}; + +const CSSNthExpression CSSNthExpressionEven = (CSSNthExpression) { + .an = 2, .b = 0 +}; + +NSString * _Nonnull NSStringFromNthExpression(CSSNthExpression expression) +{ + if (expression.an == 0 && expression.b == 0) { + return @"invalid"; + } + + if (expression.an == 0) { + return [NSString stringWithFormat:@"%ld", expression.b]; + } + if (expression.b == 0) { + return [NSString stringWithFormat:@"%ldn", expression.an]; + } + + return [NSString stringWithFormat:@"%ldn%+ld", expression.an, expression.b]; +} + +#pragma mark - Implementation + +NSInteger computeIndex(NSEnumerator *enumerator, HTMLElement *element) +{ + NSInteger index = 0; + for (HTMLNode *node in enumerator) { + if (node.nodeType != HTMLNodeElement) { + continue; + } + + if ([node.asElement.tagName isEqualToString:element.tagName]) { + index++; + } + + if (node == element) { + break; + } + } + + return index; +} + +@interface CSSNthExpressionSelector () +{ + NSString *_className; + CSSNthExpression _expression; + NSInteger (^ _computeIndex)(HTMLElement *); +} +@end + +@implementation CSSNthExpressionSelector +@synthesize expression = _expression; +@synthesize className = _className; + ++ (instancetype)nthChildSelector:(CSSNthExpression)expression +{ + return [[self alloc] initWithClassName:@"nth-child" expression:expression block:^NSInteger(HTMLElement *element) { + return [element.parentElement indexOfChildElement:element] + 1; + }]; +} + ++ (instancetype)nthLastChildSelector:(CSSNthExpression)expression +{ + return [[self alloc] initWithClassName:@"nth-last-child" expression:expression block:^NSInteger(HTMLElement *element) { + return element.parentElement.childElementsCount - [element.parentElement indexOfChildElement:element]; + }]; +} + ++ (instancetype)nthOfTypeSelector:(CSSNthExpression)expression +{ + return [[self alloc] initWithClassName:@"nth-of-type" expression:expression block:^NSInteger(HTMLElement *element) { + return computeIndex(element.parentElement.childNodes.array.objectEnumerator, element); + }]; +} + ++ (instancetype)nthLastOfTypeSelector:(CSSNthExpression)expression +{ + return [[self alloc] initWithClassName:@"nth-last-of-type" expression:expression block:^NSInteger(HTMLElement *element) { + return computeIndex(element.parentElement.childNodes.array.reverseObjectEnumerator, element); + }]; +} + +- (instancetype)initWithClassName:(NSString *)className + expression:(CSSNthExpression)expression + block:(NSInteger (^)(HTMLElement *element))block +{ + self = [super init]; + if (self) { + _className = [className copy]; + _expression = expression; + _computeIndex = [block copy]; + } + return self; +} + +- (BOOL)acceptElement:(HTMLElement *)element +{ + NSInteger index = _computeIndex(element); + + if (_expression.an == 0) { + return index == _expression.b; + } else { + NSInteger diff = (index - _expression.b); + return (diff * _expression.an >= 0) && (diff % _expression.an == 0); + } +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@":%@(%@)", self.className, NSStringFromNthExpression(self.expression)]; +} + +@end diff --git a/HTMLKit/CSSPseudoClassSelector.h b/HTMLKit/CSSPseudoClassSelector.h new file mode 100644 index 0000000..7f15cd9 --- /dev/null +++ b/HTMLKit/CSSPseudoClassSelector.h @@ -0,0 +1,21 @@ +// +// CSSPseudoClassSelector.h +// HTMLKit +// +// Created by Iska on 06/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSPseudoClassSelector : CSSSelector + +@property (nonatomic, strong, readonly) NSString *className; + +- (instancetype)initWithClassName:(NSString *)className selector:(CSSSelector *)selector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSPseudoClassSelector.m b/HTMLKit/CSSPseudoClassSelector.m new file mode 100644 index 0000000..3471670 --- /dev/null +++ b/HTMLKit/CSSPseudoClassSelector.m @@ -0,0 +1,46 @@ +// +// CSSPseudoClassSelector.m +// HTMLKit +// +// Created by Iska on 06/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSPseudoClassSelector.h" + +@interface CSSPseudoClassSelector () +{ + NSString *_className; + CSSSelector *_selector; +} +@end + +@implementation CSSPseudoClassSelector +@synthesize className = _className; + +- (instancetype)initWithClassName:(NSString *)className selector:(CSSSelector *)selector +{ + self = [super init]; + if (self) { + _className = [className copy]; + _selector = selector; + } + return self; +} + +-(BOOL)acceptElement:(HTMLElement *)element +{ + return [_selector acceptElement:element]; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@":%@", self.className]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p '%@'>", self.class, self, self.debugDescription]; +} + +@end diff --git a/HTMLKit/CSSPseudoFunctionSelector.h b/HTMLKit/CSSPseudoFunctionSelector.h new file mode 100644 index 0000000..d5d69f3 --- /dev/null +++ b/HTMLKit/CSSPseudoFunctionSelector.h @@ -0,0 +1,20 @@ +// +// CSSPseudoFunctionSelector.h +// HTMLKit +// +// Created by Iska on 07/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSPseudoFunctionSelector : CSSSelector + ++ (instancetype)notSelector:(CSSSelector *)selector; ++ (instancetype)hasSelector:(CSSSelector *)selector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSPseudoFunctionSelector.m b/HTMLKit/CSSPseudoFunctionSelector.m new file mode 100644 index 0000000..9c22407 --- /dev/null +++ b/HTMLKit/CSSPseudoFunctionSelector.m @@ -0,0 +1,89 @@ +// +// CSSPseudoFunctionSelector.m +// HTMLKit +// +// Created by Iska on 07/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSPseudoFunctionSelector.h" +#import "HTMLElement.h" + +#pragma mark - Declarations + +@interface CSSNotSelector : CSSPseudoFunctionSelector +@end + +@interface CSSHasSelector : CSSPseudoFunctionSelector +@end + +#pragma mark - Base Function Selector + +@interface CSSPseudoFunctionSelector () +{ + CSSSelector *_selector; +} +@property (nonatomic, strong, readonly) CSSSelector *selector; +@end + +@implementation CSSPseudoFunctionSelector +@synthesize selector = _selector; + ++ (instancetype)notSelector:(CSSSelector *)selector +{ + return [[CSSNotSelector alloc] initWithSelector:selector]; +} + ++ (instancetype)hasSelector:(CSSSelector *)selector +{ + return [[CSSHasSelector alloc] initWithSelector:selector]; +} + +- (instancetype)initWithSelector:(CSSSelector *)selector +{ + self = [super init]; + if (self) { + _selector = selector; + } + return self; +} + +@end + +#pragma mark - Not Selector + +@implementation CSSNotSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + return ![self.selector acceptElement:element]; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@":not(%@)", self.selector.debugDescription]; +} + +@end + +#pragma mark - Has Selector + +@implementation CSSHasSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + for (HTMLNode *child in element.childNodes) { + if (child.nodeType == HTMLNodeElement && [self.selector acceptElement:child.asElement]) { + return YES; + } + } + + return NO; +} + +- (NSString *)debugDescription +{ + return [NSString stringWithFormat:@":has(%@)", self.selector.debugDescription]; +} + +@end diff --git a/HTMLKit/CSSSelector.h b/HTMLKit/CSSSelector.h new file mode 100644 index 0000000..d13fb58 --- /dev/null +++ b/HTMLKit/CSSSelector.h @@ -0,0 +1,49 @@ +// +// HTMLSelector.h +// HTMLKit +// +// Created by Iska on 02/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import + +#pragma mark - Attribute Selector Type + +typedef NS_ENUM(NSUInteger, CSSAttributeSelectorType) +{ + CSSAttributeSelectorExists, + CSSAttributeSelectorExactMatch, + CSSAttributeSelectorIncludes, + CSSAttributeSelectorBegins, + CSSAttributeSelectorEnds, + CSSAttributeSelectorContains, + CSSAttributeSelectorHyphen, + CSSAttributeSelectorNot +}; + +#pragma mark - CSS Nth-Expression + +typedef struct CSSNthExpression +{ + NSInteger an; + NSInteger b; +} CSSNthExpression; + +NS_INLINE CSSNthExpression CSSNthExpressionMake(NSInteger an, NSInteger b) { + return (CSSNthExpression){ .an = an, .b = b }; +} + +extern const CSSNthExpression CSSNthExpressionOdd; +extern const CSSNthExpression CSSNthExpressionEven; +extern NSString * _Nonnull NSStringFromNthExpression(CSSNthExpression expression); + +#pragma mark - Base Selector Class + +@class HTMLElement; + +@interface CSSSelector : NSObject + +- (BOOL)acceptElement:(nonnull HTMLElement *)element; + +@end diff --git a/HTMLKit/CSSSelector.m b/HTMLKit/CSSSelector.m new file mode 100644 index 0000000..f3a8e52 --- /dev/null +++ b/HTMLKit/CSSSelector.m @@ -0,0 +1,33 @@ +// +// CSSSelector.m +// HTMLKit +// +// Created by Iska on 15/10/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelector.h" + +@implementation CSSSelector + +- (BOOL)acceptElement:(HTMLElement *)element +{ + [self doesNotRecognizeSelector:_cmd]; + return NO; +} + +#pragma mark - Description + +- (NSString *)debugDescription +{ + [self doesNotRecognizeSelector:_cmd]; + return @""; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p '%@'>", self.class, self, self.debugDescription]; +} + +@end diff --git a/HTMLKit/CSSSelectorBlock.h b/HTMLKit/CSSSelectorBlock.h new file mode 100644 index 0000000..f1030e7 --- /dev/null +++ b/HTMLKit/CSSSelectorBlock.h @@ -0,0 +1,21 @@ +// +// CSSSelectorBlock.h +// HTMLKit +// +// Created by Iska on 20/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@class HTMLElement; + +@interface CSSSelectorBlock : CSSSelector + +- (instancetype)initWithName:(NSString *)name block:(BOOL (^)(HTMLElement *))block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSSelectorBlock.m b/HTMLKit/CSSSelectorBlock.m new file mode 100644 index 0000000..c8d44d6 --- /dev/null +++ b/HTMLKit/CSSSelectorBlock.m @@ -0,0 +1,40 @@ +// +// CSSSelectorBlock.m +// HTMLKit +// +// Created by Iska on 20/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelectorBlock.h" + +@interface CSSSelectorBlock () +{ + NSString *_name; + BOOL (^ _acceptBlock)(HTMLElement *); +} +@end + +@implementation CSSSelectorBlock + +- (instancetype)initWithName:(NSString *)name block:(BOOL (^)(HTMLElement *))block +{ + self = [super init]; + if (self) { + _name = [name copy]; + _acceptBlock = [block copy]; + } + return self; +} + +- (BOOL)acceptElement:(HTMLElement *)element +{ + return _acceptBlock ? _acceptBlock(element) : NO; +} + +- (NSString *)debugDescription +{ + return _name; +} + +@end diff --git a/HTMLKit/CSSSelectorParser.h b/HTMLKit/CSSSelectorParser.h new file mode 100644 index 0000000..1d55788 --- /dev/null +++ b/HTMLKit/CSSSelectorParser.h @@ -0,0 +1,17 @@ +// +// CSSSelectorParser.h +// HTMLKit +// +// Created by Iska on 02/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import + +@class CSSSelector; + +@interface CSSSelectorParser : NSObject + ++ (CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error; + +@end diff --git a/HTMLKit/CSSSelectorParser.m b/HTMLKit/CSSSelectorParser.m new file mode 100644 index 0000000..c550351 --- /dev/null +++ b/HTMLKit/CSSSelectorParser.m @@ -0,0 +1,367 @@ +// +// CSSSelectorParser.m +// HTMLKit +// +// Created by Iska on 02/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelectorParser.h" +#import "CSSInputStream.h" +#import "CSSCodePoints.h" +#import "CSSSelectors.h" +#import "NSString+HTMLKit.h" +#import "NSCharacterSet+HTMLKit.h" +#import "CSSNthExpressionParser.h" +#import "CSSCompoundSelector.h" +#import "HTMLKitErrorDomain.h" + +@interface CSSSelectorParser () +{ + NSString *_string; + CSSInputStream *_inputStream; + NSUInteger _location; + + NSMutableArray *_selectors; +} +@end + +@implementation CSSSelectorParser + ++ (CSSSelector *)parseSelector:(NSString *)string error:(NSError * __autoreleasing *)error +{ + CSSSelectorParser *parser = [[CSSSelectorParser alloc] initWithString:string]; + CSSSelector *selector = [parser parse:error]; + + return selector; +} + +#pragma mark - Init + +- (instancetype)initWithString:(NSString *)string +{ + self = [super init]; + if (self) { + _string = [self preprocessInput:string]; + _location = 0; + } + return self; +} + +- (NSString *)preprocessInput:(NSString *)string +{ + string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + string = [string stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"]; + string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@"\n"]; + string = [string stringByReplacingOccurrencesOfString:@"\f" withString:@"\n"]; + string = [string stringByReplacingOccurrencesOfString:@"\0" withString:@"\uFFFD"]; + + return string; +} + +#pragma mark - Errors + +- (void)emitError:(NSError * __autoreleasing *)error reason:(NSString *)reason location:(NSUInteger)location +{ + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: @"Error parsing selector", + NSLocalizedFailureReasonErrorKey: reason, + CSSSelectorStringKey: _string, + CSSSelectorErrorLocationKey: @(location) + }; + + if(error) { + *error = [NSError errorWithDomain:HTMLKitSelectorErrorDomain code:HTMLKitSelectorParseError userInfo:userInfo]; + } +} + +#pragma mark - Parsing + +- (CSSSelector *)parse:(NSError * __autoreleasing *)error +{ + if (_string.length == 0) { + [self emitError:error reason:@"Empty selector" location:0]; + return nil; + } + + NSArray *allSubSelectors = [_string componentsSeparatedByString:@","]; + NSMutableArray *parsed = [NSMutableArray array]; + + for (NSString *subSelector in allSubSelectors) { + if ([subSelector isEqualToString:@""]) { + [self emitError:error reason:@"Empty selector" location:_location]; + break; + } + + CSSSelector *selector = [self parseSelector:subSelector error:error]; + if (selector == nil) { + break; + } + [parsed addObject:selector]; + + _location += subSelector.length; + } + + if (*error != nil) { + return nil; + } + + if (parsed.count > 1) { + return anyOf(parsed); + } + + return parsed.firstObject; +} + +- (CSSSelector *)parseSelector:(NSString *)selectorString error:(NSError * __autoreleasing *)error +{ + _inputStream = [[CSSInputStream alloc] initWithString:selectorString]; + [_inputStream consumeWhitespace]; + + CSSSelector *result = nil; + + while (YES) { + CSSSelector *selector = [self parseSequenceOfSimpleSelectors:error]; + if (selector == nil) { + break; + } + + result = result ? allOf(@[result, selector]) : selector; + + UTF32Char next = _inputStream.nextInputCharacter; + + if (isCombinator(next)) { + NSString *combinator = [_inputStream consumeCombinator]; + + if ([combinator isEqualToString:@""]) { + result = descendantOfElementSelector(result); + } else if ([combinator isEqualToString:@">"]) { + result = childOfElementSelector(result); + } else if ([combinator isEqualToString:@"+"]) { + result = adjacentSiblingSelector(result); + } else if ([combinator isEqualToString:@"~"]) { + result = generalSiblingSelector(result); + } + } + } + + return result; +} + +- (CSSSelector *)parseSequenceOfSimpleSelectors:(NSError * __autoreleasing *)error +{ + NSMutableArray *selectors = [NSMutableArray array]; + + CSSSelector *typeSelector = [self parseTypeSelector:error]; + if (typeSelector != nil) { + [selectors addObject:typeSelector]; + } + + while (YES) { + UTF32Char next = _inputStream.nextInputCharacter; + if (next == EOF || isCombinator(next)) { + break; + } + + CSSSelector *simpleSelector = [self parseSimpleSelector:error]; + if (simpleSelector == nil) { + return nil; + } + [selectors addObject:simpleSelector]; + } + + if (selectors.count > 1) { + return allOf(selectors); + } + + return selectors.firstObject; +} + +- (CSSSelector *)parseTypeSelector:(NSError * __autoreleasing *)error +{ + NSString *identifier = [_inputStream consumeIdentifier]; + if (identifier != nil) { + return typeSelector(identifier); + } + + if ([_inputStream consumeCharacter:ASTERIX]) { + return universalSelector(); + } + + return nil; +} + +- (CSSSelector *)parseSimpleSelector:(NSError * __autoreleasing *)error +{ + CSSSelector *typeSelector = [self parseTypeSelector:error]; + if (typeSelector != nil) { + return typeSelector; + } + + UTF32Char codePoint = [_inputStream consumeNextInputCharacter]; + switch (codePoint) { + case NUMBER_SIGN: + { + NSString *elementId = [_inputStream consumeIdentifier]; + if (elementId == nil) { + [self emitError:error reason:@"Invalid character" location:_location + _inputStream.currentLocation]; + return nil; + } + return idSelector(elementId); + } + case FULL_STOP: + { + NSString *className = [_inputStream consumeIdentifier]; + if (className == nil) { + [self emitError:error reason:@"Invalid character" location:_location + _inputStream.currentLocation]; + return nil; + } + return classSelector(className); + } + case LEFT_SQUARE_BRACKET: + { + return [self parseAttributeSelector:error]; + } + case COLON: + { + return [self parsePseudoSelector:error]; + } + default: + { + [self emitError:error reason:@"Invalid character" location:_location + _inputStream.currentLocation]; + return nil; + } + } +} + +- (CSSSelector *)parseAttributeSelector:(NSError * __autoreleasing *)error +{ + NSString *attribute = [_inputStream consumeIdentifier]; + if (attribute == nil) { + [self emitError:error reason:@"Invalid character" location:_location + _inputStream.currentLocation + 1]; + return nil; + } + [_inputStream consumeWhitespace]; + + CSSAttributeSelectorType type = CSSAttributeSelectorExists; + + NSString *operator = [_inputStream consumeCharactersInString:@"=~|^$*!"]; + + if ([operator isEqualToString:@"="]) { + type = CSSAttributeSelectorExactMatch; + } else if ([operator isEqualToString:@"~="]) { + type = CSSAttributeSelectorIncludes; + } else if ([operator isEqualToString:@"|="]) { + type = CSSAttributeSelectorHyphen; + } else if ([operator isEqualToString:@"^="]) { + type = CSSAttributeSelectorBegins; + } else if ([operator isEqualToString:@"$="]) { + type = CSSAttributeSelectorEnds; + } else if ([operator isEqualToString:@"*="]) { + type = CSSAttributeSelectorContains; + } else if ([operator isEqualToString:@"!="]) { + type = CSSAttributeSelectorNot; + } + + NSString *value = nil; + [_inputStream consumeWhitespace]; + + UTF32Char next = _inputStream.nextInputCharacter; + if (isQuote(next)) { + UTF32Char quote = [_inputStream consumeNextInputCharacter]; + value = [_inputStream consumeStringWithEndingCodePoint:quote]; + } else { + value = [_inputStream consumeIdentifier]; + } + + [_inputStream consumeWhitespace]; + + // Consume RIGHT_SQUARE_BRACKET + if (![_inputStream consumeCharacter:RIGHT_SQUARE_BRACKET]) { + [self emitError:error reason:@"Expected closing right square bracket ']'" location:_location + _inputStream.currentLocation]; + } + + if (type == CSSAttributeSelectorExists) { + return hasAttributeSelector(attribute); + } + + return attributeSelector(type, attribute, value); +} + +- (CSSSelector *)parsePseudoSelector:(NSError * __autoreleasing *)error +{ + NSString *pseudoClass = [_inputStream consumeIdentifier]; + + if ([pseudoClass hasPrefix:@"nth"]) { + [_inputStream consumeWhitespace]; + if (![_inputStream consumeCharacter:LEFT_PARENTHESIS]) { + [self emitError:error reason:@"Expected opening left parenthesis '('" location:_location + _inputStream.currentLocation]; + } + + NSString *functionExpression = [_inputStream consumeCharactersUpToString:@")"]; + CSSNthExpression expression = [CSSNthExpressionParser parseExpression:functionExpression]; + + [_inputStream consumeWhitespace]; + if (![_inputStream consumeCharacter:RIGHT_PARENTHESIS]) { + [self emitError:error reason:@"Expected closing right parenthesis ')'" location:_location + _inputStream.currentLocation]; + } + + if ([pseudoClass isEqualToString:@"nth-child"]) { + return nthChildSelector(expression); + } else if ([pseudoClass isEqualToString:@"nth-last-child"]) { + return nthLastChildSelector(expression); + } else if ([pseudoClass isEqualToString:@"nth-of-type"]) { + return nthOfTypeSelector(expression); + } else if ([pseudoClass isEqualToString:@"nth-last-of-type"]) { + return nthLastOfTypeSelector(expression); + } + } else if ([pseudoClass isEqualToString:@"not"]) { + [_inputStream consumeWhitespace]; + if (![_inputStream consumeCharacter:LEFT_PARENTHESIS]) { + [self emitError:error reason:@"Expected opening left parenthesis '('" location:_location + _inputStream.currentLocation]; + } + + CSSSelector *subSelector = [self parseSimpleSelector:error]; + [_inputStream consumeWhitespace]; + if (![_inputStream consumeCharacter:RIGHT_PARENTHESIS]) { + [self emitError:error reason:@"Expected closing right parenthesis ')'" location:_location + _inputStream.currentLocation]; + } + + return nay(subSelector); + } else { + if ([pseudoClass isEqualToString:@"even"]) { + return evenSlector(); + } else if ([pseudoClass isEqualToString:@"odd"]) { + return oddSelector(); + } else if ([pseudoClass isEqualToString:@"first-child"]) { + return firstChildSelector(); + } else if ([pseudoClass isEqualToString:@"last-child"]) { + return lastChildSelector(); + } else if ([pseudoClass isEqualToString:@"first-of-type"]) { + return firstOfTypeSelector(); + } else if ([pseudoClass isEqualToString:@"last-of-type"]) { + return lastOfTypeSelector(); + } else if ([pseudoClass isEqualToString:@"only-child"]) { + return onlyChildSelector(); + } else if ([pseudoClass isEqualToString:@"only-of-type"]) { + return onlyOfTypeSelector(); + } else if ([pseudoClass isEqualToString:@"root"]) { + return rootSelector(); + } else if ([pseudoClass isEqualToString:@"empty"]) { + return emptySelector(); + } else if ([pseudoClass isEqualToString:@"link"]) { + return linkSelector(); + } else if ([pseudoClass isEqualToString:@"enabled"]) { + return enabledSelector(); + } else if ([pseudoClass isEqualToString:@"disabled"]) { + return disabledSelector(); + } else if ([pseudoClass isEqualToString:@"checked"]) { + return checkedSelector(); + } + } + NSString *reason = [NSString stringWithFormat:@"Unknown pseudo class: %@", pseudoClass]; + [self emitError:error reason:reason location:_location + _inputStream.currentLocation]; + return nil; +} + +@end diff --git a/HTMLKit/CSSSelectors.h b/HTMLKit/CSSSelectors.h new file mode 100644 index 0000000..bf9c1af --- /dev/null +++ b/HTMLKit/CSSSelectors.h @@ -0,0 +1,71 @@ +// +// CSSSelectors.h +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelector.h" +#import "CSSStructuralPseudoSelectors.h" + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Type Selectors + +extern CSSSelector * universalSelector(); +extern CSSSelector * typeSelector(NSString *type); + +#pragma mark - Atribute Selectors + +extern CSSSelector * idSelector(NSString *elementId); +extern CSSSelector * classSelector(NSString *className); +extern CSSSelector * hasAttributeSelector(NSString *attribute); +extern CSSSelector * attributeSelector(CSSAttributeSelectorType type, + NSString *attribute, + NSString *value); + +#pragma mark - Nth-Expression Selectors + +extern CSSSelector * nthChildSelector(CSSNthExpression expression); +extern CSSSelector * nthLastChildSelector(CSSNthExpression expression); +extern CSSSelector * nthOfTypeSelector(CSSNthExpression expression); +extern CSSSelector * nthLastOfTypeSelector(CSSNthExpression expression); + +extern CSSSelector * oddSelector(); +extern CSSSelector * evenSlector(); + +extern CSSSelector * firstChildSelector(); +extern CSSSelector * lastChildSelector(); +extern CSSSelector * firstOfTypeSelector(); +extern CSSSelector * lastOfTypeSelector(); + +extern CSSSelector * onlyChildSelector(); +extern CSSSelector * onlyOfTypeSelector(); + +#pragma mark - Combinators + +extern CSSSelector * childOfElementSelector(CSSSelector *selector); +extern CSSSelector * descendantOfElementSelector(CSSSelector *selector); +extern CSSSelector * adjacentSiblingSelector(CSSSelector *selector); +extern CSSSelector * generalSiblingSelector(CSSSelector *selector); + +#pragma mark - Pseudo Functions + +extern CSSSelector * nay(CSSSelector *selector); +extern CSSSelector * has(CSSSelector *selector); + +#pragma mark - Compound Selectors + +extern CSSSelector * allOf(NSArray *selectors); +extern CSSSelector * anyOf(NSArray *selectors); + +#pragma mark - Pseudo + +extern CSSSelector * namedPseudoSelector(NSString *name, CSSSelector *selector); + +#pragma mark - Block + +extern CSSSelector * namedBlockSelector(NSString *name, BOOL (^ acceptBlock)(HTMLElement *element)); + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSSelectors.m b/HTMLKit/CSSSelectors.m new file mode 100644 index 0000000..d4e864f --- /dev/null +++ b/HTMLKit/CSSSelectors.m @@ -0,0 +1,177 @@ +// +// CSSSelectors.m +// HTMLKit +// +// Created by Iska on 19/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelectors.h" +#import "CSSTypeSelector.h" +#import "CSSAttributeSelector.h" +#import "CSSPseudoClassSelector.h" +#import "CSSPseudoFunctionSelector.h" +#import "CSSNthExpressionSelector.h" +#import "CSSCombinatorSelector.h" +#import "CSSCompoundSelector.h" +#import "CSSSelectorBlock.h" + +#pragma mark - Type Selectors + +CSSSelector * universalSelector() +{ + return [CSSTypeSelector universalSelector]; +} + +CSSSelector * typeSelector(NSString *type) +{ + return [[CSSTypeSelector alloc] initWithType:type]; +} + +#pragma mark - Atribute Selectors + +CSSSelector * idSelector(NSString *elementId) +{ + return [CSSAttributeSelector idSelector:elementId]; +} + +CSSSelector * classSelector(NSString *className) +{ + return [CSSAttributeSelector classSelector:className]; +} + +CSSSelector * hasAttributeSelector(NSString *attribute) +{ + return [CSSAttributeSelector hasAttributeSelector:attribute]; +} + +CSSSelector * attributeSelector(CSSAttributeSelectorType type, + NSString *attribute, + NSString *value) +{ + return [[CSSAttributeSelector alloc] initWithType:type attributeName:attribute attrbiuteValue:value]; +} + +#pragma mark - Nth-Expression Selectors + +CSSSelector * nthChildSelector(CSSNthExpression expression) +{ + return [CSSNthExpressionSelector nthChildSelector:expression]; +} + +CSSSelector * nthLastChildSelector(CSSNthExpression expression) +{ + return [CSSNthExpressionSelector nthLastChildSelector:expression]; +} + +CSSSelector * nthOfTypeSelector(CSSNthExpression expression) +{ + return [CSSNthExpressionSelector nthOfTypeSelector:expression]; +} + +CSSSelector * nthLastOfTypeSelector(CSSNthExpression expression) +{ + return [CSSNthExpressionSelector nthLastOfTypeSelector:expression]; +} + +#pragma mark - Nth-Expression Shorthand + +CSSSelector * oddSelector() +{ + return namedPseudoSelector(@"odd", nthChildSelector(CSSNthExpressionOdd)); +} + +CSSSelector * evenSlector() +{ + return namedPseudoSelector(@"even", nthChildSelector(CSSNthExpressionEven)); +} + +CSSSelector * firstChildSelector() +{ + return namedPseudoSelector(@"first-child", nthChildSelector(CSSNthExpressionMake(0, 1))); +} + +CSSSelector * lastChildSelector() +{ + return namedPseudoSelector(@"last-child", nthLastChildSelector(CSSNthExpressionMake(0, 1))); +} + +CSSSelector * firstOfTypeSelector() +{ + return namedPseudoSelector(@"first-of-type", nthOfTypeSelector(CSSNthExpressionMake(0, 1))); +} + +CSSSelector * lastOfTypeSelector() +{ + return namedPseudoSelector(@"last-of-type", nthLastOfTypeSelector(CSSNthExpressionMake(0, 1))); +} + +CSSSelector * onlyChildSelector() +{ + return namedPseudoSelector(@"only-child", allOf(@[firstChildSelector(), lastChildSelector()])); +} + +CSSSelector * onlyOfTypeSelector() +{ + return namedPseudoSelector(@"only-of-type", allOf(@[firstOfTypeSelector(), lastOfTypeSelector()])); +} + +#pragma mark - Combinators + +CSSSelector * childOfElementSelector(CSSSelector *selector) +{ + return [CSSCombinatorSelector childOfElementCombinator:selector]; +} + +CSSSelector * descendantOfElementSelector(CSSSelector *selector) +{ + return [CSSCombinatorSelector descendantOfElementCombinator:selector]; +} + +CSSSelector * adjacentSiblingSelector(CSSSelector *selector) +{ + return [CSSCombinatorSelector adjacentSiblingCombinator:selector]; +} + +CSSSelector * generalSiblingSelector(CSSSelector *selector) +{ + return [CSSCombinatorSelector generalSiblingCombinator:selector]; +} + +#pragma mark - Pseudo Functions + +CSSSelector * nay(CSSSelector *selector) +{ + return [CSSPseudoFunctionSelector notSelector:selector]; +} + +CSSSelector * has(CSSSelector *selector) +{ + return [CSSPseudoFunctionSelector hasSelector:selector]; +} + +#pragma mark - Compound Selectors + +CSSSelector * allOf( NSArray * selectors) +{ + return [CSSCompoundSelector andSelector:selectors]; +} + +CSSSelector * anyOf( NSArray * selectors) +{ + return [CSSCompoundSelector orSelector:selectors]; +} + +#pragma mark - Pseudo + +CSSSelector * namedPseudoSelector(NSString *name, CSSSelector *selector) +{ + return [[CSSPseudoClassSelector alloc] initWithClassName:name selector:selector]; +} + +#pragma mark - Block + +CSSSelector * namedBlockSelector(NSString *name, BOOL (^ acceptBlock)(HTMLElement *element)) +{ + return [[CSSSelectorBlock alloc] initWithName:name block:acceptBlock]; +} diff --git a/HTMLKit/CSSStructuralPseudoSelectors.h b/HTMLKit/CSSStructuralPseudoSelectors.h new file mode 100644 index 0000000..d004235 --- /dev/null +++ b/HTMLKit/CSSStructuralPseudoSelectors.h @@ -0,0 +1,40 @@ +// +// CSSStructuralPseudoSelector.h +// HTMLKit +// +// Created by Iska on 11/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +@class CSSSelector; + +NS_ASSUME_NONNULL_BEGIN + +extern CSSSelector * rootSelector(); +extern CSSSelector * emptySelector(); +extern CSSSelector * parentSelector(); + +extern CSSSelector * buttonSelector(); +extern CSSSelector * checkboxSelector(); +extern CSSSelector * fileSelector(); +extern CSSSelector * headerSelector(); +extern CSSSelector * imageSelector(); +extern CSSSelector * inputSelector(); +extern CSSSelector * linkSelector(); +extern CSSSelector * passwordSelector(); +extern CSSSelector * radioSelector(); +extern CSSSelector * resetSelector(); +extern CSSSelector * submitSelector(); +extern CSSSelector * textSelector(); + +extern CSSSelector * enabledSelector(); +extern CSSSelector * disabledSelector(); +extern CSSSelector * checkedSelector(); +extern CSSSelector * optionalSelector(); +extern CSSSelector * requiredSelector(); + +extern CSSSelector * ltSelector(); +extern CSSSelector * gtSelector(); +extern CSSSelector * eqSelector(); + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSStructuralPseudoSelectors.m b/HTMLKit/CSSStructuralPseudoSelectors.m new file mode 100644 index 0000000..0b4bd43 --- /dev/null +++ b/HTMLKit/CSSStructuralPseudoSelectors.m @@ -0,0 +1,301 @@ +// +// CSSStructuralPseudoSelector.m +// HTMLKit +// +// Created by Iska on 11/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSStructuralPseudoSelectors.h" +#import "CSSSelectors.h" +#import "HTMLElement.h" +#import "NSString+HTMLKit.h" + +#pragma mark - Elements + +CSSSelector * rootSelector() +{ + return namedBlockSelector(@":root", ^BOOL(HTMLElement * element) { + return element.parentElement == nil; + }); +} + +CSSSelector * emptySelector() +{ + return namedBlockSelector(@":empty", ^BOOL(HTMLElement * element) { + for (HTMLNode *child in element.childNodes) { + if (child.nodeType == HTMLNodeElement) { + return NO; + } else if (child.nodeType == HTMLNodeText && child.textContent.length > 0) { + return NO; + } + } + return YES; + }); +} + +CSSSelector * parentSelector() +{ + return namedBlockSelector(@":parent", ^BOOL(HTMLElement * element) { + return element.childNodesCount > 0; + }); +} + +CSSSelector * buttonSelector() +{ + return namedBlockSelector(@":button", ^BOOL(HTMLElement * _Nonnull element) { + if ([element.tagName isEqualToString:@"button"]) { + return YES; + } + if ([element.tagName isEqualToString:@"input"] && [element[@"type"] isEqualToString:@"button"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * checkboxSelector() +{ + return namedBlockSelector(@":checkbox", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"checkbox"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * fileSelector() +{ + return namedBlockSelector(@":file", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"file"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * headerSelector() +{ + return namedBlockSelector(@":header", ^BOOL(HTMLElement * _Nonnull element) { + if ([element.tagName isEqualToAny:@"h1", @"h2", @"h3", @"h4", @"h5", @"h6", nil]) { + return YES; + } + return NO; + }); +} + +CSSSelector * imageSelector() +{ + return namedBlockSelector(@":image", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"image"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * inputSelector() +{ + return namedBlockSelector(@":input", ^BOOL(HTMLElement * _Nonnull element) { + if ([element.tagName isEqualToAny:@"button", @"input", @"select", @"textarea", nil]) { + return YES; + } + return NO; + }); +} + +CSSSelector * linkSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-link + return namedBlockSelector(@":link", ^BOOL(HTMLElement * element) { + if ([element hasAttribute:@"href"]) { + return [element.tagName isEqualToAny:@"a", @"area", @"link", nil]; + } + return NO; + }); +} + +CSSSelector * passwordSelector() +{ + return namedBlockSelector(@":password", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"password"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * radioSelector() +{ + return namedBlockSelector(@":radio", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"radio"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * resetSelector() +{ + return namedBlockSelector(@":reset", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"reset"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * submitSelector() +{ + return namedBlockSelector(@":submit", ^BOOL(HTMLElement * _Nonnull element) { + if ([element.tagName isEqualToString:@"input"] && [element[@"type"] isEqualToString:@"submit"]) { + return YES; + } + if ([element.tagName isEqualToString:@"button"] && [element[@"type"] isEqualToString:@"submit"]) { + return YES; + } + return NO; + }); +} + +CSSSelector * textSelector() +{ + return namedBlockSelector(@":text", ^BOOL(HTMLElement * _Nonnull element) { + if ([element[@"type"] isEqualToString:@"text"]) { + return YES; + } + return NO; + }); +} + +#pragma mark - State + +CSSSelector * enabledSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + CSSSelector *candiate = anyOf(@[ + typeSelector(@"button"), + typeSelector(@"input"), + typeSelector(@"select"), + typeSelector(@"textarea"), + typeSelector(@"optgroup"), + typeSelector(@"option"), + typeSelector(@"menuitem"), + typeSelector(@"fieldset"), + ]); + return namedPseudoSelector(@"enabled", allOf(@[candiate, nay(disabledSelector())])); +} + +CSSSelector * disabledSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + CSSSelector *disabledAttribute = hasAttributeSelector(@"disabled"); + + // https://html.spec.whatwg.org/multipage/forms.html#concept-fieldset-disabled + CSSSelector *disabledFieldset = allOf(@[typeSelector(@"fieldset"), disabledAttribute]); + CSSSelector *firstLegend = allOf(@[typeSelector(@"legend"), firstOfTypeSelector()]); + CSSSelector *firstLegendDecendantDisabledFieldSet = allOf(@[firstLegend, descendantOfElementSelector(disabledFieldset)]); + + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + CSSSelector *disabledForm = anyOf(@[ + anyOf(@[ + allOf(@[typeSelector(@"button"), disabledAttribute]), + allOf(@[typeSelector(@"input"), disabledAttribute]), + allOf(@[typeSelector(@"select"), disabledAttribute]), + allOf(@[typeSelector(@"textarea"), disabledAttribute]) + ]), + allOf(@[ + descendantOfElementSelector(disabledFieldset), + nay(firstLegendDecendantDisabledFieldSet) + ]) + ]); + + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + CSSSelector *disabledMenuItem = allOf(@[typeSelector(@"menuitem"), disabledAttribute]); + CSSSelector *disabledOptgroup = allOf(@[typeSelector(@"optgroup"), disabledAttribute]); + + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + CSSSelector *disabledOption = allOf(@[ + typeSelector(@"option"), + anyOf(@[ + disabledAttribute, + descendantOfElementSelector(disabledOptgroup)]) + ]); + return namedPseudoSelector(@"disabled", + anyOf(@[disabledOption, disabledOptgroup, disabledMenuItem, disabledForm, disabledFieldset])); +} + +CSSSelector * checkedSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-checked + CSSSelector *candidate = anyOf(@[ + typeSelector(@"input"), + typeSelector(@"option"), + typeSelector(@"menutitem") + ]); + CSSSelector *hasAttribute = anyOf(@[ + hasAttributeSelector(@"checked"), + hasAttributeSelector(@"selected") + ]); + + return namedPseudoSelector(@"checked", allOf(@[candidate, hasAttribute])); +} + +CSSSelector * optionalSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-optional + CSSSelector *candidate = anyOf(@[ + typeSelector(@"input"), + typeSelector(@"select"), + typeSelector(@"textarea") + ]); + CSSSelector *noAttribute = nay(hasAttributeSelector(@"required")); + + return namedPseudoSelector(@"optional", allOf(@[candidate, noAttribute])); +} + +CSSSelector * requiredSelector() +{ + // https://html.spec.whatwg.org/multipage/scripting.html#selector-required + // https://html.spec.whatwg.org/multipage/forms.html#concept-input-required + CSSSelector *candidate = anyOf(@[ + typeSelector(@"input"), + typeSelector(@"select"), + typeSelector(@"textarea") + ]); + CSSSelector *hasAttribute = hasAttributeSelector(@"required"); + + return namedPseudoSelector(@"required", allOf(@[candidate, hasAttribute])); +} + +#pragma mark - Positional + +CSSSelector * ltSelector(NSUInteger index) +{ + NSString *name = [NSString stringWithFormat:@":lt(%lu)", (unsigned long)index]; + return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) { + return [element.parentElement indexOfChildNode:element] < index; + }); +} + +CSSSelector * gtSelector(NSUInteger index) +{ + NSString *name = [NSString stringWithFormat:@":gt(%lu)", (unsigned long)index]; + return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) { + return [element.parentElement indexOfChildNode:element] > index; + }); +} + +CSSSelector * eqSelector(NSInteger index) +{ + NSString *name = [NSString stringWithFormat:@":eq(%lu)", (unsigned long)index]; + return namedBlockSelector(name, ^BOOL(HTMLElement * _Nonnull element) { + NSUInteger elementIndex = [element.parentElement indexOfChildNode:element]; + + if (index > 0) { + return elementIndex == index; + } else { + return elementIndex == element.parentElement.childNodesCount - index - 1; + } + }); +} diff --git a/HTMLKit/CSSTypeSelector.h b/HTMLKit/CSSTypeSelector.h new file mode 100644 index 0000000..6bd1f93 --- /dev/null +++ b/HTMLKit/CSSTypeSelector.h @@ -0,0 +1,24 @@ +// +// CSSTypeSelector.h +// HTMLKit +// +// Created by Iska on 13/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelector.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface CSSTypeSelector : CSSSelector + +@property (nonatomic, strong, readonly) NSString *type; + ++ (instancetype)universalSelector; + +- (instancetype)initWithType:(NSString *)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/HTMLKit/CSSTypeSelector.m b/HTMLKit/CSSTypeSelector.m new file mode 100644 index 0000000..053ec74 --- /dev/null +++ b/HTMLKit/CSSTypeSelector.m @@ -0,0 +1,50 @@ +// +// CSSTypeSelector.m +// HTMLKit +// +// Created by Iska on 13/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "CSSTypeSelector.h" +#import "HTMLElement.h" +#import "NSString+HTMLKit.h" + +@interface CSSTypeSelector () +{ + NSString *_type; +} +@end + +@implementation CSSTypeSelector + ++ (instancetype)universalSelector +{ + return [[self alloc] initWithType:@"*"]; +} + +- (instancetype)initWithType:(NSString *)type +{ + self = [super init]; + if (self) { + _type = [type copy]; + } + return self; +} + +- (BOOL)acceptElement:(HTMLElement *)element +{ + if ([_type isEqualToString:@"*"] || [_type isEqualToStringIgnoringCase:element.tagName]) { + return YES; + } + return NO; +} + +#pragma mark - Description + +- (NSString *)debugDescription +{ + return self.type; +} + +@end diff --git a/HTMLKit/HTMLDocumentFragment.m b/HTMLKit/HTMLDocumentFragment.m index adcde5e..2f2d5a2 100644 --- a/HTMLKit/HTMLDocumentFragment.m +++ b/HTMLKit/HTMLDocumentFragment.m @@ -32,7 +32,7 @@ - (NSString *)textContent { NSMutableString *content = [NSMutableString string]; - for (HTMLNode *node in self.treeEnumerator) { + for (HTMLNode *node in self.nodeIterator) { if (node.nodeType == HTMLNodeText) { [content appendString:[(HTMLText *)node data]]; } diff --git a/HTMLKit/HTMLElement.m b/HTMLKit/HTMLElement.m index 6083537..9ebc3ad 100644 --- a/HTMLKit/HTMLElement.m +++ b/HTMLKit/HTMLElement.m @@ -180,4 +180,9 @@ return description; } +- (NSString *)debugDescription +{ + return self.description; +} + @end diff --git a/HTMLKit/HTMLInputStreamReader.h b/HTMLKit/HTMLInputStreamReader.h index 1ffdce8..dea5e29 100644 --- a/HTMLKit/HTMLInputStreamReader.h +++ b/HTMLKit/HTMLInputStreamReader.h @@ -24,6 +24,7 @@ typedef void (^ HTMLStreamReaderErrorCallback)(NSString *reason); - (UTF32Char)currentInputCharacter; - (UTF32Char)nextInputCharacter; +- (UTF32Char)inputCharacterPointAtOffset:(NSUInteger)offset; - (UTF32Char)consumeNextInputCharacter; - (void)reconsumeCurrentInputCharacter; @@ -35,6 +36,7 @@ typedef void (^ HTMLStreamReaderErrorCallback)(NSString *reason); - (BOOL)consumeString:(NSString *)string caseSensitive:(BOOL)caseSensitive; - (NSString *)consumeCharactersUpToCharactersInString:(NSString *)characters; - (NSString *)consumeCharactersUpToString:(NSString *)string; +- (NSString *)consumeCharactersInString:(NSString *)characters; - (NSString *)consumeAlphanumericCharacters; - (void)markCurrentLocation; diff --git a/HTMLKit/HTMLInputStreamReader.m b/HTMLKit/HTMLInputStreamReader.m index b2fcb88..3df5f8d 100644 --- a/HTMLKit/HTMLInputStreamReader.m +++ b/HTMLKit/HTMLInputStreamReader.m @@ -8,6 +8,7 @@ #import "HTMLInputStreamReader.h" #import "HTMLTokenizerCharacters.h" +#import "NSCharacterSet+HTMLKit.h" #pragma mark - HTMLInputStreamReader @@ -39,6 +40,7 @@ if (self) { _string = [string copy]; _scanner = [[NSScanner alloc] initWithString:string]; + _scanner.charactersToBeSkipped = nil; CFStringInitInlineBuffer((CFStringRef)_string, &_buffer, CFRangeMake(0, _string.length)); } return self; @@ -63,7 +65,6 @@ - (UTF32Char)nextInputCharacter { if (_reconsume) { - _reconsume = NO; return _currentInputCharacter; } @@ -106,6 +107,11 @@ return nextInputCharacter; } +- (UTF32Char)inputCharacterPointAtOffset:(NSUInteger)offset +{ + return CFStringGetCharacterFromInlineBuffer(&_buffer, _location + offset); +} + - (UTF32Char)consumeNextInputCharacter { if (_reconsume) { @@ -124,9 +130,12 @@ { UTF32Char nextInputCharacter = [self nextInputCharacter]; if (nextInputCharacter == character) { - _location += _consume; - _scanner.scanLocation = _location; - _currentInputCharacter = nextInputCharacter; + if (!_reconsume) { + _location += _consume; + _scanner.scanLocation = _location; + _currentInputCharacter = nextInputCharacter; + } + _reconsume = NO; return YES; } return NO; @@ -145,7 +154,7 @@ - (BOOL)consumeHexNumber:(unsigned long long *)result { - NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"]; + NSCharacterSet *set = [NSCharacterSet HTMLHexNumberCharacterSet]; NSString *string = nil; BOOL success = [_scanner scanCharactersFromSet:set intoString:&string]; @@ -193,6 +202,26 @@ return consumed; } +- (NSString *)consumeCharactersInString:(NSString *)characters +{ + NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:characters]; + + if (_reconsume) { + _scanner.scanLocation--; + } + + NSString *string = nil; + BOOL success = [_scanner scanCharactersFromSet:set intoString:&string]; + if (success == NO) { + _scanner.scanLocation++; + return nil; + } + + _reconsume = NO; + _location = _scanner.scanLocation; + return string; +} + - (NSString *)consumeAlphanumericCharacters { NSCharacterSet *set = [NSCharacterSet alphanumericCharacterSet]; diff --git a/HTMLKit/HTMLKit.h b/HTMLKit/HTMLKit.h index 3b5c810..5d85025 100644 --- a/HTMLKit/HTMLKit.h +++ b/HTMLKit/HTMLKit.h @@ -6,8 +6,7 @@ // Copyright (c) 2014 BrainCookie. All rights reserved. // -#import - -@interface HTMLKit : NSObject - -@end +#import "HTMLParser.h" +#import "HTMLDOM.h" +#import "CSSSelectors.h" +#import "HTMLKitErrorDomain.h" diff --git a/HTMLKit/HTMLKit.m b/HTMLKit/HTMLKit.m deleted file mode 100644 index da149aa..0000000 --- a/HTMLKit/HTMLKit.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// HTMLKit.m -// HTMLKit -// -// Created by Iska on 15/09/14. -// Copyright (c) 2014 BrainCookie. All rights reserved. -// - -#import "HTMLKit.h" - -@implementation HTMLKit - -@end diff --git a/HTMLKit/HTMLKitErrorDomain.h b/HTMLKit/HTMLKitErrorDomain.h new file mode 100644 index 0000000..98ca6f8 --- /dev/null +++ b/HTMLKit/HTMLKitErrorDomain.h @@ -0,0 +1,23 @@ +// +// HTMLKitErrorDomain.h +// HTMLKit +// +// Created by Iska on 24/11/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#ifndef HTMLKitErrorDomain_h +#define HTMLKitErrorDomain_h + +static NSString *const HTMLKitErrorDomain = @"HTMLKit"; +static NSString *const HTMLKitSelectorErrorDomain = @"HTMLKitSelector"; + +static NSString *const CSSSelectorStringKey = @"CSSSelectorString"; +static NSString *const CSSSelectorErrorLocationKey = @"CSSSelectorErrorLocation"; + +NS_ENUM(NSInteger) +{ + HTMLKitSelectorParseError = 4200 +}; + +#endif /* HTMLKitErrorDomain_h */ diff --git a/HTMLKit/HTMLNode.h b/HTMLKit/HTMLNode.h index eb07dbc..e5fac40 100644 --- a/HTMLKit/HTMLNode.h +++ b/HTMLKit/HTMLNode.h @@ -38,6 +38,7 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) @class HTMLDocument; @class HTMLElement; +@class CSSSelector; @interface HTMLNode : NSObject @@ -61,6 +62,10 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) @property (nonatomic, strong, readonly) HTMLNode *nextSibling; +@property (nonatomic, strong, readonly) HTMLElement *previousSiblingElement; + +@property (nonatomic, strong, readonly) HTMLElement *nextSiblingElement; + @property (nonatomic, copy) NSString *textContent; @property (nonatomic, strong, readonly) NSString *outerHTML; @@ -83,6 +88,12 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) - (NSUInteger)indexOfChildNode:(HTMLNode *)node; +- (NSUInteger)childElementsCount; + +- (HTMLElement *)childElementAtIndex:(NSUInteger)index; + +- (NSUInteger)indexOfChildElement:(HTMLElement *)element; + - (HTMLNode *)prependNode:(HTMLNode *)node; - (void)prependNodes:(NSArray *)nodes; @@ -121,6 +132,9 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) - (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions filterBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))filter; +- (HTMLElement *)firstElementMatchingSelector:(CSSSelector *)selector; +- (NSArray *)elementsMatchingSelector:(CSSSelector *)selector; + - (NSString *)treeDescription; @end diff --git a/HTMLKit/HTMLNode.m b/HTMLKit/HTMLNode.m index fdff072..c630665 100644 --- a/HTMLKit/HTMLNode.m +++ b/HTMLKit/HTMLNode.m @@ -13,6 +13,7 @@ #import "HTMLText.h" #import "HTMLComment.h" #import "HTMLKitDOMExceptions.h" +#import "CSSSelector.h" @interface HTMLDocument (Private) - (void)runRemovingStepsForNode:(HTMLNode *)oldNode @@ -98,6 +99,24 @@ return [_parentNode childNodeAtIndex:index + 1]; } +- (HTMLElement *)previousSiblingElement +{ + HTMLNode *node = self.previousSibling; + while (node && node.nodeType != HTMLNodeElement) { + node = node.previousSibling; + } + return node.asElement; +} + +- (HTMLElement *)nextSiblingElement +{ + HTMLNode *node = self.previousSibling; + while (node && node.nodeType != HTMLNodeElement) { + node = node.nextSibling; + } + return node.asElement; +} + - (NSString *)textContent { return nil; @@ -140,11 +159,46 @@ return [self.childNodes objectAtIndex:index]; } +- (NSUInteger)childElementsCount +{ + return [self.childNodes indexesOfObjectsPassingTest:^BOOL(HTMLNode * _Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) { + return node.nodeType == HTMLNodeElement; + }].count; +} + - (NSUInteger)indexOfChildNode:(HTMLNode *)node { return [self.childNodes indexOfObject:node]; } +- (HTMLElement *)childElementAtIndex:(NSUInteger)index +{ + NSUInteger counter = 0; + for (HTMLNode *node in self.childNodes) { + if (node.nodeType == HTMLNodeElement) { + if (counter == index) { + return node.asElement; + } + counter++; + } + } + return nil; +} + +- (NSUInteger)indexOfChildElement:(HTMLElement *)element +{ + NSUInteger counter = 0; + for (HTMLNode *node in self.childNodes) { + if (node.nodeType == HTMLNodeElement) { + if (node == element) { + return counter; + } + counter++; + } + } + return NSNotFound; +} + - (HTMLNode *)prependNode:(HTMLNode *)node { return [self insertNode:node beforeChildNode:self.firstChild]; @@ -386,6 +440,29 @@ return [HTMLNodeIterator iteratorWithNode:self showOptions:showOptions filter:filter]; } +#pragma mark - Selectors + +- (HTMLElement *)firstElementMatchingSelector:(CSSSelector *)selector +{ + for (HTMLElement *element in [self nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) { + if ([selector acceptElement:element]) { + return element; + } + } + return nil; +} + +- (NSArray *)elementsMatchingSelector:(CSSSelector *)selector +{ + NSMutableArray *result = [NSMutableArray array]; + for (HTMLElement *element in [self nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) { + if ([selector acceptElement:element]) { + [result addObject:element]; + } + } + return result; +} + #ifndef HTMLKIT_NO_DOM_CHECKS #pragma mark - Validity Checks @@ -610,12 +687,7 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p %@>", self.class, self, self.name]; -} - -- (NSString *)debugDescription -{ - return self.treeDescription; + return [NSString stringWithFormat:@"<%@: %p '%@'>", self.class, self, self.name]; } - (id)debugQuickLookObject diff --git a/HTMLKit/HTMLNodeFilter.h b/HTMLKit/HTMLNodeFilter.h index a32a2ea..3046762 100644 --- a/HTMLKit/HTMLNodeFilter.h +++ b/HTMLKit/HTMLNodeFilter.h @@ -26,6 +26,9 @@ typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions) HTMLNodeFilterShowDocumentFragment = 0x400 }; + +#pragma mark - Node Filter + @class HTMLNode; @protocol HTMLNodeFilter @@ -34,8 +37,20 @@ typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions) @end +#pragma mark - Block Filter + @interface HTMLNodeFilterBlock : NSObject + (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))block; @end + +#pragma mark - CSS Selector Filter + +@class CSSSelector; + +@interface HTMLSelectorNodeFilter : NSObject + ++ (instancetype)filterWithSelector:(CSSSelector *)selector; + +@end diff --git a/HTMLKit/HTMLNodeFilter.m b/HTMLKit/HTMLNodeFilter.m index 96e4843..a1e0d2b 100644 --- a/HTMLKit/HTMLNodeFilter.m +++ b/HTMLKit/HTMLNodeFilter.m @@ -7,6 +7,10 @@ // #import "HTMLNodeFilter.h" +#import "HTMLNode.h" +#import "CSSSelector.h" + +#pragma mark - Block Filter @interface HTMLNodeFilterBlock () { @@ -40,3 +44,42 @@ } @end + +#pragma mark - CSS Selector Filter + +@interface HTMLSelectorNodeFilter () +{ + CSSSelector *_selector; +} +@end + +@implementation HTMLSelectorNodeFilter + ++ (instancetype)filterWithSelector:(CSSSelector *)selector +{ + return [[self alloc] initWithSelector:selector]; +} + +- (instancetype)initWithSelector:(CSSSelector *)selector +{ + self = [super init]; + if (self) { + _selector = selector; + } + return self; +} + +- (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node +{ + if (node.nodeType != HTMLNodeElement) { + return HTMLNodeFilterSkip; + } + + if ([_selector acceptElement:node.asElement]) { + return HTMLNodeFilterAccept; + } + + return HTMLNodeFilterSkip; +} + +@end diff --git a/HTMLKit/NSCharacterSet+HTMLKit.h b/HTMLKit/NSCharacterSet+HTMLKit.h new file mode 100644 index 0000000..59dd2c7 --- /dev/null +++ b/HTMLKit/NSCharacterSet+HTMLKit.h @@ -0,0 +1,17 @@ +// +// NSCharacterSet+HTMLKit.h +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import + +@interface NSCharacterSet (HTMLKit) + ++ (instancetype)HTMLWhitespaceCharacterSet; ++ (instancetype)HTMLHexNumberCharacterSet; ++ (instancetype)CSSNthExpressionCharacterSet; + +@end diff --git a/HTMLKit/NSCharacterSet+HTMLKit.m b/HTMLKit/NSCharacterSet+HTMLKit.m new file mode 100644 index 0000000..8ad588c --- /dev/null +++ b/HTMLKit/NSCharacterSet+HTMLKit.m @@ -0,0 +1,43 @@ +// +// NSCharacterSet+HTMLKit.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "NSCharacterSet+HTMLKit.h" + +@implementation NSCharacterSet (HTMLKit) + ++ (instancetype)HTMLWhitespaceCharacterSet +{ + static NSCharacterSet *set = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r\f"]; + }); + return set; +} + ++ (instancetype)HTMLHexNumberCharacterSet +{ + static NSCharacterSet *set = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"]; + }); + return set; +} + ++ (instancetype)CSSNthExpressionCharacterSet +{ + static NSCharacterSet *set = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + set = [NSCharacterSet characterSetWithCharactersInString:@" 0123456789nN-+"]; + }); + return set; +} + +@end diff --git a/HTMLKitTests/CSSAttributeSelectorTests.m b/HTMLKitTests/CSSAttributeSelectorTests.m new file mode 100644 index 0000000..8811dff --- /dev/null +++ b/HTMLKitTests/CSSAttributeSelectorTests.m @@ -0,0 +1,238 @@ +// +// CSSAttributeSelectorTests.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLDOM.h" + +@interface CSSAttributeSelectorTests : XCTestCase +{ + HTMLElement *_element; +} +@end + +@implementation CSSAttributeSelectorTests + +- (void)setUp +{ + [super setUp]; + _element = [[HTMLElement alloc] initWithTagName:@"div"]; +} + +- (void)testAttributeExists +{ + CSSSelector *selector = hasAttributeSelector(@"attr"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"value 2"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"value 3"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeExactMatch +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorExactMatch, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value 1"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value 2"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value 3"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeIncludes +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorIncludes, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"a b value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"a value b"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeBegins +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorBegins, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"val"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"a value"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"values"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeEnds +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorEnds, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"val"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"a value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"some-value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeContains +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorContains, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"val"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"a value b"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"some-values"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeHyphen +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorHyphen, @"attr", @"top"); + + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"top_text"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"toptext"; + XCTAssertEqual([selector acceptElement:_element], NO); + + _element[@"attr"] = @"top"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"top-text"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testAttributeNot +{ + CSSSelector *selector = attributeSelector(CSSAttributeSelectorNot, @"attr", @"value"); + + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"class"] = @"class"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"top_text"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"toptext"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"top"; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"top-text"; + XCTAssertEqual([selector acceptElement:_element], YES); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertEqual([selector acceptElement:_element], YES); + + _element[@"attr"] = @"value"; + XCTAssertEqual([selector acceptElement:_element], NO); +} + +- (void)testIdSelector +{ + _element[@"id"] = @"id"; + XCTAssertEqual([idSelector(@"id") acceptElement:_element], YES); + XCTAssertEqual([idSelector(@"other id") acceptElement:_element], NO); +} + +- (void)testClassSelector +{ + _element[@"class"] = @"class"; + XCTAssertEqual([classSelector(@"class") acceptElement:_element], YES); + XCTAssertEqual([classSelector(@"other class") acceptElement:_element], NO); +} + +@end diff --git a/HTMLKitTests/CSSCombinatorSelectorTests.m b/HTMLKitTests/CSSCombinatorSelectorTests.m new file mode 100644 index 0000000..4296068 --- /dev/null +++ b/HTMLKitTests/CSSCombinatorSelectorTests.m @@ -0,0 +1,116 @@ +// +// CSSCombinatorSelectorTests.m +// HTMLKit +// +// Created by Iska on 23/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLParser.h" +#import "HTMLDOM.h" + +@interface CSSCombinatorSelectorTests : XCTestCase +{ + HTMLDocument *_document; +} +@end + +@implementation CSSCombinatorSelectorTests + +- (void)setUp +{ + [super setUp]; + + /* + | + |

+ | A paragraphA span + | + | + | + | + | + | + | + | + |
+ | Span in table + |
+ |

+ |
+ |

+ |
+ |
+ |

+ |
+ | + */ + _document = [[[HTMLParser alloc] initWithString:@"" + "

" + "A paragraphA span" + "" + "" + "" + "" + "" + "" + "
" + "Span in table" + "
" + "

" + "
" + "

" + "
" + "
" + "

" + "
" + ""] document]; +} + +-(void)testChildOfElementCombinator +{ + NSArray *elements = [_document elementsMatchingSelector:childOfElementSelector(typeSelector(@"body"))]; + NSArray *expected = @[@"p1", @"inner-div1", @"inner-div2"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_document elementsMatchingSelector:childOfElementSelector(typeSelector(@"p"))]; + expected = @[@"span1", @"table"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +-(void)testDescendantOfElementCombinator +{ + NSArray *elements = [_document elementsMatchingSelector:descendantOfElementSelector(typeSelector(@"p"))]; + NSArray *expected = @[@"span1", @"table", @"tbody", @"tr1", @"td", @"span2", @"tr2", @"tr3"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_document elementsMatchingSelector:descendantOfElementSelector(typeSelector(@"table"))]; + expected = @[@"tbody", @"tr1", @"td", @"span2", @"tr2", @"tr3"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +-(void)testAdjacentSiblingCombinator +{ + NSArray *elements = [_document elementsMatchingSelector:adjacentSiblingSelector(typeSelector(@"tr"))]; + NSArray *expected = @[@"tr2", @"tr3"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_document elementsMatchingSelector:adjacentSiblingSelector(typeSelector(@"p"))]; + expected = @[@"inner-div1"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +-(void)testGeneralSiblingCombinator +{ + NSArray *elements = [_document elementsMatchingSelector:generalSiblingSelector(typeSelector(@"tr"))]; + NSArray *expected = @[@"tr2", @"tr3"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_document elementsMatchingSelector:generalSiblingSelector(typeSelector(@"p"))]; + expected = @[@"inner-div1", @"inner-div2"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +@end diff --git a/HTMLKitTests/CSSNThExpressionSelectorTests.m b/HTMLKitTests/CSSNThExpressionSelectorTests.m new file mode 100644 index 0000000..b107eeb --- /dev/null +++ b/HTMLKitTests/CSSNThExpressionSelectorTests.m @@ -0,0 +1,352 @@ +// +// CSSNThExpressionSelectorTests.m +// HTMLKit +// +// Created by Iska on 21/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLParser.h" +#import "HTMLDOM.h" + +@interface CSSNThExpressionSelectorTests : XCTestCase +{ + HTMLDocument *_childTree; + HTMLDocument *_typeTree; +} +@end + +@implementation CSSNThExpressionSelectorTests + +- (void)setUp +{ + [super setUp]; + + /* + |
+ | + | + | + | + | + |
11
12
13
14
+ |
+ |
+ | + | + |
21
+ |
+ |
+ | + | + | + | + | + | + | + |
31
32
33
34
35
36
+ |
+ */ + _childTree = [[[HTMLParser alloc] initWithString:@"
" + "" + "" + "" + "" + "
11
12
13
14
" + "
" + "" + "
21
" + "
" + "" + "" + "" + "" + "" + "" + "
31
32
33
34
35
36
"] document]; + + /* + |
+ | s11 + | s12 + | s13 + | b1 + |
+ |
+ | b2 + | s21 + | s22 + | s23 + |
+ |
+ | s31 + | b3 + | s32 + | b4 + | s33 + | b5 + | s34 + |
+ */ + _typeTree = [[[HTMLParser alloc] initWithString:@"
" + "s11" + "s12" + "s13" + "b1" + "
" + "
" + "b2" + "s21" + "s22" + "s23" + "
" + "
" + "s31" + "b3" + "s32" + "b4" + "s33" + "b5" + "s34" + "
"] document]; +} + +- (void)testOddSelector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), oddSelector()])]; + NSArray *expected = @[@"11", @"13", @"21", @"31", @"33", @"35"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testEvenSelector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), evenSlector()])]; + NSArray *expected = @[@"12", @"14", @"32", @"34", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testFirstChildSelector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), firstChildSelector()])]; + NSArray *expected = @[@"11", @"21", @"31"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testLastChildSelector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), lastChildSelector()])]; + NSArray *expected = @[@"14", @"21", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testFirstOfTypeSelector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), firstOfTypeSelector()])]; + NSArray *expected = @[@"s11", @"s21", @"s31"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testLastOfTypeSelector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), lastOfTypeSelector()])]; + NSArray *expected = @[@"s13", @"s23", @"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testOnlyChildSelector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), onlyChildSelector()])]; + NSArray *expected = @[@"21"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)testOnlyOfTypeSelector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), onlyOfTypeSelector()])]; + NSArray *expected = @[]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), onlyOfTypeSelector()])]; + expected = @[]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"b"), onlyOfTypeSelector()])]; + expected = @[@"b1", @"b2"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +#pragma mark - Nth-Child Selector + +- (void)test_NthChild_B_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 1))])]; + NSArray *expected = @[@"11", @"21", @"31"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 2))])]; + expected = @[@"12", @"32"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 3))])]; + expected = @[@"13", @"33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthChild_An_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(2, 0))])]; + NSArray *expected = @[@"12", @"14", @"32", @"34", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 0))])]; + expected = @[@"13", @"33", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(4, 0))])]; + expected = @[@"14", @"34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthChild_An_B_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 1))])]; + NSArray *expected = @[@"11", @"14", @"21", @"31", @"34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 2))])]; + expected = @[@"12", @"32", @"35"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +#pragma mark - Nth-Last-Child Selector + +- (void)test_NthLastChild_B_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 1))])]; + NSArray *expected = @[@"14", @"21", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 2))])]; + expected = @[@"13", @"35"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 3))])]; + expected = @[@"12", @"34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthLastChild_An_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(2, 0))])]; + NSArray *expected = @[@"11", @"13", @"31", @"33", @"35"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 0))])]; + expected = @[@"12", @"31", @"34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(4, 0))])]; + expected = @[@"11", @"33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthLastChild_An_B_Selector +{ + NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 1))])]; + NSArray *expected = @[@"11", @"14", @"21", @"33", @"36"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 2))])]; + expected = @[@"13", @"32", @"35"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +#pragma mark - Nth-Of-Type Selector + +- (void)test_NthOfType_B_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 1))])]; + NSArray *expected = @[@"s11", @"s21", @"s31"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 2))])]; + expected = @[@"s12", @"s22", @"s32"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 3))])]; + expected = @[@"s13", @"s23", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthOfType_An_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 0))])]; + NSArray *expected = @[@"s12", @"s22", @"s32", @"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(3, 0))])]; + expected = @[@"s13", @"s23", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(4, 0))])]; + expected = @[@"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthOfType_An_B_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 1))])]; + NSArray *expected = @[@"s11", @"s13", @"s21", @"s23", @"s31", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 2))])]; + expected = @[@"s12", @"s22", @"s32", @"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +#pragma mark - Nth-Last-Of-Type Selector + +- (void)test_NthLastOfType_B_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 1))])]; + NSArray *expected = @[@"s13", @"s23", @"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 2))])]; + expected = @[@"s12", @"s22", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 3))])]; + expected = @[@"s11", @"s21", @"s32"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthLastOfType_An_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 0))])]; + NSArray *expected = @[@"s12", @"s22", @"s31", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(3, 0))])]; + expected = @[@"s11", @"s21", @"s32"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(4, 0))])]; + expected = @[@"s31"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +- (void)test_NthLastOfType_An_B_Selector +{ + NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 1))])]; + NSArray *expected = @[@"s11", @"s13", @"s21", @"s23", @"s32", @"s34"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); + + elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 2))])]; + expected = @[@"s12", @"s22", @"s31", @"s33"]; + XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected); +} + +@end diff --git a/HTMLKitTests/CSSNthExpressionsParserTests.m b/HTMLKitTests/CSSNthExpressionsParserTests.m new file mode 100644 index 0000000..6a811e0 --- /dev/null +++ b/HTMLKitTests/CSSNthExpressionsParserTests.m @@ -0,0 +1,158 @@ +// +// CSSNthExpressionsParserTests.m +// HTMLKit +// +// Created by Iska on 10/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSNthExpressionParser.h" + +@interface CSSNthExpressionsParserTests : XCTestCase + +@end + +@implementation CSSNthExpressionsParserTests + +- (void)testOddEvenExpression +{ + CSSNthExpression odd = [CSSNthExpressionParser parseExpression:@"odd"]; + XCTAssertEqual(odd.an, 2); + XCTAssertEqual(odd.b, 1); + + odd = [CSSNthExpressionParser parseExpression:@" odd"]; + XCTAssertEqual(odd.an, 2); + XCTAssertEqual(odd.b, 1); + + odd = [CSSNthExpressionParser parseExpression:@"odd "]; + XCTAssertEqual(odd.an, 2); + XCTAssertEqual(odd.b, 1); + + odd = [CSSNthExpressionParser parseExpression:@" odd "]; + XCTAssertEqual(odd.an, 2); + XCTAssertEqual(odd.b, 1); + + CSSNthExpression even = [CSSNthExpressionParser parseExpression:@"even"]; + XCTAssertEqual(even.an, 2); + XCTAssertEqual(even.b, 0); + + even = [CSSNthExpressionParser parseExpression:@" even"]; + XCTAssertEqual(even.an, 2); + XCTAssertEqual(even.b, 0); + + even = [CSSNthExpressionParser parseExpression:@"even "]; + XCTAssertEqual(even.an, 2); + XCTAssertEqual(even.b, 0); + + even = [CSSNthExpressionParser parseExpression:@" even "]; + XCTAssertEqual(even.an, 2); + XCTAssertEqual(even.b, 0); +} + +- (void)test_B_Expression +{ + CSSNthExpression expression = [CSSNthExpressionParser parseExpression:@"1"]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"+1"]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"-1"]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@" -1"]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"+1 "]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@" +1 "]; + XCTAssertEqual(expression.an, 0); + XCTAssertEqual(expression.b, 1); +} + +- (void)test_AN_Expression +{ + CSSNthExpression expression = [CSSNthExpressionParser parseExpression:@"n"]; + XCTAssertEqual(expression.an, 1); + XCTAssertEqual(expression.b, 0); + + expression = [CSSNthExpressionParser parseExpression:@"+n"]; + XCTAssertEqual(expression.an, 1); + XCTAssertEqual(expression.b, 0); + + expression = [CSSNthExpressionParser parseExpression:@"2n"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, 0); + + expression = [CSSNthExpressionParser parseExpression:@"+2n"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, 0); + + expression = [CSSNthExpressionParser parseExpression:@"-n"]; + XCTAssertEqual(expression.an, -1); + XCTAssertEqual(expression.b, 0); + + expression = [CSSNthExpressionParser parseExpression:@"-2n"]; + XCTAssertEqual(expression.an, -2); + XCTAssertEqual(expression.b, 0); +} + +- (void)test_AN_B_Expression +{ + CSSNthExpression expression = [CSSNthExpressionParser parseExpression:@"2n+1"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"+2n+1"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"-2n+1"]; + XCTAssertEqual(expression.an, -2); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"2n-1"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"-2n-1"]; + XCTAssertEqual(expression.an, -2); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"n-1"]; + XCTAssertEqual(expression.an, 1); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"-n-1"]; + XCTAssertEqual(expression.an, -1); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"+n-1"]; + XCTAssertEqual(expression.an, 1); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@"+2n + 1"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@"-2n + 1"]; + XCTAssertEqual(expression.an, -2); + XCTAssertEqual(expression.b, 1); + + expression = [CSSNthExpressionParser parseExpression:@" 2n - 1"]; + XCTAssertEqual(expression.an, 2); + XCTAssertEqual(expression.b, -1); + + expression = [CSSNthExpressionParser parseExpression:@" -2n -1 "]; + XCTAssertEqual(expression.an, -2); + XCTAssertEqual(expression.b, -1); +} + +@end diff --git a/HTMLKitTests/CSSSelectorParserTests.m b/HTMLKitTests/CSSSelectorParserTests.m new file mode 100644 index 0000000..1966e44 --- /dev/null +++ b/HTMLKitTests/CSSSelectorParserTests.m @@ -0,0 +1,104 @@ +// +// CSSSelectorParserTests.m +// HTMLKit +// +// Created by Iska on 23/10/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import +#import +#import "CSSSelectorTest.h" +#import "CSSSelectorParser.h" + +@interface CSSSelectorParserTests : XCTestCase +@property (nonatomic, strong) CSSSelectorTest *testCase; +@end + +@implementation CSSSelectorParserTests + ++ (XCTestSuite *)defaultTestSuite +{ + XCTestSuite *suite = [[XCTestSuite alloc] initWithName:NSStringFromClass(self)]; + + NSArray *tests = [CSSSelectorTest loadCSSSelectorTests]; + for (CSSSelectorTest *test in tests) { + [self addSelectorTest:test toTestSuite:suite]; + } + + return suite; +} + ++ (void)addSelectorTest:(CSSSelectorTest *)selectorTest toTestSuite:(XCTestSuite *)suite +{ + NSArray *allInvocations = [self testInvocations]; + for (NSInvocation *invocation in allInvocations) { + XCTestCase *testCase = [[self alloc] initWithInvocation:invocation + testCase:selectorTest]; + [suite addTest:testCase]; + } +} + +#pragma mark - Instance + +- (instancetype)initWithInvocation:(NSInvocation *)invocation + testCase:(CSSSelectorTest *)testCase +{ + self = [super initWithInvocation:invocation]; + if (self) { + _testCase = testCase; + } + return self; +} + +- (NSString *)name +{ + NSInvocation *invocation = [self invocation]; + NSString *title = self.testCase.testName.stringByDeletingPathExtension; + return [NSString stringWithFormat:@"-[%@ %@_%@]", self.class, NSStringFromSelector(invocation.selector), title]; +} + +- (NSString *)description +{ + return self.name; +} + +#pragma mark - Tests + +- (void)testParser +{ + for (NSDictionary *testDescription in self.testCase.selectors) { + NSString *selectorString = testDescription[@"selector"]; + NSArray *expectedMatches = testDescription[@"match"]; + NSNumber *expectedError = testDescription[@"error"]; + HTMLElement *testDOM = self.testCase.testDOM; + + NSError *error = nil; + CSSSelector *parsedSelector = [CSSSelectorParser parseSelector:selectorString error:&error]; + + if (expectedError) { + XCTAssertNotNil(error); + XCTAssertNil(parsedSelector); + + NSUInteger errorLocation = [error.userInfo[CSSSelectorErrorLocationKey] unsignedIntegerValue]; + XCTAssertEqual(errorLocation, expectedError.unsignedIntegerValue); + } else { + XCTAssertNil(error); + XCTAssertNotNil(parsedSelector); + + NSArray *matchedElements = [testDOM elementsMatchingSelector:parsedSelector]; + NSArray *matchedIds = [matchedElements valueForKeyPath:@"attributes.id"]; + + NSString *message = [NSString stringWithFormat:@"CSS test: \'%@\'\nInput:\n%@\nDOM:\n%@\nExpected:\n%@\nActual:\n%@\n", + self.name, + selectorString, + testDOM.outerHTML, + expectedMatches, + matchedIds]; + + XCTAssertEqualObjects(matchedIds, expectedMatches, @"IDs mismatch:\n%@", message); + } + } +} + +@end diff --git a/HTMLKitTests/CSSSelectorTest.h b/HTMLKitTests/CSSSelectorTest.h new file mode 100644 index 0000000..6bb9821 --- /dev/null +++ b/HTMLKitTests/CSSSelectorTest.h @@ -0,0 +1,21 @@ +// +// CSSSelectorTest.h +// HTMLKit +// +// Created by Iska on 22/11/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import + +@class HTMLElement; + +@interface CSSSelectorTest : NSObject + +@property (nonatomic, copy) NSString *testName; +@property (nonatomic, strong) NSArray *selectors; +@property (nonatomic, strong) HTMLElement *testDOM; + ++ (NSArray *)loadCSSSelectorTests; + +@end diff --git a/HTMLKitTests/CSSSelectorTest.m b/HTMLKitTests/CSSSelectorTest.m new file mode 100644 index 0000000..a85191e --- /dev/null +++ b/HTMLKitTests/CSSSelectorTest.m @@ -0,0 +1,60 @@ +// +// CSSSelectorTest.m +// HTMLKit +// +// Created by Iska on 22/11/15. +// Copyright © 2015 BrainCookie. All rights reserved. +// + +#import "CSSSelectorTest.h" +#import "HTMLParser.h" +#import "HTMLDocument.h" +#import "HTMLElement.h" +#import "CSSSelectors.h" + +static NSString * const CSSTests = @"css-tests"; + +@implementation CSSSelectorTest + ++ (NSArray *)loadCSSSelectorTests +{ + NSString *path = [[NSBundle bundleForClass:self.class] resourcePath]; + path = [path stringByAppendingPathComponent:CSSTests]; + + NSMutableArray *tests = [NSMutableArray array]; + NSArray *testFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]; + + for (NSString *testFile in testFiles) { + if (![testFile.pathExtension isEqualToString:@"html"]) { + continue; + } + + NSString *testFilePath = [path stringByAppendingPathComponent:testFile]; + CSSSelectorTest *test = [CSSSelectorTest testWithFileAtPath:testFilePath]; + [tests addObject:test]; + } + + return tests; +} + ++ (instancetype)testWithFileAtPath:(NSString *)filePath +{ + NSString *testName = filePath.lastPathComponent.stringByDeletingPathExtension; + + NSString *html = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + + HTMLDocument *document = [HTMLDocument documentWithString:html]; + + HTMLElement *domElement = [document firstElementMatchingSelector:idSelector(@"testDOM")]; + HTMLElement *scriptElement = [document firstElementMatchingSelector:idSelector(@"selectors")]; + NSData *data = [scriptElement.textContent dataUsingEncoding:NSUTF8StringEncoding]; + NSArray *selectors = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; + + CSSSelectorTest *instance = [CSSSelectorTest new]; + instance.testName = testName; + instance.selectors = selectors; + instance.testDOM = domElement; + return instance; +} + +@end diff --git a/HTMLKitTests/CSSTypeSelectorTests.m b/HTMLKitTests/CSSTypeSelectorTests.m new file mode 100644 index 0000000..58b26a8 --- /dev/null +++ b/HTMLKitTests/CSSTypeSelectorTests.m @@ -0,0 +1,43 @@ +// +// CSSTypeSelectorTests.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLDOM.h" +#import "CSSSelectorParser.h" + +@interface CSSTypeSelectorTests : XCTestCase + +@end + +@implementation CSSTypeSelectorTests + +- (void)testUniversalSelector +{ + CSSSelector *selector = universalSelector(); + + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:nil]], YES); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@""]], YES); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"div"]], YES); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"p"]], YES); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"any other name"]], YES); +} + +- (void)testTypeSelector +{ + CSSSelector *selector = typeSelector(@"div"); + + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:nil]], NO); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@""]], NO); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"p"]], NO); + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"any other name"]], NO); + + XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"div"]], YES); +} + +@end diff --git a/HTMLKitTests/css-tests/1.html b/HTMLKitTests/css-tests/1.html new file mode 100644 index 0000000..7a929b6 --- /dev/null +++ b/HTMLKitTests/css-tests/1.html @@ -0,0 +1,13 @@ + +
+
    +
  • The background of this list item should be green
  • +
  • The background of this second list item should be also green
  • +
+

The background of this paragraph should be green.

+
diff --git a/HTMLKitTests/css-tests/10.html b/HTMLKitTests/css-tests/10.html new file mode 100644 index 0000000..4cac7d8 --- /dev/null +++ b/HTMLKitTests/css-tests/10.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background because its title attribute ends with "bar"

+
diff --git a/HTMLKitTests/css-tests/11.html b/HTMLKitTests/css-tests/11.html new file mode 100644 index 0000000..e324c90 --- /dev/null +++ b/HTMLKitTests/css-tests/11.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background because its title attribute contains "bar"

+
diff --git a/HTMLKitTests/css-tests/13.html b/HTMLKitTests/css-tests/13.html new file mode 100644 index 0000000..ff0776a --- /dev/null +++ b/HTMLKitTests/css-tests/13.html @@ -0,0 +1,23 @@ + +
+
    +
  • This list item should have green background because its class is "t1"
  • +
  • This list item should have green background because its class is "t2"
  • +
  • + This list item should have green background because the inner SPAN does not match SPAN.t3 +
  • +
+
diff --git a/HTMLKitTests/css-tests/14.html b/HTMLKitTests/css-tests/14.html new file mode 100644 index 0000000..9746a50 --- /dev/null +++ b/HTMLKitTests/css-tests/14.html @@ -0,0 +1,30 @@ + +
+

This paragraph should have a green background and a green thick solid border because it carries both classes t1 and t2.

+
This line should be green.
+
diff --git a/HTMLKitTests/css-tests/144.html b/HTMLKitTests/css-tests/144.html new file mode 100644 index 0000000..255ea3d --- /dev/null +++ b/HTMLKitTests/css-tests/144.html @@ -0,0 +1,11 @@ + +
+
+

This paragraph should have a green background.

+
+
diff --git a/HTMLKitTests/css-tests/148.html b/HTMLKitTests/css-tests/148.html new file mode 100644 index 0000000..87d2a6a --- /dev/null +++ b/HTMLKitTests/css-tests/148.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/149.html b/HTMLKitTests/css-tests/149.html new file mode 100644 index 0000000..c5bdb92 --- /dev/null +++ b/HTMLKitTests/css-tests/149.html @@ -0,0 +1,10 @@ + +
+
+
This line should have a green background.
+
diff --git a/HTMLKitTests/css-tests/14b.html b/HTMLKitTests/css-tests/14b.html new file mode 100644 index 0000000..de12356 --- /dev/null +++ b/HTMLKitTests/css-tests/14b.html @@ -0,0 +1,22 @@ + +
+

This line should be green.

+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/14c.html b/HTMLKitTests/css-tests/14c.html new file mode 100644 index 0000000..26c5459 --- /dev/null +++ b/HTMLKitTests/css-tests/14c.html @@ -0,0 +1,19 @@ + +
+

This line should be green.

+
This line should be green.
+
This line should be green.
+
diff --git a/HTMLKitTests/css-tests/14d.html b/HTMLKitTests/css-tests/14d.html new file mode 100644 index 0000000..ef67d2d --- /dev/null +++ b/HTMLKitTests/css-tests/14d.html @@ -0,0 +1,21 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/14e.html b/HTMLKitTests/css-tests/14e.html new file mode 100644 index 0000000..90ec981 --- /dev/null +++ b/HTMLKitTests/css-tests/14e.html @@ -0,0 +1,19 @@ + +
+

This line should be green.

+
This line should be green.
+
This line should be green.
+
diff --git a/HTMLKitTests/css-tests/15.html b/HTMLKitTests/css-tests/15.html new file mode 100644 index 0000000..40ccf78 --- /dev/null +++ b/HTMLKitTests/css-tests/15.html @@ -0,0 +1,27 @@ + +
+
    +
  • This list item should have a green background. because its ID is "t1"
  • +
  • This list item should have a green background. because its ID is "t2"
  • +
  • + This list item should have a green background. because the inner SPAN does not match "#t4" +
  • +
+
diff --git a/HTMLKitTests/css-tests/150.html b/HTMLKitTests/css-tests/150.html new file mode 100644 index 0000000..209522a --- /dev/null +++ b/HTMLKitTests/css-tests/150.html @@ -0,0 +1,11 @@ + +
+
+
This line should have a green background.
+

(Note: This test is based on unpublished errata.)

+
diff --git a/HTMLKitTests/css-tests/151.html b/HTMLKitTests/css-tests/151.html new file mode 100644 index 0000000..5f267e2 --- /dev/null +++ b/HTMLKitTests/css-tests/151.html @@ -0,0 +1,10 @@ + +
+
+
This line should have a green background.
+
diff --git a/HTMLKitTests/css-tests/152.html b/HTMLKitTests/css-tests/152.html new file mode 100644 index 0000000..83c251f --- /dev/null +++ b/HTMLKitTests/css-tests/152.html @@ -0,0 +1,10 @@ + +
+
+
This line should have a green background.
+
diff --git a/HTMLKitTests/css-tests/154.html b/HTMLKitTests/css-tests/154.html new file mode 100644 index 0000000..ad60662 --- /dev/null +++ b/HTMLKitTests/css-tests/154.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/155.html b/HTMLKitTests/css-tests/155.html new file mode 100644 index 0000000..5c6b222 --- /dev/null +++ b/HTMLKitTests/css-tests/155.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/155a.html b/HTMLKitTests/css-tests/155a.html new file mode 100644 index 0000000..df6b43b --- /dev/null +++ b/HTMLKitTests/css-tests/155a.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/155b.html b/HTMLKitTests/css-tests/155b.html new file mode 100644 index 0000000..7cc185e --- /dev/null +++ b/HTMLKitTests/css-tests/155b.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/155c.html b/HTMLKitTests/css-tests/155c.html new file mode 100644 index 0000000..12ecc98 --- /dev/null +++ b/HTMLKitTests/css-tests/155c.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/155d.html b/HTMLKitTests/css-tests/155d.html new file mode 100644 index 0000000..bbcf40b --- /dev/null +++ b/HTMLKitTests/css-tests/155d.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/156.html b/HTMLKitTests/css-tests/156.html new file mode 100644 index 0000000..2349293 --- /dev/null +++ b/HTMLKitTests/css-tests/156.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/157.html b/HTMLKitTests/css-tests/157.html new file mode 100644 index 0000000..75df363 --- /dev/null +++ b/HTMLKitTests/css-tests/157.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/158.html b/HTMLKitTests/css-tests/158.html new file mode 100644 index 0000000..51ae49a --- /dev/null +++ b/HTMLKitTests/css-tests/158.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/15b.html b/HTMLKitTests/css-tests/15b.html new file mode 100644 index 0000000..6420813 --- /dev/null +++ b/HTMLKitTests/css-tests/15b.html @@ -0,0 +1,22 @@ + +
+

This line should be green.

+
This line should be green.
+
diff --git a/HTMLKitTests/css-tests/16.html b/HTMLKitTests/css-tests/16.html new file mode 100644 index 0000000..dc2ffbe --- /dev/null +++ b/HTMLKitTests/css-tests/16.html @@ -0,0 +1,15 @@ + +
+

+ This link should have green background. (Don't follow this link.) +

+
diff --git a/HTMLKitTests/css-tests/160.html b/HTMLKitTests/css-tests/160.html new file mode 100644 index 0000000..e8400a3 --- /dev/null +++ b/HTMLKitTests/css-tests/160.html @@ -0,0 +1,10 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/170.html b/HTMLKitTests/css-tests/170.html new file mode 100644 index 0000000..7ed4a5e --- /dev/null +++ b/HTMLKitTests/css-tests/170.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/170a.html b/HTMLKitTests/css-tests/170a.html new file mode 100644 index 0000000..d4de3c7 --- /dev/null +++ b/HTMLKitTests/css-tests/170a.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/170b.html b/HTMLKitTests/css-tests/170b.html new file mode 100644 index 0000000..6829742 --- /dev/null +++ b/HTMLKitTests/css-tests/170b.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/170c.html b/HTMLKitTests/css-tests/170c.html new file mode 100644 index 0000000..d063fb4 --- /dev/null +++ b/HTMLKitTests/css-tests/170c.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/170d.html b/HTMLKitTests/css-tests/170d.html new file mode 100644 index 0000000..1487f3a --- /dev/null +++ b/HTMLKitTests/css-tests/170d.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/175a.html b/HTMLKitTests/css-tests/175a.html new file mode 100644 index 0000000..40f60bb --- /dev/null +++ b/HTMLKitTests/css-tests/175a.html @@ -0,0 +1,10 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/175b.html b/HTMLKitTests/css-tests/175b.html new file mode 100644 index 0000000..264e958 --- /dev/null +++ b/HTMLKitTests/css-tests/175b.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/175c.html b/HTMLKitTests/css-tests/175c.html new file mode 100644 index 0000000..2b39faf --- /dev/null +++ b/HTMLKitTests/css-tests/175c.html @@ -0,0 +1,9 @@ + +
+

This line should be green.

+
diff --git a/HTMLKitTests/css-tests/176.html b/HTMLKitTests/css-tests/176.html new file mode 100644 index 0000000..698d05f --- /dev/null +++ b/HTMLKitTests/css-tests/176.html @@ -0,0 +1,30 @@ + +
+

This line should be green.

+
This line should be green.
+
diff --git a/HTMLKitTests/css-tests/177b.html b/HTMLKitTests/css-tests/177b.html new file mode 100644 index 0000000..df37984 --- /dev/null +++ b/HTMLKitTests/css-tests/177b.html @@ -0,0 +1,12 @@ + +
+
+

This line should be green.

+
+
diff --git a/HTMLKitTests/css-tests/181.html b/HTMLKitTests/css-tests/181.html new file mode 100644 index 0000000..a6ba620 --- /dev/null +++ b/HTMLKitTests/css-tests/181.html @@ -0,0 +1,26 @@ + +
+
+ + +
+

This line should be green.

+

This line should be green.

+

This line should be green.

+
+ +
+
diff --git a/HTMLKitTests/css-tests/183.html b/HTMLKitTests/css-tests/183.html new file mode 100644 index 0000000..582fee1 --- /dev/null +++ b/HTMLKitTests/css-tests/183.html @@ -0,0 +1,25 @@ + +
+

This text should be green.

+

This text should be green.

+

This text should be green.

+

This text should be green.

+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184a.html b/HTMLKitTests/css-tests/184a.html new file mode 100644 index 0000000..cc43a72 --- /dev/null +++ b/HTMLKitTests/css-tests/184a.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184b.html b/HTMLKitTests/css-tests/184b.html new file mode 100644 index 0000000..f92d416 --- /dev/null +++ b/HTMLKitTests/css-tests/184b.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184c.html b/HTMLKitTests/css-tests/184c.html new file mode 100644 index 0000000..8d25e8a --- /dev/null +++ b/HTMLKitTests/css-tests/184c.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184d.html b/HTMLKitTests/css-tests/184d.html new file mode 100644 index 0000000..dfc0f97 --- /dev/null +++ b/HTMLKitTests/css-tests/184d.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184e.html b/HTMLKitTests/css-tests/184e.html new file mode 100644 index 0000000..45c3433 --- /dev/null +++ b/HTMLKitTests/css-tests/184e.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/184f.html b/HTMLKitTests/css-tests/184f.html new file mode 100644 index 0000000..d669805 --- /dev/null +++ b/HTMLKitTests/css-tests/184f.html @@ -0,0 +1,10 @@ + +
+

This text should be green.

+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/2.html b/HTMLKitTests/css-tests/2.html new file mode 100644 index 0000000..c1efff3 --- /dev/null +++ b/HTMLKitTests/css-tests/2.html @@ -0,0 +1,9 @@ + +
+
This address element should have a green background.
+
diff --git a/HTMLKitTests/css-tests/23.html b/HTMLKitTests/css-tests/23.html new file mode 100644 index 0000000..5ffbae0 --- /dev/null +++ b/HTMLKitTests/css-tests/23.html @@ -0,0 +1,17 @@ + +
+

+ +
+ +

+
diff --git a/HTMLKitTests/css-tests/24.html b/HTMLKitTests/css-tests/24.html new file mode 100644 index 0000000..4455e33 --- /dev/null +++ b/HTMLKitTests/css-tests/24.html @@ -0,0 +1,17 @@ + +
+

+ +
+ +

+
diff --git a/HTMLKitTests/css-tests/25.html b/HTMLKitTests/css-tests/25.html new file mode 100644 index 0000000..11d0372 --- /dev/null +++ b/HTMLKitTests/css-tests/25.html @@ -0,0 +1,20 @@ + +
+

+ + Everything in this paragraph should have a green background +

+
diff --git a/HTMLKitTests/css-tests/27a.html b/HTMLKitTests/css-tests/27a.html new file mode 100644 index 0000000..f8be676 --- /dev/null +++ b/HTMLKitTests/css-tests/27a.html @@ -0,0 +1,61 @@ + +
+

This line should be green (there should be no red on this page).

+
diff --git a/HTMLKitTests/css-tests/27b.html b/HTMLKitTests/css-tests/27b.html new file mode 100644 index 0000000..3c189ed --- /dev/null +++ b/HTMLKitTests/css-tests/27b.html @@ -0,0 +1,13 @@ + +
+

This line should be green (there should be no red on this page).

+
diff --git a/HTMLKitTests/css-tests/28.html b/HTMLKitTests/css-tests/28.html new file mode 100644 index 0000000..7769632 --- /dev/null +++ b/HTMLKitTests/css-tests/28.html @@ -0,0 +1,103 @@ + +
+
    +
  • This first list item should have a green background
  • +
  • Second list item
  • +
  • This third list item should have a green background
  • +
  • Fourth list item
  • +
  • This fifth list item should have a green background
  • +
  • Sixth list item
  • +
+
    +
  1. First list item
  2. +
  3. This second list item should have a green background
  4. +
  5. Third list item
  6. +
  7. This fourth list item should have a green background
  8. +
  9. Fifth list item
  10. +
  11. This sixth list item should have a green background
  12. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Green row : 1.11.21.3
Green row : 2.12.22.3
Green row : 3.13.23.3
Green row : 4.14.24.3
5.15.25.3
6.16.26.3
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
green cell1.21.3green cell1.51.6green cell1.8
green cell2.22.3green cell2.52.6green cell2.8
green cell3.23.3green cell3.53.6green cell3.8
+
+
diff --git a/HTMLKitTests/css-tests/29.html b/HTMLKitTests/css-tests/29.html new file mode 100644 index 0000000..845fb64 --- /dev/null +++ b/HTMLKitTests/css-tests/29.html @@ -0,0 +1,103 @@ + +
+
    +
  • First list item
  • +
  • This second list item should have a green background
  • +
  • Third list item
  • +
  • This fourth list item should have a green background
  • +
  • Fifth list item
  • +
  • This sixth list item should have a green background
  • +
+
    +
  1. This first list item should have a green background
  2. +
  3. Second list item
  4. +
  5. This third list item should have a green background
  6. +
  7. Fourth list item
  8. +
  9. This fifth list item should have a green background
  10. +
  11. Sixth list item
  12. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.11.21.3
2.12.22.3
Green row : 3.13.23.3
Green row : 4.14.24.3
Green row : 5.15.25.3
Green row : 6.16.26.3
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.1green cell1.31.4green cell1.61.7green cell
2.1green cell2.32.4green cell2.62.7green cell
3.1green cell3.33.4green cell3.63.7green cell
+
+
diff --git a/HTMLKitTests/css-tests/3.html b/HTMLKitTests/css-tests/3.html new file mode 100644 index 0000000..c0aa613 --- /dev/null +++ b/HTMLKitTests/css-tests/3.html @@ -0,0 +1,18 @@ + +
+

+ This paragraph, and all textual contents in the document, should be green. +

+
    +
  • This item should be green.
  • +
+
diff --git a/HTMLKitTests/css-tests/30.html b/HTMLKitTests/css-tests/30.html new file mode 100644 index 0000000..9d22198 --- /dev/null +++ b/HTMLKitTests/css-tests/30.html @@ -0,0 +1,30 @@ + +
+

This paragraph is here only to fill space in the DOM

+
And this address too..
+

So does this paragraph !

+

But this one should have green background

+
+
First definition term that should have green background
+
First definition that should have green background
+
Second definition term
+
Second definition
+
Third definition term
+
Third definition
+
Fourth definition term that should have green background
+
Fourth definition that should have green background
+
Fifth definition term
+
Fifth definition
+
Sixth definition term
+
Sixth definition
+
+
diff --git a/HTMLKitTests/css-tests/31.html b/HTMLKitTests/css-tests/31.html new file mode 100644 index 0000000..57c516b --- /dev/null +++ b/HTMLKitTests/css-tests/31.html @@ -0,0 +1,30 @@ + +
+

This paragraph should have green background

+
But this address is here only to fill space in the dom..
+

So does this paragraph !

+

And so does this one too.

+
+
First definition term
+
First definition
+
Second definition term
+
Second definition
+
Third definition term that should have green background
+
Third definition that should have green background
+
Fourth definition term
+
Fourth definition
+
Fifth definition term
+
Fifth definition
+
Sixth definition term that should have green background
+
Sixth definition that should have green background
+
+
diff --git a/HTMLKitTests/css-tests/32.html b/HTMLKitTests/css-tests/32.html new file mode 100644 index 0000000..f310ef7 --- /dev/null +++ b/HTMLKitTests/css-tests/32.html @@ -0,0 +1,34 @@ + +
+
+ + + + + + + + + + + + + + + + +
green cell1.21.3
green cell2.22.3
green cell3.23.3
+
+

This paragraph contains some text + and a span that should have a green background +

+
diff --git a/HTMLKitTests/css-tests/33.html b/HTMLKitTests/css-tests/33.html new file mode 100644 index 0000000..6b2d3e1 --- /dev/null +++ b/HTMLKitTests/css-tests/33.html @@ -0,0 +1,34 @@ + +
+
+ + + + + + + + + + + + + + + + +
1.11.2green cell
2.12.2green cell
3.13.2green cell
+
+

+ This paragraph contains a span that should + have a green background and some text after it.

+
diff --git a/HTMLKitTests/css-tests/34.html b/HTMLKitTests/css-tests/34.html new file mode 100644 index 0000000..0d4952a --- /dev/null +++ b/HTMLKitTests/css-tests/34.html @@ -0,0 +1,13 @@ + +
+
This div contains 3 addresses: +
A first address that should have a green background
+
A second address with normal background
+
A third address with normal background
+
+
diff --git a/HTMLKitTests/css-tests/35.html b/HTMLKitTests/css-tests/35.html new file mode 100644 index 0000000..9720100 --- /dev/null +++ b/HTMLKitTests/css-tests/35.html @@ -0,0 +1,14 @@ + +
+
+
A first address with normal background
+
A second address with normal background
+
A third address that should have a green background
+ This div contains 3 addresses above this sentence. +
+
diff --git a/HTMLKitTests/css-tests/36.html b/HTMLKitTests/css-tests/36.html new file mode 100644 index 0000000..acadf0f --- /dev/null +++ b/HTMLKitTests/css-tests/36.html @@ -0,0 +1,16 @@ + +
+

This paragraph should have normal background

+
This div contains only one paragraph +

This paragraph should have green background

+
+
diff --git a/HTMLKitTests/css-tests/37.html b/HTMLKitTests/css-tests/37.html new file mode 100644 index 0000000..f482dc0 --- /dev/null +++ b/HTMLKitTests/css-tests/37.html @@ -0,0 +1,13 @@ + +
+
+

This paragraph should have normal background

+
But this address should have green background
+

This paragraph should have normal background

+
+
diff --git a/HTMLKitTests/css-tests/4.html b/HTMLKitTests/css-tests/4.html new file mode 100644 index 0000000..0f69206 --- /dev/null +++ b/HTMLKitTests/css-tests/4.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background

+
diff --git a/HTMLKitTests/css-tests/43.html b/HTMLKitTests/css-tests/43.html new file mode 100644 index 0000000..83ac030 --- /dev/null +++ b/HTMLKitTests/css-tests/43.html @@ -0,0 +1,29 @@ + +
+
+

This paragraph should have a green background

+ + + + + + +
+

This paragraph should have a green background

+
+
+ + + + + + +
+

This paragraph should be unstyled.

+
+
diff --git a/HTMLKitTests/css-tests/44.html b/HTMLKitTests/css-tests/44.html new file mode 100644 index 0000000..076b4b2 --- /dev/null +++ b/HTMLKitTests/css-tests/44.html @@ -0,0 +1,23 @@ + +
+
+

This paragraph should have a green background

+
+

This paragraph should have a green background

+
+
+ + + + + + +
+

This paragraph should be unstyled.

+
+
diff --git a/HTMLKitTests/css-tests/44c.html b/HTMLKitTests/css-tests/44c.html new file mode 100644 index 0000000..5c6007b --- /dev/null +++ b/HTMLKitTests/css-tests/44c.html @@ -0,0 +1,10 @@ + +
+
This should be unstyled.
+
This should have a green background.
+
diff --git a/HTMLKitTests/css-tests/44d.html b/HTMLKitTests/css-tests/44d.html new file mode 100644 index 0000000..3d6e5c9 --- /dev/null +++ b/HTMLKitTests/css-tests/44d.html @@ -0,0 +1,10 @@ + +
+
This should be unstyled.
+

This should have a green background.

+
diff --git a/HTMLKitTests/css-tests/45.html b/HTMLKitTests/css-tests/45.html new file mode 100644 index 0000000..4d84ec7 --- /dev/null +++ b/HTMLKitTests/css-tests/45.html @@ -0,0 +1,15 @@ + +
+
+

This paragraph should be unstyled.

+

But this one should have a green background.

+

And this one should also have a green background.

+
This address is only here to fill some space between two paragraphs.
+

This paragraph should be unstyled.

+
+
diff --git a/HTMLKitTests/css-tests/45c.html b/HTMLKitTests/css-tests/45c.html new file mode 100644 index 0000000..ca52954 --- /dev/null +++ b/HTMLKitTests/css-tests/45c.html @@ -0,0 +1,10 @@ + +
+
This should be unstyled.
+
This should have a green background.
+
diff --git a/HTMLKitTests/css-tests/46.html b/HTMLKitTests/css-tests/46.html new file mode 100644 index 0000000..863ea22 --- /dev/null +++ b/HTMLKitTests/css-tests/46.html @@ -0,0 +1,15 @@ + +
+
+

This paragraph should be unstyled.

+

But this one should have a green background

+

And this one should also have a green background

+
This address is only here to fill some space between two paragraphs
+

This paragraph should have a green background

+
+
diff --git a/HTMLKitTests/css-tests/5.html b/HTMLKitTests/css-tests/5.html new file mode 100644 index 0000000..6ce6434 --- /dev/null +++ b/HTMLKitTests/css-tests/5.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background because its TITLE attribute is set.

+
diff --git a/HTMLKitTests/css-tests/54.html b/HTMLKitTests/css-tests/54.html new file mode 100644 index 0000000..4c36daf --- /dev/null +++ b/HTMLKitTests/css-tests/54.html @@ -0,0 +1,19 @@ + +
+
+

This paragraph should be in green characters.

+

This paragraph should be in green characters.

+

+ This paragraph should be in green characters. +

+
+
diff --git a/HTMLKitTests/css-tests/55.html b/HTMLKitTests/css-tests/55.html new file mode 100644 index 0000000..ebe5406 --- /dev/null +++ b/HTMLKitTests/css-tests/55.html @@ -0,0 +1,19 @@ + +
+
+

This paragraph should be in green characters.

+

This paragraph should be in green characters.

+

+ This paragraph should be in green characters. +

+
+
diff --git a/HTMLKitTests/css-tests/56.html b/HTMLKitTests/css-tests/56.html new file mode 100644 index 0000000..8bd5345 --- /dev/null +++ b/HTMLKitTests/css-tests/56.html @@ -0,0 +1,19 @@ + +
+
+

This paragraph should be in green characters.

+

This paragraph should be in green characters.

+

+ This paragraph should be in green characters. +

+
+
diff --git a/HTMLKitTests/css-tests/59.html b/HTMLKitTests/css-tests/59.html new file mode 100644 index 0000000..2c0d5ab --- /dev/null +++ b/HTMLKitTests/css-tests/59.html @@ -0,0 +1,19 @@ + +
+
+

This paragraph should be in green characters.

+

This paragraph should be in green characters.

+

+ This paragraph should be in green characters. +

+
+
diff --git a/HTMLKitTests/css-tests/6.html b/HTMLKitTests/css-tests/6.html new file mode 100644 index 0000000..d2ec421 --- /dev/null +++ b/HTMLKitTests/css-tests/6.html @@ -0,0 +1,21 @@ + +
+
+ This line should + have a green background. + +
+
diff --git a/HTMLKitTests/css-tests/60.html b/HTMLKitTests/css-tests/60.html new file mode 100644 index 0000000..0b74f40 --- /dev/null +++ b/HTMLKitTests/css-tests/60.html @@ -0,0 +1,19 @@ + +
+
+

This paragraph should be in green characters.

+

This paragraph should be in green characters.

+

+ This paragraph should be in green characters. +

+
+
diff --git a/HTMLKitTests/css-tests/68.html b/HTMLKitTests/css-tests/68.html new file mode 100644 index 0000000..856c58e --- /dev/null +++ b/HTMLKitTests/css-tests/68.html @@ -0,0 +1,17 @@ + +
+

+ +
+ +

+
diff --git a/HTMLKitTests/css-tests/69.html b/HTMLKitTests/css-tests/69.html new file mode 100644 index 0000000..0e77724 --- /dev/null +++ b/HTMLKitTests/css-tests/69.html @@ -0,0 +1,17 @@ + +
+

+ +
+ +

+
diff --git a/HTMLKitTests/css-tests/7.html b/HTMLKitTests/css-tests/7.html new file mode 100644 index 0000000..08bd82e --- /dev/null +++ b/HTMLKitTests/css-tests/7.html @@ -0,0 +1,21 @@ + +
+

This paragraph should have green background because CLASS contains "b"

+
+ This address should also + have green background because the selector in the last rule does not apply to the inner SPANs. +
+
diff --git a/HTMLKitTests/css-tests/70.html b/HTMLKitTests/css-tests/70.html new file mode 100644 index 0000000..596b63e --- /dev/null +++ b/HTMLKitTests/css-tests/70.html @@ -0,0 +1,18 @@ + +
+

+ Everything in this paragraph should have a green background

+
diff --git a/HTMLKitTests/css-tests/72.html b/HTMLKitTests/css-tests/72.html new file mode 100644 index 0000000..7b4d261 --- /dev/null +++ b/HTMLKitTests/css-tests/72.html @@ -0,0 +1,11 @@ + +
+
+

This paragraph should have a green background and there should be no red anywhere.

+
+
diff --git a/HTMLKitTests/css-tests/72b.html b/HTMLKitTests/css-tests/72b.html new file mode 100644 index 0000000..c1b2cbb --- /dev/null +++ b/HTMLKitTests/css-tests/72b.html @@ -0,0 +1,11 @@ + +
+
+

This paragraph should have a green background and there should be no red anywhere.

+
+
diff --git a/HTMLKitTests/css-tests/73.html b/HTMLKitTests/css-tests/73.html new file mode 100644 index 0000000..fbd1b61 --- /dev/null +++ b/HTMLKitTests/css-tests/73.html @@ -0,0 +1,103 @@ + +
+
    +
  • First list item
  • +
  • This second list item should have a green background
  • +
  • Third list
  • +
  • This fourth list item should have a green background
  • +
  • Fifth list item
  • +
  • This sixth list item should have a green background
  • +
+
    +
  1. This first list item should have a green background
  2. +
  3. Second list item
  4. +
  5. This third list item should have a green background
  6. +
  7. Fourth list item
  8. +
  9. This fifth list item should have a green background
  10. +
  11. Sixth list item
  12. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.11.21.3
2.12.22.3
3.13.23.3
4.14.24.3
Green row : 5.15.25.3
Green row : 6.16.26.3
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1.1green cellgreen cell1.4green cellgreen cell1.7green cell
2.1green cellgreen cell2.4green cellgreen cell2.7green cell
3.1green cellgreen cell3.4green cellgreen cell3.7green cell
+
+
diff --git a/HTMLKitTests/css-tests/74.html b/HTMLKitTests/css-tests/74.html new file mode 100644 index 0000000..11789d9 --- /dev/null +++ b/HTMLKitTests/css-tests/74.html @@ -0,0 +1,103 @@ + +
+
    +
  • This first list item should have a green background
  • +
  • Second list item
  • +
  • This third list item should have a green background
  • +
  • Fourth list item
  • +
  • This fifth list item should have a green background
  • +
  • Sixth list item
  • +
+
    +
  1. First list item
  2. +
  3. This second list item should have a green background
  4. +
  5. Third list item
  6. +
  7. This fourth list item should have a green background
  8. +
  9. Fifth list item
  10. +
  11. This sixth list item should have a green background
  12. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Green row : 1.11.21.3
Green row : 2.12.22.3
3.13.23.3
4.14.24.3
5.15.25.3
6.16.26.3
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
green cell1.2green cellgreen cell1.5green cellgreen cell1.8
green cell2.2green cellgreen cell2.5green cellgreen cell2.8
green cell3.2green cellgreen cell3.5green cellgreen cell3.8
+
+
diff --git a/HTMLKitTests/css-tests/75.html b/HTMLKitTests/css-tests/75.html new file mode 100644 index 0000000..868e05e --- /dev/null +++ b/HTMLKitTests/css-tests/75.html @@ -0,0 +1,30 @@ + +
+

This paragraph should have green background

+
And this address should be unstyled.
+

This paragraph should also have green background!

+

But this one should be unstyled again.

+
+
First definition term
+
First definition
+
Second definition term that should have green background
+
Second definition that should have green background
+
Third definition term that should have green background
+
Third definition that should have green background
+
Fourth definition term
+
Fourth definition
+
Fifth definition term that should have green background
+
Fifth definition that should have green background
+
Sixth definition term that should have green background
+
Sixth definition that should have green background
+
+
diff --git a/HTMLKitTests/css-tests/76.html b/HTMLKitTests/css-tests/76.html new file mode 100644 index 0000000..5791a6e --- /dev/null +++ b/HTMLKitTests/css-tests/76.html @@ -0,0 +1,30 @@ + +
+

This paragraph should be unstyled.

+
This address should be unstyled.
+

This paragraph should have green background.

+

This paragraph should have green background.

+
+
First definition term that should have green background.
+
First definition that should also have a green background.
+
Second definition term that should have green background.
+
Second definition that should have green background.
+
Third definition term.
+
Third definition.
+
Fourth definition term that should have green background.
+
Fourth definition that should have green background.
+
Fifth definition term that should have green background.
+
Fifth definition that should have green background.
+
Sixth definition term.
+
Sixth definition.
+
+
diff --git a/HTMLKitTests/css-tests/77.html b/HTMLKitTests/css-tests/77.html new file mode 100644 index 0000000..149bf72 --- /dev/null +++ b/HTMLKitTests/css-tests/77.html @@ -0,0 +1,32 @@ + +
+
+ + + + + + + + + + + + + + + + +
1.1green cellgreen cell
2.1green cellgreen cell
3.1green cellgreen cell
+
+

This paragraph should be unstyled.

+
diff --git a/HTMLKitTests/css-tests/78.html b/HTMLKitTests/css-tests/78.html new file mode 100644 index 0000000..0e7cb69 --- /dev/null +++ b/HTMLKitTests/css-tests/78.html @@ -0,0 +1,32 @@ + +
+
+ + + + + + + + + + + + + + + + +
green cellgreen cell1.3
green cellgreen cell2.3
green cellgreen cell3.3
+
+

This paragraph should be unstyled.

+
diff --git a/HTMLKitTests/css-tests/79.html b/HTMLKitTests/css-tests/79.html new file mode 100644 index 0000000..36dbf48 --- /dev/null +++ b/HTMLKitTests/css-tests/79.html @@ -0,0 +1,13 @@ + +
+
This div contains 3 addresses : +
A first address with normal background
+
A second address that should have a green background
+
A third address that should have a green background
+
+
diff --git a/HTMLKitTests/css-tests/7b.html b/HTMLKitTests/css-tests/7b.html new file mode 100644 index 0000000..6e629a6 --- /dev/null +++ b/HTMLKitTests/css-tests/7b.html @@ -0,0 +1,9 @@ + +
+

This line should have a green background.

+
diff --git a/HTMLKitTests/css-tests/8.html b/HTMLKitTests/css-tests/8.html new file mode 100644 index 0000000..741f5b6 --- /dev/null +++ b/HTMLKitTests/css-tests/8.html @@ -0,0 +1,21 @@ + +
+

This paragraph should have green background because its language is "en-gb"

+
+ This address should also + have green background because the language of the inner SPANs id="" is not French. +
+
diff --git a/HTMLKitTests/css-tests/80.html b/HTMLKitTests/css-tests/80.html new file mode 100644 index 0000000..20d0cc8 --- /dev/null +++ b/HTMLKitTests/css-tests/80.html @@ -0,0 +1,14 @@ + +
+
+
A first address that should have a green background
+
A second address that should have a green background
+
A third address with normal background
+ This div should have three addresses above it. +
+
diff --git a/HTMLKitTests/css-tests/81.html b/HTMLKitTests/css-tests/81.html new file mode 100644 index 0000000..9568093 --- /dev/null +++ b/HTMLKitTests/css-tests/81.html @@ -0,0 +1,16 @@ + +
+

This paragraph should have a green background.

+
This div contains only one paragraph. +

This paragraph should be unstyled.

+
+
diff --git a/HTMLKitTests/css-tests/82.html b/HTMLKitTests/css-tests/82.html new file mode 100644 index 0000000..f1149ce --- /dev/null +++ b/HTMLKitTests/css-tests/82.html @@ -0,0 +1,13 @@ + +
+
+

This paragraph should have green background.

+
But this address should be unstyled.
+

This paragraph should have green background.

+
+
diff --git a/HTMLKitTests/css-tests/83.html b/HTMLKitTests/css-tests/83.html new file mode 100644 index 0000000..74f32da --- /dev/null +++ b/HTMLKitTests/css-tests/83.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background

+
diff --git a/HTMLKitTests/css-tests/86.html b/HTMLKitTests/css-tests/86.html new file mode 100644 index 0000000..659e073 --- /dev/null +++ b/HTMLKitTests/css-tests/86.html @@ -0,0 +1,15 @@ + +
+
+
+
+

This text should be green.

+
+
+
+
diff --git a/HTMLKitTests/css-tests/87.html b/HTMLKitTests/css-tests/87.html new file mode 100644 index 0000000..c3be690 --- /dev/null +++ b/HTMLKitTests/css-tests/87.html @@ -0,0 +1,12 @@ + +
+
This text should be unstyled.
+
This text should be unstyled.
+
This text should be unstyled.
+

This text should be green.

+
diff --git a/HTMLKitTests/css-tests/88.html b/HTMLKitTests/css-tests/88.html new file mode 100644 index 0000000..4b3b73e --- /dev/null +++ b/HTMLKitTests/css-tests/88.html @@ -0,0 +1,14 @@ + +
+
This text should be unstyled.
+
+
+

This text should be green.

+
+
+
diff --git a/HTMLKitTests/css-tests/89.html b/HTMLKitTests/css-tests/89.html new file mode 100644 index 0000000..35f9d52 --- /dev/null +++ b/HTMLKitTests/css-tests/89.html @@ -0,0 +1,15 @@ + +
+
+
+
+

This text should be green.

+
+
+
+
diff --git a/HTMLKitTests/css-tests/9.html b/HTMLKitTests/css-tests/9.html new file mode 100644 index 0000000..40204f2 --- /dev/null +++ b/HTMLKitTests/css-tests/9.html @@ -0,0 +1,9 @@ + +
+

This paragraph should have a green background
because its title attribute begins with "foo"

+
diff --git a/HTMLKitTests/css-tests/90.html b/HTMLKitTests/css-tests/90.html new file mode 100644 index 0000000..6344b6b --- /dev/null +++ b/HTMLKitTests/css-tests/90.html @@ -0,0 +1,12 @@ + +
+
This text should be unstyled.
+
This text should be unstyled.
+
This text should be unstyled.
+

This text should be green.

+