111 Commits

Author SHA1 Message Date
iska de2d35fbe6 Merge branch 'release/1.0.0' 2016-09-28 02:09:00 +02:00
iska 76a7930e7d Bump HTMLKit version to 1.0.0 2016-09-28 02:02:51 +02:00
iska 8dc5d0ea50 Update jazzy.yaml for 1.0.0 2016-09-28 02:02:31 +02:00
iska 0e9956efc0 Update podspec for 1.0.0 2016-09-28 02:02:18 +02:00
iska d5888e68a7 Add Changelog entry for HTMLKit 1.0.0 2016-09-28 02:01:10 +02:00
iska 02177e7fac Fix macOS scheme and sdk in travis.yml 2016-09-28 01:55:10 +02:00
iska af76666f3c Add watchOS2.0 and tvOS9.0 destinations to travis.yml 2016-09-28 01:44:09 +02:00
iska 73dc32aae9 Set deployment targets to macOS 10.9, iOS 9.0, tvOS 9.0 and watchOS 2.0 2016-09-28 01:39:38 +02:00
iska 64cba55677 Replace OSX with macOS throughout project 2016-09-28 01:38:59 +02:00
iska 214722c0bf Share example project's scheme 2016-09-28 01:36:05 +02:00
iska b8592630d0 Fix simulator name in travis.yml 2016-09-28 01:10:04 +02:00
iska a641c64f74 Fix typo in travis.yml 2016-09-27 23:34:24 +02:00
iska e20531925a Update travis.yaml for Xcode8 and iOS10 2016-09-27 23:00:45 +02:00
iska 024ab12242 Add docs directory to gitignores 2016-09-27 22:50:02 +02:00
iska c2a11e6f97 Add .jazzy.yaml configuration file 2016-09-27 22:49:49 +02:00
iska 800336d317 Add nullability annotation for CSSSelectorParser's parse method 2016-09-27 22:32:30 +02:00
iska a751cec215 Add example project 2016-09-27 22:30:45 +02:00
iska 87a476e523 Change html5lib-tests submodule name 2016-09-20 19:30:10 +02:00
iska 7e42fd1e08 Add missing lightweight generics in Parser, Element & Node classes
To play nicely with Swift 3
2016-09-20 19:28:08 +02:00
iska 7d1b94219d Add missing deployment target settings in project file 2016-09-20 19:27:21 +02:00
iska 29bd89b808 Update playground to Swift 3 2016-09-20 19:27:05 +02:00
iska 45a8e25028 Update project and schemes for Xcode 8 2016-09-13 22:47:33 +02:00
iska 33bb1e39a4 Merge branch 'release/0.9.4' into develop 2016-09-03 17:23:09 +02:00
iska 44c987ec13 Merge branch 'release/0.9.4'
# Conflicts:
#	Tests/html5lib-tests
2016-09-03 17:21:13 +02:00
iska 3bd5b2d4a2 Fix source code and header paths in podspec file
Source code resides in "Sources" and "Sources/include" now after spm
refactor
2016-09-03 17:08:17 +02:00
iska 8c312e1508 Bump HTMLKit version to 0.9.4 2016-09-03 16:53:23 +02:00
iska 20d8449a94 Update podspec for 0.9.4 2016-09-03 16:51:58 +02:00
iska 16b85af5af Update README.md 2016-09-03 16:51:46 +02:00
iska 3c56a1d694 Add Changelog entry for HTMLKit 0.9.4 2016-09-03 16:51:33 +02:00
iska ca20e6d03f Add HTMLKit modulemap file 2016-09-03 16:18:28 +02:00
iska f58c2e3f94 Remove unused strings plist from tests code 2016-08-28 01:17:53 +02:00
iska 9698919d35 Fix import in private HTMLNode header 2016-08-27 02:07:54 +02:00
iska 9a1a12c788 Remove prefix header and necessary foundation imports 2016-08-27 02:02:43 +02:00
iska e56a980e80 Move header files into include directory 2016-08-27 01:59:53 +02:00
iska a440fd56b2 Add Package.swift 2016-08-24 20:27:50 +02:00
iska 1a3c1dd3d2 Update gitignore 2016-08-24 20:23:20 +02:00
iska 170c298571 Remove unused strings plist 2016-08-24 20:04:13 +02:00
iska f51c76d257 Update project paths for info.plist and prefix header 2016-08-24 20:02:09 +02:00
iska 1df63b8e00 Move test source code to Tests directory 2016-08-24 19:55:59 +02:00
iska 37444d5899 Move source code to Sources directory 2016-08-24 19:54:41 +02:00
iska 85e4941057 Move css-tests to Tests directory 2016-08-24 19:51:41 +02:00
iska c7a339fbed Move html5lib-tests submodule to Tests directory 2016-08-24 19:50:23 +02:00
iska 0f80b0bbe2 Merge branch 'release/0.9.3' 2016-07-16 14:50:07 +02:00
iska b1a9b7ecee Merge branch 'release/0.9.3' into develop 2016-07-16 14:50:07 +02:00
iska f794e04b9f Bump HTMLKit version to 0.9.3 2016-07-16 14:49:23 +02:00
iska 0ffecea0f3 Update podspec for 0.9.3 2016-07-16 14:49:23 +02:00
iska 62fef829d3 Set deployment targets for watchOS 2016-07-16 14:49:23 +02:00
iska 21dd607ec6 Update README.md 2016-07-16 14:48:44 +02:00
iska 7ae337471c Add Changelog entry for HTMLKit 0.9.3 2016-07-16 13:59:36 +02:00
iska 730b8a3239 Fix format arguments in Test Observer class 2016-07-16 13:51:09 +02:00
iska 33a8238513 Fix product name in tvOS scheme 2016-07-16 13:38:36 +02:00
iska 769113ec0e Fix travis.yml
Add missing semicolon to end if-then-statement
2016-07-16 13:37:50 +02:00
iska 4970976485 Exclude watchOS scheme from testing in travis.yml 2016-07-16 02:25:57 +02:00
iska 38fef77be5 Update travis.yml for watchOS & tvOS targets 2016-07-16 01:28:51 +02:00
iska 754b7191b9 Add tvOS target 2016-07-16 01:14:02 +02:00
iska 56cc5b1a3e Add watchOS target 2016-07-16 01:05:43 +02:00
iska ccecc4106d Update html5lib-tests to latest commit as of 2016.07.15
Commit: c305da74fae50fb018870de7a042da36c1a93b65
2016-07-15 22:57:30 +02:00
iska 39dda3aaf5 Update html5lib-tests to latest commit as of 2016.06.29
Commit: 2998f9afa303bfb603c9c97a9565c8bfa71eef4f
2016-06-29 00:43:31 +02:00
iska a136976462 Update html5lib-tests to latest commit as of 2016.06.116
Commit: 927f779be5b9aed4b5a04f404e95f9b3b80bb409
2016-06-16 23:26:54 +02:00
iska 8aabc94fdb Merge branch 'release/0.9.2' 2016-05-18 21:17:44 +02:00
iska 322b42b9d1 Merge branch 'release/0.9.2' into develop 2016-05-18 21:17:44 +02:00
iska c2acbb6344 Bump HTMLKit version to 0.9.2 2016-05-18 21:16:43 +02:00
iska a6e4aac937 Bump Pod version to 0.9.2 2016-05-18 21:15:51 +02:00
iska 899438fa24 Update README.md 2016-05-18 21:14:23 +02:00
iska 137fa8617e Add Changelog entry for HTMLKit 0.9.2 2016-05-18 21:13:14 +02:00
iska 70abd998f7 Fix adoption agency algorithm according to the latest specification
This implements the specification change:
https://github.com/whatwg/html/commit/22ce3c31

Current implementation should pass all new html5lib test cases, including
those from Blink, WebKit, and namespace sensitivity.

See related:
https://github.com/html5lib/html5lib-tests/issues/78
https://bugzilla.mozilla.org/show_bug.cgi?id=901319
https://lists.w3.org/Archives/Public/public-html/2013Aug/0002.html
https://lists.w3.org/Archives/Public/public-whatwg-archive/2013Jul/0401.html
https://lists.w3.org/Archives/Public/public-whatwg-archive/2013Jul/0006.html
2016-05-18 19:59:54 +02:00
iska bb948e0ef8 Check the qualified instead of the local name in the stack of open elements
This fixes the parser's behaviour when handling elements in the MathML and
SVG namespaces.

See:
https://bugs.webkit.org/show_bug.cgi?id=113723
https://www.w3.org/Bugs/Public/show_bug.cgi?id=21308
https://www.w3.org/Bugs/Public/show_bug.cgi?id=21292
2016-05-18 19:48:37 +02:00
iska b0bad5068f Update parsing logic for <menuitem> and <menu> elements
The current spec (2016.05.15) is missing the instruction to "reconstruct
the active formatting elements" to match the handling of the <option>
element

See relevant discussions:
https://github.com/whatwg/html/pull/907
https://github.com/whatwg/html/issues/234
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/MkEDloT-yu8
https://www.w3.org/Bugs/Public/show_bug.cgi?id=25325
2016-05-15 03:44:00 +02:00
iska a01f1c1c5b Remove handling for <isindex> and <input name=isindex>
Everybody else is doing it, so why can't we?
See: https://github.com/whatwg/html/pull/1095

