109 Commits

Author SHA1 Message Date
iska e788c832c6 Merge branch 'release/0.3.0' 2015-11-29 03:35:31 +01:00
iska a33f4e0834 Use nodes tree description in HTML Parser tests 2015-11-29 03:29:13 +01:00
iska 9e4007dcba Use nullability annotations for HTML Ordered Dictionary 2015-11-29 03:29:12 +01:00
iska 50b67cfa94 Add CSS Selector tests into own virtual group 2015-11-29 03:29:12 +01:00
iska 47d244289e Merge branch 'feature/css_selectors' into develop 2015-11-28 21:14:24 +01:00
iska 6b81d6e465 Add tests for the CSS Selector Parser 2015-11-28 21:11:48 +01:00
iska 13b8fe7808 Add CSS Selectors Parser implementation 2015-11-28 21:11:16 +01:00
iska 94fed8afa1 Add CSS test fixtures
Tests are adapted from the official suite:
http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/static/flat/

Test file format:
Each test file is a HTML fragment with:

<script> element with id="selectors": contains a JSON array of several selector
definitions. Each selector definition has a selector string as input, a "match" array
of the expected matched IDs. Some selectors must fail with a parse error, such
selectors have an "error" key with the error location in the selector string.

<div> element with id="testDOM": contains the DOM fragment which should be
used to select the elements for each of the defined selectors.
2015-11-28 21:10:31 +01:00
iska 30dc6cf343 Add HTML Node method to count child elements 2015-11-28 21:09:44 +01:00
iska badf070907 Add HTMLKit error domain header 2015-11-28 21:09:25 +01:00
iska 3443321459 Add missing check in cosnume-character HTML stream method
Should only advance location if not reconsuming previous character
2015-11-28 21:08:39 +01:00
iska 60dc6bfc43 Fix nth-last-child selector 2015-11-28 21:07:10 +01:00
iska 60a5821a2c Fix general sibling combinator selector 2015-11-28 21:06:52 +01:00
iska 621dbe36d6 Fix pseudo selectors' names 2015-11-27 19:44:57 +01:00
iska 50ae2c5283 Fix :root selector 2015-11-27 19:41:09 +01:00
iska 0cb374681c Fix sibling combinator selectors 2015-11-27 01:10:27 +01:00
iska c09adc2f96 Add Node properties for previous and next sibling elements 2015-11-27 01:10:07 +01:00
iska 09991a149f Fix :disabled selector's check for disabled form elements
Should've  used or- instead of all-combinator
2015-11-27 01:01:02 +01:00
iska f735fcdfd6 Treat nil attribute value as an empty string in the Attribute selector 2015-11-27 00:47:45 +01:00
iska 5a3c1063e7 Fix Nth-Expression selector's compute-index methods 2015-11-27 00:47:24 +01:00
iska 8cb088367d Add Node methods to handle child elements' indices 2015-11-27 00:46:57 +01:00
iska 7ec90d6470 Fix escaped-code-point consuming in CSS input stream 2015-11-25 21:34:43 +01:00
iska 002564f9ae Use debug description in combinator selectors 2015-11-25 21:33:06 +01:00
iska 4c80c520d4 Fix reconsume checks in input stream reader for CSS logic 2015-11-24 23:04:21 +01:00
iska 85abf35099 Fix implementation of the shorthand "anyOf" selector 2015-11-24 23:03:13 +01:00
iska 578806ec2f Add description methods for compound selectors 2015-11-24 23:02:32 +01:00
iska 7923efb02b Add compound selector method to append further selectors 2015-11-24 23:02:14 +01:00
iska f4d42e0753 Fix description methods for combinator selectors 2015-11-24 23:01:49 +01:00
iska 56f99f9168 Add input stream method to consume a CSS combinator 2015-11-24 23:01:27 +01:00
iska c8dd1d7791 Fix consume CSS identifier input stream method
http://www.w3.org/TR/CSS21/syndata.html#characters
https://drafts.csswg.org/css-syntax/#consume-name
2015-11-24 23:01:11 +01:00
iska c57d3453fc Add id & class selector tests 2015-10-26 22:27:00 +01:00
iska a413156514 Fix method name for checked element selector 2015-10-26 22:26:43 +01:00
iska 203d153487 Fix hyphen-attribute test 2015-10-26 22:26:19 +01:00
iska 4ceb913b9f Add HTMLKit workspace and setup project headers 2015-10-26 22:26:00 +01:00
iska 7896f1687e Remove temp test case from type selector tests class 2015-10-23 23:51:30 +02:00
iska 55bb8effb2 Add tests for the CSS Combinator selectors 2015-10-23 23:48:47 +02:00
iska 2e10c23f52 Add debug description method to HTML Element 2015-10-23 22:54:34 +02:00
iska 4f47a750e0 Use lowercase string in the Nth-Expression selector parser 2015-10-23 22:54:06 +02:00
iska 46beae1b2d Change attribute selector's debug description string 2015-10-23 22:53:06 +02:00
iska 2e441727bc Fix equals method in the attribute selector for iOS target 2015-10-23 22:52:40 +02:00
iska cc101b9f4e Fix type selectors in the main header's implementation 2015-10-23 22:52:14 +02:00
iska 0635744a2d Add a CSS selector-base Node Filter implementation 2015-10-23 22:50:51 +02:00
iska b5bb0a48b6 Add tests for the Nth-Expression selectors 2015-10-23 22:50:20 +02:00
iska 95ffccf67b Add HTML Node methods for selecting elements with given CSS Selectors 2015-10-23 22:49:25 +02:00
iska 6af01a1214 Add -ObjC to iOS testing target to load category methods 2015-10-22 19:20:22 +02:00
iska 667693939f Update project settings for Xcode7 2015-10-22 19:12:42 +02:00
iska f05adfb56b Add implementation for the Nth-Expressions selector
http://www.w3.org/TR/css3-selectors/#structural-pseudos
2015-10-21 23:34:24 +02:00
iska bed2edf22a Remove obsolete CSS Tokenizer and Token classes 2015-10-21 22:32:09 +02:00
iska 2574736359 Use pseudo class and block selectors for parameterless pseudo class selectors 2015-10-21 22:30:58 +02:00
iska ab7de014cf Add implementation for "required" and "optional" selectors
https://html.spec.whatwg.org/multipage/scripting.html#selector-reqiored
https://html.spec.whatwg.org/multipage/scripting.html#selector-optional
2015-10-21 22:30:22 +02:00
iska 15e768267a Rename CSS tokenizer code points header file 2015-10-21 22:21:24 +02:00
iska ee82cacc48 Add CSS input stream method to consume characters till given codepoint is met 2015-10-21 22:16:18 +02:00
iska 61d7c683fb Add implementations for structural pseudo class selectors
https://html.spec.whatwg.org/multipage/scripting.html#selectors
http://api.jquery.com/category/selectors/jquery-selector-extensions/
http://sizzlejs.com
2015-10-21 22:15:36 +02:00
iska bd84884bf7 Add a block-based selector class for inline selector implementations 2015-10-21 22:13:03 +02:00
iska f248b39d26 Move Nth-Expression typedef to the public header 2015-10-21 00:35:07 +02:00
iska 118ea137f4 Update existing type and attribute tests for new structure 2015-10-20 21:31:08 +02:00
iska 0366f39d1a Add public header for all available selectors and hide the actual implementations 2015-10-20 21:30:39 +02:00
iska d107c05a44 Add stubs for the Nth-Expression Selectors
http://www.w3.org/TR/css3-selectors/#structural-pseudos
2015-10-20 21:17:42 +02:00
iska 5ca3bf1192 Replace nullability specifiers from methods and properties with nullability-regions 2015-10-20 21:15:30 +02:00
iska 02393ddedd Add implementation for the CSS Combinators
http://www.w3.org/TR/css3-selectors/#combinators
2015-10-19 21:51:46 +02:00
iska 33df9e7fb2 Add implementation for combining multiple selectors with "All" and "Exists" quantifiers 2015-10-19 21:49:51 +02:00
iska 6020b2bdd9 Add implementation for the negation and "has" selectors
The negation selector is specified here:
http://www.w3.org/TR/css3-selectors/#negation

