80 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 25ad5a3f82 Merge branch 'release/0.9.1' into develop 2016-01-29 00:56:54 +01:00
271 changed files with 2518 additions and 393 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)
+27 -16
View File
@@ -1,5 +1,5 @@
language: objective-c
osx_image: xcode7.2
osx_image: xcode8
branches:
except:
@@ -14,21 +14,32 @@ env:
- LANG=en_US.UTF-8
- WORKSPACE=HTMLKit.xcworkspace
- IOS_FRAMEWORK_SCHEME=HTMLKit-iOS
- OSX_FRAMEWORK_SCHEME=HTMLKit-OSX
- IOS_SDK=iphonesimulator9.2
- OSX_SDK=macosx10.11
- 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="OS=9.0,name=iPhone 6 Plus" SIMULATOR="iPhone 6 Plus (9.0)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=9.1,name=iPhone 6S" SIMULATOR="iPhone 6S (9.1)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="OS=9.2,name=iPhone 6S Plus" SIMULATOR="iPhone 6S Plus (9.2)" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
- DESTINATION="arch=x86_64" SIMULATOR="" SCHEME="$OSX_FRAMEWORK_SCHEME" SDK="$OSX_SDK"
- 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
- xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO test | xcpretty -c
- 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'/>
+5 -3
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "HTMLKit"
s.version = "0.9.1"
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"
@@ -9,12 +9,14 @@ Pod::Spec.new do |s|
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 = "HTMLKit", "HTMLKit/**/*.{h,m}"
s.source_files = "Sources", "Sources/**/*.{h,m}"
s.private_header_files = [
'HTMLKit/**/*{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'
'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
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"
)
+95 -5
View File
@@ -1,10 +1,15 @@
# 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://travis-ci.org/iabudiab/HTMLKit.svg?branch=develop)](https://travis-ci.org/iabudiab/HTMLKit) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![License MIT](https://img.shields.io/badge/license-MIT-4481C7.svg)](https://opensource.org/licenses/MIT)
[![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
@@ -18,7 +23,7 @@ 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 for the Blink changes introduced on the 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 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.
@@ -26,6 +31,87 @@ The CSS3 Selector implementation is tested with an adapted version of the [CSS3
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:
@@ -180,7 +266,7 @@ NSArray *hasSiblingParagraph = [document elementsMatchingSelector:generalSibling
NSArray *nonParagraphChildOfDiv = [document elementsMatchingSelector:
allOf(@[
childOfElementSelector(typeSelector(@"div")),
nay(typeSelector(@"p"))
not(typeSelector(@"p"))
])
];
```
@@ -214,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.
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.9.1</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";
+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;
@@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
@see CSSelector
*/
+ (CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
+ (nullable CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
@end
@@ -6,6 +6,8 @@
// Copyright © 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@class CSSSelector;
NS_ASSUME_NONNULL_BEGIN

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