<isindex> is not only deprecated, it is completely removed from the spec
html5lib-tests: f99e2cb1851de9674519a220a1ccb3174b8cb846
2016-05-15 03:44:00 +02:00
iska 6967798823 Update html5lib-tests to latest commit as of 2016.05.15
Commit: b2f4f5844192ed097bd7993dfb0bcbd4c7a4aeb0
2016-05-15 03:44:00 +02:00
iska 58b60dd390 Add test utility class for adding test cases dynamically at runtime 2016-04-12 00:21:20 +02:00
iska 4441b7decd Generate HTMLKit's Tokenizer tests dynamically for better failure reporting
TODO: refactor dynamic tests generation into helper class/method
2016-04-11 01:18:33 +02:00
iska 0b2681f8a8 Generate HTMLKit's Tree Construction tests dynamically for better failure reporting
TODO: refactor dynamic tests generation into helper class/method
2016-04-11 01:14:15 +02:00
iska 1e07acd032 Use tests observer in the HTMLKit Tree Construction tests 2016-04-11 01:13:24 +02:00
iska 432df997b3 Add simple tests observer class for failure reporting 2016-04-11 01:12:40 +02:00
iska c9d72646bc Update htlm5lib-tests to include Blink changes
Commit: 193fa43bd66e9f0c416b6e2b358711644c5f55d6
2016-04-10 16:48:31 +02:00
iska 1af25abadb Fix tags links in the CHANGELOG.md 2016-03-31 13:11:23 +02:00
iska 75138cc35f Add CHANGELOG.md 2016-02-01 22:07:43 +01:00
iska 93401e4054 Update badges in README.md 2016-01-30 14:12:45 +01:00
iska 266621edf2 Merge branch 'release/0.9.1' 2016-01-29 00:56:54 +01:00
iska 25ad5a3f82 Merge branch 'release/0.9.1' into develop 2016-01-29 00:56:54 +01:00
iska cac1e4cedd Add podspec file for HTMLKit 2016-01-29 00:56:45 +01:00
iska abc847a33b Set version to 0.9.1 2016-01-29 00:55:32 +01:00
iska 4680a66fd1 Fix all warnings related to type conversion in NSLog statements 2016-01-29 00:43:01 +01:00
iska 465b78dbba Change build settings to treat warnings as errors 2016-01-29 00:39:11 +01:00
iska a64ff8782e Fix variable types in README.md examples 2016-01-28 23:20:30 +01:00
iska e03a384aa7 Update logo image 2016-01-28 23:17:06 +01:00
iska 6d2cb09082 Add travis build status to README.md 2016-01-28 22:17:18 +01:00
iska 222bfa03e1 Remove iOS 8 simulators from the build matrix in the travis.yml
Till these get fixed:
https://github.com/travis-ci/travis-ci/issues/4906
https://github.com/travis-ci/travis-ci/issues/3040
2016-01-28 22:14:48 +01:00
iska 6254e8a578 Add imports for the public categories in the umbrella header 2016-01-28 22:12:37 +01:00
iska 01be0acc0a Move the private HTMLNode header to the corresponding section 2016-01-28 22:12:13 +01:00
iska 58f0b88ff8 Add simulator-id to the build matrix in travis.yml 2016-01-20 00:33:35 +01:00
iska b90e673dc0 Add command to start the simulator before building and running tests in travis.yml 2016-01-19 21:36:50 +01:00
iska 22f293e718 Fix workspace env variable in tavis.yml 2016-01-19 01:19:39 +01:00
iska 4511335e9b Fix indentation in tavis.yml 2016-01-19 01:17:10 +01:00
iska dd2d29b8f0 Add matrix and destinations to travis.yml 2016-01-19 01:13:28 +01:00
iska f267958e83 Set deployment target to iOS 8.0 2016-01-19 00:50:57 +01:00
iska b94a80bd24 Remove code signing identity 2016-01-19 00:50:39 +01:00
iska 1df0c4ce1f Use debug configuration in travis.yml 2016-01-19 00:41:33 +01:00
iska ac49520ad9 Use correct schemes in travis.yml 2016-01-19 00:37:23 +01:00
iska ee6dbff8d5 Use ipgonesimulator SDK in travis.yml 2016-01-19 00:31:23 +01:00
iska f004e6328c Remove Team ID from project settings 2016-01-19 00:31:23 +01:00
iska f8255c861a Add .travis.yml file 2016-01-19 00:26:55 +01:00
iska 4592037aba Fix "return" attribute in source code documentation
@returns is ignored by jazzy
2016-01-18 21:48:00 +01:00
iska 948c07e4ae Merge branch 'hotfix/fix_readme' 2015-12-24 00:35:15 +01:00
iska 41d9d98201 Merge branch 'hotfix/fix_readme' into develop 2015-12-24 00:35:15 +01:00
iska 8199f647f4 Fix some typos in the README 2015-12-24 00:35:08 +01:00
iska 977737d538 Merge branch 'hotfix/fix_readme' 2015-12-23 21:53:07 +01:00
iska b8d17162d5 Merge branch 'hotfix/fix_readme' into develop 2015-12-23 21:53:07 +01:00
iska 27e1ed2bda Add new line after logo in README 2015-12-23 21:53:00 +01:00
iska c169f0ed07 Merge branch 'release/0.9.0' into develop 2015-12-23 21:49:36 +01:00
272 changed files with 2779 additions and 579 deletions
+4 -1
View File
@@ -26,6 +26,7 @@ xcuserdata
## Obj-C/Swift specific
*.hmap
*.ipa
.build/
# CocoaPods
#
@@ -39,5 +40,7 @@ Pods/
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
Carthage/Checkouts
Carthage/Build
Carthage/Build
# Jazzy
docs/
+2 -2
View File
@@ -1,3 +1,3 @@
[submodule "HTMLKitTests/html5lib-tests"]
path = HTMLKitTests/html5lib-tests
[submodule "html5lib-tests"]
path = Tests/html5lib-tests
url = https://github.com/html5lib/html5lib-tests.git
+121
View File
@@ -0,0 +1,121 @@
module: HTMLKit
module_version: 1.0.0
author: Iskandar Abudiab
author_url: https://twitter.com/iabudiab
github_url: https://github.com/iabudiab/HTMLKit
github_file_prefix: https://github.com/iabudiab/HTMLKit/tree/master
output: docs
umbrella_header: Sources/include/HTMLKit.h
clean: true
objc: true
skip_undocumented: true
custom_categories:
- name: Parsing
children:
- HTMLParser
- name: DOM
children:
- HTMLNamespace
- HTMLNode
- HTMLNodeType
- HTMLElement
- HTMLDocument
- HTMLDocumentReadyState
- HTMLQuirksMode
- HTMLDocumentType
- HTMLDocumentFragment
- HTMLDocumentPosition
- HTMLText
- HTMLComment
- HTMLTemplate
- HTMLDOMTokenList
- name: Iteration & Filtering
children:
- HTMLNodeIterator
- HTMLNodeFilter
- HTMLNodeFilterShowOptions
- HTMLNodeFilterValue
- HTMLNodeFilterBlock
- HTMLSelectorNodeFilter
- HTMLTreeWalker
- name: Structures
children:
- HTMLOrderedDictionary
- CSSNthExpression
- name: CSS Selectors Implementation
children:
- CSSSelector
- CSSSelectorParser
- CSSTypeSelector
- CSSAttributeSelector
- CSSNthExpressionParser
- CSSNthExpressionSelector
- CSSPseudoClassSelector
- CSSPseudoFunctionSelector
- CSSSelectorBlock
- CSSCombinatorSelector
- CSSCompoundSelector
- name: Typed Selectors and Extensions
children:
- adjacentSiblingSelector
- allOf
- anyOf
- attributeSelector
- buttonSelector
- checkboxSelector
- checkedSelector
- childOfElementSelector
- classSelector
- descendantOfElementSelector
- disabledSelector
- emptySelector
- enabledSelector
- eqSelector
- evenSlector
- fileSelector
- firstChildSelector
- firstOfTypeSelector
- generalSiblingSelector
- gtSelector
- has
- hasAttributeSelector
- headerSelector
- idSelector
- imageSelector
- inputSelector
- lastChildSelector
- lastOfTypeSelector
- linkSelector
- ltSelector
- namedBlockSelector
- namedPseudoSelector
- not
- nthChildSelector
- nthLastChildSelector
- nthLastOfTypeSelector
- nthOfTypeSelector
- oddSelector
- onlyChildSelector
- onlyOfTypeSelector
- optionalSelector
- parentSelector
- passwordSelector
- radioSelector
- requiredSelector
- resetSelector
- rootSelector
- submitSelector
- textSelector
- typeSelector
- universalSelector
- name: Categories
children:
- NSCharacterSet(HTMLKit)
- NSString(HTMLKit)
+45
View File
@@ -0,0 +1,45 @@
language: objective-c
osx_image: xcode8
branches:
except:
- gh-pages
install:
- gem install xcpretty
env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
- WORKSPACE=HTMLKit.xcworkspace
- IOS_FRAMEWORK_SCHEME=HTMLKit-iOS
- MACOS_FRAMEWORK_SCHEME=HTMLKit-macOS
- WATCHOS_FRAMEWORK_SCHEME="HTMLKit-watchOS"
- TVOS_FRAMEWORK_SCHEME="HTMLKit-tvOS"
- IOS_SDK=iphonesimulator10.0
- MACOS_SDK=macosx10.12
- WATCHOS_SDK=watchsimulator3.0
- TVOS_SDK=appletvsimulator10.0
matrix:
- DESTINATION="arch=x86_64" SIMULATOR="" SCHEME="$MACOS_FRAMEWORK_SCHEME" SDK="$MACOS_SDK"
- DESTINATION="OS=9.0,name=iPhone 6" SIMULATOR="iPhone 6 (9.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=9.1,name=iPhone 6 Plus" SIMULATOR="iPhone 6 Plus (9.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=9.2,name=iPhone 6S" SIMULATOR="iPhone 6S (9.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=9.3,name=iPhone 6S Plus" SIMULATOR="iPhone 6S Plus (9.3)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=10.0,name=iPhone 7 Plus" SIMULATOR="iPhone 7 Plus (10.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=2.0,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (2.2)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK"
- DESTINATION="OS=3.0,name=Apple Watch - 42mm" SIMULATOR="Apple Watch - 42mm (3.0)" SCHEME="$WATCHOS_FRAMEWORK_SCHEME" SDK="$WATCHOS_SDK"
- DESTINATION="OS=9.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (9.2)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK"
- DESTINATION="OS=10.0,name=Apple TV 1080p" SIMULATOR="Apple TV 1080p (10.0)" SCHEME="$TVOS_FRAMEWORK_SCHEME" SDK="$TVOS_SDK"
script:
- set -o pipefail
- xcodebuild -version
- xcodebuild -showsdks
- SIMULATOR_ID=$(xcrun instruments -s devices | grep -io "$SIMULATOR \[.*\]" | grep -o "\[.*\]" | sed "s/^\[\(.*\)\]$/\1/")
- open -b com.apple.iphonesimulator --args -CurrentDeviceUDID $SIMULATOR_ID
- xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean build | xcpretty -c
- if [ "$SDK" != "$WATCHOS_SDK" ]; then
xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c;
fi
+166
View File
@@ -0,0 +1,166 @@
# Change Log
## [1.0.0](https://github.com/iabudiab/HTMLKit/releases/tag/1.0.0)
Released on 2016.09.28
### Added
- Jazzy configuration file
- Example HTMLKit project
### Updated
- Project for Xcode 8
- Playground syntax for Swift 3
- Travis config for iOS 10.0, macOS 10.12, tvOS 10.0 and watchOS 3.0
- Deployment targets to macOS 10.9, iOS 9.0, tvOS 9.0 and watchOS 2.0
### Fixed
- Nullability annotation in `CSSSelectorParser` class
- Missing lightweight generics in `HTMLParser`, `HTMLNode` & `HTMLElement`
## [0.9.4](https://github.com/iabudiab/HTMLKit/releases/tag/0.9.4)
Released on 2016.09.03
### Added
- `Swift Package Manager` support
## [0.9.3](https://github.com/iabudiab/HTMLKit/releases/tag/0.9.3)
Released on 2016.07.16
This release passes all tokenizer and tree construction html5lib-tests as of 2016.07.16
### Added
- `watchOS` and `tvOS` targets
- Updated HTML5Lib-Tests submodule (c305da7)
## [0.9.2](https://github.com/iabudiab/HTMLKit/releases/tag/0.9.2)
Released on 2016.05.18
This release passes all tokenizer and tree construction html5lib-tests as of 2016.05.18
### Added
- Handling for `<menu>` and `<menuitem>`
- Changelog
### Changed
- Updated adoption agency algorithm according to the latest specification, see:
- [whatwg/html@22ce3c3](https://github.com/whatwg/html/commit/22ce3c3)
- [Mozilla Bug 901319](https://bugzilla.mozilla.org/show_bug.cgi?id=901319)
- [Chrome Issue 268121](https://bugs.chromium.org/p/chromium/issues/detail?id=268121)
- [WebKit Bug 119478](https://bugs.webkit.org/show_bug.cgi?id=119478)
- `<isindex>` is completely removed from the spec now, therefore it is dropped from the implementation
- `Tokenizer` and `Tree-Construction` tests are now generated dynamically
- Test failures are collected by a `XCTestObservation` for better reporting
- `<isindex>` is completely removed from the spec now, therefore it is dropped from the implementation
- `Tokenizer` and `Tree-Construction` tests are now generated dynamically
- Test failures are collected by a `XCTestObservation` for better reporting
### Fixed
- Parser now checks the qualified name instead of the local name when handling elements in the `MathML` and `SVG` namespaces
## [0.9.1](https://github.com/iabudiab/HTMLKit/releases/tag/0.9.1)
Released on 2016.01.29
### Added
- Travis-CI integration.
- CocoaPods spec.
### Changed
- Warnings are treated as errors.
### Fixed
- Warnings related to format specifier and loss of precision due to NS(U)-integer usage.
- Replaced `@returns` with `@return` throughout the documentation to play nicely with Jazzy.
- Some README examples used Swift syntax.
## [0.9.0](https://github.com/iabudiab/HTMLKit/releases/tag/0.9.0)
Released on 2015.12.23
This is the first public release of `HTMLKit`.
### Added
- `iOS` & `OSX` Frameworks.
- Source code documentation.
- CSS Selectors extension (analogous to jQuery selectors).
- `DOMTokenList` for malipulating `HTMLElements` attributes as a list, e.g. `class`.
- Handling for `<ruby>` elements in the Parser implementation.
- Updated HTML5Lib-Tests submodule (56c435f)
- Xcode Playground with Swift documentation.
### Removed
- Unused namespaces.
- Historical node types.
### Fixed
- `lt`, `gt` & `eq` CSS Selectors method declarations.
## [0.3.0](https://github.com/iabudiab/HTMLKit/releases/tag/0.3.0)
Released on 2015.11.29
### Added
- CSS3 Selectors support.
- Nullability annotations.
- `HTMLNode` properties for previous and next sibling elements.
- `HTMLNode` methods for accessing child elements (analogous to child nodes).
- `NSCharacterSet` category for HTML-related character sets.
### Fixed
- `InputStreaReader`'s reconsume-logic that is required by the CSS Parser.
## [0.2.0](https://github.com/iabudiab/HTMLKit/releases/tag/0.1.0)
Released on 2015.06.06
### Added
- `HTMLDocument` methods to access `root`, `head` & `body` elements.
- `innerHTML` implementation for the `HTMLElement`.
- `HTMLNode` methods to append, prepend, check containment and descendancy of nodes.
- `HTMLNode` methods to enumerate child nodes.
- Implementations for `NodeIterator` and `NodeFilter`
- Implementation for `TreeWalker`
- Validation for DOM manipulations.
- Tests for the DOM implementation.
### Changed
- `type` property renamed to `nodeType` in `HTMLNode`.
- `firstChildNode` and `lastChildNode` renamed to `firtChild` and `lastChild` in `HTMLNode`.
### Removed
- `baseURI` proeprty from `HTMLNode`
- `HTMLNodeTreeEnumerator` is superseded by the `HTMLNodeIterator`.
## [0.1.0](https://github.com/iabudiab/HTMLKit/releases/tag/0.1.0)
Released on 2015.04.20
### Added
- Initial release.
- Initial DOM implementation.
- Tokenizer and Parser pass all [HTML5Lib](https://github.com/html5lib/html5lib-tests) tokenizer and tree construction tests except for `<ruby>` elements.
@@ -0,0 +1,257 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
629A63CD1D9AFE0E0089679F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629A63CC1D9AFE0E0089679F /* main.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
629A63C71D9AFE0E0089679F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
629A63C91D9AFE0E0089679F /* HTMLKitExample */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = HTMLKitExample; sourceTree = BUILT_PRODUCTS_DIR; };
629A63CC1D9AFE0E0089679F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
629A63C61D9AFE0E0089679F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
629A63C01D9AFE0E0089679F = {
isa = PBXGroup;
children = (
629A63CB1D9AFE0E0089679F /* HTMLKitExample */,
629A63CA1D9AFE0E0089679F /* Products */,
);
sourceTree = "<group>";
};
629A63CA1D9AFE0E0089679F /* Products */ = {
isa = PBXGroup;
children = (
629A63C91D9AFE0E0089679F /* HTMLKitExample */,
);
name = Products;
sourceTree = "<group>";
};
629A63CB1D9AFE0E0089679F /* HTMLKitExample */ = {
isa = PBXGroup;
children = (
629A63CC1D9AFE0E0089679F /* main.swift */,
);
path = HTMLKitExample;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
629A63C81D9AFE0E0089679F /* HTMLKitExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 629A63D01D9AFE0E0089679F /* Build configuration list for PBXNativeTarget "HTMLKitExample" */;
buildPhases = (
629A63C51D9AFE0E0089679F /* Sources */,
629A63C61D9AFE0E0089679F /* Frameworks */,
629A63C71D9AFE0E0089679F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = HTMLKitExample;
productName = HTMLKitExample;
productReference = 629A63C91D9AFE0E0089679F /* HTMLKitExample */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
629A63C11D9AFE0E0089679F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = iabudiab;
TargetAttributes = {
629A63C81D9AFE0E0089679F = {
CreatedOnToolsVersion = 8.0;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 629A63C41D9AFE0E0089679F /* Build configuration list for PBXProject "HTMLKitExample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 629A63C01D9AFE0E0089679F;
productRefGroup = 629A63CA1D9AFE0E0089679F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
629A63C81D9AFE0E0089679F /* HTMLKitExample */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
629A63C51D9AFE0E0089679F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
629A63CD1D9AFE0E0089679F /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
629A63CE1D9AFE0E0089679F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
629A63CF1D9AFE0E0089679F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
629A63D11D9AFE0E0089679F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
629A63D21D9AFE0E0089679F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
629A63C41D9AFE0E0089679F /* Build configuration list for PBXProject "HTMLKitExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
629A63CE1D9AFE0E0089679F /* Debug */,
629A63CF1D9AFE0E0089679F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
629A63D01D9AFE0E0089679F /* Build configuration list for PBXNativeTarget "HTMLKitExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
629A63D11D9AFE0E0089679F /* Debug */,
629A63D21D9AFE0E0089679F /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 629A63C11D9AFE0E0089679F /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:HTMLKitExample.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "629A63C81D9AFE0E0089679F"
BuildableName = "HTMLKitExample"
BlueprintName = "HTMLKitExample"
ReferencedContainer = "container:HTMLKitExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "629A63C81D9AFE0E0089679F"
BuildableName = "HTMLKitExample"
BlueprintName = "HTMLKitExample"
ReferencedContainer = "container:HTMLKitExample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "629A63C81D9AFE0E0089679F"
BuildableName = "HTMLKitExample"
BlueprintName = "HTMLKitExample"
ReferencedContainer = "container:HTMLKitExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "629A63C81D9AFE0E0089679F"
BuildableName = "HTMLKitExample"
BlueprintName = "HTMLKitExample"
ReferencedContainer = "container:HTMLKitExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,167 @@
//
// main.swift
// HTMLKitExample
//
// Created by Iska on 27/09/16.
// Copyright © 2016 iabudiab. All rights reserved.
//
import HTMLKit
// Simple scraper that is able to load a page, query via CSS Selectors, and following links
class Scraper {
enum ScrapingError: Error {
case DocumentNotLoaded
case ElementNotFound(String)
case InvalidAnchorUrl(String)
case CouldNotLoadPage(URL)
}
private var url: URL
private(set) var document: HTMLDocument?
init(url: URL) {
self.url = url
self.document = nil
}
func load() throws {
try loadDocument(at: url)
}
func listElements(matching selector: CSSSelector) throws -> [HTMLElement] {
guard let document = document else {
throw ScrapingError.DocumentNotLoaded
}
return document.elements(matching: selector)
}
func followLink(matchingSelector selector: CSSSelector) throws {
guard let document = document else {
throw ScrapingError.DocumentNotLoaded
}
guard let link = document.firstElement(matching: selector) else {
throw ScrapingError.ElementNotFound(selector.debugDescription)
}
guard let targetUrl = URL(string: link["href"], relativeTo: url) else {
throw ScrapingError.InvalidAnchorUrl(link["href"])
}
try loadDocument(at: targetUrl)
}
private func loadDocument(at url: URL) throws {
guard let content = try? String(contentsOf: url) else {
throw ScrapingError.CouldNotLoadPage(url)
}
document = HTMLDocument(string: content)
}
}
// A custom block-based selector, that matches only elements having the given text content:
// i.e. textContentSelector("Hello") will match <p>Hello</p> and <a href='example.com'>Hello</a>
// but wont match <div>World</div> or <p>Hello there</p>
func textContentSelector(text: String) -> CSSSelector {
return namedBlockSelector("[@textContent='\(text)']") { (element) -> Bool in
return element.textContent == text
}
}
// Helper function to create a typed-selector matching an anchor element that has the given
// text content.
func anchorElement(havingContent: String) -> CSSSelector {
return allOf(
[
typeSelector("a"),
textContentSelector(text: havingContent)
]
)
}
// Helper function to print the content of a github repository file content
func printRepositoryFile(element: HTMLElement) {
// A node iterator filter that iterates only <td> elements of class "content" i.e. <td class='content'>
let contentIterator = element.nodeIterator(showOptions: .element) { (node) -> HTMLNodeFilterValue in
guard let element = node as? HTMLElement else { return .reject }
if element.tagName == "td" && element["class"] == "content" {
return .accept
}
return .reject
}
for td in contentIterator {
// The cast is necessary because Swift3 wont import the generics info of the NSEnumerator class
// i.e. the nextObject() function alwasy has the following signature 'func nextObject() -> Any?'
let title = (td as AnyObject).textContent.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
print("- \(title)")
}
}
let htmlKitUrl = URL(string: "https://github.com/iabudiab/HTMLKit")!
let scraper = Scraper(url: htmlKitUrl)
do {
// Load the page
try scraper.load()
// Parse the selector
let repositoryContent = try CSSSelectorParser.parseSelector("[role='main'] .repository-content > .file-wrap > .files tr.js-navigation-item")
// Query matching elements
let files = try scraper.listElements(matching: repositoryContent)
print("HTMLKit repositroy root:")
files.forEach(printRepositoryFile)
} catch let error {
print(error)
}
do {
// Follow some links
try scraper.followLink(matchingSelector: anchorElement(havingContent: "Sources"))
try scraper.followLink(matchingSelector: anchorElement(havingContent: "HTMLEOFToken.m"))
// The following selector: "[role='main'] div.file table.js-file-line-container td:nth-child(2)"
// can be defined in type-safe manner:
let selector = allOf([
descendantOfElementSelector(
attributeSelector(.exactMatch, "role", "main")
),
descendantOfElementSelector(
allOf([
typeSelector("div"),
classSelector("file")
])
),
descendantOfElementSelector(
allOf([
typeSelector("table"),
classSelector("js-file-line-container")
])
),
typeSelector("td"),
nthChildSelector(
CSSNthExpressionMake(0, 2)
)
])
// Query matching elements
let elements = try scraper.listElements(matching: selector)
// This will print the source code for the "HTMLEOFToken.m" file under this url:
// https://github.com/iabudiab/HTMLKit/blob/master/Sources/HTMLEOFToken.m
print("\nHTMLEOFToken:")
elements.forEach {
print($0.textContent)
}
} catch let error {
print(error)
}
@@ -28,22 +28,22 @@ var nonParagraphChildOfDiv = document.querySelectorAll("div :not(p)")
/*:
HTMLKit also provides API to create selector instances in a type-safe manner without the need to parse them first. The previous examples would like this:
*/
paragraphs = document.elementsMatchingSelector(typeSelector("p"))
paragraphsOrHeaders = document.elementsMatchingSelector(
paragraphs = document.elements(matching: typeSelector("p"))
paragraphsOrHeaders = document.elements(matching:
anyOf([
typeSelector("p"), typeSelector("h1")
])
)
hasClassAttribute = document.elementsMatchingSelector(hasAttributeSelector("class"))
greetings = document.elementsMatchingSelector(classSelector("greeting"))
classNameStartsWith_de = document.elementsMatchingSelector(attributeSelector(.Begins, "class", "de"))
hasClassAttribute = document.elements(matching: hasAttributeSelector("class"))
greetings = document.elements(matching: classSelector("greeting"))
classNameStartsWith_de = document.elements(matching: attributeSelector(.begins, "class", "de"))
hasAdjacentHeader = document.elementsMatchingSelector(adjacentSiblingSelector(typeSelector("h1")))
hasAdjacentHeader = document.elementsMatchingSelector(generalSiblingSelector(typeSelector("h1")))
hasAdjacentHeader = document.elementsMatchingSelector(generalSiblingSelector(typeSelector("p")))
hasAdjacentHeader = document.elements(matching: adjacentSiblingSelector(typeSelector("h1")))
hasAdjacentHeader = document.elements(matching: generalSiblingSelector(typeSelector("h1")))
hasAdjacentHeader = document.elements(matching: generalSiblingSelector(typeSelector("p")))
nonParagraphChildOfDiv = document.elementsMatchingSelector(
nonParagraphChildOfDiv = document.elements(matching:
allOf([
childOfElementSelector(typeSelector("div")),
not(typeSelector("p"))
@@ -54,17 +54,17 @@ nonParagraphChildOfDiv = document.elementsMatchingSelector(
Here are more examples
*/
let firstDivElement = document.firstElementMatchingSelector(typeSelector("div"))!
let firstDivElement = document.firstElement(matching: typeSelector("div"))!
var secondChildOfDiv = firstDivElement.querySelectorAll(":nth-child(2)")
var secondOfType = firstDivElement.querySelectorAll(":nth-of-type(2n)")
secondChildOfDiv = firstDivElement.elementsMatchingSelector(nthChildSelector(CSSNthExpression(an: 0, b: 2)))
secondOfType = firstDivElement.elementsMatchingSelector(nthOfTypeSelector(CSSNthExpression(an: 2, b: 0)))
secondChildOfDiv = firstDivElement.elements(matching: nthChildSelector(CSSNthExpression(an: 0, b: 2)))
secondOfType = firstDivElement.elements(matching: nthOfTypeSelector(CSSNthExpression(an: 2, b: 0)))
var notParagraphAndNotDiv = firstDivElement.querySelectorAll(":not(p):not(div)")
notParagraphAndNotDiv = firstDivElement.elementsMatchingSelector(
notParagraphAndNotDiv = firstDivElement.elements(matching:
allOf([
not(typeSelector("p")),
not(typeSelector("div"))
@@ -77,4 +77,4 @@ One more thing! You can also create your own selectors. You either subclass the
let myAwesomeSelector = namedBlockSelector("myAwesomeSelector", { (element) -> Bool in
return element.tagName != "p" && element.tagName != "div"
})
firstDivElement.elementsMatchingSelector(myAwesomeSelector)
firstDivElement.elements(matching: myAwesomeSelector)
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Timeline
version = "3.0">
<TimelineItems>
</TimelineItems>
</Timeline>
@@ -9,7 +9,8 @@ import HTMLKit
Given some HTML content
*/
let htmlString = try! String(contentsOfURL: [#FileReference(fileReferenceLiteral: "HTMLKit.html")#])
let htmlString = "<div><h1>HTMLKit</h1><p class='greeting'>Hello there!</p><p class='description'>This is a demo of HTMLKit</p></div>"
htmlString
/*:
You can parse it using the HTMLParser:
@@ -3,10 +3,20 @@
version = "3.0">
<TimelineItems>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=318&amp;EndingColumnNumber=26&amp;EndingLineNumber=13&amp;StartingColumnNumber=1&amp;StartingLineNumber=13&amp;Timestamp=472578634.909266"
documentLocation = "#CharacterRangeLen=0&amp;CharacterRangeLoc=581&amp;EndingColumnNumber=26&amp;EndingLineNumber=11&amp;StartingColumnNumber=1&amp;StartingLineNumber=11&amp;Timestamp=496084829.845787"
lockedSize = "{800, 186}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=27&amp;CharacterRangeLoc=393&amp;EndingColumnNumber=28&amp;EndingLineNumber=20&amp;StartingColumnNumber=1&amp;StartingLineNumber=20&amp;Timestamp=496084834.772773"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=544&amp;EndingColumnNumber=19&amp;EndingLineNumber=27&amp;StartingColumnNumber=1&amp;StartingLineNumber=27&amp;Timestamp=496084834.772773"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
</TimelineItems>
</Timeline>
@@ -18,7 +18,7 @@ You can prase it as a document fragment in a specified context element:
let parser = HTMLParser(string: htmlString)
let tableContext = HTMLElement(tagName: "table")
var elements = parser.parseFragmentWithContextElement(tableContext)
var elements = parser.parseFragment(withContextElement: tableContext)
for element in elements {
print(element.outerHTML)
@@ -29,7 +29,7 @@ The same parser instance can be reusued:
*/
let bodyContext = HTMLElement(tagName: "body")
elements = parser.parseFragmentWithContextElement(bodyContext)
elements = parser.parseFragment(withContextElement: bodyContext)
for element in elements {
print(element.outerHTML)
@@ -21,13 +21,13 @@
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=453&amp;EndingColumnNumber=26&amp;EndingLineNumber=23&amp;StartingColumnNumber=2&amp;StartingLineNumber=23&amp;Timestamp=472578641.006933"
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=455&amp;EndingColumnNumber=26&amp;EndingLineNumber=23&amp;StartingColumnNumber=2&amp;StartingLineNumber=23&amp;Timestamp=495492881.371878"
lockedSize = "{775, 83}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=668&amp;EndingColumnNumber=26&amp;EndingLineNumber=34&amp;StartingColumnNumber=2&amp;StartingLineNumber=34&amp;Timestamp=472578641.007156"
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=672&amp;EndingColumnNumber=26&amp;EndingLineNumber=34&amp;StartingColumnNumber=2&amp;StartingLineNumber=34&amp;Timestamp=495493308.359844"
lockedSize = "{775, 76}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "YES">
@@ -39,7 +39,7 @@
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=448&amp;EndingColumnNumber=26&amp;EndingLineNumber=21&amp;StartingColumnNumber=2&amp;StartingLineNumber=21&amp;Timestamp=472579861.71569"
documentLocation = "#CharacterRangeLen=24&amp;CharacterRangeLoc=450&amp;EndingColumnNumber=26&amp;EndingLineNumber=21&amp;StartingColumnNumber=2&amp;StartingLineNumber=21&amp;Timestamp=495492881.372527"
lockedSize = "{775, 68}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "YES">
@@ -21,7 +21,7 @@ description["content"] = "HTMLKit for iOS & OSX"
Append nodes to the document
*/
let head = document.head!
head.appendNode(description)
head.append(description)
document.innerHTML
let body = document.body!
@@ -30,17 +30,17 @@ let nodes = [
HTMLElement(tagName: "div", attributes: ["class": "green"]),
HTMLElement(tagName: "div", attributes: ["class": "blue"])
]
body.appendNodes(nodes)
body.append(nodes)
body.innerHTML
/*:
Enumerate child elements and perform DOM manipulation
*/
body.enumerateChildElementsUsingBlock { (element, index, stop) -> Void in
body.enumerateChildElements { (element, index, stop) -> Void in
if element.tagName == "div" {
let lorem = HTMLElement(tagName: "p")
lorem.textContent = "Lorem ipsum: \(index)"
element.appendNode(lorem)
element.append(lorem)
}
}
body.innerHTML
@@ -48,7 +48,7 @@ body.innerHTML
/*:
Remove nodes from the document
*/
body.removeChildNodeAtIndex(1)
body.removeChildNode(at: 1)
body.innerHTML
/*:
@@ -56,24 +56,26 @@ Navigate to child and sibling nodes
*/
body.lastChild!.removeFromParentNode()
let greenDiv = body.firstChild!.nextSibling!
greenDiv.outerHTML
/*:
Manipulate the HTML directly
*/
greenDiv.innerHTML = "<ul><li>item 1<li>item 2"
greenDiv.outerHTML
/*:
Iterate the DOM tree with custom filters
*/
let filter = HTMLNodeFilterBlock.filterWithBlock { (node) -> HTMLNodeFilterValue in
let filter = HTMLNodeFilterBlock.filter { (node) -> HTMLNodeFilterValue in
if node.childNodesCount() != 1 {
return .Reject
return .reject
}
return .Accept
return .accept
}
for element in body.nodeIteratorWithShowOptions(.Element, filter: filter) {
element.outerHTML
for element in body.nodeIterator(showOptions: .element, filter: filter) {
(element as! AnyObject).outerHTML
}
//: [Next](@next)
@@ -3,71 +3,65 @@
version = "3.0">
<TimelineItems>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=19&amp;CharacterRangeLoc=575&amp;EndingColumnNumber=26&amp;EndingLineNumber=24&amp;StartingColumnNumber=1&amp;StartingLineNumber=24&amp;Timestamp=472578662.196737"
documentLocation = "#CharacterRangeLen=19&amp;CharacterRangeLoc=571&amp;EndingColumnNumber=26&amp;EndingLineNumber=24&amp;StartingColumnNumber=1&amp;StartingLineNumber=24&amp;Timestamp=495493395.434491"
lockedSize = "{763, 104}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=15&amp;CharacterRangeLoc=843&amp;EndingColumnNumber=22&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=472578662.197012"
documentLocation = "#CharacterRangeLen=15&amp;CharacterRangeLoc=834&amp;EndingColumnNumber=22&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=495493408.111041"
lockedSize = "{763, 75}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=1757&amp;EndingColumnNumber=44&amp;EndingLineNumber=75&amp;StartingColumnNumber=2&amp;StartingLineNumber=75&amp;Timestamp=472578674.159974"
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=1774&amp;EndingColumnNumber=44&amp;EndingLineNumber=77&amp;StartingColumnNumber=2&amp;StartingLineNumber=77&amp;Timestamp=496085091.150842"
lockedSize = "{763, 176}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=844&amp;EndingColumnNumber=15&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=472578662.197451"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=835&amp;EndingColumnNumber=15&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=495493408.111552"
lockedSize = "{762, 70}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=576&amp;EndingColumnNumber=19&amp;EndingLineNumber=24&amp;StartingColumnNumber=1&amp;StartingLineNumber=24&amp;Timestamp=472578662.197662"
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=572&amp;EndingColumnNumber=19&amp;EndingLineNumber=24&amp;StartingColumnNumber=1&amp;StartingLineNumber=24&amp;Timestamp=495493395.435449"
lockedSize = "{752, 99}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=1757&amp;EndingColumnNumber=16&amp;EndingLineNumber=75&amp;StartingColumnNumber=2&amp;StartingLineNumber=75&amp;Timestamp=472578674.160606"
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=1774&amp;EndingColumnNumber=16&amp;EndingLineNumber=77&amp;StartingColumnNumber=2&amp;StartingLineNumber=77&amp;Timestamp=496085091.151491"
lockedSize = "{763, 102}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=1740&amp;EndingColumnNumber=39&amp;EndingLineNumber=75&amp;StartingColumnNumber=2&amp;StartingLineNumber=75&amp;Timestamp=472578674.160818"
documentLocation = "#CharacterRangeLen=33&amp;CharacterRangeLoc=1742&amp;EndingColumnNumber=39&amp;EndingLineNumber=77&amp;StartingColumnNumber=2&amp;StartingLineNumber=77&amp;Timestamp=496085091.151711"
lockedSize = "{759, 149}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=17&amp;CharacterRangeLoc=1741&amp;EndingColumnNumber=19&amp;EndingLineNumber=75&amp;StartingColumnNumber=2&amp;StartingLineNumber=75&amp;Timestamp=472578674.161034"
documentLocation = "#CharacterRangeLen=32&amp;CharacterRangeLoc=1743&amp;EndingColumnNumber=19&amp;EndingLineNumber=77&amp;StartingColumnNumber=2&amp;StartingLineNumber=77&amp;Timestamp=496085091.151931"
lockedSize = "{763, 120}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1230&amp;EndingColumnNumber=15&amp;EndingLineNumber=51&amp;StartingColumnNumber=1&amp;StartingLineNumber=51&amp;Timestamp=472578674.161242"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1204&amp;EndingColumnNumber=15&amp;EndingLineNumber=51&amp;StartingColumnNumber=1&amp;StartingLineNumber=51&amp;Timestamp=495493441.437517"
lockedSize = "{763, 94}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1145&amp;EndingColumnNumber=15&amp;EndingLineNumber=45&amp;StartingColumnNumber=1&amp;StartingLineNumber=45&amp;Timestamp=472578674.161449"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1122&amp;EndingColumnNumber=15&amp;EndingLineNumber=45&amp;StartingColumnNumber=1&amp;StartingLineNumber=45&amp;Timestamp=495493427.982381"
lockedSize = "{760, 97}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1332&amp;EndingColumnNumber=13&amp;EndingLineNumber=57&amp;StartingColumnNumber=5&amp;StartingLineNumber=57&amp;Timestamp=472578674.161666"
lockedSize = "{763, 74}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=397&amp;EndingColumnNumber=19&amp;EndingLineNumber=14&amp;StartingColumnNumber=1&amp;StartingLineNumber=14&amp;Timestamp=472578662.199111"
lockedSize = "{762, 90}"
@@ -75,76 +69,82 @@
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=701&amp;EndingColumnNumber=15&amp;EndingLineNumber=26&amp;StartingColumnNumber=1&amp;StartingLineNumber=26&amp;Timestamp=472578662.199312"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=697&amp;EndingColumnNumber=15&amp;EndingLineNumber=26&amp;StartingColumnNumber=1&amp;StartingLineNumber=26&amp;Timestamp=495493395.437213"
lockedSize = "{763, 76}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1002&amp;EndingColumnNumber=15&amp;EndingLineNumber=38&amp;StartingColumnNumber=1&amp;StartingLineNumber=38&amp;Timestamp=472578674.162269"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=983&amp;EndingColumnNumber=15&amp;EndingLineNumber=38&amp;StartingColumnNumber=1&amp;StartingLineNumber=38&amp;Timestamp=495493427.983236"
lockedSize = "{763, 92}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1049&amp;EndingColumnNumber=15&amp;EndingLineNumber=41&amp;StartingColumnNumber=1&amp;StartingLineNumber=41&amp;Timestamp=472578674.162475"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=1030&amp;EndingColumnNumber=15&amp;EndingLineNumber=41&amp;StartingColumnNumber=1&amp;StartingLineNumber=41&amp;Timestamp=495493427.983458"
lockedSize = "{763, 83}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1108&amp;EndingColumnNumber=13&amp;EndingLineNumber=44&amp;StartingColumnNumber=5&amp;StartingLineNumber=44&amp;Timestamp=472578674.162693"
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1089&amp;EndingColumnNumber=13&amp;EndingLineNumber=44&amp;StartingColumnNumber=5&amp;StartingLineNumber=44&amp;Timestamp=495493427.983688"
lockedSize = "{763, 73}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=17&amp;CharacterRangeLoc=1598&amp;EndingColumnNumber=19&amp;EndingLineNumber=68&amp;StartingColumnNumber=2&amp;StartingLineNumber=68&amp;Timestamp=472578674.162898"
documentLocation = "#CharacterRangeLen=17&amp;CharacterRangeLoc=1601&amp;EndingColumnNumber=19&amp;EndingLineNumber=70&amp;StartingColumnNumber=2&amp;StartingLineNumber=70&amp;Timestamp=496085091.153628"
lockedSize = "{763, 92}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1410&amp;EndingColumnNumber=9&amp;EndingLineNumber=61&amp;StartingColumnNumber=1&amp;StartingLineNumber=59&amp;Timestamp=472578674.163102"
lockedSize = "{763, 60}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=590&amp;EndingColumnNumber=15&amp;EndingLineNumber=21&amp;StartingColumnNumber=1&amp;StartingLineNumber=21&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=586&amp;EndingColumnNumber=15&amp;EndingLineNumber=21&amp;StartingColumnNumber=1&amp;StartingLineNumber=21&amp;Timestamp=495493395.438545"
lockedSize = "{763, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=830&amp;EndingColumnNumber=15&amp;EndingLineNumber=30&amp;StartingColumnNumber=1&amp;StartingLineNumber=30&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=9&amp;CharacterRangeLoc=826&amp;EndingColumnNumber=15&amp;EndingLineNumber=30&amp;StartingColumnNumber=1&amp;StartingLineNumber=30&amp;Timestamp=495493408.115325"
lockedSize = "{763, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=877&amp;EndingColumnNumber=15&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=14&amp;CharacterRangeLoc=868&amp;EndingColumnNumber=15&amp;EndingLineNumber=33&amp;StartingColumnNumber=1&amp;StartingLineNumber=33&amp;Timestamp=495493408.115547"
lockedSize = "{763, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=936&amp;EndingColumnNumber=13&amp;EndingLineNumber=36&amp;StartingColumnNumber=5&amp;StartingLineNumber=36&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=927&amp;EndingColumnNumber=13&amp;EndingLineNumber=36&amp;StartingColumnNumber=5&amp;StartingLineNumber=36&amp;Timestamp=495493408.115762"
lockedSize = "{763, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=978&amp;EndingColumnNumber=9&amp;EndingLineNumber=38&amp;StartingColumnNumber=1&amp;StartingLineNumber=38&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=959&amp;EndingColumnNumber=9&amp;EndingLineNumber=38&amp;StartingColumnNumber=1&amp;StartingLineNumber=38&amp;Timestamp=495493427.985192"
lockedSize = "{763, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=17&amp;CharacterRangeLoc=1261&amp;EndingColumnNumber=19&amp;EndingLineNumber=48&amp;StartingColumnNumber=2&amp;StartingLineNumber=48&amp;Timestamp=472579886.937978"
documentLocation = "#CharacterRangeLen=17&amp;CharacterRangeLoc=1235&amp;EndingColumnNumber=19&amp;EndingLineNumber=48&amp;StartingColumnNumber=2&amp;StartingLineNumber=48&amp;Timestamp=495493441.440785"
lockedSize = "{763, 92}"
selectedRepresentationIndex = "1"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=1451&amp;EndingColumnNumber=19&amp;EndingLineNumber=64&amp;StartingColumnNumber=1&amp;StartingLineNumber=64&amp;Timestamp=496085091.155099"
lockedSize = "{740, 65}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "YES">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=18&amp;CharacterRangeLoc=1347&amp;EndingColumnNumber=19&amp;EndingLineNumber=58&amp;StartingColumnNumber=1&amp;StartingLineNumber=58&amp;Timestamp=496085092.425909"
lockedSize = "{740, 69}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
</TimelineItems>
</Timeline>
-11
View File
@@ -1,11 +0,0 @@
<html>
<head>
<title>HTMLKit</title>
</head>
<body>
<h1>HTMLKit</h1>
<p>HTMLKit is a <a href="https://html.spec.whatwg.org/multipage">WHATWG specification-compliant</a> Objective-C framework for parsing and serializing HTML documents and document fragments for iOS and OSX.</p>
<p>HTMLKit parses real-world HTML the same way modern web browsers would.</p>
<p>HTMLKit comes armed with a <a href="http://www.w3.org/TR/css3-selectors">CSS3 Selectors</a> engine for querying the DOM.</p>
</body>
</html>
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='6.0' target-platform='ios' display-mode='rendered'>
<playground version='6.0' target-platform='macos' display-mode='rendered' last-migration='0800'>
<pages>
<page name='Intro'/>
<page name='Parsing Documents'/>
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 116 KiB

+23
View File
@@ -0,0 +1,23 @@
Pod::Spec.new do |s|
s.name = "HTMLKit"
s.version = "1.0.0"
s.summary = "HTMLKit, an Objective-C framework for your everyday HTML needs."
s.license = "MIT"
s.homepage = "https://github.com/iabudiab/HTMLKit"
s.author = "iabudiab"
s.social_media_url = "https://twitter.com/_iabudiab"
s.ios.deployment_target = "8.0"
s.osx.deployment_target = "10.9"
s.watchos.deployment_target = "2.0"
s.tvos.deployment_target = "9.0"
s.source = { :git => "https://github.com/iabudiab/HTMLKit.git", :tag => s.version }
s.source_files = "Sources", "Sources/**/*.{h,m}"
s.private_header_files = [
'Sources/**/*{HTMLToken,HTMLTokens,HTMLTagToken,HTMLCharacterToken,HTMLCommentToken,HTMLDOCTYPEToken,HTMLEOFToken,HTMLTokenizer,HTMLTokenizerCharacters,HTMLTokenizerEntities,HTMLTokenizerStates,HTMLElementAdjustment,HTMLElementTypes,HTMLInputStreamReader,HTMLListOfActiveFormattingElements,HTMLNodeTraversal,HTMLParseErrorToken,HTMLParserInsertionModes,HTMLStackOfOpenElements,HTMLNode+Private,HTMLMarker,CSSCodePoints,CSSInputStream}.h'
]
s.requires_arc = true
end
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -16,7 +16,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "625A14AB19C7829400AD0C32"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-OSX"
BlueprintName = "HTMLKit-macOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -33,8 +33,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "625A14C219C7829400AD0C32"
BuildableName = "HTMLKitTests-OSX.xctest"
BlueprintName = "HTMLKitTests-OSX"
BuildableName = "HTMLKitTests-macOS.xctest"
BlueprintName = "HTMLKitTests-macOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
<SkippedTests>
@@ -58,7 +58,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "625A14AB19C7829400AD0C32"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-OSX"
BlueprintName = "HTMLKit-macOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -80,7 +80,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "625A14AB19C7829400AD0C32"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-OSX"
BlueprintName = "HTMLKit-macOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -98,7 +98,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "625A14AB19C7829400AD0C32"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-OSX"
BlueprintName = "HTMLKit-macOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857CE91D39A262008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-tvOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857CF21D39A262008DC254"
BuildableName = "HTMLKit-tvOSTests.xctest"
BlueprintName = "HTMLKit-tvOSTests"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "HTMLKitParserPerformance">
</Test>
<Test
Identifier = "HTMLKitTokenizerPerformance">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857CE91D39A262008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-tvOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857CE91D39A262008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-tvOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857CE91D39A262008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-tvOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857C4D1D398642008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-watchOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857C4D1D398642008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-watchOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "62857C4D1D398642008DC254"
BuildableName = "HTMLKit.framework"
BlueprintName = "HTMLKit-watchOS"
ReferencedContainer = "container:HTMLKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+3
View File
@@ -7,4 +7,7 @@
<FileRef
location = "group:HTMLKit.playground">
</FileRef>
<FileRef
location = "group:Example/HTMLKitExample/HTMLKitExample.xcodeproj">
</FileRef>
</Workspace>
-9
View File
@@ -1,9 +0,0 @@
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
-2
View File
@@ -1,2 +0,0 @@
/* Localized versions of Info.plist keys */
-2
View File
@@ -1,2 +0,0 @@
/* Localized versions of Info.plist keys */
+5
View File
@@ -0,0 +1,5 @@
import PackageDescription
let package = Package(
name: "HTMLKit"
)
+104 -11
View File
@@ -1,8 +1,16 @@
# HTMLKit
![HTMLKit Logo](HTMLKit.png)
![HTMLKit Logo](https://raw.githubusercontent.com/iabudiab/HTMLKit/master/HTMLKit.png)
An Objective-C framework for your everyday HTML needs.
[![Build Status](https://img.shields.io/travis/iabudiab/HTMLKit/master.svg?style=flat)](https://travis-ci.org/iabudiab/HTMLKit)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/HTMLKit.svg?style=flat)](https://cocoapods.org/pods/HTMLKit)
[![CocoaDocs](https://img.shields.io/cocoapods/metrics/doc-percent/HTMLKit.svg?style=flat)](http://cocoadocs.org/docsets/HTMLKit)
[![Platform](https://img.shields.io/cocoapods/p/HTMLKit.svg?style=flat)](http://cocoadocs.org/docsets/HTMLKit)
[![License MIT](https://img.shields.io/badge/license-MIT-4481C7.svg?style=flat)](https://opensource.org/licenses/MIT)
# Quick Overview
HTMLKit is a [WHATWG specification](https://html.spec.whatwg.org/multipage/)-compliant framework for parsing and serializing HTML documents and document fragments for iOS and OSX. HTMLKit parses real-world HTML the same way modern web browsers would.
@@ -15,14 +23,95 @@ DOM mutations are validated as described in the [WHATWG DOM Standard](https://do
## Tests
HTMLKit passes all of the [HTML5Lib](https://github.com/html5lib/html5lib-tests) Tokenizer and Tree Construction tests except the Blink changes introduced on 16.09.2015. The `html5lib-tests` is configured as a git-submodule. If you plan to run the tests, do not forget to pull it too.
HTMLKit passes all of the [HTML5Lib](https://github.com/html5lib/html5lib-tests) Tokenizer and Tree Construction tests. The `html5lib-tests` is configured as a git-submodule. If you plan to run the tests, do not forget to pull it too.
The CSS3 Selector implementation is tested with the an adapted version of the [CSS3 Selectors Test Suite](http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/full/flat/index.html), ignoring the tests that require user interaction, session history, and scripting.
The CSS3 Selector implementation is tested with an adapted version of the [CSS3 Selectors Test Suite](http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/full/flat/index.html), ignoring the tests that require user interaction, session history, and scripting.
## Does it Swift?
Check out the playground!
# Installation
### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
If you don't have Carthage yet, you can install it with Homebrew using the following command:
```bash
$ brew update
$ brew install carthage
```
To add `HTMLKit` as a dependency into your project using Carthage just add the following line in your `Cartfile`:
```
github "iabudiab/HTMLKit"
```
Then run the following command to build the framework and drag the built `HTMLKit.framework` into your Xcode project.
```bash
$ carthage update
```
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects.
If you don't have CocoaPods yet, you can install it with the following command:
```bash
$ gem install cocoapods
```
To add `HTMLKit` as a dependency into your project using CocoaPods just add the following in your `Podfile`:
```ruby
use_frameworks!
target 'MyTarget' do
pod 'HTMLKit', '~> 0.9'
end
```
Then, run the following command:
```bash
$ pod install
```
### Swift Package Manager
[Swift Package Manager](https://github.com/apple/swift-package-manager) is the package manager for the Swift programming language.
Add `HTMLKit` to your `Package.swift` dependecies:
```swift
.Package(url: "https://github.com/iabudiab/HTMLKit", majorVersion: 0, minor: 9)
```
Then run:
```bash
$ swift build
```
### Manually
1- Add `HTMLKit` as git submodule
```bash
$ git submodule add https://github.com/iabudiab/HTMLKit.git
```
2- Open the `HTMLKit` folder and drag'n'drop the `HTMLKit.xcodeproj` into the Project Navigator in Xcode to add it as a sub-project.
3- In the General panel of your target add `HTMLKit.framework` under the `Embedded Binaries`
# Features
# Parsing Documents
Given some HTML content, you can parse it either via the `HTMLParser` or instatiate a `HTMLDocument` directly:
@@ -66,7 +155,7 @@ Here are some of the things you can do:
* Create new elements and assign attributes
```objective-c
HTMLElement *description = [[HTMLElement alloc] initWithTagName:@"body" attributes: @{@"name": @"description"}];
HTMLElement *description = [[HTMLElement alloc] initWithTagName:@"meta" attributes: @{@"name": @"description"}];
description[@"content"] = @"HTMLKit for iOS & OSX";
```
@@ -177,7 +266,7 @@ NSArray *hasSiblingParagraph = [document elementsMatchingSelector:generalSibling
NSArray *nonParagraphChildOfDiv = [document elementsMatchingSelector:
allOf(@[
childOfElementSelector(typeSelector(@"div")),
nay(typeSelector(@"p"))
not(typeSelector(@"p"))
])
];
```
@@ -187,17 +276,17 @@ Here are more examples:
```objective-c
HTMLNode *firstDivElement = [document firstElementMatchingSelector:typeSelector(@"div")];
var secondChildOfDiv = [firstDivElement querySelectorAll:@":nth-child(2)"];
var secondOfType = [firstDivElement querySelectorAll:@":nth-of-type(2n)"];
NSArray *secondChildOfDiv = [firstDivElement querySelectorAll:@":nth-child(2)"];
NSArray *secondOfType = [firstDivElement querySelectorAll:@":nth-of-type(2n)"];
secondChildOfDiv = [firstDivElement elementsMatchingSelector:nthChildSelector(CSSNthExpressionMake(0, 2))];
secondOfType = [firstDivElement elementsMatchingSelector:nthOfTypeSelector(CSSNthExpressionMake(2, 0))];
var notParagraphAndNotDiv = [firstDivElement querySelectorAll:@":not(p):not(div)"];
NSArray *notParagraphAndNotDiv = [firstDivElement querySelectorAll:@":not(p):not(div)"];
notParagraphAndNotDiv = [firstDivElement elementsMatchingSelector:
allOf([
nay(typeSelector(@"p")),
nay(typeSelector(@"div"))
not(typeSelector(@"p")),
not(typeSelector(@"div"))
])
];
```
@@ -211,6 +300,10 @@ CSSSelector *myAwesomeSelector = namedBlockSelector(@"myAwesomeSelector", ^BOOL
notParagraphAndNotDiv = [firstDivElement elementsMatchingSelector:myAwesomeSelector];
```
# Change Log
See the [CHANGELOG.md](CHANGELOG.md) for more info.
# License
HTMLKit is available under the MIT license. See the LICENSE file for more info.
HTMLKit is available under the MIT license. See the [LICENSE](LICENSE) file for more info.
@@ -106,7 +106,7 @@
}
NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexString)];
UTF32Char number;
unsigned int number;
[scanner scanHexInt:&number];
return isValidEscapedCodePoint(number) ? number : REPLACEMENT_CHARACTER;
@@ -27,13 +27,13 @@ NSString * _Nonnull NSStringFromNthExpression(CSSNthExpression expression)
}
if (expression.an == 0) {
return [NSString stringWithFormat:@"%ld", expression.b];
return [NSString stringWithFormat:@"%ld", (long)expression.b];
}
if (expression.b == 0) {
return [NSString stringWithFormat:@"%ldn", expression.an];
return [NSString stringWithFormat:@"%ldn", (long)expression.an];
}
return [NSString stringWithFormat:@"%ldn%+ld", expression.an, expression.b];
return [NSString stringWithFormat:@"%ldn%+ld", (long)expression.an, (long)expression.b];
}
#pragma mark - Implementation
@@ -82,7 +82,7 @@
return LINE_FEED;
}
if (CFStringIsSurrogateLowCharacter(nextInputCharacter)) {
NSString *reason = [NSString stringWithFormat:@"Non-Unicode character found (an isolated low surrogate: 0x%X)", nextInputCharacter];
NSString *reason = [NSString stringWithFormat:@"Non-Unicode character found (an isolated low surrogate: 0x%X)", (unsigned int)nextInputCharacter];
[self emitParseError:reason];
return nextInputCharacter;
}
@@ -90,7 +90,7 @@
if (CFStringIsSurrogateHighCharacter(nextInputCharacter)) {
UniChar surrogateLow = CFStringGetCharacterFromInlineBuffer(&_buffer, _location + 1);
if (CFStringIsSurrogateLowCharacter(surrogateLow) == NO) {
NSString *reason = [NSString stringWithFormat:@"Non-Unicode character found (an isolated high surrogate: 0x%X)", nextInputCharacter];
NSString *reason = [NSString stringWithFormat:@"Non-Unicode character found (an isolated high surrogate: 0x%X)", (unsigned int)nextInputCharacter];
[self emitParseError:reason];
return nextInputCharacter;
}
@@ -100,7 +100,7 @@
}
if (isControlOrUndefinedCharacter(nextInputCharacter)) {
NSString *reason = [NSString stringWithFormat:@"A control/undefined character found: (0x%X)", nextInputCharacter];
NSString *reason = [NSString stringWithFormat:@"A control/undefined character found: (0x%X)", (unsigned int)nextInputCharacter];
[self emitParseError:reason];
}
@@ -9,7 +9,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.braincookie.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -6,6 +6,7 @@
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HTMLKitDOMExceptions.h"
NSString * const HTMLKitHierarchyRequestError = @"HierarchyRequestError";
@@ -32,7 +32,7 @@
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p Reason='%@' Location='%lu'>", self.class, self, _reason, _location];
return [NSString stringWithFormat:@"<%@: %p Reason='%@' Location='%lu'>", self.class, self, _reason, (unsigned long)_location];
}
@end
+39 -59
View File
@@ -519,7 +519,7 @@
- (void)generateImpliedEndTagsExceptForElement:(NSString *)tagName
{
while ([self.currentNode.tagName isEqualToAny:@"dd", @"dt", @"li", @"option", @"optgroup", @"p", @"rb", @"rp", @"rt", @"rtc", nil] &&
while ([self.currentNode.tagName isEqualToAny:@"dd", @"dt", @"li", @"menuitem", @"option", @"optgroup", @"p", @"rb", @"rp", @"rt", @"rtc", nil] &&
![self.currentNode.tagName isEqualToString:tagName]) {
[_stackOfOpenElements popCurrentNode];
}
@@ -588,20 +588,29 @@
HTMLElement *lastNode = furthestBlock;
NSUInteger index = [_stackOfOpenElements indexOfElement:node];
for (int innerLoopCounter = 0; innerLoopCounter < 3; innerLoopCounter ++) {
index--;
int innerLoopCounter = 0;
while (YES) {
innerLoopCounter += 1;
index -= 1;
node = _stackOfOpenElements[index];
if ([node isEqual:formattingElement]) {
break;
}
if (innerLoopCounter > 3 && [_listOfActiveFormattingElements containsElement:node]) {
[_listOfActiveFormattingElements removeElement:node];
continue;
}
if (![_listOfActiveFormattingElements containsElement:node]) {
[_stackOfOpenElements removeElement:node];
continue;
}
if ([node isEqual:formattingElement]) {
break;
}
HTMLElement *newElement = [node copy];
[_listOfActiveFormattingElements replaceElementAtIndex:[_listOfActiveFormattingElements indexOfElement:node]
withElement:newElement];
@@ -1158,8 +1167,8 @@
[self HTMLInsertionModeInTemplate:token];
} else {
for (HTMLElement *node in _stackOfOpenElements) {
if ([node.tagName isEqualToAny:@"dd", @"dt", @"li", @"optgroup", @"option", @"p", @"rb", @"rp",
@"rt", @"rtc", @"tbody", @"td", @"tfoot", @"th", @"thead", @"tr", @"body", @"html", nil]) {
if ([node.tagName isEqualToAny:@"dd", @"dt", @"li", @"menuitem", @"optgroup", @"option", @"p", @"rb",
@"rp", @"rt", @"rtc", @"tbody", @"td", @"tfoot", @"th", @"thead", @"tr", @"body", @"html", nil]) {
[self emitParseError:@"EOF reached with unclosed element <%@> in <body>", node.tagName];
break;
}
@@ -1222,12 +1231,20 @@
[self switchInsertionMode:HTMLInsertionModeInFrameset];
} else if ([tagName isEqualToAny:@"address", @"article", @"aside", @"blockquote", @"center",
@"details", @"dialog", @"dir", @"div", @"dl", @"fieldset", @"figcaption", @"figure",
@"footer", @"header", @"hgroup", @"main", @"menu", @"nav", @"ol", @"p", @"section",
@"footer", @"header", @"hgroup", @"main", @"nav", @"ol", @"p", @"section",
@"summary", @"ul", nil]) {
if ([_stackOfOpenElements hasElementInButtonScopeWithTagName:@"p"]) {
[self closePElement];
}
[self insertElementForToken:token];
} else if ([tagName isEqualToString:@"menu"]) {
if ([_stackOfOpenElements hasElementInButtonScopeWithTagName:@"p"]) {
[self closePElement];
}
if ([self.currentNode.tagName isEqualToString:@"menuitem"]) {
[_stackOfOpenElements popCurrentNode];
}
[self insertElementForToken:token];
} else if ([tagName isEqualToAny:@"h1", @"h2", @"h3", @"h4", @"h5", @"h6", nil]) {
if ([_stackOfOpenElements hasElementInButtonScopeWithTagName:@"p"]) {
[self closePElement];
@@ -1364,13 +1381,16 @@
if (type == nil || ![type isEqualToStringIgnoringCase:@"hidden"]) {
_framesetOkFlag = NO;
}
} else if ([tagName isEqualToAny:@"menuitem", @"param", @"source", @"track", nil]) {
} else if ([tagName isEqualToAny:@"param", @"source", @"track", nil]) {
[self insertElementForToken:token];
[_stackOfOpenElements popCurrentNode];
} else if ([tagName isEqualToString:@"hr"]) {
if ([_stackOfOpenElements hasElementInButtonScopeWithTagName:@"p"]) {
[self closePElement];
}
if ([self.currentNode.tagName isEqualToString:@"menuitem"]) {
[_stackOfOpenElements popCurrentNode];
}
[self insertElementForToken:token];
[_stackOfOpenElements popCurrentNode];
_framesetOkFlag = NO;
@@ -1378,52 +1398,6 @@
[self emitParseError:@"Image Start Tag Token with tagname <image> should be <img>. Don't ask."];
token.tagName = @"img";
[self reprocessToken:token];
} else if ([tagName isEqualToString:@"isindex"]) {
[self emitParseError:@"Unexpected start tag <isindex> in <body>"];
if (_formElementPointer != nil && ![_stackOfOpenElements containsElementWithTagName:@"template"]) {
return;
}
_framesetOkFlag = NO;
if ([_stackOfOpenElements hasElementInButtonScopeWithTagName:@"p"]) {
[self closePElement];
}
HTMLStartTagToken *formToken = [[HTMLStartTagToken alloc] initWithTagName:@"form"];
HTMLElement *form = [self insertElementForToken:formToken];
if (![_stackOfOpenElements containsElementWithTagName:@"template"]) {
_formElementPointer = form;
}
NSString *action = token.attributes[@"action"];
if (action != nil) {
form.attributes[@"action"] = action;
}
HTMLStartTagToken *hrToken = [[HTMLStartTagToken alloc] initWithTagName:@"hr"];
[self insertElementForToken:hrToken];
[_stackOfOpenElements popCurrentNode];
[self reconstructActiveFormattingElements];
HTMLStartTagToken *labelToken = [[HTMLStartTagToken alloc] initWithTagName:@"label"];
[self insertElementForToken:labelToken];
NSString *prompt = token.attributes[@"prompt"] ?: @"This is a searchable index. Enter search keywords: ";
[self insertCharacters:prompt];
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:token.attributes];
attributes[@"name"] = @"isindex";
[attributes removeObjectForKey:@"action"];
[attributes removeObjectForKey:@"prompt"];
HTMLStartTagToken *inputToken = [[HTMLStartTagToken alloc] initWithTagName:@"input" attributes:attributes];
[self insertElementForToken:inputToken];
[_stackOfOpenElements popCurrentNode];
[_stackOfOpenElements popCurrentNode];
[self insertElementForToken:hrToken];
[_stackOfOpenElements popCurrentNode];
[_stackOfOpenElements popCurrentNode];
_formElementPointer = nil;
} else if ([tagName isEqualToString:@"textarea"]) {
[self insertElementForToken:token];
_ignoreNextLineFeedCharacterToken = YES;
@@ -1462,6 +1436,12 @@
}
[self reconstructActiveFormattingElements];
[self insertElementForToken:token];
} else if ([tagName isEqualToString:@"menuitem"]) {
if ([self.currentNode.tagName isEqualToString:@"menuitem"]) {
[_stackOfOpenElements popCurrentNode];
}
[self reconstructActiveFormattingElements];
[self insertElementForToken:token];
} else if ([tagName isEqualToAny:@"rb", @"rtc", nil]) {
if ([_stackOfOpenElements hasElementInScopeWithTagName:@"ruby"]) {
[self generateImpliedEndTagsExceptForElement:nil];
@@ -1516,8 +1496,8 @@
[self emitParseError:@"Unexpected end tag </body> without body element in scope in <body>"];
}
for (HTMLElement *node in _stackOfOpenElements) {
if ([node.tagName isEqualToAny:@"dd", @"dt", @"li", @"optgroup", @"option", @"p", @"rb", @"rp", @"rt",
@"rtc", @"tbody", @"td", @"tfoot", @"th", @"thead", @"tr", @"body", @"html", nil]) {
if ([node.tagName isEqualToAny:@"dd", @"dt", @"li", @"menuitem", @"optgroup", @"option", @"p", @"rb", @"rp",
@"rt", @"rtc", @"tbody", @"td", @"tfoot", @"th", @"thead", @"tr", @"body", @"html", nil]) {
[self emitParseError:@"Misnested end tag </%@> with open element <%@> in <body>", tagName, node.tagName];
break;
}
@@ -129,7 +129,11 @@
- (void)popElementsUntilElementPoppedWithTagName:(NSString *)tagName
{
while (self.currentNode && ![self.currentNode.tagName isEqualToString:tagName]) {
while (self.currentNode) {
if (self.currentNode.htmlNamespace == HTMLNamespaceHTML &&
[self.currentNode.tagName isEqualToString:tagName]) {
break;
}
[_stack removeLastObject];
}
[_stack removeLastObject];
@@ -137,7 +141,11 @@
- (void)popElementsUntilAnElementPoppedWithAnyOfTagNames:(NSArray *)tagNames
{
while (self.currentNode && ![tagNames containsObject:self.currentNode.tagName]) {
while (self.currentNode) {
if (self.currentNode.htmlNamespace == HTMLNamespaceHTML &&
[tagNames containsObject:self.currentNode.tagName]) {
break;
}
[_stack removeLastObject];
}
[_stack removeLastObject];
@@ -257,7 +265,10 @@
{
for (HTMLElement *node in _stack.reverseObjectEnumerator) {
if ([tagNames containsObject:node.tagName]) {
return node;
NSNumber *namespace = elementTypes[node.tagName] ?: @(HTMLNamespaceHTML);
if ([namespace isEqual:@(node.htmlNamespace)]) {
return node;
}
}
if ([elementTypes[node.tagName] isEqual:@(node.htmlNamespace)]) {
return nil;
@@ -452,7 +452,6 @@
NSString *entityName = nil;
NSString *entityReplacement = nil;
#warning Improve Named Entity Search
UTF32Char inputCharacter = [_inputStreamReader consumeNextInputCharacter];
NSArray *names = [HTMLTokenizerEntities entities];
NSMutableString *name = [NSMutableString stringWithString:StringFromUTF32Char(inputCharacter)];
@@ -671,7 +670,7 @@
[_inputStreamReader reconsumeCurrentInputCharacter];
break;
default:
[self emitParseError:@"Unexpected character (0x%X) in Tag Open state", character];
[self emitParseError:@"Unexpected character (0x%X) in Tag Open state", (unsigned int)character];
[self switchToState:HTMLTokenizerStateData];
[self emitCharacterToken:LESS_THAN_SIGN];
[_inputStreamReader reconsumeCurrentInputCharacter];
@@ -702,7 +701,7 @@
[_inputStreamReader reconsumeCurrentInputCharacter];
break;
default:
[self emitParseError:@"Unexpected character (0x%X) in End Tag Open state", character];
[self emitParseError:@"Unexpected character (0x%X) in End Tag Open state", (unsigned int)character];
[self switchToState:HTMLTokenizerStateBogusComment];
[_inputStreamReader reconsumeCurrentInputCharacter];
break;
@@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
Intializes and returns a CSS class selector.
@param className The class name to match.
@returns A new instance of class selector.
@return A new instance of class selector.
*/
+ (instancetype)classSelector:(NSString *)className;
@@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
Intializes and returns a CSS id selector.
@param elementId The element id to match.
@returns A new instance of id selector.
@return A new instance of id selector.
*/
+ (instancetype)idSelector:(NSString *)elementId;
@@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
Intializes and returns a CSS has-attribute selector.
@param attributeName The attribute name to match.
@returns A new instance of has-attribute selector.
@return A new instance of has-attribute selector.
*/
+ (instancetype)hasAttributeSelector:(NSString *)attributeName;
@@ -61,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
@param type The selector type.
@param name The attribute name to match.
@param value The value to match.
@returns A new instance of attribute selector.
@return A new instance of attribute selector.
*/
- (instancetype)initWithType:(CSSAttributeSelectorType)type
attributeName:(NSString *)name
@@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a CSS child-of-element selector, e.g. 'div > p'
@param selector The selector matching the parent element.
@returns A new instance of the child of element selector.
@return A new instance of the child of element selector.
*/
+ (instancetype)childOfElementCombinator:(CSSSelector *)selector;
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a CSS descendant-of-element selector, e.g. 'div p'
@param selector The selector matching the ancestor element.
@returns A new instance of the descendant of element selector.
@return A new instance of the descendant of element selector.
*/
+ (instancetype)descendantOfElementCombinator:(CSSSelector *)selector;
@@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a CSS adjacent sibling selector, e.g. 'p + a'
@param selector The selector matching the adjacent sibling element.
@returns A new instance of the adjacent sibling selector.
@return A new instance of the adjacent sibling selector.
*/
+ (instancetype)adjacentSiblingCombinator:(CSSSelector *)selector;
@@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a CSS general sibling selector, e.g. 'p ~ a'
@param selector The selector matching the general sibling element.
@returns A new instance of the general sibling selector.
@return A new instance of the general sibling selector.
*/
+ (instancetype)generalSiblingCombinator:(CSSSelector *)selector;
@@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a new compound selector matching only elements that match all of the specified selectors.
@param selectors The selectors list.
@returns A new instance of the All-Of selector.
@return A new instance of the All-Of selector.
*/
+ (instancetype)andSelector:(NSArray<CSSSelector *> *)selectors;
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a new compound selector matching all elements that match at least one of the specified selectors.
@param selectors The selectors list.
@returns A new instance of the Any-Of selector.
@return A new instance of the Any-Of selector.
*/
+ (instancetype)orSelector:(NSArray<CSSSelector *> *)selectors;
@@ -31,7 +31,7 @@
http://www.w3.org/TR/css-syntax-3/#consume-a-string-token
http://www.w3.org/TR/css-syntax-3/#would-start-an-identifier
@returns A consumed identifier, `nil` if the stream doesn't start with a valid identifier.
@return A consumed identifier, `nil` if the stream doesn't start with a valid identifier.
*/
- (NSString *)consumeIdentifier;
@@ -39,7 +39,7 @@
Consumes characters until the specified code-point is met.
@param endingCodePoint The code-point at which the input stream stops consuming.
@returns The consumed string, `nil` nothing was consumed.
@return The consumed string, `nil` nothing was consumed.
*/
- (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint;
@@ -48,14 +48,14 @@
http://www.w3.org/TR/css-syntax-3/#consume-an-escaped-code-point
http://www.w3.org/TR/css-syntax-3/#starts-with-a-valid-escape
@returns The value of the escaped code-point.
@return The value of the escaped code-point.
*/
- (UTF32Char)consumeEscapedCodePoint;
/**
Consumes a CSS selector combinator.
@returns The consumed combinator, `nil` if nothing was consumed.
@return The consumed combinator, `nil` if nothing was consumed.
*/
- (NSString *)consumeCombinator;
@@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new CSS nth-child selector, e.g. ':nth-child(2n+3)'
@param expression The nth-expression.
@returns Nth-Child selector for the specified expression.
@return Nth-Child selector for the specified expression.
@see CSSNthExpression
*/
@@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new CSS nth-last-child selector, e.g. ':nth-last-child(2n+3)'
@param expression The nth-expression.
@returns Nth-Last-Child selector for the specified expression.
@return Nth-Last-Child selector for the specified expression.
@see CSSNthExpression
*/
@@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new CSS nth-of-type selector, e.g. ':nth-of-type(2n+3)'
@param expression The nth-expression.
@returns Nth-Of-Type selector for the specified expression.
@return Nth-Of-Type selector for the specified expression.
@see CSSNthExpression
*/
@@ -61,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new CSS nth-last-of-type selector, e.g. ':nth-last-of-type(2n+3)'
@param expression The nth-expression.
@returns Nth-Last-Of-Type selector for the specified expression.
@return Nth-Last-Of-Type selector for the specified expression.
@see CSSNthExpression
*/
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@param className The pseudo class name.
@param selector The underlying selector.
@returns A new instance of a pseudo-class selector.
@return A new instance of a pseudo-class selector.
*/
- (instancetype)initWithClassName:(NSString *)className selector:(CSSSelector *)selector;
@@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes and returns a CSS nagation selector, e.g. ':not(div)'
@param selector The selector which should be negated.
@returns A new instance of the negation selector.
@return A new instance of the negation selector.
*/
+ (instancetype)notSelector:(CSSSelector *)selector;
@@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
@discussion 'div:has(p)' matches all <div> elements which have a descendant <p> element.
@param selector The selector matching a descendant element.
@returns A new instance of the has-descendant selector.
@return A new instance of the has-descendant selector.
*/
+ (instancetype)hasSelector:(CSSSelector *)selector;
@@ -74,7 +74,7 @@ extern NSString * _Nonnull NSStringFromNthExpression(CSSNthExpression expression
Initializes and returns a new instance of CSS Selector.
@param string The selector string which will be parsed.
@returns A new instance of a parsed CSS Selector, `nil` if the string is not a valid selector string.
@return A new instance of a parsed CSS Selector, `nil` if the string is not a valid selector string.
*/
+ (nullable instancetype)selectorWithString:(NSString *)stirng;
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
@param name The name of the selector.
@param block The block that should match desired elements.
@returns A new instance of the block-based selector.
@return A new instance of the block-based selector.
*/
- (instancetype)initWithName:(NSString *)name block:(BOOL (^)(HTMLElement *))block;
@@ -25,11 +25,11 @@ NS_ASSUME_NONNULL_BEGIN
@param string The CSS3 selector string.
@param error If an error occurs, upon return contains an `NSError` object that describes the problem.
@returns A parsed CSSSelector, `nil` if an error occurred.
@return A parsed CSSSelector, `nil` if an error occurred.
@see CSSelector
*/
+ (CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
+ (nullable CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
@end
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Universal CSS selector: '*'
@returns The universal CSS selector.
@return The universal CSS selector.
*/
extern CSSSelector * universalSelector();
@@ -32,7 +32,7 @@ extern CSSSelector * universalSelector();
CSS type selector, e.g. 'div', 'p', ...etc.
@param type The element type.
@returns Type selector for the specified type.
@return Type selector for the specified type.
*/
extern CSSSelector * typeSelector(NSString *type);
@@ -42,7 +42,7 @@ extern CSSSelector * typeSelector(NSString *type);
CSS id selector, e.g. '#someId'
@param elementId The element id.
@returns Id selector for the specified element id.
@return Id selector for the specified element id.
*/
extern CSSSelector * idSelector(NSString *elementId);
@@ -50,7 +50,7 @@ extern CSSSelector * idSelector(NSString *elementId);
CSS class selector, e.g. '.someClass'
@param className The class name.
@returns Class selector for the specified class name.
@return Class selector for the specified class name.
*/
extern CSSSelector * classSelector(NSString *className);
@@ -58,7 +58,7 @@ extern CSSSelector * classSelector(NSString *className);
CSS has-attribute selector, e.g. '[href]'
@param attribute The attribute.
@returns Has-Attribute selector for the specified attribute.
@return Has-Attribute selector for the specified attribute.
*/
extern CSSSelector * hasAttributeSelector(NSString *attribute);
@@ -68,7 +68,7 @@ extern CSSSelector * hasAttributeSelector(NSString *attribute);
@param type The attribute selector type.
@param attribute The attribute.
@param value The value of the attribute.
@returns Attribute selector.
@return Attribute selector.
@see CSSAttributeSelectorType
*/
@@ -82,7 +82,7 @@ extern CSSSelector * attributeSelector(CSSAttributeSelectorType type,
CSS nth-child selector, e.g. ':nth-child(2n+3)'
@param expression The nth-expression.
@returns Nth-Child selector for the specified expression.
@return Nth-Child selector for the specified expression.
@see CSSNthExpression
*/
@@ -92,7 +92,7 @@ extern CSSSelector * nthChildSelector(CSSNthExpression expression);
CSS nth-last-child selector, e.g. ':nth-last-child(2n+3)'
@param expression The nth-expression.
@returns Nth-Last-Child selector for the specified expression.
@return Nth-Last-Child selector for the specified expression.
@see CSSNthExpression
*/
@@ -102,7 +102,7 @@ extern CSSSelector * nthLastChildSelector(CSSNthExpression expression);
CSS nth-of-type selector, e.g. ':nth-of-type(2n+3)'
@param expression The nth-expression.
@returns Nth-Of-Type selector for the specified expression.
@return Nth-Of-Type selector for the specified expression.
@see CSSNthExpression
*/
@@ -112,7 +112,7 @@ extern CSSSelector * nthOfTypeSelector(CSSNthExpression expression);
CSS nth-last-of-type selector, e.g. ':nth-last-of-type(2n+3)'
@param expression The nth-expression.
@returns Nth-Last-Of-Type selector for the specified expression.
@return Nth-Last-Of-Type selector for the specified expression.
@see CSSNthExpression
*/
@@ -123,7 +123,7 @@ extern CSSSelector * nthLastOfTypeSelector(CSSNthExpression expression);
This is analogous to ':nth-child(2n+1)'
@returns Odd-Child selector.
@return Odd-Child selector.
*/
extern CSSSelector * oddSelector();
@@ -132,49 +132,49 @@ extern CSSSelector * oddSelector();
This is analogous to ':nth-child(2n)'
@returns Even-Child selector.
@return Even-Child selector.
*/
extern CSSSelector * evenSlector();
/**
CSS first-child selector: ':nth-child(1)'
@returns First-Child selector.
@return First-Child selector.
*/
extern CSSSelector * firstChildSelector();
/**
CSS first-child selector: ':nth-last-child(1)'
@returns First-Child selector.
@return First-Child selector.
*/
extern CSSSelector * lastChildSelector();
/**
CSS first-of-type selector: ':nth-first-of-type(1)'
@returns First-Of-Type selector.
@return First-Of-Type selector.
*/
extern CSSSelector * firstOfTypeSelector();
/**
CSS last-of-type selector: ':nth-last-of-type(1)'
@returns Last-Of-Type selector.
@return Last-Of-Type selector.
*/
extern CSSSelector * lastOfTypeSelector();
/**
CSS only-child selector: ':first-child:last-child'
@returns Only-Child selector.
@return Only-Child selector.
*/
extern CSSSelector * onlyChildSelector();
/**
CSS only-of-type selector: ':first-of-type:last-of-type'
@returns Only-Of-Type selector.
@return Only-Of-Type selector.
*/
extern CSSSelector * onlyOfTypeSelector();
@@ -184,7 +184,7 @@ extern CSSSelector * onlyOfTypeSelector();
CSS child-of-element selector, e.g. 'div > p'
@param selector The selector matching the parent element.
@returns A child of element selector.
@return A child of element selector.
*/
extern CSSSelector * childOfElementSelector(CSSSelector *selector);
@@ -192,7 +192,7 @@ extern CSSSelector * childOfElementSelector(CSSSelector *selector);
CSS descendant-of-element selector, e.g. 'div p'
@param selector The selector matching the ancestor element.
@returns A descendant of element selector.
@return A descendant of element selector.
*/
extern CSSSelector * descendantOfElementSelector(CSSSelector *selector);
@@ -200,7 +200,7 @@ extern CSSSelector * descendantOfElementSelector(CSSSelector *selector);
CSS adjacent sibling selector, e.g. 'p + a'
@param selector The selector matching the adjacent sibling element.
@returns A adjacent sibling selector.
@return A adjacent sibling selector.
*/
extern CSSSelector * adjacentSiblingSelector(CSSSelector *selector);
@@ -208,7 +208,7 @@ extern CSSSelector * adjacentSiblingSelector(CSSSelector *selector);
CSS general sibling selector, e.g. 'p ~ a'
@param selector The selector matching the general sibling element.
@returns A general sibling selector.
@return A general sibling selector.
*/
extern CSSSelector * generalSiblingSelector(CSSSelector *selector);
@@ -218,7 +218,7 @@ extern CSSSelector * generalSiblingSelector(CSSSelector *selector);
CSS nagation selector: ':not(div)'
@param selector The selector which should be negated.
@returns A negation selector.
@return A negation selector.
*/
extern CSSSelector * not(CSSSelector *selector);
@@ -228,7 +228,7 @@ extern CSSSelector * not(CSSSelector *selector);
@discussion 'div:has(p)' matches all <div> elements which have a descendant <p> element.
@param selector The selector matching a descendant element.
@returns A has-descendant selector.
@return A has-descendant selector.
*/
extern CSSSelector * has(CSSSelector *selector);
@@ -238,7 +238,7 @@ extern CSSSelector * has(CSSSelector *selector);
A compound selector matching only elements that match all of the specified selectors.
@param selectors The selectors list.
@returns All-Of selector.
@return All-Of selector.
*/
extern CSSSelector * allOf(NSArray<CSSSelector *> *selectors);
@@ -246,7 +246,7 @@ extern CSSSelector * allOf(NSArray<CSSSelector *> *selectors);
A compound selector matching all elements that match at least one of the specified selectors.
@param selectors The selectors list.
@returns Any-Of selector.
@return Any-Of selector.
*/
extern CSSSelector * anyOf(NSArray<CSSSelector *> *selectors);
@@ -259,7 +259,7 @@ extern CSSSelector * anyOf(NSArray<CSSSelector *> *selectors);
@param name The name of the selector.
@param selector The underlying selector.
@returns A named-pseudo selector.
@return A named-pseudo selector.
*/
extern CSSSelector * namedPseudoSelector(NSString *name, CSSSelector *selector);
@@ -270,7 +270,7 @@ extern CSSSelector * namedPseudoSelector(NSString *name, CSSSelector *selector);
@param name The name of the selector.
@param acceptBlock The block which provides the implementation for the accept-element logic.
@returns A named-block selector.
@return A named-block selector.
*/
extern CSSSelector * namedBlockSelector(NSString *name, BOOL (^ acceptBlock)(HTMLElement *element));
@@ -6,107 +6,109 @@
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@class CSSSelector;
NS_ASSUME_NONNULL_BEGIN
/**
@returns Root element selector: ':root'
@return Root element selector: ':root'
*/
extern CSSSelector * rootSelector();
/**
@returns Empy element selector: ':empty'
@return Empy element selector: ':empty'
*/
extern CSSSelector * emptySelector();
/**
@returns A parent element selector: ':parent'
@return A parent element selector: ':parent'
*/
extern CSSSelector * parentSelector();
/**
@returns A button element selector: ':button'
@return A button element selector: ':button'
*/
extern CSSSelector * buttonSelector();
/**
@returns A checkbox element selector: ':checkbox'
@return A checkbox element selector: ':checkbox'
*/
extern CSSSelector * checkboxSelector();
/**
@returns A file element selector: ':file'
@return A file element selector: ':file'
*/
extern CSSSelector * fileSelector();
/**
@returns A header element selector: ':header'
@return A header element selector: ':header'
*/
extern CSSSelector * headerSelector();
/**
@returns An image element selector: ':image'
@return An image element selector: ':image'
*/
extern CSSSelector * imageSelector();
/**
@returns A parent element selector: ':parent'
@return A parent element selector: ':parent'
*/
extern CSSSelector * inputSelector();
/**
@returns A link element selector: ':link'
@return A link element selector: ':link'
*/
extern CSSSelector * linkSelector();
/**
@returns A password element selector: ':password'
@return A password element selector: ':password'
*/
extern CSSSelector * passwordSelector();
/**
@returns A radio element selector: ':radio'
@return A radio element selector: ':radio'
*/
extern CSSSelector * radioSelector();
/**
@returns A reset element selector: ':reset'
@return A reset element selector: ':reset'
*/
extern CSSSelector * resetSelector();
/**
@returns A submit element selector: ':submit'
@return A submit element selector: ':submit'
*/
extern CSSSelector * submitSelector();
/**
@returns A text element selector: ':text'
@return A text element selector: ':text'
*/
extern CSSSelector * textSelector();
/**
@returns An enabled element selector: ':enabled'
@return An enabled element selector: ':enabled'
*/
extern CSSSelector * enabledSelector();
/**
@returns A disabled element selector: ':disabled'
@return A disabled element selector: ':disabled'
*/
extern CSSSelector * disabledSelector();
/**
@returns A checked element selector: ':checked'
@return A checked element selector: ':checked'
*/
extern CSSSelector * checkedSelector();
/**
@returns An optional element selector: ':optional'
@return An optional element selector: ':optional'
*/
extern CSSSelector * optionalSelector();
/**
@returns A required element selector: ':required'
@return A required element selector: ':required'
*/
extern CSSSelector * requiredSelector();
@@ -116,7 +118,7 @@ extern CSSSelector * requiredSelector();
Selects all elements at an index less than the specified index. A negative index counts backwards from the last element.
@param index The zero-based index of the element to match.
@returns A Less-Than selector.
@return A Less-Than selector.
*/
extern CSSSelector * ltSelector(NSInteger index);
@@ -127,7 +129,7 @@ extern CSSSelector * ltSelector(NSInteger index);
last element.
@param index The zero-based index of the element to match.
@returns A Greater-Than selector.
@return A Greater-Than selector.
*/
extern CSSSelector * gtSelector(NSInteger index);
@@ -137,7 +139,7 @@ extern CSSSelector * gtSelector(NSInteger index);
Selects the element at the specified index. A negative index counts backwards from the last element.
@param index The zero-based index of the element to match.
@returns An Equal selector.
@return An Equal selector.
*/
extern CSSSelector * eqSelector(NSInteger index);
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
Returns the universal selector.
@returns A new instance of a universal selector that matches all elements.
@return A new instance of a universal selector that matches all elements.
*/
+ (instancetype)universalSelector;
@@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new selector for the specified type.
@param type The type of elements that should be matched.
@returns A new instance of a type selector.
@return A new instance of a type selector.
*/
- (instancetype)initWithType:(NSString *)type;
@@ -25,7 +25,7 @@
Initializes a new character token.
@param string The string with which to initialize the token.
@returns A new instance of a character token.
@return A new instance of a character token.
*/
- (instancetype)initWithString:(NSString *)string;
@@ -42,14 +42,14 @@
@discussion HTML whitespace characters are: CHARACTER TABULATION U+0009, LINE FEED U+000A, FORM FEED U+000C,
CARRIAGE RETURN U+000D, and SPACE U+0020
@returns `YES` if this token contains only whitespace characters, `NO` otherwise.
@return `YES` if this token contains only whitespace characters, `NO` otherwise.
*/
- (BOOL)isWhitespaceToken;
/**
Checks whether this token is empty.
@returns `YES` if this token is empty, `NO` otherwise.
@return `YES` if this token is empty, `NO` otherwise.
*/
- (BOOL)isEmpty;
@@ -74,7 +74,7 @@
Splits this token retaining only characters after the leading whitespace. The leading whitespace characters are then
returned a new characters token.
@returns A characters token with leading whitespace characters. Returns 'nil` if no leading whitespace exists.
@return A characters token with leading whitespace characters. Returns 'nil` if no leading whitespace exists.
*/
- (HTMLCharacterToken *)tokenBySplitingLeadingWhiteSpace;
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
Initializes a new HTML comment node.
@param data The comment string.
@returns A new isntance of a HTML comment node.
@return A new isntance of a HTML comment node.
*/
- (instancetype)initWithData:(NSString *)data;
@@ -25,7 +25,7 @@
Initializes a new comment token.
@param string The string with which to initialize the token.
@returns A new instance of a comment token.
@return A new instance of a comment token.
*/
- (instancetype)initWithData:(NSString *)data;
@@ -34,7 +34,7 @@
Initializes a new DOCTYPE token.
@param name The name with which to initialize the token.
@returns A new instance of a DOCTYPE token.
@return A new instance of a DOCTYPE token.
*/
- (instancetype)initWithName:(NSString *)name;
@@ -33,12 +33,12 @@ NS_ASSUME_NONNULL_BEGIN
@param element The associated context element.
@param attribute The associated attribute.
@param value The initial attribute's value.
@returns A new instance of the DOM token list.
@return A new instance of the DOM token list.
*/
- (instancetype)initWithElement:(HTMLElement *)element attribute:(NSString *)attribute value:(NSString *)value;
/**
@returns The length of this token list
@return The length of this token list
*/
- (NSUInteger)length;
@@ -46,7 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
Checks whether this list contains the given token.
@param token The token.
@returns `YES` if the given token is in this list, `NO` otherwise.
@return `YES` if the given token is in this list, `NO` otherwise.
*/
- (BOOL)contains:(NSString *)token;
@@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
Toggles the given token.
@param token The token to toggle.
@returns `YES` if the token was added to the list, `NO` if it was removed from it.
@return `YES` if the token was added to the list, `NO` if it was removed from it.
*/
- (BOOL)toggle:(NSString *)token;
@@ -84,7 +84,7 @@ NS_ASSUME_NONNULL_BEGIN
Returns the value of the token at the given index.
@param index The index at which to return the token.
@returns The token at the given index. If index is greater than or equal to the value returned by count, an
@return The token at the given index. If index is greater than or equal to the value returned by count, an
NSRangeException is raised.
*/
- (NSString *)objectAtIndexedSubscript:(NSUInteger)index;
@@ -99,7 +99,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setObject:(NSString *)obj atIndexedSubscript:(NSUInteger)index;
/**
@returns The string representation of this token list, which can be used as the attribute's value.
@return The string representation of this token list, which can be used as the attribute's value.
*/
- (NSString *)stringify;

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