The "has" selector is an extra convenience selector
2015-10-19 21:41:33 +02:00
iska c44c77d63d Refactor selectors code
- Remove simple sequence
- Remove simple selector protocol
- Let selectors subclass CSSSelector directly
2015-10-18 22:36:03 +02:00
iska 9905f45e27 Change the CSS selector base class to a protocol unrelated to the HTML Node Filter 2015-10-12 20:12:50 +02:00
iska c868bd1a56 Add HTML stream method to consume characters in given string 2015-10-12 20:00:44 +02:00
iska 8f38aed6c6 Add "not" attribute selector to match attribute not-having given value 2015-10-12 20:00:08 +02:00
iska 1917fb1f1c Add base class for pseudo class selectors
http://www.w3.org/TR/css3-selectors/#pseudo-classes
2015-10-11 23:43:29 +02:00
iska dc93bb07f6 Remove unneeded methods from the base selector class 2015-10-11 23:41:15 +02:00
iska a74be4dfa9 Add nullability specifiers to the simple sequence of selectors 2015-10-11 23:40:51 +02:00
iska 7cd47486ac Add nullability specifiers to type selector 2015-10-11 23:40:15 +02:00
iska ad902e3138 Add nullability specifiers to attribute selector 2015-10-11 23:40:03 +02:00
iska 6cfe3b6f83 Add implementation for CSS nth-expressions
https://drafts.csswg.org/css-syntax/#anb-microsyntax
2015-10-10 21:34:50 +02:00
iska a2096b0e54 Add debug descriptions for the attribute, type & sequence selectors 2015-10-10 00:06:09 +02:00
iska 79fda9fdbe Remove extra initializer methods from type and attribute selectors
keep it simple
2015-10-06 23:05:25 +02:00
iska 1a05c41f86 Refactor CSS input stream to subclass the HTML input stream class to prevent duplication 2015-10-06 23:01:59 +02:00
iska bf751d94b1 Add category method for the hex number character set
and use a dispatch once to initialize the set only once
2015-10-04 23:50:39 +02:00
iska 43705dac69 Update gitignore file 2015-10-02 19:29:10 +02:00
iska 3c7e6e1913 Change returned code points to UniChar instead of UTF32Chars in CSS input stream 2015-10-02 19:28:32 +02:00
iska af4444e9a8 Add log message on CSS Tokenizer error
Proper handling will be implemented later
2015-06-23 00:07:47 +02:00
iska 23d0d62295 Reorganize CSS related classes 2015-06-22 23:48:31 +02:00
iska b0668e121e Remove obsolete CSS lexer 2015-06-22 23:40:16 +02:00
iska aa95bbd9f2 Add Unicode Range CSS Token parsing 2015-06-22 20:55:33 +02:00
iska 1544f71c50 Add initial implementation for a CSS Tokenizer
http://www.w3.org/TR/2013/WD-css-syntax-3-20131105/#tokenization
2015-06-22 00:44:09 +02:00
iska b1ddbc5f75 Add CSS Tokenizer related helper function for dealing with code points 2015-06-22 00:43:32 +02:00
iska 576dc4dfb2 Add CSS Token classes 2015-06-22 00:42:34 +02:00
iska c4aacfae2b Add CSS Input Stream class
http://www.w3.org/TR/2013/WD-css-syntax-3-20131105/#tokenizing-and-parsing
2015-06-15 22:06:26 +02:00
iska a54cae8829 Fix type & attribute selectors and their tests after merge with new DOM 2015-06-07 22:34:50 +02:00
iska 852dfad19c Add enum values for the other different tokens in a CSS Selector 2015-06-07 20:52:42 +02:00
iska a5d53b3eef Fix acceptNode method in the selector's implementation after merge with new DOM 2015-06-07 00:08:40 +02:00
iska 5e5b903c52 Fix import in CSS Selector test classes 2015-06-06 23:29:04 +02:00
iska 40b6e41e12 Merge branch 'develop' into feature/css_selectors
Conflicts:
	HTMLKit.xcodeproj/project.pbxproj
	HTMLKit/HTMLNodeFilter.h
2015-06-06 20:20:27 +02:00
iska 05e224283a Expose tokenizer's position variables for better error reporting 2015-05-16 14:23:06 +02:00
iska 8490d4d2ca Add tokenizer method to get next-non-space token 2015-05-16 14:22:44 +02:00
iska 52b850317e Remove selector method to match a HTML Element used in the simple selectors
Selectors have only one method to implement, the Node Filter's acceptNode
2015-05-15 22:37:56 +02:00
iska f5d970ba87 Add implementation for a CSS Simple Sequence of Selectors
http://www.w3.org/TR/css3-selectors/#sequence
2015-05-15 02:37:51 +02:00
iska 0c8fd754c3 Add CSS Simple Selector protocol to the Type & Attribute selectors 2015-05-15 02:29:18 +02:00
iska 4f03e00003 Add a protocol for CSS Simple Selectors
Simple Selectors should conform to this protocol in order to be addable to the Simple Selector Sequence.
2015-05-15 02:28:03 +02:00
iska 62b385d9b4 Add test cases for changing selectors' properties for the Type & Attribute selectors 2015-05-14 21:42:53 +02:00
iska a7a30a7cbf Add convenience initializer for the Type Selector 2015-05-14 21:27:08 +02:00
iska 221b085fe5 Add tests for the Type & Attribute selectors 2015-05-14 21:18:55 +02:00
iska a2d9e65f0e Fix Attribute Selector for the Hyphen-case
Check for prefix instead of suffix with "-"
2015-05-14 21:16:29 +02:00
iska 745d0f72a7 Add convenience methods to create Class & ID Attribute Selectors
http://www.w3.org/TR/css3-selectors/#class-html
http://www.w3.org/TR/css3-selectors/#id-selectors
2015-05-14 21:15:39 +02:00
iska c401c3ca2c Add umbrella header for all CSS Selectors 2015-05-14 17:09:17 +02:00
iska 3cb5ed9a42 Add implementation for a CSS Attribute Selector
http://www.w3.org/TR/css3-selectors/#attribute-selectors
2015-05-14 16:32:47 +02:00
iska acec99ffea Add implementation for a CSS Type Selector
Matches an Element with the given tag name or all Elements (universal selector)
http://www.w3.org/TR/css3-selectors/#type-selectors
2015-05-14 16:23:23 +02:00
iska 7c58268dfd Add initial implementation for the CSS Selector base class 2015-05-14 16:21:26 +02:00
iska c87076b470 Add a NSCharacterSet category for HTML Whitespace characters
http://www.w3.org/TR/css3-selectors/#whitespace
2015-05-14 16:19:31 +02:00
iska 81a20f0333 Add HTML Node Filter protocol
https://dom.spec.whatwg.org/#interface-nodefilter
2015-05-14 16:15:41 +02:00
iska 4fcaf4c810 Add implementation for a CSS Selector Tokenizer
The Tokenizer is based on a flex-generated lexer for the grammar defined in the CSS Selectors Level 3 Spec
http://www.w3.org/TR/css3-selectors/#lex
2015-05-09 18:58:50 +02:00
159 changed files with 6044 additions and 141 deletions
+25 -6
View File
@@ -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
+314 -85
View File
@@ -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 = "<group>"; };
620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSCompoundSelector.h; sourceTree = "<group>"; };
620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCompoundSelector.m; sourceTree = "<group>"; };
620EE9471BC46F2A0028ED34 /* CSSPseudoClassSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPseudoClassSelector.h; sourceTree = "<group>"; };
620EE9481BC46F2A0028ED34 /* CSSPseudoClassSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSPseudoClassSelector.m; sourceTree = "<group>"; };
62132E571C01F83200084175 /* CSSSelectorTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorTest.h; sourceTree = "<group>"; };
62132E581C01F83200084175 /* CSSSelectorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorTest.m; sourceTree = "<group>"; };
62132E5B1C021FF200084175 /* css-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "css-tests"; sourceTree = "<group>"; };
621FBE591BDAD68700BC9555 /* CSSSelectorParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParserTests.m; sourceTree = "<group>"; };
621FBE5C1BDAD90200BC9555 /* CSSCombinatorSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelectorTests.m; sourceTree = "<group>"; };
6223211D1A969B9300BACED5 /* HTMLElementTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLElementTypes.h; sourceTree = "<group>"; };
622BF57F1BBF2FD700363583 /* CSSSelectorParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorParser.h; sourceTree = "<group>"; };
622BF5801BBF2FD700363583 /* CSSSelectorParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorParser.m; sourceTree = "<group>"; };
623406DF1ADB04F9004677A3 /* HTMLTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTemplate.h; sourceTree = "<group>"; };
623406E01ADB04F9004677A3 /* HTMLTemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTemplate.m; sourceTree = "<group>"; };
623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDocumentFragment.h; sourceTree = "<group>"; };
@@ -230,10 +302,22 @@
6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeIterator.h; sourceTree = "<group>"; };
6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeIterator.m; sourceTree = "<group>"; };
6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeFilter.h; sourceTree = "<group>"; };
624AB3151B04EA4200F3830D /* CSSSelectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSSelectors.h; sourceTree = "<group>"; };
624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTypeSelectorTests.m; sourceTree = "<group>"; };
624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSAttributeSelectorTests.m; sourceTree = "<group>"; };
624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokens.h; sourceTree = "<group>"; };
624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTokenizerTests.m; sourceTree = "<group>"; };
624AC90419FBFE8A00BD3C4A /* html5lib-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "html5lib-tests"; sourceTree = "<group>"; };
624AC90D19FC702E00BD3C4A /* HTML Standard.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "HTML Standard.html"; sourceTree = "<group>"; };
624B28B61B03DA820048D328 /* CSSTypeSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSTypeSelector.h; sourceTree = "<group>"; };
624B28B71B03DA820048D328 /* CSSTypeSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTypeSelector.m; sourceTree = "<group>"; };
624B28BD1B0413200048D328 /* CSSAttributeSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSAttributeSelector.h; sourceTree = "<group>"; };
624B28BE1B0413200048D328 /* CSSAttributeSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSAttributeSelector.m; sourceTree = "<group>"; };
624B28C21B04190D0048D328 /* NSCharacterSet+HTMLKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCharacterSet+HTMLKit.h"; sourceTree = "<group>"; };
624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSCharacterSet+HTMLKit.m"; sourceTree = "<group>"; };
624B371C1B24E9BA0010BDDF /* CSSInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSInputStream.h; sourceTree = "<group>"; };
624B371D1B24E9BA0010BDDF /* CSSInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSInputStream.m; sourceTree = "<group>"; };
624B37211B250BB50010BDDF /* CSSCodePoints.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSCodePoints.h; sourceTree = "<group>"; };
624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitStringCategoryTests.m; sourceTree = "<group>"; };
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitOrderedDictionaryTests.m; sourceTree = "<group>"; };
624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = "<group>"; };
@@ -246,7 +330,6 @@
625A14B919C7829400AD0C32 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
625A14BB19C7829400AD0C32 /* HTMLKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HTMLKit-Prefix.pch"; sourceTree = "<group>"; };
625A14BC19C7829400AD0C32 /* HTMLKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLKit.h; sourceTree = "<group>"; };
625A14BD19C7829400AD0C32 /* HTMLKit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTMLKit.m; sourceTree = "<group>"; };
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 = "<group>"; };
@@ -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 = "<group>"; };
625A150719C78ABA00AD0C32 /* HTMLInputStreamReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLInputStreamReader.m; sourceTree = "<group>"; };
626652F81C03D30F00C3F121 /* HTMLKitErrorDomain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLKitErrorDomain.h; sourceTree = "<group>"; };
6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLParserInsertionModes.h; sourceTree = "<group>"; };
6279F87219E1808D00F12EE5 /* HTMLElement.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = HTMLElement.h; sourceTree = "<group>"; };
6279F87319E1808D00F12EE5 /* HTMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLElement.m; sourceTree = "<group>"; };
628AF62E1BC99A6C00496128 /* CSSNthExpressionsParserTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionsParserTests.m; sourceTree = "<group>"; };
628AF6311BC9A63D00496128 /* CSSNthExpressionSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSNthExpressionSelector.h; sourceTree = "<group>"; };
628AF6321BC9A63D00496128 /* CSSNthExpressionSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionSelector.m; sourceTree = "<group>"; };
628AF63C1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSStructuralPseudoSelectors.h; sourceTree = "<group>"; };
628AF63D1BC9D6FB00496128 /* CSSStructuralPseudoSelectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSStructuralPseudoSelectors.m; sourceTree = "<group>"; };
628B7CE61A080E1000602C87 /* HTMLNamespaces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLNamespaces.h; sourceTree = "<group>"; };
62ACB8DB1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPseudoFunctionSelector.h; sourceTree = "<group>"; };
62ACB8DC1BC5C13E00E283C1 /* CSSPseudoFunctionSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSPseudoFunctionSelector.m; sourceTree = "<group>"; };
62AE593319F97D880043F069 /* HTMLParseErrorToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParseErrorToken.h; sourceTree = "<group>"; };
62AE593419F97D880043F069 /* HTMLParseErrorToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParseErrorToken.m; sourceTree = "<group>"; };
62AE593819F97E1C0043F069 /* HTMLDOCTYPEToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLDOCTYPEToken.h; sourceTree = "<group>"; };
@@ -276,8 +367,17 @@
62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = "<group>"; };
62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerEntities.h; sourceTree = "<group>"; };
62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizerEntities.m; sourceTree = "<group>"; };
62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSNthExpressionParser.h; sourceTree = "<group>"; };
62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNthExpressionParser.m; sourceTree = "<group>"; };
62F6586F1BD83C8E0045F137 /* CSSNThExpressionSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSNThExpressionSelectorTests.m; sourceTree = "<group>"; };
62F873E919E088C90062683C /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParser.h; sourceTree = "<group>"; };
62F873EA19E088C90062683C /* HTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLParser.m; sourceTree = "<group>"; };
62FA04E11BCC360D009ABF98 /* CSSCombinatorSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSCombinatorSelector.h; sourceTree = "<group>"; };
62FA04E21BCC360D009ABF98 /* CSSCombinatorSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSCombinatorSelector.m; sourceTree = "<group>"; };
62FA98031BD57B6200A2AF86 /* CSSSelectors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectors.m; sourceTree = "<group>"; };
62FA98061BD5A7E200A2AF86 /* CSSSelectorBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSelectorBlock.h; sourceTree = "<group>"; };
62FA98071BD5A7E200A2AF86 /* CSSSelectorBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelectorBlock.m; sourceTree = "<group>"; };
62FC60451BD0519B0042BBE7 /* CSSSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSelector.m; sourceTree = "<group>"; };
/* 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 = "<group>";
};
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";
@@ -481,6 +618,7 @@
624B9FB71AE072CB00646C4C /* DOM */,
624B9FB81AE072D500646C4C /* Categories */,
624E1A2D1B1D1C8A00E66AAC /* Structures */,
62FF516C1C0A430A009BFDFE /* Selectors */,
625A14CB19C7829400AD0C32 /* Supporting Files */,
);
name = Tests;
@@ -490,6 +628,7 @@
625A14CB19C7829400AD0C32 /* Supporting Files */ = {
isa = PBXGroup;
children = (
62132E5B1C021FF200084175 /* css-tests */,
624AC90D19FC702E00BD3C4A /* HTML Standard.html */,
624AC90419FBFE8A00BD3C4A /* html5lib-tests */,
625A14CC19C7829400AD0C32 /* HTMLKitTests-Info.plist */,
@@ -521,6 +660,8 @@
children = (
6235CE991AA509430026937B /* NSString+HTMLKit.h */,
6235CE9A1AA509430026937B /* NSString+HTMLKit.m */,
624B28C21B04190D0048D328 /* NSCharacterSet+HTMLKit.h */,
624B28C31B04190D0048D328 /* NSCharacterSet+HTMLKit.m */,
);
name = Categories;
sourceTree = "<group>";
@@ -564,6 +705,21 @@
name = Tokenizing;
sourceTree = "<group>";
};
62FF516C1C0A430A009BFDFE /* Selectors */ = {
isa = PBXGroup;
children = (
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 = Selectors;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -571,45 +727,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 +865,7 @@
625A14A319C7829400AD0C32 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = BrainCookie;
TargetAttributes = {
625A14C219C7829400AD0C32 = {
@@ -739,6 +911,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 +920,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
62132E5C1C021FF200084175 /* css-tests in Resources */,
624AC90619FBFEA000BD3C4A /* html5lib-tests in Resources */,
624AC90E19FC702E00BD3C4A /* HTML Standard.html in Resources */,
);
@@ -759,34 +933,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 +984,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 +1000,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 +1011,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 +1019,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 +1061,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 +1077,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 +1135,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 +1193,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 +1210,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 +1239,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 +1258,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 +1268,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 +1287,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 +1316,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 +1337,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)";
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:HTMLKit.xcodeproj">
</FileRef>
</Workspace>
+30
View File
@@ -0,0 +1,30 @@
//
// CSSAttributeSelector.h
// HTMLKit
//
// Created by Iska on 14/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#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
+111
View File
@@ -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
+140
View File
@@ -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);
}
+22
View File
@@ -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
+154
View File
@@ -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
+22
View File
@@ -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<CSSSelector *> *)selectors;
+ (instancetype)orSelector:(NSArray<CSSSelector *> *)selectors;
- (void)addSelector:(CSSSelector *)selector;
@end
NS_ASSUME_NONNULL_END
+99
View File
@@ -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
+20
View File
@@ -0,0 +1,20 @@
//
// CSSInputStream.h
// HTMLKit
//
// Created by Iska on 07/06/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HTMLInputStreamReader.h"
@interface CSSInputStream : HTMLInputStreamReader
- (void)consumeWhitespace;
- (NSString *)consumeIdentifier;
- (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint;
- (UTF32Char)consumeEscapedCodePoint;
- (NSString *)consumeCombinator;
@end
+128
View File
@@ -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
+16
View File
@@ -0,0 +1,16 @@
//
// CSSNthExpression.h
// HTMLKit
//
// Created by Iska on 10/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "CSSSelectors.h"
@interface CSSNthExpressionParser : NSObject
+ (CSSNthExpression)parseExpression:(NSString *)expression;
@end
+50
View File
@@ -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
+25
View File
@@ -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
+130
View File
@@ -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
+21
View File
@@ -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
+46
View File
@@ -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
+20
View File
@@ -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
+89
View File
@@ -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
+49
View File
@@ -0,0 +1,49 @@
//
// HTMLSelector.h
// HTMLKit
//
// Created by Iska on 02/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#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
+33
View File
@@ -0,0 +1,33 @@
//
// CSSSelector.m
// HTMLKit
//
// Created by Iska on 15/10/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#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
+21
View File
@@ -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
+40
View File
@@ -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
+17
View File
@@ -0,0 +1,17 @@
//
// CSSSelectorParser.h
// HTMLKit
//
// Created by Iska on 02/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@class CSSSelector;
@interface CSSSelectorParser : NSObject
+ (CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
@end
+367
View File
@@ -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
+71
View File
@@ -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<CSSSelector *> *selectors);
extern CSSSelector * anyOf(NSArray<CSSSelector *> *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
+177
View File
@@ -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<CSSSelector *> * selectors)
{
return [CSSCompoundSelector andSelector:selectors];
}
CSSSelector * anyOf( NSArray<CSSSelector *> * 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];
}
+40
View File
@@ -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
+301
View File
@@ -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;
}
});
}
+24
View File
@@ -0,0 +1,24 @@
//
// CSSTypeSelector.h
// HTMLKit
//
// Created by Iska on 13/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#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
+50
View File
@@ -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
+1 -1
View File
@@ -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]];
}
+5
View File
@@ -180,4 +180,9 @@
return description;
}
- (NSString *)debugDescription
{
return self.description;
}
@end
+2
View File
@@ -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;
+34 -5
View File
@@ -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];
+4 -5
View File
@@ -6,8 +6,7 @@
// Copyright (c) 2014 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface HTMLKit : NSObject
@end
#import "HTMLParser.h"
#import "HTMLDOM.h"
#import "CSSSelectors.h"
#import "HTMLKitErrorDomain.h"
-13
View File
@@ -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
+23
View File
@@ -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 */
+14
View File
@@ -38,6 +38,7 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition)
@class HTMLDocument;
@class HTMLElement;
@class CSSSelector;
@interface HTMLNode : NSObject <NSCopying>
@@ -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<HTMLElement *> *)elementsMatchingSelector:(CSSSelector *)selector;
- (NSString *)treeDescription;
@end
+78 -6
View File
@@ -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<HTMLElement *> *)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
+15
View File
@@ -26,6 +26,9 @@ typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions)
HTMLNodeFilterShowDocumentFragment = 0x400
};
#pragma mark - Node Filter
@class HTMLNode;
@protocol HTMLNodeFilter <NSObject>
@@ -34,8 +37,20 @@ typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions)
@end
#pragma mark - Block Filter
@interface HTMLNodeFilterBlock : NSObject <HTMLNodeFilter>
+ (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))block;
@end
#pragma mark - CSS Selector Filter
@class CSSSelector;
@interface HTMLSelectorNodeFilter : NSObject <HTMLNodeFilter>
+ (instancetype)filterWithSelector:(CSSSelector *)selector;
@end
+43
View File
@@ -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
+12 -8
View File
@@ -8,18 +8,22 @@
#import <Foundation/Foundation.h>
@interface HTMLOrderedDictionary : NSMutableDictionary
NS_ASSUME_NONNULL_BEGIN
- (id)objectAtIndex:(NSUInteger)index;
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey atIndex:(NSUInteger)index;
@interface HTMLOrderedDictionary<KeyType, ObjectType> : NSMutableDictionary<KeyType, ObjectType>
- (ObjectType)objectAtIndex:(NSUInteger)index;
- (void)setObject:(ObjectType)anObject forKey:(KeyType<NSCopying>)aKey atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceKeyValueAtIndex:(NSUInteger)index withObject:(id)anObject andKey:(id<NSCopying>)aKey;
- (void)replaceKey:(id<NSCopying>)aKey withKey:(id<NSCopying>)newKey;
- (NSUInteger)indexOfKey:(id<NSCopying>)aKey;
- (void)replaceKeyValueAtIndex:(NSUInteger)index withObject:(ObjectType)anObject andKey:(KeyType<NSCopying>)aKey;
- (void)replaceKey:(KeyType<NSCopying>)aKey withKey:(KeyType<NSCopying>)newKey;
- (NSUInteger)indexOfKey:(KeyType<NSCopying>)aKey;
- (id)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)index;
- (ObjectType)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject:(ObjectType)obj atIndexedSubscript:(NSUInteger)index;
- (NSEnumerator *)reverseKeyEnumerator;
@end
NS_ASSUME_NONNULL_END
+17
View File
@@ -0,0 +1,17 @@
//
// NSCharacterSet+HTMLKit.h
// HTMLKit
//
// Created by Iska on 14/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSCharacterSet (HTMLKit)
+ (instancetype)HTMLWhitespaceCharacterSet;
+ (instancetype)HTMLHexNumberCharacterSet;
+ (instancetype)CSSNthExpressionCharacterSet;
@end
+43
View File
@@ -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
+238
View File
@@ -0,0 +1,238 @@
//
// CSSAttributeSelectorTests.m
// HTMLKit
//
// Created by Iska on 14/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#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
+116
View File
@@ -0,0 +1,116 @@
//
// CSSCombinatorSelectorTests.m
// HTMLKit
//
// Created by Iska on 23/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "CSSSelectors.h"
#import "HTMLParser.h"
#import "HTMLDOM.h"
@interface CSSCombinatorSelectorTests : XCTestCase
{
HTMLDocument *_document;
}
@end
@implementation CSSCombinatorSelectorTests
- (void)setUp
{
[super setUp];
/*
| <body>
| <p id='p1'>
| A paragraph<span id='span1'>A span</span>
| <table id='table'>
| <tbody id='tbody'>
| <tr id='tr1'>
| <td id='td'>
| <span id='span2'>Span in table</span>
| </td>
| </tr>
| <tr id='tr2'></tr>
| <tr id='tr3'></tr>
| </tbody>
| </table>
| </p>
| <div id='inner-div1'>
| <p id='p2'></p>
| </div>
| <div id='inner-div2'>
| <p id='p3'></p>
| </div>
| </body>
*/
_document = [[[HTMLParser alloc] initWithString:@"<body>"
"<p id='p1'>"
"A paragraph<span id='span1'>A span</span>"
"<table id='table'>"
"<tbody id='tbody'>"
"<tr id='tr1'><td id='td'>"
"<span id='span2'>Span in table</span>"
"</td></tr>"
"<tr id='tr2'></tr>"
"<tr id='tr3'></tr>"
"</tbody>"
"</table>"
"</p>"
"<div id='inner-div1'>"
"<p id='p2'></p>"
"</div>"
"<div id='inner-div2'>"
"<p id='p3'></p>"
"</div>"
"</body>"] 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
@@ -0,0 +1,352 @@
//
// CSSNThExpressionSelectorTests.m
// HTMLKit
//
// Created by Iska on 21/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "CSSSelectors.h"
#import "HTMLParser.h"
#import "HTMLDOM.h"
@interface CSSNThExpressionSelectorTests : XCTestCase
{
HTMLDocument *_childTree;
HTMLDocument *_typeTree;
}
@end
@implementation CSSNThExpressionSelectorTests
- (void)setUp
{
[super setUp];
/*
| <div>
| <table>
| <tr id='11'><td>11</td></tr>
| <tr id='12'><td>12</td></tr>
| <tr id='13'><td>13</td></tr>
| <tr id='14'><td>14</td></tr>
| </table>
| </div>
| <div>
| <table>
| <tr id='21'><td>21</td></tr>
| </table>
| </div>
| <div>
| <table>
| <tr id='31'><td>31</td></tr>
| <tr id='32'><td>32</td></tr>
| <tr id='33'><td>33</td></tr>
| <tr id='34'><td>34</td></tr>
| <tr id='35'><td>35</td></tr>
| <tr id='36'><td>36</td></tr>
| </table>
| </div>
*/
_childTree = [[[HTMLParser alloc] initWithString:@"<div><table>"
"<tr id='11'><td>11</td></tr>"
"<tr id='12'><td>12</td></tr>"
"<tr id='13'><td>13</td></tr>"
"<tr id='14'><td>14</td></tr>"
"</table></div>"
"<div><table>"
"<tr id='21'><td>21</td></tr>"
"</table></div>"
"<div><table>"
"<tr id='31'><td>31</td></tr>"
"<tr id='32'><td>32</td></tr>"
"<tr id='33'><td>33</td></tr>"
"<tr id='34'><td>34</td></tr>"
"<tr id='35'><td>35</td></tr>"
"<tr id='36'><td>36</td></tr>"
"</table></div>"] document];
/*
| <div>
| <span id='s11'>s11</span>
| <span id='s12'>s12</span>
| <span id='s13'>s13</span>
| <b id='b1'>b1</b>
| </div>
| <div>
| <b id='b2'>b2</b>
| <span id='s21'>s21</span>
| <span id='s22'>s22</span>
| <span id='s23'>s23</span>
| </div>
| <div>
| <span id='s31'>s31</span>
| <b id='b3'>b3</b>
| <span id='s32'>s32</span>
| <b id='b4'>b4</b>
| <span id='s33'>s33</span>
| <b id='b5'>b5</b>
| <span id='s34'>s34</span>
| </div>
*/
_typeTree = [[[HTMLParser alloc] initWithString:@"<div>"
"<span id='s11'>s11</span>"
"<span id='s12'>s12</span>"
"<span id='s13'>s13</span>"
"<b id='b1'>b1</b>"
"</div>"
"<div>"
"<b id='b2'>b2</b>"
"<span id='s21'>s21</span>"
"<span id='s22'>s22</span>"
"<span id='s23'>s23</span>"
"</div>"
"<div>"
"<span id='s31'>s31</span>"
"<b id='b3'>b3</b>"
"<span id='s32'>s32</span>"
"<b id='b4'>b4</b>"
"<span id='s33'>s33</span>"
"<b id='b5'>b5</b>"
"<span id='s34'>s34</span>"
"</div>"] 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
+158
View File
@@ -0,0 +1,158 @@
//
// CSSNthExpressionsParserTests.m
// HTMLKit
//
// Created by Iska on 10/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#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
+104
View File
@@ -0,0 +1,104 @@
//
// CSSSelectorParserTests.m
// HTMLKit
//
// Created by Iska on 23/10/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import <HTMLKit/HTMLKit.h>
#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
+21
View File
@@ -0,0 +1,21 @@
//
// CSSSelectorTest.h
// HTMLKit
//
// Created by Iska on 22/11/15.
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@class HTMLElement;
@interface CSSSelectorTest : NSObject
@property (nonatomic, copy) NSString *testName;
@property (nonatomic, strong) NSArray *selectors;
@property (nonatomic, strong) HTMLElement *testDOM;
+ (NSArray *)loadCSSSelectorTests;
@end
+60
View File
@@ -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
+43
View File
@@ -0,0 +1,43 @@
//
// CSSTypeSelectorTests.m
// HTMLKit
//
// Created by Iska on 14/05/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#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
@@ -38,9 +38,6 @@
[_dictionary setObject:@"3" forKey:@"C"];
expected = @[@"A", @"B", @"C"];
XCTAssertEqualObjects(_dictionary.keyEnumerator.allObjects, expected);
XCTAssertThrows([_dictionary setObject:nil forKey:@"Key"]);
XCTAssertThrows([_dictionary setObject:@"Object" forKey:nil]);
}
- (void)testIndexOfKey
@@ -51,7 +48,6 @@
XCTAssertEqual([_dictionary indexOfKey:@"A"], 0);
XCTAssertEqual([_dictionary indexOfKey:@"B"], 1);
XCTAssertEqual([_dictionary indexOfKey:@"C"], 2);
XCTAssertEqual([_dictionary indexOfKey:nil], NSNotFound);
}
- (void)testObjectAtIndex
@@ -64,8 +60,6 @@
[_dictionary setObject:@"3" forKey:@"C" atIndex:1];
XCTAssertEqualObjects([_dictionary objectAtIndex:1], @"3");
XCTAssertThrows([_dictionary setObject:nil forKey:@"Key" atIndex:0]);
XCTAssertThrows([_dictionary setObject:@"Object" forKey:nil atIndex:0]);
XCTAssertThrows([_dictionary setObject:@"Object" forKey:@"Key" atIndex:100]);
}
@@ -120,8 +114,6 @@
XCTAssertEqualObjects(_dictionary[2], @"5");
XCTAssertEqualObjects(_dictionary[@"A"], @"5");
XCTAssertThrows([_dictionary setObject:nil forKey:@"Key" atIndex:0]);
XCTAssertThrows([_dictionary setObject:@"Object" forKey:nil atIndex:0]);
XCTAssertThrows([_dictionary setObject:@"Object" forKey:@"Key" atIndex:100]);
}
@@ -158,8 +150,6 @@
XCTAssertEqualObjects(_dictionary[0], @"5");
XCTAssertEqualObjects(_dictionary[@"E"], @"5");
XCTAssertThrows([_dictionary replaceKeyValueAtIndex:1 withObject:nil andKey:@"Key"]);
XCTAssertThrows([_dictionary replaceKeyValueAtIndex:1 withObject:@"Object" andKey:nil]);
XCTAssertThrows([_dictionary replaceKeyValueAtIndex:100 withObject:@"Object" andKey:@"Key"]);
}
+2 -2
View File
@@ -96,8 +96,8 @@
actual = [parser parseFragmentWithContextElement:contextElement];
}
NSString *expectedNodes = [[test.nodes valueForKey:@"debugDescription"] componentsJoinedByString:@"\n"];
NSString *actualNodes = [[parser.document.childNodes.array valueForKey:@"debugDescription"] componentsJoinedByString:@"\n"];
NSString *expectedNodes = [[test.nodes valueForKey:@"treeDescription"] componentsJoinedByString:@"\n"];
NSString *actualNodes = [[actual valueForKey:@"treeDescription"] componentsJoinedByString:@"\n"];
NSString *message = [NSString stringWithFormat:@"HTML5Lib test in file: \'%@\'\nInput:\n%@\nExpected:\n%@\nActual:\n%@\n",
test.testFile,
+13
View File
@@ -0,0 +1,13 @@
<script type="application/json" id="selectors">
[{
"selector": "li,p",
"match": ["1", "2", "3"]
}]
</script>
<div id="testDOM">
<ul>
<li id="1">The background of this list item should be green</li>
<li id="2">The background of this second list item should be also green</li>
</ul>
<p id="3">The background of this paragraph should be green.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": "p[title$=\"bar\"]",
"match": ["1"]
}]
</script>
<div id="testDOM">
<p id="1" title="foobar">This paragraph should have a green background because its title attribute ends with &quot;bar&quot;</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": "p[title*=\"bar\"]",
"match": ["1"]
}]
</script>
<div id="testDOM">
<p id="1" title="foobarufoo">This paragraph should have a green background because its title attribute contains &quot;bar&quot;</p>
</div>
+23
View File
@@ -0,0 +1,23 @@
<script type="application/json" id="selectors">
[{
"selector": ".t1",
"match": ["1"]
},
{
"selector": "li.t2",
"match": ["2", "3"]
},
{
"selector": ".t3",
"match": []
}]
</script>
<div id="testDOM">
<ul>
<li id="1" class="t1">This list item should have green background because its class is &quot;t1&quot;</li>
<li id="2" class="t2">This list item should have green background because its class is &quot;t2&quot;</li>
<li id="3" class="t2">
<span id="4" class="t33">This list item should have green background because the inner SPAN does not match SPAN.t3</span>
</li>
</ul>
</div>
+30
View File
@@ -0,0 +1,30 @@
<script type="application/json" id="selectors">
[{
"selector": "p.t1",
"match": ["1"]
},
{
"selector": "p.t2",
"match": ["1"]
},
{
"selector": "div.teST",
"match": []
},
{
"selector": "div.te",
"match": []
},
{
"selector": "div.st",
"match": []
},
{
"selector": "div.te.st",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="t1 t2">This paragraph should have a green background and a green thick solid border because it carries both classes t1 and t2.</p>
<div id="2" class="test">This line should be green.</div>
</div>
+11
View File
@@ -0,0 +1,11 @@
<script type="application/json" id="selectors">
[{
"selector": "div :not(:enabled):not(:disabled)",
"match": ["1", "2"]
}]
</script>
<div id="testDOM">
<div id="1">
<p id="2">This paragraph should have a green background.</p>
</div>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": "p:empty",
"match": []
}]
</script>
<div id="testDOM">
<p id="1">This line should have a green background.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "address:empty",
"match": ["1"]
}]
</script>
<div id="testDOM">
<address id="1"></address>
<div id="2" class="text">This line should have a green background.</div>
</div>
+22
View File
@@ -0,0 +1,22 @@
<script type="application/json" id="selectors">
[{
"selector": ".t1.fail",
"match": []
},
{
"selector": ".fail.t2",
"match": []
},
{
"selector": ".t2.fail",
"match": []
},
{
"selector": ".fail.t2",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="t1">This line should be green.</p>
<p id="2" class="t1 t2">This line should be green.</p>
</div>
+19
View File
@@ -0,0 +1,19 @@
<script type="application/json" id="selectors">
[{
"selector": "p.t1.t2",
"match": ["1"]
},
{
"selector": "div.t1",
"match": []
},
{
"selector": "address.t5.t5",
"match": ["3"]
}]
</script>
<div id="testDOM">
<p id="1" class="t1 t2">This line should be green.</p>
<div id="2" class="t3">This line should be green.</div>
<address id="3" class="t4 t5 t6">This line should be green.</address>
</div>
+21
View File
@@ -0,0 +1,21 @@
<script type="application/json" id="selectors">
[{
"selector": ".t1:not(.t2)",
"match": []
},
{
"selector": ":not(.t2).t1",
"match": []
},
{
"selector": ".t2:not(.t1)",
"match": []
},
{
"selector": ":not(.t1).t2",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="t1 t2">This line should be green.</p>
</div>
+19
View File
@@ -0,0 +1,19 @@
<script type="application/json" id="selectors">
[{
"selector": "p:not(.t1):not(.t2)",
"match": []
},
{
"selector": "div:not(.t1)",
"match": ["testDOM", "2"]
},
{
"selector": "address:not(.t5):not(.t5)",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="t1 t2">This line should be green.</p>
<div id="2" class="t3">This line should be green.</div>
<address id="3" class="t4 t5 t6">This line should be green.</address>
</div>
+27
View File
@@ -0,0 +1,27 @@
<script type="application/json" id="selectors">
[{
"selector": "#t1",
"match": ["t1"]
},
{
"selector": "li#t2",
"match": ["t2"]
},
{
"selector": "li#t3",
"match": ["t3"]
},
{
"selector": "#t4",
"match": []
}]
</script>
<div id="testDOM">
<ul id="1">
<li id="t1">This list item should have a green background. because its ID is &quot;t1&quot;</li>
<li id="t2">This list item should have a green background. because its ID is &quot;t2&quot;</li>
<li id="t3">
<span id="t44">This list item should have a green background. because the inner SPAN does not match &quot;#t4&quot;</span>
</li>
</ul>
</div>
+11
View File
@@ -0,0 +1,11 @@
<script type="application/json" id="selectors">
[{
"selector": "address:empty",
"match": ["1"]
}]
</script>
<div id="testDOM">
<address id="1"><!-- --><?test random PI></address>
<div id="2" class="text">This line should have a green background.</div>
<p id="3">(Note: This test is based on unpublished errata.)</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "address:empty",
"match": []
}]
</script>
<div id="testDOM">
<address id="1"> </address>
<div id="2" class="text">This line should have a green background.</div>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "address:empty",
"match": []
}]
</script>
<div id="testDOM">
<address id="1"><span id="2"></span></address>
<div id="3" class="text">This line should have a green background.</div>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p,",
"match": [],
"error": 1
}]
</script>
<div id="testDOM">
<p id="1">This line should have a green background.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": ".5cm",
"match": [],
"error": 1
}]
</script>
<div id="testDOM">
<p id="1" class="5cm">This line should have a green background.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".\\5cm",
"match": []
}]
</script>
<div id="testDOM">
<p class="5cm">This line should have a green background.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".two\\ words",
"match": []
}]
</script>
<div id="testDOM">
<p class="two words">This line should have a green background.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".one.word",
"match": []
}]
</script>
<div id="testDOM">
<p class="one.word">This line should have a green background.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".one\\.word",
"match": ["1"]
}]
</script>
<div id="testDOM">
<p id="1" class="one.word">This line should have a green background.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "foo & address, p",
"match": [],
"error": 5
}]
</script>
<div id="testDOM">
<p>This line should have a green background.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "[*=test]",
"match": [],
"error": 2
}]
</script>
<div id="testDOM">
<p class="test">This line should have a green background.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "[*|*=test]",
"match": [],
"error": 2
}]
</script>
<div id="testDOM">
<p class="test">This line should have a green background.</p>
</div>
+22
View File
@@ -0,0 +1,22 @@
<script type="application/json" id="selectors">
[{
"selector": "#test#fail",
"match": []
},
{
"selector": "#fail#test",
"match": []
},
{
"selector": "#fail",
"match": []
},
{
"selector": "#pass#pass",
"match": ["pass"]
}]
</script>
<div id="testDOM">
<p id="test">This line should be green.</p>
<div id="pass">This line should be green.</div>
</div>
+15
View File
@@ -0,0 +1,15 @@
<script type="application/json" id="selectors">
[{
"selector": "p.test a",
"match": ["2"]
},
{
"selector": "p.test *:link",
"match": ["2"]
}]
</script>
<div id="testDOM">
<p id="1" class="test">
<a id="2" href="http://unvisited.example.org/css3-modsel-16/">This link should have green background.</a> (Don&#39;t follow this link.)
</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p:subject",
"match": [],
"error": 9
}]
</script>
<div id="testDOM">
<p class="test">This line should have a green background.</p>
</div>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": ".13",
"match": [],
"error": 1
}]
</script>
<div id="testDOM">
<p id="1" class="13">This line should be green.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".\13",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="13">This line should be green.</p>
</div>
+9
View File
@@ -0,0 +1,9 @@
<script type="application/json" id="selectors">
[{
"selector": ".\31 \33",
"match": ["1"]
}]
</script>
<div id="testDOM">
<p id="1" class="13">This line should be green.</p>
</div>
+30
View File
@@ -0,0 +1,30 @@
<script type="application/json" id="selectors">
[{
"selector": "p:not(#other).class:not(.fail).test#id#id",
"match": ["id"]
},
{
"selector": "div:not(#theid).class:not(.fail).test#theid#theid",
"match": []
},
{
"selector": "div:not(#other).notclass:not(.fail).test#theid#theid",
"match": []
},
{
"selector": "div:not(#other).class:not(.test).test#theid#theid",
"match": []
},
{
"selector": "div:not(#other).class:not(.fail).nottest#theid#theid",
"match": []
},
{
"selector": "div:not(#other).class:not(.fail).nottest#theid#other",
"match": []
}]
</script>
<div id="testDOM">
<p id="id" class="class test">This line should be green.</p>
<div id="theid" class="class test">This line should be green.</div>
</div>
+12
View File
@@ -0,0 +1,12 @@
<script type="application/json" id="selectors">
[{
"selector": "p::first-child",
"match": [],
"error": 2
}]
</script>
<div id="testDOM">
<div>
<p>This line should be green.</p>
</div>
</div>
+26
View File
@@ -0,0 +1,26 @@
<script type="application/json" id="selectors">
[{
"selector": ".ci P",
"match": ["2", "3", "4"]
},
{
"selector": ".ci .a",
"match": []
},
{
"selector": ".ci SPAN",
"match": ["5"]
}]
</script>
<div id="testDOM">
<div>
<div id="1" class="ci">
<p id="2">This line should be green.</p>
<p id="3" class="A">This line should be green.</p>
<p id="4"><SPAN id="5">This line should be green.</SPAN></p>
</div>
</div>
</div>
+25
View File
@@ -0,0 +1,25 @@
<script type="application/json" id="selectors">
[{
"selector": "..test",
"match": [],
"error": 1
},
{
"selector": ".foo..quux ",
"match": [],
"error": 5
},
{
"selector": ".bar.",
"match": [],
"error": 5
}]
</script>
<div id="testDOM">
<p class="test">This text should be green.</p>
<p class=".test">This text should be green.</p>
<p class="foo">This text should be green.</p>
<p class="foo quux">This text should be green.</p>
<p class="foo quux">This text should be green.</p>
<p class=" bar ">This text should be green.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p[class$=\"\"]",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="">This text should be green.</p>
<p id="2">This text should be green.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p[class^=\"\"]",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="">This text should be green.</p>
<p id="2">This text should be green.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p[class*=\"\"]",
"match": []
}]
</script>
<div id="testDOM">
<p id="1" class="">This text should be green.</p>
<p id="2">This text should be green.</p>
</div>
+10
View File
@@ -0,0 +1,10 @@
<script type="application/json" id="selectors">
[{
"selector": "p:not([class$=\"\"])",
"match": ["1", "2"]
}]
</script>
<div id="testDOM">
<p id="1" class="">This text should be green.</p>
<p id="2">This text should be green.</p>
</div>

Some files were not shown because too many files have changed in this diff Show More