├── . codecov.yml
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── .jazzy.yaml
├── CHANGELOG.md
├── Example
└── HTMLKitExample
│ ├── HTMLKitExample.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── HTMLKitExample.xcscheme
│ └── HTMLKitExample
│ └── main.swift
├── HTMLKit.playground
├── Pages
│ ├── CSS Selectors.xcplaygroundpage
│ │ └── Contents.swift
│ ├── Intro.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ │ └── HTMLKit.png
│ │ └── timeline.xctimeline
│ ├── Parsing Documents.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ ├── Parsing Fragments.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ └── The DOM.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
├── contents.xcplayground
└── playground.xcworkspace
│ └── contents.xcworkspacedata
├── HTMLKit.png
├── HTMLKit.podspec
├── HTMLKit.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ ├── xcbaselines
│ └── 625A14C219C7829400AD0C32.xcbaseline
│ │ ├── 5AB53A08-CDD0-43FB-B47F-2EE38B3FE707.plist
│ │ └── Info.plist
│ └── xcschemes
│ ├── HTMLKit-iOS.xcscheme
│ ├── HTMLKit-macOS.xcscheme
│ ├── HTMLKit-tvOS.xcscheme
│ └── HTMLKit-watchOS.xcscheme
├── HTMLKit.xcworkspace
└── contents.xcworkspacedata
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── CSSAttributeSelector.m
├── CSSCombinatorSelector.m
├── CSSCompoundSelector.m
├── CSSInputStream.m
├── CSSNthExpressionParser.m
├── CSSNthExpressionSelector.m
├── CSSPseudoClassSelector.m
├── CSSPseudoFunctionSelector.m
├── CSSSelector.m
├── CSSSelectorBlock.m
├── CSSSelectorParser.m
├── CSSSelectors.m
├── CSSStructuralPseudoSelectors.m
├── CSSTypeSelector.m
├── HTMLCharacterData.m
├── HTMLCharacterToken.m
├── HTMLComment.m
├── HTMLCommentToken.m
├── HTMLDOCTYPEToken.m
├── HTMLDOMTokenList.m
├── HTMLDOMUtils.m
├── HTMLDocument.m
├── HTMLDocumentFragment.m
├── HTMLDocumentType.m
├── HTMLEOFToken.m
├── HTMLElement.m
├── HTMLInputStreamReader.m
├── HTMLKit-Info.plist
├── HTMLKitDOMExceptions.m
├── HTMLListOfActiveFormattingElements.m
├── HTMLMarker.m
├── HTMLNode.m
├── HTMLNodeFilter.m
├── HTMLNodeIterator.m
├── HTMLNodeTraversal.m
├── HTMLNodeVisitor.m
├── HTMLOrderedDictionary.m
├── HTMLParseErrorToken.m
├── HTMLParser.m
├── HTMLQuircksMode.m
├── HTMLRange.m
├── HTMLSerializer.m
├── HTMLStackOfOpenElements.m
├── HTMLTagToken.m
├── HTMLTemplate.m
├── HTMLText.m
├── HTMLToken.m
├── HTMLTokenizer.m
├── HTMLTokenizerEntities.m
├── HTMLTreeVisitor.m
├── HTMLTreeWalker.m
├── NSCharacterSet+HTMLKit.m
├── NSString+HTMLKit.m
├── NSString+Private.m
└── include
│ ├── CSSAttributeSelector.h
│ ├── CSSCodePoints.h
│ ├── CSSCombinatorSelector.h
│ ├── CSSCompoundSelector.h
│ ├── CSSInputStream.h
│ ├── CSSNthExpressionParser.h
│ ├── CSSNthExpressionSelector.h
│ ├── CSSPseudoClassSelector.h
│ ├── CSSPseudoFunctionSelector.h
│ ├── CSSSelector.h
│ ├── CSSSelectorBlock.h
│ ├── CSSSelectorParser.h
│ ├── CSSSelectors.h
│ ├── CSSStructuralPseudoSelectors.h
│ ├── CSSTypeSelector.h
│ ├── HTMLCharacterData+Private.h
│ ├── HTMLCharacterData.h
│ ├── HTMLCharacterToken.h
│ ├── HTMLComment.h
│ ├── HTMLCommentToken.h
│ ├── HTMLDOCTYPEToken.h
│ ├── HTMLDOM.h
│ ├── HTMLDOMTokenList.h
│ ├── HTMLDOMUtils.h
│ ├── HTMLDocument+Private.h
│ ├── HTMLDocument.h
│ ├── HTMLDocumentFragment.h
│ ├── HTMLDocumentType.h
│ ├── HTMLEOFToken.h
│ ├── HTMLElement.h
│ ├── HTMLElementAdjustment.h
│ ├── HTMLElementTypes.h
│ ├── HTMLInputStreamReader.h
│ ├── HTMLKit.h
│ ├── HTMLKitDOMExceptions.h
│ ├── HTMLKitErrorDomain.h
│ ├── HTMLListOfActiveFormattingElements.h
│ ├── HTMLMarker.h
│ ├── HTMLNamespaces.h
│ ├── HTMLNode+Private.h
│ ├── HTMLNode.h
│ ├── HTMLNodeFilter.h
│ ├── HTMLNodeIterator+Private.h
│ ├── HTMLNodeIterator.h
│ ├── HTMLNodeTraversal.h
│ ├── HTMLNodeVisitor.h
│ ├── HTMLOrderedDictionary.h
│ ├── HTMLParseErrorToken.h
│ ├── HTMLParser+Private.h
│ ├── HTMLParser.h
│ ├── HTMLParserInsertionModes.h
│ ├── HTMLQuirksMode.h
│ ├── HTMLRange+Private.h
│ ├── HTMLRange.h
│ ├── HTMLSerializer.h
│ ├── HTMLStackOfOpenElements.h
│ ├── HTMLTagToken.h
│ ├── HTMLTemplate.h
│ ├── HTMLText.h
│ ├── HTMLToken.h
│ ├── HTMLTokenizer.h
│ ├── HTMLTokenizerCharacters.h
│ ├── HTMLTokenizerEntities.h
│ ├── HTMLTokenizerStates.h
│ ├── HTMLTokens.h
│ ├── HTMLTreeVisitor.h
│ ├── HTMLTreeWalker.h
│ ├── NSCharacterSet+HTMLKit.h
│ ├── NSString+HTMLKit.h
│ ├── NSString+Private.h
│ └── module.modulemap
└── Tests
├── Fixtures
├── HTML Standard.html
└── bug33.html
├── HTMLKitTests
├── CSSAttributeSelectorTests.m
├── CSSCombinatorSelectorTests.m
├── CSSExtensionSelectorsParsingTests.m
├── CSSNThExpressionSelectorTests.m
├── CSSNthExpressionsParserTests.m
├── CSSSelectorParserTests.m
├── CSSSelectorTest.h
├── CSSSelectorTest.m
├── CSSStructuralPseudoSelectors.m
├── CSSTypeSelectorTests.m
├── HTML5LibTokenizerTest.h
├── HTML5LibTokenizerTest.m
├── HTML5LibTreeConstructionTest.h
├── HTML5LibTreeConstructionTest.m
├── HTMLCharacterDataTests.m
├── HTMLDOMTokenListTests.m
├── HTMLKitParserIssuesTests.m
├── HTMLKitParserPerformance.m
├── HTMLKitTestObserver.h
├── HTMLKitTestObserver.m
├── HTMLKitTestUtil.h
├── HTMLKitTestUtil.m
├── HTMLKitTests-Info.plist
├── HTMLKitTokenizerPerformance.m
├── HTMLKitTokenizerTests.m
├── HTMLKitTreeConstructionTests.m
├── HTMLMutationAlgorithmsTests.m
├── HTMLNodeIteratorTests.m
├── HTMLNodesTests.m
├── HTMLOrderedDictionaryTests.m
├── HTMLRangeTests.m
├── HTMLSerializationTests.m
├── HTMLStringCategoryTests.m
├── HTMLTreeVisitorTests.m
└── HTMLTreeWalkerTests.m
└── css-tests
├── 1.html
├── 10.html
├── 11.html
├── 13.html
├── 14.html
├── 144.html
├── 148.html
├── 149.html
├── 14b.html
├── 14c.html
├── 14d.html
├── 14e.html
├── 15.html
├── 150.html
├── 151.html
├── 152.html
├── 154.html
├── 155.html
├── 155a.html
├── 155b.html
├── 155c.html
├── 155d.html
├── 156.html
├── 157.html
├── 158.html
├── 15b.html
├── 16.html
├── 160.html
├── 170.html
├── 170a.html
├── 170b.html
├── 170c.html
├── 170d.html
├── 175a.html
├── 175b.html
├── 175c.html
├── 176.html
├── 177b.html
├── 181.html
├── 183.html
├── 184a.html
├── 184b.html
├── 184c.html
├── 184d.html
├── 184e.html
├── 184f.html
├── 2.html
├── 23.html
├── 24.html
├── 25.html
├── 27a.html
├── 27b.html
├── 28.html
├── 29.html
├── 3.html
├── 30.html
├── 31.html
├── 32.html
├── 33.html
├── 34.html
├── 35.html
├── 36.html
├── 37.html
├── 4.html
├── 43.html
├── 44.html
├── 44c.html
├── 44d.html
├── 45.html
├── 45c.html
├── 46.html
├── 5.html
├── 54.html
├── 55.html
├── 56.html
├── 59.html
├── 6.html
├── 60.html
├── 68.html
├── 69.html
├── 7.html
├── 70.html
├── 72.html
├── 72b.html
├── 73.html
├── 74.html
├── 75.html
├── 76.html
├── 77.html
├── 78.html
├── 79.html
├── 7b.html
├── 8.html
├── 80.html
├── 81.html
├── 82.html
├── 83.html
├── 86.html
├── 87.html
├── 88.html
├── 89.html
├── 9.html
└── 90.html
/. codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | branch: develop
3 |
4 | ignore:
5 | - "Tests/"
6 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: HTMLKit CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | macOS:
7 | name: Test macOS
8 | runs-on: macOS-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | with:
12 | submodules: recursive
13 | - name: macOS
14 | run: xcodebuild -workspace "HTMLKit.xcworkspace" -scheme "HTMLKit-macOS" -destination "platform=macOS" -enableCodeCoverage YES clean test | xcpretty
15 | - name: code coverage
16 | uses: codecov/codecov-action@v1
17 | iOS:
18 | name: Test iOS
19 | runs-on: macOS-latest
20 | env:
21 | DEVELOPER_DIR: /Applications/Xcode_11.5.app/Contents/Developer
22 | strategy:
23 | matrix:
24 | destination: ["OS=13.5,name=iPhone 11 Pro", "OS=12.4,name=iPhone XS", "OS=11.4,name=iPhone X"]
25 | steps:
26 | - uses: actions/checkout@v2
27 | with:
28 | submodules: recursive
29 | - name: iOS - ${{ matrix.destination }}
30 | run: xcodebuild -workspace "HTMLKit.xcworkspace" -scheme "HTMLKit-iOS" -destination "${{ matrix.destination }}" clean test | xcpretty
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 | .build/
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | Pods/
38 |
39 | # Carthage
40 | #
41 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
42 | Carthage/Checkouts
43 | Carthage/Build
44 |
45 | # Jazzy
46 | docs/
47 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "html5lib-tests"]
2 | path = Tests/html5lib-tests
3 | url = https://github.com/html5lib/html5lib-tests.git
4 |
--------------------------------------------------------------------------------
/Example/HTMLKitExample/HTMLKitExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Intro.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | /*:
2 | # HTMLKit
3 |
4 | 
5 |
6 | ****
7 |
8 | An Objective-C kit for your everyday HTML needs.
9 |
10 | ****
11 |
12 | HTMLKit is a [WHATWG](https://html.spec.whatwg.org/multipage/) specification-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.
13 |
14 | ****
15 |
16 | HTMLKit is available under the MIT License
17 |
18 | ****
19 |
20 | # Table of Contents
21 |
22 | - [Parsing Document](Parsing%20Documents)
23 | - [Parsing Fragments](Parsing%20Fragments)
24 | - [The DOM](The%20DOM)
25 | - [CSS Selectors](CSS%20Selectors)
26 |
27 | ****
28 |
29 | [Next](@next)
30 | */
31 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Intro.xcplaygroundpage/Resources/HTMLKit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iabudiab/HTMLKit/118cb4197164cc6987f41fae7e1eb21eb96b5f20/HTMLKit.playground/Pages/Intro.xcplaygroundpage/Resources/HTMLKit.png
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Intro.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Parsing Documents.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | /*:
3 | # Parsing HTML Documents
4 | */
5 |
6 | import HTMLKit
7 |
8 | /*:
9 | Given some HTML content
10 | */
11 |
12 | let htmlString = "
HTMLKit Hello there!
This is a demo of HTMLKit
"
13 | htmlString
14 |
15 | /*:
16 | You can parse it using the HTMLParser:
17 | */
18 |
19 | let parser = HTMLParser(string: htmlString)
20 | let documentViaParser = parser.parseDocument()
21 | documentViaParser.innerHTML
22 |
23 | /*:
24 | You can also create a document from a given HTML string directly:
25 | */
26 |
27 | let document = HTMLDocument(string: htmlString)
28 | document.innerHTML
29 |
30 | //: [Next](@next)
31 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Parsing Documents.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
15 |
16 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/Parsing Fragments.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | /*:
3 | # Parsing Document Fragments
4 | */
5 |
6 | import HTMLKit
7 |
8 | /*:
9 | Given some HTML content
10 | */
11 |
12 | let htmlString = "some table data"
13 |
14 | /*:
15 | You can prase it as a document fragment in a specified context element:
16 | */
17 |
18 | let parser = HTMLParser(string: htmlString)
19 |
20 | let tableContext = HTMLElement(tagName: "table")
21 | var elements = parser.parseFragment(withContextElement: tableContext)
22 |
23 | for element in elements {
24 | print(element.outerHTML)
25 | }
26 |
27 | /*:
28 | The same parser instance can be reusued:
29 | */
30 |
31 | let bodyContext = HTMLElement(tagName: "body")
32 | elements = parser.parseFragment(withContextElement: bodyContext)
33 |
34 | for element in elements {
35 | print(element.outerHTML)
36 | }
37 |
38 | //: [Next](@next)
39 |
--------------------------------------------------------------------------------
/HTMLKit.playground/Pages/The DOM.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | /*:
3 | # The DOM
4 |
5 | HTMLKit provides a rich DOM implementation for manipulating and navigating the document tree. Here are some of the features:
6 | */
7 |
8 | import HTMLKit
9 |
10 | let htmlString = ""
11 | let document = HTMLDocument(string: htmlString)
12 |
13 | /*:
14 | Create new elements and assign attributes
15 | */
16 |
17 | let description = HTMLElement(tagName:"meta", attributes: ["name": "description"])
18 | description["content"] = "HTMLKit for iOS & OSX"
19 |
20 | /*:
21 | Append nodes to the document
22 | */
23 | let head = document.head!
24 | head.append(description)
25 | document.innerHTML
26 |
27 | let body = document.body!
28 | let nodes = [
29 | HTMLElement(tagName: "div", attributes: ["class": "red"]),
30 | HTMLElement(tagName: "div", attributes: ["class": "green"]),
31 | HTMLElement(tagName: "div", attributes: ["class": "blue"])
32 | ]
33 | body.append(nodes)
34 | body.innerHTML
35 |
36 | /*:
37 | Enumerate child elements and perform DOM manipulation
38 | */
39 | body.enumerateChildElements { (element, index, stop) -> Void in
40 | if element.tagName == "div" {
41 | let lorem = HTMLElement(tagName: "p")
42 | lorem.textContent = "Lorem ipsum: \(index)"
43 | element.append(lorem)
44 | }
45 | }
46 | body.innerHTML
47 |
48 | /*:
49 | Remove nodes from the document
50 | */
51 | body.removeChildNode(at: 1)
52 | body.innerHTML
53 |
54 | /*:
55 | Navigate to child and sibling nodes
56 | */
57 | body.lastChild!.removeFromParentNode()
58 | let greenDiv = body.firstChild!.nextSibling!
59 | greenDiv.outerHTML
60 |
61 | /*:
62 | Manipulate the HTML directly
63 | */
64 | greenDiv.innerHTML = "item 1 item 2"
65 | greenDiv.outerHTML
66 |
67 | /*:
68 | Iterate the DOM tree with custom filters
69 | */
70 | let filter = HTMLNodeFilterBlock.filter { (node) -> HTMLNodeFilterValue in
71 | if node.childNodesCount() != 1 {
72 | return .reject
73 | }
74 | return .accept
75 | }
76 |
77 | for element in body.nodeIterator(showOptions: .element, filter: filter) {
78 | (element as! AnyObject).outerHTML
79 | }
80 |
81 | //: [Next](@next)
82 |
--------------------------------------------------------------------------------
/HTMLKit.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/HTMLKit.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/HTMLKit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iabudiab/HTMLKit/118cb4197164cc6987f41fae7e1eb21eb96b5f20/HTMLKit.png
--------------------------------------------------------------------------------
/HTMLKit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "HTMLKit"
3 | s.version = "4.2.0"
4 | s.summary = "HTMLKit, an Objective-C framework for your everyday HTML needs."
5 | s.license = "MIT"
6 | s.homepage = "https://github.com/iabudiab/HTMLKit"
7 | s.author = "iabudiab"
8 | s.social_media_url = "https://twitter.com/_iabudiab"
9 |
10 | s.ios.deployment_target = "8.0"
11 | s.osx.deployment_target = "10.9"
12 | s.watchos.deployment_target = "2.0"
13 | s.tvos.deployment_target = "9.0"
14 |
15 | s.source = { :git => "https://github.com/iabudiab/HTMLKit.git", :tag => s.version }
16 |
17 | s.source_files = "Sources", "Sources/**/*.{h,m}"
18 | s.private_header_files = [
19 | 'Sources/**/*{HTMLToken,HTMLTokens,HTMLTagToken,HTMLCharacterToken,HTMLCommentToken,HTMLDOCTYPEToken,HTMLEOFToken,HTMLTokenizer,HTMLTokenizerCharacters,HTMLTokenizerEntities,HTMLTokenizerStates,HTMLElementAdjustment,HTMLElementTypes,HTMLInputStreamReader,HTMLListOfActiveFormattingElements,HTMLParseErrorToken,HTMLParserInsertionModes,HTMLStackOfOpenElements,HTMLMarker,HTMLNode+Private,HTMLDocument+Private,HTMLCharacterData+Private,HTMLRange+Private,HTMLParser+Private,HTMLNodeIterator+Private,HTMLNodeTraversal,HTMLDOMUtils,CSSCodePoints,CSSInputStream}.h'
20 | ]
21 |
22 | s.requires_arc = true
23 | end
24 |
--------------------------------------------------------------------------------
/HTMLKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/HTMLKit.xcodeproj/xcshareddata/xcbaselines/625A14C219C7829400AD0C32.xcbaseline/5AB53A08-CDD0-43FB-B47F-2EE38B3FE707.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | classNames
6 |
7 | HTMLKitParserPerformance
8 |
9 | testParserPerformance
10 |
11 | com.apple.XCTPerformanceMetric_WallClockTime
12 |
13 | baselineAverage
14 | 18.23
15 | baselineIntegrationDisplayName
16 | Local Baseline
17 |
18 |
19 |
20 | HTMLKitTokenizerPerformance
21 |
22 | testTokenizerPerformance
23 |
24 | com.apple.XCTPerformanceMetric_WallClockTime
25 |
26 | baselineAverage
27 | 14.55
28 | baselineIntegrationDisplayName
29 | Local Baseline
30 |
31 |
32 |
33 | HTMLTokenizerTests
34 |
35 | testTokenizerPerformance
36 |
37 | com.apple.XCTPerformanceMetric_WallClockTime
38 |
39 | baselineAverage
40 | 15.47
41 | baselineIntegrationDisplayName
42 | Local Baseline
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/HTMLKit.xcodeproj/xcshareddata/xcbaselines/625A14C219C7829400AD0C32.xcbaseline/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | runDestinationsByUUID
6 |
7 | 5AB53A08-CDD0-43FB-B47F-2EE38B3FE707
8 |
9 | localComputer
10 |
11 | busSpeedInMHz
12 | 1600
13 | cpuCount
14 | 2
15 | cpuKind
16 | Quad-Core Intel Xeon
17 | cpuSpeedInMHz
18 | 2800
19 | logicalCPUCoresPerPackage
20 | 4
21 | modelCode
22 | MacPro3,1
23 | physicalCPUCoresPerPackage
24 | 4
25 | platformIdentifier
26 | com.apple.platform.macosx
27 |
28 | targetArchitecture
29 | x86_64
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/HTMLKit.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2020 Iskandar Abudiab
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "HTMLKit",
6 | products: [.library(name: "HTMLKit", targets: ["HTMLKit"])],
7 | targets: [.target(name: "HTMLKit", dependencies: [], path: "Sources")],
8 | swiftLanguageVersions: [.v5]
9 | )
10 |
--------------------------------------------------------------------------------
/Sources/CSSCompoundSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSCompoundSelector.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 18/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSCompoundSelector.h"
10 |
11 | #pragma mark - Declarations
12 |
13 | @interface CSSAndCompoundSelector : CSSCompoundSelector
14 | @end
15 |
16 | @interface CSSOrCompoundSelector : CSSCompoundSelector
17 | @end
18 |
19 | #pragma mark - Base Combinator
20 |
21 | @interface CSSCompoundSelector ()
22 | {
23 | NSMutableArray *_selectors;
24 | }
25 | @property (nonatomic, strong, readonly) NSArray *selectors;
26 | @end
27 |
28 | @implementation CSSCompoundSelector
29 | @synthesize selectors = _selectors;
30 |
31 | + (instancetype)andSelector:(NSArray *)selectors
32 | {
33 | return [[CSSAndCompoundSelector alloc] initWithSelectors:selectors];
34 | }
35 |
36 | + (instancetype)orSelector:(NSArray *)selectors
37 | {
38 | return [[CSSOrCompoundSelector alloc] initWithSelectors:selectors];
39 | }
40 |
41 | - (instancetype)initWithSelectors:(NSArray *)selectors
42 | {
43 | self = [super init];
44 | if (self) {
45 | _selectors = [[NSMutableArray alloc] initWithArray:selectors];
46 | }
47 | return self;
48 | }
49 |
50 | - (void)addSelector:(CSSSelector *)selector
51 | {
52 | [_selectors addObject:selector];
53 | }
54 |
55 | @end
56 |
57 | #pragma mark - And Compound Selector
58 |
59 | @implementation CSSAndCompoundSelector
60 |
61 | - (BOOL)acceptElement:(HTMLElement *)element
62 | {
63 | for (CSSSelector *selector in self.selectors) {
64 | if (![selector acceptElement:element]) {
65 | return NO;
66 | }
67 | }
68 | return YES;
69 | }
70 |
71 | - (NSString *)debugDescription
72 | {
73 | NSArray *descriptions = [self.selectors valueForKey:@"debugDescription"];
74 | return [descriptions componentsJoinedByString:@""];
75 | }
76 |
77 | @end
78 |
79 | #pragma mark - Or Compound Selector
80 |
81 | @implementation CSSOrCompoundSelector
82 |
83 | - (BOOL)acceptElement:(HTMLElement *)element
84 | {
85 | for (CSSSelector *selector in self.selectors) {
86 | if ([selector acceptElement:element]) {
87 | return YES;
88 | }
89 | }
90 | return NO;
91 | }
92 |
93 | - (NSString *)debugDescription
94 | {
95 | NSArray *descriptions = [self.selectors valueForKey:@"debugDescription"];
96 | return [descriptions componentsJoinedByString:@","];
97 | }
98 |
99 | @end
100 |
--------------------------------------------------------------------------------
/Sources/CSSNthExpressionParser.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSNthExpression.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 10/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSNthExpressionParser.h"
10 | #import "CSSCodePoints.h"
11 | #import "NSString+Private.h"
12 | #import "NSCharacterSet+HTMLKit.h"
13 |
14 | @implementation CSSNthExpressionParser
15 |
16 | + (CSSNthExpression)parseExpression:(NSString *)expression
17 | {
18 | NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
19 |
20 | NSString *string = [expression.lowercaseString copy];
21 | string = [[string stringByTrimmingCharactersInSet:whitespace] copy];
22 |
23 | if ([string isEqualToStringIgnoringCase:@"odd"]) {
24 | return CSSNthExpressionOdd;
25 | } else if ([string isEqualToStringIgnoringCase:@"even"]) {
26 | return CSSNthExpressionEven;
27 | }
28 |
29 | NSCharacterSet *set = [[NSCharacterSet htmlkit_CSSNthExpressionCharacterSet] invertedSet];
30 | if ([string rangeOfCharacterFromSet:set].location != NSNotFound) {
31 | return CSSNthExpressionMake(0, 0);
32 | }
33 | NSArray *parts = [string componentsSeparatedByString:@"n"];
34 |
35 | if (parts.count == 1) {
36 | NSInteger b = [parts[0] integerValue];
37 | return CSSNthExpressionMake(0, b);
38 | } else if (parts.count == 2) {
39 | NSInteger a = [parts[0] integerValue];
40 | if (a == 0) {
41 | a = [parts[0] isEqualToString:@"-"] ? -1 : 1;
42 | }
43 | NSInteger b = [parts[1] integerValue];
44 | return CSSNthExpressionMake(a, b);
45 | } else {
46 | return CSSNthExpressionMake(0, 0);
47 | }
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Sources/CSSPseudoClassSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSPseudoClassSelector.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 06/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSPseudoClassSelector.h"
10 |
11 | @interface CSSPseudoClassSelector ()
12 | {
13 | NSString *_className;
14 | CSSSelector *_selector;
15 | }
16 | @end
17 |
18 | @implementation CSSPseudoClassSelector
19 | @synthesize className = _className;
20 |
21 | - (instancetype)initWithClassName:(NSString *)className selector:(CSSSelector *)selector
22 | {
23 | self = [super init];
24 | if (self) {
25 | _className = [className copy];
26 | _selector = selector;
27 | }
28 | return self;
29 | }
30 |
31 | -(BOOL)acceptElement:(HTMLElement *)element
32 | {
33 | return [_selector acceptElement:element];
34 | }
35 |
36 | - (NSString *)debugDescription
37 | {
38 | return [NSString stringWithFormat:@":%@", self.className];
39 | }
40 |
41 | - (NSString *)description
42 | {
43 | return [NSString stringWithFormat:@"<%@: %p '%@'>", self.class, self, self.debugDescription];
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Sources/CSSPseudoFunctionSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSPseudoFunctionSelector.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 07/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSPseudoFunctionSelector.h"
10 | #import "HTMLElement.h"
11 | #import "HTMLNode+Private.h"
12 |
13 | #pragma mark - Declarations
14 |
15 | @interface CSSNotSelector : CSSPseudoFunctionSelector
16 | @end
17 |
18 | @interface CSSHasSelector : CSSPseudoFunctionSelector
19 | @end
20 |
21 | #pragma mark - Base Function Selector
22 |
23 | @interface CSSPseudoFunctionSelector ()
24 | {
25 | CSSSelector *_selector;
26 | }
27 | @property (nonatomic, strong, readonly) CSSSelector *selector;
28 | @end
29 |
30 | @implementation CSSPseudoFunctionSelector
31 | @synthesize selector = _selector;
32 |
33 | + (instancetype)notSelector:(CSSSelector *)selector
34 | {
35 | return [[CSSNotSelector alloc] initWithSelector:selector];
36 | }
37 |
38 | + (instancetype)hasSelector:(CSSSelector *)selector
39 | {
40 | return [[CSSHasSelector alloc] initWithSelector:selector];
41 | }
42 |
43 | - (instancetype)initWithSelector:(CSSSelector *)selector
44 | {
45 | self = [super init];
46 | if (self) {
47 | _selector = selector;
48 | }
49 | return self;
50 | }
51 |
52 | @end
53 |
54 | #pragma mark - Not Selector
55 |
56 | @implementation CSSNotSelector
57 |
58 | - (BOOL)acceptElement:(HTMLElement *)element
59 | {
60 | return ![self.selector acceptElement:element];
61 | }
62 |
63 | - (NSString *)debugDescription
64 | {
65 | return [NSString stringWithFormat:@":not(%@)", self.selector.debugDescription];
66 | }
67 |
68 | @end
69 |
70 | #pragma mark - Has Selector
71 |
72 | @implementation CSSHasSelector
73 |
74 | - (BOOL)acceptElement:(HTMLElement *)element
75 | {
76 | HTMLNodeIterator *iterator = [element nodeIteratorWithShowOptions:HTMLNodeFilterShowAll filter:nil];
77 | for (HTMLNode *descendant in iterator) {
78 | if (descendant.nodeType == HTMLNodeElement && [self.selector acceptElement:descendant.asElement]) {
79 | return YES;
80 | }
81 | }
82 |
83 | return NO;
84 | }
85 |
86 | - (NSString *)debugDescription
87 | {
88 | return [NSString stringWithFormat:@":has(%@)", self.selector.debugDescription];
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/Sources/CSSSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelector.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 15/10/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelector.h"
11 | #import "CSSSelectorParser.h"
12 |
13 | @implementation CSSSelector
14 |
15 | + (instancetype)selectorWithString:(NSString *)string
16 | {
17 | NSError *error = nil;
18 | CSSSelector *instance = [CSSSelectorParser parseSelector:string error:&error];
19 | if (error) {
20 | return nil;
21 | }
22 | return instance;
23 | }
24 |
25 | - (BOOL)acceptElement:(HTMLElement *)element
26 | {
27 | [self doesNotRecognizeSelector:_cmd];
28 | return NO;
29 | }
30 |
31 | #pragma mark - Description
32 |
33 | - (NSString *)debugDescription
34 | {
35 | [self doesNotRecognizeSelector:_cmd];
36 | return @"";
37 | }
38 |
39 | - (NSString *)description
40 | {
41 | return [NSString stringWithFormat:@"<%@: %p '%@'>", self.class, self, self.debugDescription];
42 | }
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/Sources/CSSSelectorBlock.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelectorBlock.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 20/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelectorBlock.h"
10 |
11 | @interface CSSSelectorBlock ()
12 | {
13 | NSString *_name;
14 | BOOL (^ _acceptBlock)(HTMLElement *);
15 | }
16 | @end
17 |
18 | @implementation CSSSelectorBlock
19 |
20 | - (instancetype)initWithName:(NSString *)name block:(BOOL (^)(HTMLElement *))block
21 | {
22 | self = [super init];
23 | if (self) {
24 | _name = [name copy];
25 | _acceptBlock = [block copy];
26 | }
27 | return self;
28 | }
29 |
30 | - (BOOL)acceptElement:(HTMLElement *)element
31 | {
32 | return _acceptBlock ? _acceptBlock(element) : NO;
33 | }
34 |
35 | - (NSString *)debugDescription
36 | {
37 | return _name;
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/Sources/CSSTypeSelector.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSTypeSelector.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 13/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSTypeSelector.h"
10 | #import "HTMLElement.h"
11 | #import "NSString+Private.h"
12 |
13 | @interface CSSTypeSelector ()
14 | {
15 | NSString *_type;
16 | }
17 | @end
18 |
19 | @implementation CSSTypeSelector
20 |
21 | + (instancetype)universalSelector
22 | {
23 | return [[self alloc] initWithType:@"*"];
24 | }
25 |
26 | - (instancetype)initWithType:(NSString *)type
27 | {
28 | self = [super init];
29 | if (self) {
30 | _type = [type copy];
31 | }
32 | return self;
33 | }
34 |
35 | - (BOOL)acceptElement:(HTMLElement *)element
36 | {
37 | if ([_type isEqualToString:@"*"] || [_type isEqualToStringIgnoringCase:element.tagName]) {
38 | return YES;
39 | }
40 | return NO;
41 | }
42 |
43 | #pragma mark - Description
44 |
45 | - (NSString *)debugDescription
46 | {
47 | return self.type;
48 | }
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/Sources/HTMLCharacterToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCharacterToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLCharacterToken.h"
10 | #import "NSString+HTMLKit.h"
11 |
12 | @interface HTMLCharacterToken ()
13 | {
14 | NSMutableString *_characters;
15 | }
16 | @end
17 |
18 | @implementation HTMLCharacterToken
19 |
20 | - (instancetype)initWithString:(NSString *)string
21 | {
22 | self = [super init];
23 | if (self) {
24 | _characters = [string mutableCopy];
25 | }
26 | return self;
27 | }
28 |
29 | - (void)appendString:(NSString *)string
30 | {
31 | if (_characters == nil) {
32 | _characters = [NSMutableString new];
33 | }
34 | [_characters appendString:string];
35 | }
36 |
37 | - (BOOL)isWhitespaceToken
38 | {
39 | return [_characters htmlkit_isHTMLWhitespaceString];
40 | }
41 |
42 | - (BOOL)isEmpty
43 | {
44 | return _characters.length == 0;
45 | }
46 |
47 | - (void)retainLeadingWhitespace
48 | {
49 | NSUInteger index = _characters.htmlkit_leadingHTMLWhitespaceLength;
50 | if (index > 0) {
51 | [_characters setString:[_characters substringToIndex:index]];
52 | }
53 | }
54 |
55 | - (void)trimLeadingWhitespace
56 | {
57 | NSUInteger index = _characters.htmlkit_leadingHTMLWhitespaceLength;
58 | if (index > 0) {
59 | [_characters setString:[_characters substringFromIndex:index]];
60 | }
61 | }
62 |
63 | - (void)trimFormIndex:(NSUInteger)index
64 | {
65 | [_characters setString:[_characters substringFromIndex:index]];
66 | }
67 |
68 | - (HTMLCharacterToken *)tokenBySplitingLeadingWhiteSpace
69 | {
70 | NSUInteger index = _characters.htmlkit_leadingHTMLWhitespaceLength;
71 | if (index > 0) {
72 | NSString *leading = [_characters substringToIndex:index];
73 | [_characters setString:[_characters substringFromIndex:index]];
74 | return [[HTMLCharacterToken alloc] initWithString:leading];
75 | }
76 |
77 | return nil;
78 | }
79 |
80 | #pragma mark - NSObject
81 |
82 | - (BOOL)isEqual:(id)other
83 | {
84 | if ([other isKindOfClass:[self class]]) {
85 | HTMLCharacterToken *token = (HTMLCharacterToken *)other;
86 | return bothNilOrEqual(self.characters, token.characters);
87 | }
88 | return NO;
89 | }
90 |
91 | - (NSUInteger)hash
92 | {
93 | return self.characters.hash;
94 | }
95 |
96 | - (NSString *)description
97 | {
98 | return [NSString stringWithFormat:@"<%@: %p Characters='%@'>", self.class, self, _characters];
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/Sources/HTMLComment.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLComment.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLComment.h"
10 | #import "HTMLCharacterData+Private.h"
11 |
12 | @implementation HTMLComment
13 |
14 | - (instancetype)init
15 | {
16 | return [self initWithData:@""];
17 | }
18 |
19 | - (instancetype)initWithData:(NSString *)data
20 | {
21 | return [super initWithName:@"#comment" type:HTMLNodeComment data:data];
22 | }
23 |
24 | #pragma mark - Description
25 |
26 | - (NSString *)description
27 | {
28 | return [NSString stringWithFormat:@"<%@: %p >", self.class, self, self.data];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Sources/HTMLCommentToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCommentToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLCommentToken.h"
10 |
11 | @interface HTMLCommentToken ()
12 | {
13 | NSMutableString *_data;
14 | }
15 | @end
16 |
17 | @implementation HTMLCommentToken
18 | @synthesize data = _data;
19 |
20 | - (instancetype)initWithData:(NSString *)data
21 | {
22 | self = [super init];
23 | if (self) {
24 | self.type = HTMLTokenTypeComment;
25 | _data = [data mutableCopy];
26 | }
27 | return self;
28 | }
29 |
30 | - (void)appendStringToData:(NSString *)string
31 | {
32 | if (_data == nil) {
33 | _data = [NSMutableString new];
34 | }
35 | [_data appendString:string];
36 | }
37 |
38 | #pragma mark - NSObject
39 |
40 | - (BOOL)isEqual:(id)other
41 | {
42 | if ([other isKindOfClass:[self class]]) {
43 | HTMLCommentToken *token = (HTMLCommentToken *)other;
44 | return bothNilOrEqual(self.data, token.data);
45 | }
46 | return NO;
47 | }
48 |
49 | - (NSUInteger)hash
50 | {
51 | return self.data.hash;
52 | }
53 |
54 | - (NSString *)description
55 | {
56 | return [NSString stringWithFormat:@"<%@: %p Data='%@'>", self.class, self, _data];
57 | }
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/Sources/HTMLDOCTYPEToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDOCTYPEToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLDOCTYPEToken.h"
10 |
11 | @interface HTMLDOCTYPEToken ()
12 | {
13 | NSMutableString *_name;
14 | }
15 |
16 | @end
17 |
18 | @implementation HTMLDOCTYPEToken
19 | @synthesize name = _name;
20 |
21 | - (instancetype)init
22 | {
23 | return [self initWithName:nil];
24 | }
25 |
26 | - (instancetype)initWithName:(NSString *)name
27 | {
28 | self = [super init];
29 | if (self) {
30 | self.type = HTMLTokenTypeDoctype;
31 | _name = [name mutableCopy];
32 | }
33 | return self;
34 | }
35 |
36 | - (void)appendStringToName:(NSString *)string
37 | {
38 | if (_name == nil) {
39 | _name = [NSMutableString new];
40 | }
41 | [_name appendString:string];
42 | }
43 |
44 | - (void)appendStringToPublicIdentifier:(NSString *)string
45 | {
46 | if (_publicIdentifier == nil) {
47 | _publicIdentifier = [NSMutableString new];
48 | }
49 | [_publicIdentifier appendString:string];
50 | }
51 |
52 | - (void)appendStringToSystemIdentifier:(NSString *)string
53 | {
54 | if (_systemIdentifier == nil) {
55 | _systemIdentifier = [NSMutableString new];
56 | }
57 | [_systemIdentifier appendString:string];
58 | }
59 |
60 | #pragma mark - NSObject
61 |
62 | - (BOOL)isEqual:(id)other
63 | {
64 | if ([other isKindOfClass:[self class]]) {
65 | HTMLDOCTYPEToken *token = (HTMLDOCTYPEToken *)other;
66 | return (bothNilOrEqual(self.name, token.name) &&
67 | bothNilOrEqual(self.publicIdentifier, token.publicIdentifier) &&
68 | bothNilOrEqual(self.systemIdentifier, token.systemIdentifier) &&
69 | self.forceQuirks == token.forceQuirks);
70 | }
71 | return NO;
72 | }
73 |
74 | - (NSUInteger)hash
75 | {
76 | return self.name.hash + self.publicIdentifier.hash + self.systemIdentifier.hash;
77 | }
78 |
79 | - (NSString *)description
80 | {
81 | return [NSString stringWithFormat:@"<%@: %p Name='%@' Public='%@' System='%@' ForceQuirks='%@'>", self.class, self, _name, _publicIdentifier, _systemIdentifier, @(_forceQuirks)];
82 | }
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/Sources/HTMLDOMTokenList.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDOMTokenList.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30/11/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLDOMTokenList.h"
10 | #import "HTMLElement.h"
11 |
12 | @interface HTMLDOMTokenList ()
13 | {
14 | HTMLElement *_element;
15 | NSString *_attribute;
16 | NSMutableOrderedSet *_tokens;
17 | }
18 | @end
19 |
20 | @implementation HTMLDOMTokenList
21 | @synthesize element = _element;
22 | @synthesize attribute = _attribute;
23 |
24 | #pragma mark - Init
25 |
26 | - (instancetype)initWithElement:(HTMLElement *)element attribute:(NSString *)attribute value:(NSString *)value
27 | {
28 | self = [super init];
29 | if (self) {
30 | _element = element;
31 | _attribute = [attribute copy];
32 | _tokens = [NSMutableOrderedSet new];
33 | [self add:[value componentsSeparatedByString:@" "]];
34 | }
35 | return self;
36 | }
37 |
38 | #pragma mark - Access
39 |
40 | - (void)updateValue
41 | {
42 | _element[_attribute] = self.stringify;
43 | }
44 |
45 | - (NSUInteger)length
46 | {
47 | return _tokens.count;
48 | }
49 |
50 | - (BOOL)contains:(NSString *)token
51 | {
52 | return [_tokens containsObject:token];
53 | }
54 |
55 | - (void)add:(NSArray *)tokens
56 | {
57 | for (NSString *token in tokens) {
58 | if (![token isEqualToString:@""]) {
59 | [_tokens addObject:token];
60 | }
61 | }
62 | [self updateValue];
63 | }
64 |
65 | - (void)remove:(NSArray *)tokens
66 | {
67 | for (NSString *token in tokens) {
68 | [_tokens removeObject:token];
69 | }
70 | [self updateValue];
71 | }
72 |
73 | - (BOOL)toggle:(NSString *)token
74 | {
75 | if ([_tokens containsObject:token]) {
76 | [_tokens removeObject:token];
77 | [self updateValue];
78 | return NO;
79 | } else {
80 | [_tokens addObject:token];
81 | [self updateValue];
82 | return YES;
83 | }
84 | }
85 |
86 | - (void)replaceToken:(NSString *)token withToken:(NSString *)newToken
87 | {
88 | NSUInteger index = [_tokens indexOfObject:token];
89 | _tokens[index] = newToken;
90 | [self updateValue];
91 | }
92 |
93 | - (NSString *)objectAtIndexedSubscript:(NSUInteger)index
94 | {
95 | return _tokens[index];
96 | }
97 |
98 | - (void)setObject:(NSString *)obj atIndexedSubscript:(NSUInteger)index
99 | {
100 | _tokens[index] = obj;
101 | [self updateValue];
102 | }
103 |
104 | - (NSString *)stringify
105 | {
106 | return [_tokens.array componentsJoinedByString:@" "];
107 | }
108 |
109 | @end
110 |
--------------------------------------------------------------------------------
/Sources/HTMLDOMUtils.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDOMUtils.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 03/12/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLDOMUtils.h"
10 | #import "HTMLNode.h"
11 |
12 | extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB)
13 | {
14 | for (HTMLNode *parentA = nodeA; parentA != nil; parentA = parentA.parentNode) {
15 | for (HTMLNode *parentB = nodeB; parentB != nil; parentB = parentB.parentNode) {
16 | if (parentA == parentB) {
17 | return parentA;
18 | }
19 | }
20 | }
21 |
22 | return nil;
23 | }
24 |
25 | extern NSArray * GetAncestorNodes(HTMLNode *node)
26 | {
27 | NSMutableArray *ancestors = [NSMutableArray array];
28 | for (HTMLNode *it = node; it; it = it.parentNode) {
29 | [ancestors addObject:it];
30 | }
31 | return ancestors;
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/HTMLDocumentFragment.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDocumentFragment.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 12/04/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLDocumentFragment.h"
10 | #import "HTMLText.h"
11 | #import "HTMLNode+Private.h"
12 |
13 | @implementation HTMLDocumentFragment
14 |
15 | - (instancetype)init
16 | {
17 | return [self initWithDocument:nil];
18 | }
19 |
20 | - (instancetype)initWithDocument:(HTMLDocument *)document
21 | {
22 | self = [super initWithName:@"#document-fragment" type:HTMLNodeDocumentFragment];
23 | if (self) {
24 | self.ownerDocument = document;
25 | }
26 | return self;
27 | }
28 |
29 | - (NSString *)textContent
30 | {
31 | NSMutableString *content = [NSMutableString string];
32 | for (HTMLNode *node in self.nodeIterator) {
33 | if (node.nodeType == HTMLNodeText) {
34 | [content appendString:[(HTMLText *)node data]];
35 | }
36 | }
37 | return content;
38 | }
39 |
40 | - (void)setTextContent:(NSString *)textContent
41 | {
42 | HTMLText *node = [[HTMLText alloc] initWithData:textContent];
43 | [self replaceAllChildNodesWithNode:node];
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Sources/HTMLEOFToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLEOFToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 15/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLEOFToken.h"
10 |
11 | @implementation HTMLEOFToken
12 |
13 | + (instancetype)token
14 | {
15 | static dispatch_once_t onceToken;
16 | static HTMLEOFToken *singleton = nil;
17 | dispatch_once(&onceToken, ^{
18 | singleton = [[self alloc] init];
19 | });
20 | return singleton;
21 | }
22 |
23 | - (instancetype)init
24 | {
25 | self = [super init];
26 | if (self) {
27 | self.type = HTMLTokenTypeEOF;
28 | }
29 | return self;
30 | }
31 |
32 | - (NSString *)description
33 | {
34 | return [NSString stringWithFormat:@"<%@: %p EOF>", self.class, self];
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/Sources/HTMLKit-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSHumanReadableCopyright
26 | Copyright © 2014 iabudiab. All rights reserved.
27 | NSPrincipalClass
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Sources/HTMLKitDOMExceptions.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitExceptions.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 17/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLKitDOMExceptions.h"
11 |
12 | NSString * const HTMLKitHierarchyRequestError = @"HierarchyRequestError";
13 | NSString * const HTMLKitNotFoundError = @"NotFoundError";
14 | NSString * const HTMLKitNotSupportedError = @"NotSupportedError";
15 | NSString * const HTMLKitSyntaxError = @"SyntaxError";
16 | NSString * const HTMLKitInvalidCharacterError = @"InvalidCharacterError";
17 | NSString * const HTMLKitInvalidNodeTypeError = @"InvalidNodeTypeError";
18 | NSString * const HTMLKitIndexSizeError = @"IndexSizeError";
19 | NSString * const HTMLKitWrongDocumentError = @"WrongDocumentError";
20 | NSString * const HTMLKitInvalidStateError = @"InvalidStateError";
21 |
--------------------------------------------------------------------------------
/Sources/HTMLMarker.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLMarker.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLMarker.h"
10 |
11 | @implementation HTMLMarker
12 |
13 | + (instancetype)marker
14 | {
15 | static dispatch_once_t onceToken;
16 | static HTMLMarker *singleton = nil;
17 | dispatch_once(&onceToken, ^{
18 | singleton = [[self alloc] init];
19 | });
20 | return singleton;
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Sources/HTMLNodeFilter.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeFilter.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 05/06/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNodeFilter.h"
10 | #import "HTMLNode.h"
11 | #import "HTMLNode+Private.h"
12 | #import "CSSSelector.h"
13 |
14 | #pragma mark - Block Filter
15 |
16 | @interface HTMLNodeFilterBlock ()
17 | {
18 | HTMLNodeFilterValue (^ _block)(HTMLNode *);
19 | }
20 | @end
21 |
22 | @implementation HTMLNodeFilterBlock
23 |
24 | + (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
25 | {
26 | return [[self alloc] initWithBlock:block];
27 | }
28 |
29 | - (instancetype)initWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
30 | {
31 | self = [super init];
32 | if (self) {
33 | _block = [block copy];
34 | }
35 | return self;
36 | }
37 |
38 | - (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node
39 | {
40 | if (!_block) {
41 | return HTMLNodeFilterSkip;
42 | }
43 |
44 | return _block(node);
45 | }
46 |
47 | @end
48 |
49 | #pragma mark - CSS Selector Filter
50 |
51 | @interface HTMLSelectorNodeFilter ()
52 | {
53 | CSSSelector *_selector;
54 | }
55 | @end
56 |
57 | @implementation HTMLSelectorNodeFilter
58 |
59 | + (instancetype)filterWithSelector:(CSSSelector *)selector
60 | {
61 | return [[self alloc] initWithSelector:selector];
62 | }
63 |
64 | - (instancetype)initWithSelector:(CSSSelector *)selector
65 | {
66 | self = [super init];
67 | if (self) {
68 | _selector = selector;
69 | }
70 | return self;
71 | }
72 |
73 | - (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node
74 | {
75 | if (node.nodeType != HTMLNodeElement) {
76 | return HTMLNodeFilterSkip;
77 | }
78 |
79 | if ([_selector acceptElement:node.asElement]) {
80 | return HTMLNodeFilterAccept;
81 | }
82 |
83 | return HTMLNodeFilterSkip;
84 | }
85 |
86 | @end
87 |
--------------------------------------------------------------------------------
/Sources/HTMLNodeTraversal.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeTraversal.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 05/06/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNodeTraversal.h"
10 | #import "HTMLNode.h"
11 | #import "HTMLNodeFilter.h"
12 |
13 | HTMLNode * PrecedingNode(HTMLNode *node, HTMLNode *root)
14 | {
15 | HTMLNode *previous = node.previousSibling;
16 | if (previous != nil) {
17 | while (previous.lastChild != nil) {
18 | previous = previous.lastChild;
19 | }
20 | return previous;
21 | }
22 |
23 | if (node == root) {
24 | return nil;
25 | }
26 |
27 | return node.parentNode;
28 | }
29 |
30 | HTMLNode * FollowingNode(HTMLNode *node, HTMLNode *root)
31 | {
32 | if (node.firstChild != nil) {
33 | return node.firstChild;
34 | }
35 |
36 | do {
37 | if (node == root) {
38 | return nil;
39 | }
40 | if (node.nextSibling != nil) {
41 | return node.nextSibling;
42 | }
43 | node = node.parentNode;
44 | } while (node != nil);
45 |
46 | return nil;
47 | }
48 |
49 | HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root)
50 | {
51 | do {
52 | if (node == root) {
53 | return nil;
54 | }
55 | if (node.nextSibling != nil) {
56 | return node.nextSibling;
57 | }
58 | node = node.parentNode;
59 | } while (node != nil);
60 |
61 | return nil;
62 | }
63 |
64 | HTMLNodeFilterValue FilterNode(id filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node)
65 | {
66 | unsigned long nthBit = (1 << (node.nodeType - 1)) & whatToShow;
67 | if (!nthBit) {
68 | return HTMLNodeFilterSkip;
69 | }
70 |
71 | if (filter == nil) {
72 | return HTMLNodeFilterAccept;
73 | }
74 |
75 | return [filter acceptNode:node];
76 | }
77 |
--------------------------------------------------------------------------------
/Sources/HTMLNodeVisitor.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeVisitor.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30.07.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNodeVisitor.h"
10 |
11 | #pragma mark - Block Visitor
12 |
13 | @interface HTMLNodeVisitorBlock ()
14 | {
15 | void (^ _enter)(HTMLNode *);
16 | void (^ _leave)(HTMLNode *);
17 | }
18 | @end
19 |
20 | @implementation HTMLNodeVisitorBlock
21 |
22 | + (instancetype)visitorWithEnterBlock:(void (^)(HTMLNode * _Nonnull))enterBlock
23 | leaveBlock:(void (^)(HTMLNode * _Nonnull))leaveBlock
24 | {
25 | return [[HTMLNodeVisitorBlock alloc] initWithEnterBlock:enterBlock leaveBlock:leaveBlock];
26 | }
27 |
28 | - (instancetype)initWithEnterBlock:(void (^)(HTMLNode * _Nonnull))enterBlock
29 | leaveBlock:(void (^)(HTMLNode * _Nonnull))leaveBlock
30 | {
31 | self = [super init];
32 | if (self) {
33 | _enter = [enterBlock copy];
34 | _leave = [leaveBlock copy];
35 | }
36 | return self;
37 | }
38 |
39 | - (void)enter:(HTMLNode *)node
40 | {
41 | if (_enter) {
42 | _enter(node);
43 | }
44 | }
45 |
46 | - (void)leave:(HTMLNode *)node
47 | {
48 | if (_leave) {
49 | _leave(node);
50 | }
51 | }
52 |
53 | @end
54 |
55 |
--------------------------------------------------------------------------------
/Sources/HTMLParseErrorToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLParseErrorToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLParseErrorToken.h"
10 |
11 | @interface HTMLParseErrorToken ()
12 | {
13 | NSString *_code;
14 | NSString *_details;
15 | NSUInteger _location;
16 | }
17 | @end
18 |
19 | @implementation HTMLParseErrorToken
20 | @synthesize code = _code;
21 | @synthesize details = _details;
22 | @synthesize location = _location;
23 |
24 | - (instancetype)initWithCode:(NSString *)code details:(NSString *)details location:(NSUInteger)location
25 | {
26 | self = [super init];
27 | if (self) {
28 | self.type = HTMLTokenTypeParseError;
29 | _code = [code copy];
30 | _details = [details copy];
31 | _location = location;
32 | }
33 | return self;
34 | }
35 |
36 | - (BOOL)isEqual:(id)other
37 | {
38 | if ([other isKindOfClass:[self class]]) {
39 | HTMLParseErrorToken *token = (HTMLParseErrorToken *)other;
40 | return bothNilOrEqual(self.code, token.code);
41 | }
42 | return NO;
43 | }
44 |
45 | - (NSUInteger)hash
46 | {
47 | return self.code.hash + self.code.hash;
48 | }
49 |
50 | - (NSString *)description
51 | {
52 | return [NSString stringWithFormat:@"<%@: %p Code='%@' Details='%@' Location='%lu'>", self.class, self, _code, _details, (unsigned long)_location];
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/Sources/HTMLQuircksMode.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLQuircksMode.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26.03.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLQuirksMode.h"
11 | #import "NSString+Private.h"
12 |
13 | BOOL QuirksModePrefixMatch(NSString *publicIdentifier)
14 | {
15 | for (int i = 0; i < sizeof(HTMLQuirksModePrefixes) / sizeof(HTMLQuirksModePrefixes[0]); i++) {
16 | if ([publicIdentifier hasPrefixIgnoringCase:HTMLQuirksModePrefixes[i]]) {
17 | return YES;
18 | }
19 | }
20 | return NO;
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/HTMLTemplate.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTemplate.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 12/04/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLTemplate.h"
10 | #import "HTMLDocument.h"
11 | #import "HTMLNode+Private.h"
12 |
13 | @implementation HTMLTemplate
14 |
15 | - (instancetype)init
16 | {
17 | self = [super initWithTagName:@"template"];
18 | return self;
19 | }
20 |
21 | - (void)setOwnerDocument:(HTMLDocument *)ownerDocument
22 | {
23 | [super setOwnerDocument:ownerDocument];
24 | [self.ownerDocument adoptNode:self.content];
25 | }
26 |
27 | - (HTMLDocumentFragment *)content
28 | {
29 | if (_content == nil) {
30 | _content = [[HTMLDocumentFragment alloc] initWithDocument:self.ownerDocument.associatedInertTemplateDocument];
31 | }
32 |
33 | return _content;
34 | }
35 |
36 | - (NSOrderedSet *)childNodes
37 | {
38 | return self.content.childNodes;
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Sources/HTMLText.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLText.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLText.h"
10 | #import "HTMLElement.h"
11 | #import "NSString+Private.h"
12 | #import "HTMLCharacterData+Private.h"
13 | #import "HTMLKitDOMExceptions.h"
14 | #import "HTMLDocument+Private.h"
15 |
16 | @implementation HTMLText
17 |
18 | - (instancetype)init
19 | {
20 | return [self initWithData:@""];
21 | }
22 |
23 | - (instancetype)initWithData:(NSString *)data
24 | {
25 | return [super initWithName:@"#text" type:HTMLNodeText data:data];
26 | }
27 |
28 | - (void)appendString:(NSString *)string
29 | {
30 | [self appendData:string];
31 | }
32 |
33 | NS_INLINE void CheckValidOffset(HTMLNode *node, NSUInteger offset, NSString *cmd)
34 | {
35 | if (offset > node.length) {
36 | [NSException raise:HTMLKitIndexSizeError
37 | format:@"%@: Index Size Error, invalid offset %lu for splitting text node %@.",
38 | cmd, (unsigned long)offset, node];
39 | }
40 | }
41 |
42 | - (HTMLText *)splitTextAtOffset:(NSUInteger)offset
43 | {
44 | CheckValidOffset(self, offset, NSStringFromSelector(_cmd));
45 |
46 | NSUInteger length = self.length;
47 | NSUInteger count = length - offset;
48 | NSRange range = NSMakeRange(offset, count);
49 |
50 | NSString *newData = [self.data substringWithRange:range];
51 | HTMLText *newNode = [[HTMLText alloc] initWithData:newData];
52 | [self.ownerDocument adoptNode:newNode];
53 |
54 | HTMLNode *parent = self.parentNode;
55 | if (parent != nil) {
56 | [parent insertNode:newNode beforeChildNode:self.nextSibling];
57 | [self.ownerDocument didInsertNewTextNode:newNode intoParent:parent afterSplittingTextNode:self atOffset:offset];
58 | }
59 |
60 | [self deleteDataInRange:range];
61 |
62 | if (parent != nil) {
63 | [self.ownerDocument clampRangesAfterSplittingTextNode:self atOffset:offset];
64 | }
65 |
66 | return newNode;
67 | }
68 |
69 | #pragma mark - Description
70 |
71 | - (NSString *)description
72 | {
73 | return [NSString stringWithFormat:@"<%@: %p \"%@\">", self.class, self, self.data];
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/Sources/HTMLToken.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLToken.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 20/09/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLToken.h"
10 |
11 | @interface HTMLToken ()
12 | {
13 | HTMLTokenType _type;
14 | }
15 |
16 | @end
17 |
18 | @implementation HTMLToken
19 | @synthesize type = _type;
20 |
21 | - (BOOL)isDoctypeToken
22 | {
23 | return _type == HTMLTokenTypeDoctype;
24 | }
25 |
26 | - (BOOL)isStartTagToken
27 | {
28 | return _type == HTMLTokenTypeStartTag;
29 | }
30 |
31 | - (BOOL)isEndTagToken
32 | {
33 | return _type == HTMLTokenTypeEndTag;
34 | }
35 |
36 | - (BOOL)isCommentToken
37 | {
38 | return _type == HTMLTokenTypeComment;
39 | }
40 |
41 | - (BOOL)isCharacterToken
42 | {
43 | return _type == HTMLTokenTypeCharacter;
44 | }
45 |
46 | - (BOOL)isEOFToken
47 | {
48 | return _type == HTMLTokenTypeEOF;
49 | }
50 |
51 | - (BOOL)isParseError
52 | {
53 | return _type == HTMLTokenTypeParseError;
54 | }
55 |
56 | - (HTMLDOCTYPEToken *)asDoctypeToken
57 | {
58 | return (HTMLDOCTYPEToken *)self;
59 | }
60 |
61 | - (HTMLTagToken *)asTagToken
62 | {
63 | return (HTMLTagToken *)self;
64 | }
65 |
66 | - (HTMLStartTagToken *)asStartTagToken
67 | {
68 | return (HTMLStartTagToken *)self;
69 | }
70 |
71 | - (HTMLEndTagToken *)asEndTagToken
72 | {
73 | return (HTMLEndTagToken *)self;
74 | }
75 |
76 | - (HTMLCommentToken *)asCommentToken
77 | {
78 | return (HTMLCommentToken *)self;
79 | }
80 |
81 | - (HTMLCharacterToken *)asCharacterToken
82 | {
83 | return (HTMLCharacterToken *)self;
84 | }
85 |
86 | - (HTMLParseErrorToken *)asParseError
87 | {
88 | return (HTMLParseErrorToken *)self;
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/Sources/HTMLTreeVisitor.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTreeVisitor.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30.07.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLTreeVisitor.h"
10 | #import "HTMLNode.h"
11 | #import "HTMLTreeWalker.h"
12 |
13 | @interface HTMLTreeVisitor()
14 | {
15 | HTMLNode *_root;
16 | HTMLTreeWalker *_treeWalker;
17 | }
18 | @end
19 |
20 | @implementation HTMLTreeVisitor
21 |
22 | - (instancetype)initWithNode:(HTMLNode *)node
23 | {
24 | self = [super init];
25 | if (self) {
26 | _root = node;
27 | _treeWalker = [[HTMLTreeWalker alloc] initWithNode:node];
28 | }
29 | return self;
30 | }
31 |
32 | - (void)walkWithNodeVisitor:(id)visitor
33 | {
34 | HTMLNode *currentNode = _treeWalker.currentNode;
35 | while (currentNode) {
36 | [visitor enter:currentNode];
37 | if (currentNode.hasChildNodes) {
38 | currentNode = [_treeWalker firstChild];
39 | continue;
40 | }
41 |
42 | HTMLNode *next = [_treeWalker nextSibling];
43 | if (next) {
44 | [visitor leave:currentNode];
45 | currentNode = next;
46 | continue;
47 | }
48 |
49 | while (!next && _treeWalker.currentNode != _root) {
50 | [visitor leave:_treeWalker.currentNode];
51 | currentNode = [_treeWalker parentNode];
52 | next = [_treeWalker nextSibling];
53 | }
54 | [visitor leave:currentNode];
55 | currentNode = _treeWalker.currentNode;
56 |
57 | if (currentNode == _root) {
58 | break;
59 | }
60 | }
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/Sources/NSCharacterSet+HTMLKit.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSCharacterSet+HTMLKit.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 14/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "NSCharacterSet+HTMLKit.h"
10 |
11 | @implementation NSCharacterSet (HTMLKit)
12 |
13 | + (instancetype)htmlkit_HTMLWhitespaceCharacterSet
14 | {
15 | static NSCharacterSet *set = nil;
16 | static dispatch_once_t onceToken;
17 | dispatch_once(&onceToken, ^{
18 | set = [NSCharacterSet characterSetWithCharactersInString:@" \t\n\r\f"];
19 | });
20 | return set;
21 | }
22 |
23 | + (instancetype)htmlkit_HTMLHexNumberCharacterSet
24 | {
25 | static NSCharacterSet *set = nil;
26 | static dispatch_once_t onceToken;
27 | dispatch_once(&onceToken, ^{
28 | set = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"];
29 | });
30 | return set;
31 | }
32 |
33 | + (instancetype)htmlkit_CSSNthExpressionCharacterSet
34 | {
35 | static NSCharacterSet *set = nil;
36 | static dispatch_once_t onceToken;
37 | dispatch_once(&onceToken, ^{
38 | set = [NSCharacterSet characterSetWithCharactersInString:@" 0123456789nN-+"];
39 | });
40 | return set;
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Sources/NSString+HTMLKit.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+HTMLKit.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "NSString+HTMLKit.h"
10 |
11 | NS_INLINE BOOL isHtmlWhitespaceChar(unichar c)
12 | {
13 | return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r';
14 | }
15 |
16 | @implementation NSString (HTMLKit)
17 |
18 | - (BOOL)htmlkit_isHTMLWhitespaceString
19 | {
20 | return self.htmlkit_leadingHTMLWhitespaceLength == self.length;
21 | }
22 |
23 | - (NSUInteger)htmlkit_leadingHTMLWhitespaceLength
24 | {
25 | size_t idx = 0;
26 | NSUInteger length = self.length;
27 | while (idx < length) {
28 | if (!isHtmlWhitespaceChar([self characterAtIndex:idx])) {
29 | return idx;
30 | }
31 | idx++;
32 | }
33 | return idx;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Sources/NSString+Private.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Private.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26.03.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "NSString+Private.h"
10 |
11 | @implementation NSString (Private)
12 |
13 | - (BOOL)isEqualToStringIgnoringCase:(NSString *)aString
14 | {
15 | return [self caseInsensitiveCompare:aString] == NSOrderedSame;
16 | }
17 |
18 | - (BOOL)isEqualToAny:(NSString *)first, ... NS_REQUIRES_NIL_TERMINATION
19 | {
20 | va_list list;
21 | va_start(list, first);
22 | for (NSString *next = first; next != nil; next = va_arg(list, NSString *)) {
23 | if ([self isEqualToString:next]) {
24 | return YES;
25 | }
26 | }
27 | va_end(list);
28 | return NO;
29 | }
30 |
31 | - (BOOL)hasPrefixIgnoringCase:(NSString *)aString
32 | {
33 | NSRange reange = [self rangeOfString:aString
34 | options:NSAnchoredSearch|NSCaseInsensitiveSearch];
35 | return reange.location != NSNotFound;
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Sources/include/CSSAttributeSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSAttributeSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 14/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelector.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | CSS Attribute Selector.
16 | */
17 | @interface CSSAttributeSelector : CSSSelector
18 |
19 | /**
20 | The selector type.
21 | */
22 | @property (nonatomic, assign, readonly) CSSAttributeSelectorType type;
23 |
24 | /**
25 | The attribute name which should be matched.
26 | */
27 | @property (nonatomic, strong, readonly) NSString *name;
28 |
29 | /**
30 | The attribute value against which should be checked.
31 | */
32 | @property (nonatomic, strong, readonly) NSString *value;
33 |
34 | /**
35 | Intializes and returns a CSS class selector.
36 |
37 | @param className The class name to match.
38 | @return A new instance of class selector.
39 | */
40 | + (instancetype)classSelector:(NSString *)className;
41 |
42 | /**
43 | Intializes and returns a CSS id selector.
44 |
45 | @param elementId The element id to match.
46 | @return A new instance of id selector.
47 | */
48 | + (instancetype)idSelector:(NSString *)elementId;
49 |
50 | /**
51 | Intializes and returns a CSS has-attribute selector.
52 |
53 | @param attributeName The attribute name to match.
54 | @return A new instance of has-attribute selector.
55 | */
56 | + (instancetype)hasAttributeSelector:(NSString *)attributeName;
57 |
58 | /**
59 | Intializes and returns a CSS attribute selector.
60 |
61 | @param type The selector type.
62 | @param name The attribute name to match.
63 | @param value The value to match.
64 | @return A new instance of attribute selector.
65 | */
66 | - (instancetype)initWithType:(CSSAttributeSelectorType)type
67 | attributeName:(NSString *)name
68 | attrbiuteValue:(NSString *)value;
69 |
70 | @end
71 |
72 | NS_ASSUME_NONNULL_END
73 |
--------------------------------------------------------------------------------
/Sources/include/CSSCombinatorSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSCombinatorSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 12/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | CSS Combinator Selector.
15 | */
16 | @interface CSSCombinatorSelector : CSSSelector
17 |
18 | /**
19 | Initializes and returns a CSS child-of-element selector, e.g. 'div > p'
20 |
21 | @param selector The selector matching the parent element.
22 | @return A new instance of the child of element selector.
23 | */
24 | + (instancetype)childOfElementCombinator:(CSSSelector *)selector;
25 |
26 | /**
27 | Initializes and returns a CSS descendant-of-element selector, e.g. 'div p'
28 |
29 | @param selector The selector matching the ancestor element.
30 | @return A new instance of the descendant of element selector.
31 | */
32 | + (instancetype)descendantOfElementCombinator:(CSSSelector *)selector;
33 |
34 | /**
35 | Initializes and returns a CSS adjacent sibling selector, e.g. 'p + a'
36 |
37 | @param selector The selector matching the adjacent sibling element.
38 | @return A new instance of the adjacent sibling selector.
39 | */
40 | + (instancetype)adjacentSiblingCombinator:(CSSSelector *)selector;
41 |
42 | /**
43 | Initializes and returns a CSS general sibling selector, e.g. 'p ~ a'
44 |
45 | @param selector The selector matching the general sibling element.
46 | @return A new instance of the general sibling selector.
47 | */
48 | + (instancetype)generalSiblingCombinator:(CSSSelector *)selector;
49 |
50 | @end
51 |
52 | NS_ASSUME_NONNULL_END
53 |
--------------------------------------------------------------------------------
/Sources/include/CSSCompoundSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSCompoundSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 18/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | A Compound Selector, groups other selectors with a 'all-of' or 'any-of' relationship.
15 | */
16 | @interface CSSCompoundSelector : CSSSelector
17 |
18 | /**
19 | Initializes and returns a new compound selector matching only elements that match all of the specified selectors.
20 |
21 | @param selectors The selectors list.
22 | @return A new instance of the All-Of selector.
23 | */
24 | + (instancetype)andSelector:(NSArray *)selectors;
25 |
26 | /**
27 | Initializes and returns a new compound selector matching all elements that match at least one of the specified selectors.
28 |
29 | @param selectors The selectors list.
30 | @return A new instance of the Any-Of selector.
31 | */
32 | + (instancetype)orSelector:(NSArray *)selectors;
33 |
34 | /**
35 | Add the specified selector to the compound.
36 |
37 | @param selector The selector to add.
38 | */
39 | - (void)addSelector:(CSSSelector *)selector;
40 |
41 | @end
42 |
43 | NS_ASSUME_NONNULL_END
44 |
--------------------------------------------------------------------------------
/Sources/include/CSSInputStream.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSInputStream.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 07/06/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLInputStreamReader.h"
15 |
16 | /**
17 | The CSS Inpute Stream.
18 |
19 | Extends the HTML Input Stream with methods relevant to CSS selectors tokenizing/parsing.
20 | */
21 | @interface CSSInputStream : HTMLInputStreamReader
22 |
23 | /**
24 | Consumes leading whitespace characters.
25 | */
26 | - (void)consumeWhitespace;
27 |
28 | /**
29 | Consumes a CSS identifier.
30 | http://www.w3.org/TR/css-syntax-3/#consume-an-ident-like-token
31 | http://www.w3.org/TR/css-syntax-3/#consume-a-string-token
32 | http://www.w3.org/TR/css-syntax-3/#would-start-an-identifier
33 |
34 | @return A consumed identifier, `nil` if the stream doesn't start with a valid identifier.
35 | */
36 | - (NSString *)consumeIdentifier;
37 |
38 | /**
39 | Consumes characters until the specified code-point is met.
40 |
41 | @param endingCodePoint The code-point at which the input stream stops consuming.
42 | @return The consumed string, `nil` nothing was consumed.
43 | */
44 | - (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint;
45 |
46 | /**
47 | Consumes an escaped code point.
48 | http://www.w3.org/TR/css-syntax-3/#consume-an-escaped-code-point
49 | http://www.w3.org/TR/css-syntax-3/#starts-with-a-valid-escape
50 |
51 | @return The value of the escaped code-point.
52 | */
53 | - (UTF32Char)consumeEscapedCodePoint;
54 |
55 | /**
56 | Consumes a CSS selector combinator.
57 |
58 | @return The consumed combinator, `nil` if nothing was consumed.
59 | */
60 | - (NSString *)consumeCombinator;
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Sources/include/CSSNthExpressionParser.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSNthExpression.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 10/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelectors.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | The Nth-Expression Parser.
16 |
17 | Parses CSS nth-expressions, e.g. '-2n+3', 'odd', ...etc.
18 | */
19 | @interface CSSNthExpressionParser : NSObject
20 |
21 | /**
22 | Parses a CSS nth-exrepssion string.
23 |
24 | @param expression The expression string to parse.
25 | @see CSSNthExpression
26 | */
27 | + (CSSNthExpression)parseExpression:(NSString *)expression;
28 |
29 | @end
30 |
31 | NS_ASSUME_NONNULL_END
32 |
--------------------------------------------------------------------------------
/Sources/include/CSSNthExpressionSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSNthExpressionSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 10/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | CSS Nth-Expression Selector.
15 | */
16 | @interface CSSNthExpressionSelector : CSSSelector
17 |
18 | /**
19 | The pseudo-class name.
20 | */
21 | @property (nonatomic, strong, readonly) NSString *className;
22 |
23 | /**
24 | The nth-expression.
25 |
26 | @see CSSNthExpression
27 | */
28 | @property (nonatomic, assign, readonly) CSSNthExpression expression;
29 |
30 | /**
31 | Initializes a new CSS nth-child selector, e.g. ':nth-child(2n+3)'
32 |
33 | @param expression The nth-expression.
34 | @return Nth-Child selector for the specified expression.
35 |
36 | @see CSSNthExpression
37 | */
38 | + (instancetype)nthChildSelector:(CSSNthExpression)expression;
39 |
40 | /**
41 | Initializes a new CSS nth-last-child selector, e.g. ':nth-last-child(2n+3)'
42 |
43 | @param expression The nth-expression.
44 | @return Nth-Last-Child selector for the specified expression.
45 |
46 | @see CSSNthExpression
47 | */
48 | + (instancetype)nthLastChildSelector:(CSSNthExpression)expression;
49 |
50 | /**
51 | Initializes a new CSS nth-of-type selector, e.g. ':nth-of-type(2n+3)'
52 |
53 | @param expression The nth-expression.
54 | @return Nth-Of-Type selector for the specified expression.
55 |
56 | @see CSSNthExpression
57 | */
58 | + (instancetype)nthOfTypeSelector:(CSSNthExpression)expression;
59 |
60 | /**
61 | Initializes a new CSS nth-last-of-type selector, e.g. ':nth-last-of-type(2n+3)'
62 |
63 | @param expression The nth-expression.
64 | @return Nth-Last-Of-Type selector for the specified expression.
65 |
66 | @see CSSNthExpression
67 | */
68 | + (instancetype)nthLastOfTypeSelector:(CSSNthExpression)expression;
69 |
70 | @end
71 |
72 | NS_ASSUME_NONNULL_END
73 |
--------------------------------------------------------------------------------
/Sources/include/CSSPseudoClassSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSPseudoClassSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 06/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | Base class for CSS Pseudo Class Selectors. This is just a simple named wrapper around another selector.
15 | */
16 | @interface CSSPseudoClassSelector : CSSSelector
17 |
18 | /**
19 | The pseudo-class name.
20 | */
21 | @property (nonatomic, strong, readonly) NSString *className;
22 |
23 | /**
24 | Initializes and return a new pseudo-class selector.
25 |
26 | @param className The pseudo class name.
27 | @param selector The underlying selector.
28 | @return A new instance of a pseudo-class selector.
29 | */
30 | - (instancetype)initWithClassName:(NSString *)className selector:(CSSSelector *)selector;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/Sources/include/CSSPseudoFunctionSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSPseudoFunctionSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 07/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | CSS Pseudo-Function Selector
15 | */
16 | @interface CSSPseudoFunctionSelector : CSSSelector
17 |
18 | /**
19 | Initializes and returns a CSS nagation selector, e.g. ':not(div)'
20 |
21 | @param selector The selector which should be negated.
22 | @return A new instance of the negation selector.
23 | */
24 | + (instancetype)notSelector:(CSSSelector *)selector;
25 |
26 | /**
27 | Initializes and returns a CSS has-descendant selector, e.g. 'div:has(p)'
28 |
29 | @discussion 'div:has(p)' matches all <div> elements which have a descendant <p> element.
30 |
31 | @param selector The selector matching a descendant element.
32 | @return A new instance of the has-descendant selector.
33 | */
34 | + (instancetype)hasSelector:(CSSSelector *)selector;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/Sources/include/CSSSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | #pragma mark - Attribute Selector Type
14 |
15 | /**
16 | Attribute selector type.
17 | */
18 | typedef NS_ENUM(NSUInteger, CSSAttributeSelectorType)
19 | {
20 | /** Attribute exists: '[src]' */
21 | CSSAttributeSelectorExists,
22 |
23 | /** Attribute has exact value: '[title="HTMLKit"]' */
24 | CSSAttributeSelectorExactMatch,
25 |
26 | /** Attribute includes value: '[title~="foo"]' */
27 | CSSAttributeSelectorIncludes,
28 |
29 | /** Attribute's value begins with: '[title^="HTML"]' */
30 | CSSAttributeSelectorBegins,
31 |
32 | /** Attribute's value ends with: '[title$="Kit"]' */
33 | CSSAttributeSelectorEnds,
34 |
35 | /** Attribute's value ends with: '[title*="ML"]' */
36 | CSSAttributeSelectorContains,
37 |
38 | /** Attribute's value ends with: '[title|="en"]' */
39 | CSSAttributeSelectorHyphen,
40 |
41 | /** Attribute's value does not equal: '[title!="foo"]' */
42 | CSSAttributeSelectorNot
43 | };
44 |
45 | #pragma mark - CSS Nth-Expression
46 |
47 | /**
48 | CSS Nth-Expression
49 | */
50 | typedef struct CSSNthExpression
51 | {
52 | NSInteger an;
53 | NSInteger b;
54 | } CSSNthExpression;
55 |
56 | NS_INLINE CSSNthExpression CSSNthExpressionMake(NSInteger an, NSInteger b) {
57 | return (CSSNthExpression){ .an = an, .b = b };
58 | }
59 |
60 | extern const CSSNthExpression CSSNthExpressionOdd;
61 | extern const CSSNthExpression CSSNthExpressionEven;
62 | extern NSString * _Nonnull NSStringFromNthExpression(CSSNthExpression expression);
63 |
64 | #pragma mark - Base Selector Class
65 |
66 | @class HTMLElement;
67 |
68 | /**
69 | Base class for all CSS Selector implementations
70 | */
71 | @interface CSSSelector : NSObject
72 |
73 | /**
74 | Initializes and returns a new instance of CSS Selector.
75 |
76 | @param string The selector string which will be parsed.
77 | @return A new instance of a parsed CSS Selector, `nil` if the string is not a valid selector string.
78 | */
79 | + (nullable instancetype)selectorWithString:(NSString *)string;
80 |
81 | /**
82 | Implementations should override this method to provide the selector-sprecific logic for matching elements.
83 |
84 | @abstract Use one of the concrete subclasses.
85 | */
86 | - (BOOL)acceptElement:(HTMLElement *)element;
87 |
88 | @end
89 |
90 | NS_ASSUME_NONNULL_END
91 |
--------------------------------------------------------------------------------
/Sources/include/CSSSelectorBlock.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelectorBlock.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 20/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelector.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @class HTMLElement;
14 |
15 | /**
16 | A block-based CSS Selector implementation
17 | */
18 | @interface CSSSelectorBlock : CSSSelector
19 |
20 | /**
21 | Initializes and returns a new block-based selector.
22 |
23 | @param name The name of the selector.
24 | @param block The block that should match desired elements.
25 | @return A new instance of the block-based selector.
26 | */
27 | - (instancetype)initWithName:(NSString *)name block:(BOOL (^)(HTMLElement *))block;
28 |
29 | @end
30 |
31 | NS_ASSUME_NONNULL_END
32 |
--------------------------------------------------------------------------------
/Sources/include/CSSSelectorParser.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelectorParser.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/10/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @class CSSSelector;
14 |
15 | /**
16 | The CSS Selectors Parser.
17 |
18 | Parses CSS Level 3 Selectors:
19 | http://www.w3.org/TR/css3-selectors/
20 | */
21 | @interface CSSSelectorParser : NSObject
22 |
23 | /**
24 | Parses a CSS3 selector string.
25 |
26 | @param string The CSS3 selector string.
27 | @param error If an error occurs, upon return contains an `NSError` object that describes the problem.
28 | @return A parsed CSSSelector, `nil` if an error occurred.
29 |
30 | @see CSSelector
31 | */
32 | + (nullable CSSSelector *)parseSelector:(NSString *)string error:(NSError **)error;
33 |
34 | @end
35 |
36 | NS_ASSUME_NONNULL_END
37 |
--------------------------------------------------------------------------------
/Sources/include/CSSTypeSelector.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSTypeSelector.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 13/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelector.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | CSS Type Selector.
16 | */
17 | @interface CSSTypeSelector : CSSSelector
18 |
19 | /**
20 | The type of elements being matched.
21 | */
22 | @property (nonatomic, strong, readonly) NSString *type;
23 |
24 | /**
25 | Returns the universal selector.
26 |
27 | @return A new instance of a universal selector that matches all elements.
28 | */
29 | + (instancetype)universalSelector;
30 |
31 | /**
32 | Initializes a new selector for the specified type.
33 |
34 | @param type The type of elements that should be matched.
35 | @return A new instance of a type selector.
36 | */
37 | - (instancetype)initWithType:(NSString *)type;
38 |
39 | @end
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/Sources/include/HTMLCharacterData+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCharacterData+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26/11/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLCharacterData.h"
10 | #import "HTMLNode.h"
11 |
12 | /**
13 | Private HTML Character Data methods which are not intended for public API.
14 | */
15 | @interface HTMLCharacterData ()
16 |
17 | /**
18 | Designated initializer of the HTML CharacterData, which, however, should not be used directly. It is intended to be
19 | called only by subclasses, i.e. HTMLText and HTMLComment.
20 |
21 | @param name The node's name.
22 | @param type The node's type.
23 | @param data The node's data string.
24 | @return A new instance of a HTML CharacterData.
25 | */
26 | - (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type data:(NSString *)data NS_DESIGNATED_INITIALIZER;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Sources/include/HTMLCharacterData.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCharacterData.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26/11/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNode.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | A HTML CharacterData
15 |
16 | https://dom.spec.whatwg.org/#characterdata
17 | */
18 | @interface HTMLCharacterData : HTMLNode
19 |
20 | /** @brief The associated data string. */
21 | @property (nonatomic, copy, readonly) NSString *data;
22 |
23 | - (void)setData:(NSString *)data;
24 | - (void)appendData:(NSString *)data;
25 | - (void)insertData:(NSString *)data atOffset:(NSUInteger)offset;
26 | - (void)deleteDataInRange:(NSRange)range;
27 | - (void)replaceDataInRange:(NSRange)range withData:(NSString *)data;
28 | - (NSString *)substringDataWithRange:(NSRange)range;
29 |
30 | @end
31 |
32 | NS_ASSUME_NONNULL_END
33 |
--------------------------------------------------------------------------------
/Sources/include/HTMLCharacterToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCharacterToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 |
16 | /**
17 | HTML Character Token
18 | */
19 | @interface HTMLCharacterToken : HTMLToken
20 |
21 | /** @brief The characters in this token. */
22 | @property (nonatomic, copy) NSString *characters;
23 |
24 | /**
25 | Initializes a new character token.
26 |
27 | @param string The string with which to initialize the token.
28 | @return A new instance of a character token.
29 | */
30 | - (instancetype)initWithString:(NSString *)string;
31 |
32 | /**
33 | Appends the given string to this token.
34 |
35 | @param string The string to append.
36 | */
37 | - (void)appendString:(NSString *)string;
38 |
39 | /**
40 | Checks whether this token is a whitespace character token.
41 |
42 | @discussion HTML whitespace characters are: CHARACTER TABULATION U+0009, LINE FEED U+000A, FORM FEED U+000C,
43 | CARRIAGE RETURN U+000D, and SPACE U+0020
44 |
45 | @return `YES` if this token contains only whitespace characters, `NO` otherwise.
46 | */
47 | - (BOOL)isWhitespaceToken;
48 |
49 | /**
50 | Checks whether this token is empty.
51 |
52 | @return `YES` if this token is empty, `NO` otherwise.
53 | */
54 | - (BOOL)isEmpty;
55 |
56 | /**
57 | Retains all leading whitespace characters in this token.
58 | */
59 | - (void)retainLeadingWhitespace;
60 |
61 | /**
62 | Trims all leading whitespace characters in this token.
63 | */
64 | - (void)trimLeadingWhitespace;
65 |
66 | /**
67 | Trims the characters in this token from a given index
68 |
69 | @param index The start index from which to trim the token.
70 | */
71 | - (void)trimFormIndex:(NSUInteger)index;
72 |
73 | /**
74 | Splits this token retaining only characters after the leading whitespace. The leading whitespace characters are then
75 | returned a new characters token.
76 |
77 | @return A characters token with leading whitespace characters. Returns 'nil` if no leading whitespace exists.
78 | */
79 | - (HTMLCharacterToken *)tokenBySplitingLeadingWhiteSpace;
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/Sources/include/HTMLComment.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLComment.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLCharacterData.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | A HTML Comment node
15 | */
16 | @interface HTMLComment : HTMLCharacterData
17 |
18 | /**
19 | Decalration override for `NS_UNAVAILABLE` declared in `HTMLNode`
20 | */
21 | - (instancetype)init;
22 |
23 | /**
24 | Initializes a new HTML comment node.
25 |
26 | @param data The comment string.
27 | @return A new isntance of a HTML comment node.
28 | */
29 | - (instancetype)initWithData:(NSString *)data;
30 |
31 | @end
32 |
33 | NS_ASSUME_NONNULL_END
34 |
--------------------------------------------------------------------------------
/Sources/include/HTMLCommentToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLCommentToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 |
16 | /**
17 | HTML Comment Token
18 | */
19 | @interface HTMLCommentToken : HTMLToken
20 |
21 | /** @brief The comment string in this token. */
22 | @property (nonatomic, copy) NSString *data;
23 |
24 | /**
25 | Initializes a new comment token.
26 |
27 | @param data The string with which to initialize the token.
28 | @return A new instance of a comment token.
29 | */
30 | - (instancetype)initWithData:(NSString *)data;
31 |
32 | /**
33 | Appends the given string to this token.
34 |
35 | @param string The string to append.
36 | */
37 | - (void)appendStringToData:(NSString *)string;
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Sources/include/HTMLDOCTYPEToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDOCTYPEToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 |
16 | /**
17 | HTML DOCTYPE Token
18 | */
19 | @interface HTMLDOCTYPEToken : HTMLToken
20 |
21 | /** @brief The DOCTYPE's name. */
22 | @property (nonatomic, copy) NSString *name;
23 |
24 | /** @brief The DOCTYPE's public identifier. */
25 | @property (nonatomic, strong) NSMutableString *publicIdentifier;
26 |
27 | /** @brief The DOCTYPE's system identifier. */
28 | @property (nonatomic, strong) NSMutableString *systemIdentifier;
29 |
30 | /** @brief Flag whether this DOCTYPE forces quirks mode. */
31 | @property (nonatomic, assign) BOOL forceQuirks;
32 |
33 | /**
34 | Initializes a new DOCTYPE token.
35 |
36 | @param name The name with which to initialize the token.
37 | @return A new instance of a DOCTYPE token.
38 | */
39 | - (instancetype)initWithName:(NSString *)name;
40 |
41 | /**
42 | Appends the given string to this DOCTYPE's name.
43 |
44 | @param string The string to append.
45 | */
46 | - (void)appendStringToName:(NSString *)string;
47 |
48 | /**
49 | Appends the given string to this DOCTYPE's public identifier.
50 |
51 | @param string The string to append.
52 | */
53 | - (void)appendStringToPublicIdentifier:(NSString *)string;
54 |
55 | /**
56 | Appends the given string to this DOCTYPE's system identifier.
57 |
58 | @param string The string to append.
59 | */
60 | - (void)appendStringToSystemIdentifier:(NSString *)string;
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Sources/include/HTMLDOM.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodes.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNode.h"
10 | #import "HTMLDocument.h"
11 | #import "HTMLDocumentType.h"
12 | #import "HTMLDocumentFragment.h"
13 | #import "HTMLElement.h"
14 | #import "HTMLCharacterData.h"
15 | #import "HTMLComment.h"
16 | #import "HTMLText.h"
17 | #import "HTMLTemplate.h"
18 | #import "HTMLRange.h"
19 | #import "HTMLDOMTokenList.h"
20 | #import "HTMLNodeIterator.h"
21 | #import "HTMLTreeVisitor.h"
22 | #import "HTMLTreeWalker.h"
23 | #import "HTMLNodeFilter.h"
24 |
25 | #import "HTMLKitDOMExceptions.h"
26 | #import "HTMLNamespaces.h"
27 | #import "HTMLQuirksMode.h"
28 |
29 | #import "HTMLOrderedDictionary.h"
30 |
--------------------------------------------------------------------------------
/Sources/include/HTMLDOMUtils.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDOMUtils.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 03/12/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLDOM.h"
11 |
12 | @class HTMLNode;
13 |
14 | extern HTMLNode * GetCommonAncestorContainer(HTMLNode *nodeA, HTMLNode *nodeB);
15 | extern NSArray * GetAncestorNodes(HTMLNode *node);
16 |
--------------------------------------------------------------------------------
/Sources/include/HTMLDocumentFragment.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDocumentFragment.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 12/04/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNode.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | A HTML Document Fragment. Represents a minimal document object that has no parent. It is used as a light-weight
15 | version of Document
16 |
17 | https://dom.spec.whatwg.org/#interface-documentfragment
18 | */
19 | @interface HTMLDocumentFragment : HTMLNode
20 |
21 | /**
22 | Decalration override for `NS_UNAVAILABLE` declared in `HTMLNode`
23 | */
24 | - (instancetype)init;
25 |
26 | /**
27 | Initializes a new document fragment with the given document as owner.
28 |
29 | @param document The owner document.
30 | @return A new instance of a document fragment.
31 | */
32 | - (instancetype)initWithDocument:(nullable HTMLDocument *)document;
33 |
34 | @end
35 |
36 | NS_ASSUME_NONNULL_END
37 |
--------------------------------------------------------------------------------
/Sources/include/HTMLDocumentType.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLDocumentType.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNode.h"
10 | #import "HTMLQuirksMode.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | A HTML Document Type node. There is only one valid document type, which is ``.
16 |
17 | Other DOCTYPES, e.g.
18 | are obsolete but permitted.
19 |
20 | https://dom.spec.whatwg.org/#interface-documenttype
21 | */
22 | @interface HTMLDocumentType : HTMLNode
23 |
24 | /**
25 | The public identifier
26 | */
27 | @property (nonatomic, copy, readonly) NSString *publicIdentifier;
28 |
29 | /**
30 | The system identifier
31 | */
32 | @property (nonatomic, copy, readonly) NSString *systemIdentifier;
33 |
34 | /**
35 | Decalration override for `NS_UNAVAILABLE` declared in `HTMLNode`
36 | */
37 | - (instancetype)init;
38 |
39 | /**
40 | Initializes and returns a new isntance of a Document Type node.
41 |
42 | @param name The name.
43 | @param publicIdentifier The public identifier.
44 | @param systemIdentifier The system identigier
45 | @return A new document type instance.
46 | */
47 | - (instancetype)initWithName:(NSString *)name
48 | publicIdentifier:(nullable NSString *)publicIdentifier
49 | systemIdentifier:(nullable NSString *)systemIdentifier;
50 |
51 | /**
52 | Checks whether this DOCTYPE is valid.
53 |
54 | @return `YES` if this is a valid DOCTYPE, `NO` otherwise.
55 | */
56 | - (BOOL)isValid;
57 |
58 | /**
59 | Return the quirks mode of this DOCTYPE.
60 |
61 | @return The quirks mode.
62 |
63 | @see HTMLQuirksMode
64 | */
65 | - (HTMLQuirksMode)quirksMode;
66 |
67 | @end
68 |
69 | NS_ASSUME_NONNULL_END
70 |
--------------------------------------------------------------------------------
/Sources/include/HTMLEOFToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLEOFToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 15/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import "HTMLToken.h"
14 |
15 | /**
16 | A HTML EOF Token.
17 | */
18 | @interface HTMLEOFToken : HTMLToken
19 |
20 | /** Returns the singleton instance of the EOF Token. */
21 | + (instancetype)token;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Sources/include/HTMLElementTypes.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLElementTypes.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 19/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import "HTMLNode+Private.h"
14 | #import "HTMLElement.h"
15 | #import "HTMLNamespaces.h"
16 | #import "NSString+Private.h"
17 |
18 | NS_INLINE BOOL IsNodeMathMLTextIntegrationPoint(HTMLElement *node)
19 | {
20 | return (node.htmlNamespace == HTMLNamespaceMathML && [node.tagName isEqualToAny:@"mi", @"mo", @"mn", @"ms", @"mtext", nil]);
21 | }
22 |
23 | NS_INLINE BOOL IsNodeHTMLIntegrationPoint(HTMLElement *node)
24 | {
25 | if (node.htmlNamespace == HTMLNamespaceMathML && [node.tagName isEqualToString:@"annotation-xml"]) {
26 | NSString *encoding = node.attributes[@"encoding"];
27 | return [encoding isEqualToStringIgnoringCase:@"text/html"] || [encoding isEqualToStringIgnoringCase:@"application/xhtml+xml"];
28 | } else if (node.htmlNamespace == HTMLNamespaceSVG) {
29 | return [node.tagName isEqualToAny:@"foreignObject", @"desc", @"title", nil];
30 | }
31 | return NO;
32 | }
33 |
34 | NS_INLINE BOOL IsSpecialElement(HTMLElement *element)
35 | {
36 | if (element.htmlNamespace == HTMLNamespaceHTML) {
37 | return [element.tagName isEqualToAny:@"address", @"applet", @"area", @"article",
38 | @"aside", @"base", @"basefont", @"bgsound", @"blockquote", @"body", @"br",
39 | @"button", @"caption", @"center", @"col", @"colgroup", @"dd", @"details",
40 | @"dir", @"div", @"dl", @"dt", @"embed", @"fieldset", @"figcaption",
41 | @"figure", @"footer", @"form", @"frame", @"frameset", @"h1", @"h2", @"h3",
42 | @"h4", @"h5", @"h6", @"head", @"header", @"hgroup", @"hr", @"html", @"iframe",
43 | @"img", @"input", @"li", @"link", @"listing", @"main", @"marquee",
44 | @"menu", @"meta", @"nav", @"noembed", @"noframes", @"noscript",
45 | @"object", @"ol", @"p", @"param", @"plaintext", @"pre", @"script", @"section",
46 | @"select", @"source", @"style", @"summary", @"table", @"tbody", @"td",
47 | @"template", @"textarea", @"tfoot", @"th", @"thead", @"title", @"tr",
48 | @"track", @"ul", @"wbr", @"xmp", nil];
49 | } else if (element.htmlNamespace == HTMLNamespaceMathML) {
50 | return [element.tagName isEqualToAny:@"mi", @"mo", @"mn", @"ms", @"mtext", @"annotation-xml", nil];
51 | } else if (element.htmlNamespace == HTMLNamespaceSVG) {
52 | return [element.tagName isEqualToAny:@"foreignObject", @"desc", @"title", nil];
53 | }
54 | return NO;
55 | }
56 |
57 | NS_INLINE BOOL DoesNodeSerializeAsVoid(HTMLNode *node)
58 | {
59 | if (node.nodeType != HTMLNodeElement) {
60 | return false;
61 | }
62 |
63 | return [node.asElement.tagName isEqualToAny:@"area", @"base", @"basefont", @"bgsound", @"br", @"col", @"embed",
64 | @"frame", @"hr", @"img", @"input", @"keygen", @"link", @"meta", @"param", @"source", @"track", @"wbr", nil];
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/Sources/include/HTMLKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKit.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 15/09/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for HTMLKit.
12 | extern double HTMLKitVersionNumber;
13 |
14 | //! Project version string for HTMLKit.
15 | extern const unsigned char HTMLKitVersionString[];
16 |
17 | #import "HTMLDOM.h"
18 | #import "HTMLParser.h"
19 | #import "HTMLSerializer.h"
20 | #import "HTMLKitErrorDomain.h"
21 | #import "HTMLOrderedDictionary.h"
22 |
23 | #import "CSSSelectors.h"
24 | #import "CSSSelectorParser.h"
25 | #import "CSSNthExpressionParser.h"
26 |
27 | #import "NSString+HTMLKit.h"
28 | #import "NSCharacterSet+HTMLKit.h"
29 |
--------------------------------------------------------------------------------
/Sources/include/HTMLKitDOMExceptions.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitExceptions.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 17/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | extern NSString * const HTMLKitHierarchyRequestError;
12 | extern NSString * const HTMLKitNotFoundError;
13 | extern NSString * const HTMLKitNotSupportedError;
14 |
15 | extern NSString * const HTMLKitSyntaxError;
16 | extern NSString * const HTMLKitInvalidCharacterError;
17 |
18 | extern NSString * const HTMLKitInvalidNodeTypeError;
19 | extern NSString * const HTMLKitIndexSizeError;
20 | extern NSString * const HTMLKitWrongDocumentError;
21 | extern NSString * const HTMLKitInvalidStateError;
22 |
--------------------------------------------------------------------------------
/Sources/include/HTMLKitErrorDomain.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitErrorDomain.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 24/11/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #ifndef HTMLKitErrorDomain_h
10 | #define HTMLKitErrorDomain_h
11 |
12 | static NSString *const HTMLKitErrorDomain = @"HTMLKit";
13 | static NSString *const HTMLKitSelectorErrorDomain = @"HTMLKitSelector";
14 |
15 | static NSString *const CSSSelectorStringKey = @"CSSSelectorString";
16 | static NSString *const CSSSelectorErrorLocationKey = @"CSSSelectorErrorLocation";
17 |
18 | NS_ENUM(NSInteger)
19 | {
20 | HTMLKitSelectorParseError = 4200
21 | };
22 |
23 | #endif /* HTMLKitErrorDomain_h */
24 |
--------------------------------------------------------------------------------
/Sources/include/HTMLMarker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLMarker.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 |
15 | /**
16 | A Maker that is used in the List of Active Formatting Elements.
17 |
18 | @see HTMLListOfActiveFormattingElements
19 | */
20 | @interface HTMLMarker : NSObject
21 |
22 | /**
23 | Returns the singleton instance of the Marker.
24 | */
25 | + (instancetype)marker;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNamespaces.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNamespaces.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 03/11/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | /**
10 | HTML Namespaces
11 | https://html.spec.whatwg.org/multipage/infrastructure.html#namespaces
12 | */
13 | typedef NS_ENUM(NSInteger, HTMLNamespace)
14 | {
15 | /** The default HTML namespace. */
16 | HTMLNamespaceHTML,
17 |
18 | /** The namespace for most of the elements. */
19 | HTMLNamespaceMathML,
20 |
21 | /** The namespace for most of the elements. */
22 | HTMLNamespaceSVG
23 | };
24 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNode+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNode+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 20/12/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import "HTMLNode.h"
14 |
15 | @class HTMLText;
16 | @class HTMLComment;
17 | @class HTMLDocumentType;
18 |
19 | /**
20 | Private HTML Node methods which are not intended for public API.
21 | */
22 | @interface HTMLNode ()
23 |
24 | /**
25 | A read-write redeclaration of the same property in the public API.
26 | */
27 | @property (nonatomic, weak) HTMLDocument *ownerDocument;
28 |
29 | /**
30 | A read-write redeclaration of the same property in the public API.
31 | */
32 | @property (nonatomic, weak) HTMLNode *parentNode;
33 |
34 | /**
35 | Designated initializer of the HTML Node, which, however, should not be used directly. It is intended to be called only
36 | by subclasses.
37 |
38 | @abstract Use concrete subclasses of the HTML Node.
39 |
40 | @param name The node's name.
41 | @param type The node's type.
42 | @return A new instance of a HTML Node.
43 | */
44 | - (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type NS_DESIGNATED_INITIALIZER;
45 |
46 | /**
47 | Casts this node to a HTML Element. This cast should only be performed after the appropriate check.
48 | */
49 | - (HTMLElement *)asElement;
50 |
51 | /**
52 | Casts this node to a HTML Text. This cast should only be performed after the appropriate check.
53 | */
54 | - (HTMLText *)asText;
55 |
56 | /**
57 | Casts this node to a HTML Comment. This cast should only be performed after the appropriate check.
58 | */
59 | - (HTMLComment *)asComment;
60 |
61 | /**
62 | Casts this node to a HTML Document Type. This cast should only be performed after the appropriate check.
63 | */
64 | - (HTMLDocumentType *)asDocumentType;
65 |
66 | /**
67 | Returns the same string representation of the DOM tree rooted at this node that is used by html5lib-tests.
68 |
69 | @disucssion This method is indended for testing purposes.
70 | */
71 | - (NSString *)treeDescription;
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNodeFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeFilter.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | The node filter's value when applied to a given HTML node. The node filter can either accept a node, skip it, or
15 | reject it. Rejecting a node means skipping the node itself and all of it descendants.
16 | */
17 | typedef NS_ENUM(unsigned short, HTMLNodeFilterValue)
18 | {
19 | HTMLNodeFilterAccept = 1,
20 | HTMLNodeFilterReject = 2,
21 | HTMLNodeFilterSkip = 3
22 | };
23 |
24 | /**
25 | The show options for the HTML node iterator and tree walker.
26 |
27 | @see HTMLNodeIterator
28 | @see HTMLTreeWalker
29 | */
30 | typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions)
31 | {
32 | HTMLNodeFilterShowAll = 0xFFFFFFFF,
33 | HTMLNodeFilterShowElement = 0x1,
34 | HTMLNodeFilterShowText = 0x4,
35 | HTMLNodeFilterShowComment = 0x80,
36 | HTMLNodeFilterShowDocument = 0x100,
37 | HTMLNodeFilterShowDocumentType = 0x200,
38 | HTMLNodeFilterShowDocumentFragment = 0x400
39 | };
40 |
41 |
42 | #pragma mark - Node Filter
43 |
44 | @class HTMLNode;
45 |
46 | /**
47 | A HTML Node Filter which can be used with a node iterator or a tree walker.
48 |
49 | @see HTMLNodeIterator
50 | @see HTMLTreeWalker
51 | */
52 | @protocol HTMLNodeFilter
53 | @required
54 | /**
55 | The implementation should return a HTMLNodeFilterValue to indicate accepting, skipping or rejecting a node.
56 |
57 | @param node The node to be filtered.
58 | @return `HTMLNodeFilterAccept` if accepted, `HTMLNodeFilterSkip` if skipped, or `HTMLNodeFilterReject` if rejected.
59 | */
60 | - (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node;
61 |
62 | @end
63 |
64 | #pragma mark - Block Filter
65 |
66 | /**
67 | A concrete block-based HTML Node Filter implementation.
68 | */
69 | @interface HTMLNodeFilterBlock : NSObject
70 |
71 | /**
72 | Initializes and returns a new instance of this filter.
73 |
74 | @param block The block to apply on each node to be filtered.
75 | */
76 | + (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))block;
77 |
78 | @end
79 |
80 | #pragma mark - CSS Selector Filter
81 |
82 | @class CSSSelector;
83 |
84 | /**
85 | A concrete css-selector-based HTML Node Filter implementation.
86 | */
87 | @interface HTMLSelectorNodeFilter : NSObject
88 |
89 | /**
90 | Initializes and returns a new instance of this filter.
91 |
92 | @param selector The selector to apply on each node to be filtered.
93 | */
94 | + (instancetype)filterWithSelector:(CSSSelector *)selector;
95 |
96 | @end
97 |
98 | NS_ASSUME_NONNULL_END
99 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNodeIterator+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeIterator+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/11/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLNodeIterator.h"
10 | #import "HTMLNode.h"
11 |
12 | /**
13 | Private HTML Node Iterator methods which are not intended for public API.
14 | */
15 | @interface HTMLNodeIterator (Private)
16 |
17 | /**
18 | Runs the necessary steps after removing a node from the DOM.
19 |
20 | @param oldNode The old node that was removed.
21 | @param oldParent The old parent of the node that was removed.
22 | @param oldPreviousSibling The old previous sibling node of the node that was removed.
23 | */
24 | - (void)runRemovingStepsForNode:(HTMLNode *)oldNode
25 | withOldParent:(HTMLNode *)oldParent
26 | andOldPreviousSibling:(HTMLNode *)oldPreviousSibling;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNodeIterator.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeIterator.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLNodeFilter.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @class HTMLNode;
15 |
16 | /**
17 | A HTML Node Iterator, which iterates the nodes in the DOM in tree order, i.e. depth-first traversal of the tree.
18 |
19 | https://dom.spec.whatwg.org/#interface-nodeiterator
20 | */
21 | @interface HTMLNodeIterator : NSEnumerator
22 |
23 | /**
24 | The root element of this iterator, i.e. the traversed tree is rooted at this element.
25 | */
26 | @property (nonatomic, strong, readonly) HTMLNode *root;
27 |
28 | /**
29 | The current reference node.
30 | */
31 | @property (nonatomic, strong, readonly) HTMLNode *referenceNode;
32 |
33 | /**
34 | Whether the iterator's pointer is before the reference node.
35 | */
36 | @property (nonatomic, assign, readonly) BOOL pointerBeforeReferenceNode;
37 |
38 | /**
39 | The iterator's show options. These options control what types of elements are shown or skipped during iteration.
40 |
41 | @see HTMLNodeFilterShowOptions
42 | */
43 | @property (nonatomic, assign, readonly) HTMLNodeFilterShowOptions whatToShow;
44 |
45 | /**
46 | A node filter, that is applied to each node during iteration.
47 |
48 | @see HTMLNodeFilter
49 | */
50 | @property (nonatomic, strong, readonly, nullable) id filter;
51 |
52 |
53 | /**
54 | Initializes a new node iterator with no filter and HTMLNodeFilterShowAll show options.
55 |
56 | @param node The root node.
57 | @return A new instance of a node iterator.
58 | */
59 | - (instancetype)initWithNode:(HTMLNode *)node;
60 |
61 | /**
62 | Initializes a new node iterator with HTMLNodeFilterShowAll show options.
63 |
64 | @param node The root node.
65 | @param filter The node filter to use.
66 | @return A new instance of a node iterator.
67 | */
68 | - (instancetype)initWithNode:(HTMLNode *)node
69 | filter:(nullable id)filter;
70 |
71 | /**
72 | Initializes a new node iterator.
73 |
74 | @param node The root node.
75 | @param showOptions The show options for the iterator.
76 | @param filter The node filter to use.
77 | @return A new instance of a node iterator.
78 | */
79 | - (instancetype)initWithNode:(HTMLNode *)node
80 | showOptions:(HTMLNodeFilterShowOptions)showOptions
81 | filter:(nullable id)filter;
82 |
83 | /**
84 | @return The next iterated node in tree order, `nil` if there are no more nodes to iterate.
85 | */
86 | - (nullable HTMLNode *)nextNode;
87 |
88 | /**
89 | @return The previous iterated node in tree order, `nil` if there are no more nodes to iterate.
90 | */
91 | - (nullable HTMLNode *)previousNode;
92 |
93 | @end
94 |
95 | NS_ASSUME_NONNULL_END
96 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNodeTraversal.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeTraversal.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 05/06/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLNodeFilter.h"
15 |
16 | @class HTMLNode;
17 |
18 | extern HTMLNode * PrecedingNode(HTMLNode *node, HTMLNode *root);
19 | extern HTMLNode * FollowingNode(HTMLNode *node, HTMLNode *root);
20 | extern HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root);
21 | extern HTMLNodeFilterValue FilterNode(id filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node);
22 |
--------------------------------------------------------------------------------
/Sources/include/HTMLNodeVisitor.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLNodeVisitor.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30.07.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @class HTMLNode;
14 |
15 | #pragma mark - Node Visitor
16 |
17 | /**
18 | A HTML Node Visitor which can be used with a tree visitor.
19 |
20 | @see HTMLTreeVisitor
21 | */
22 | @protocol HTMLNodeVisitor
23 | @required
24 |
25 | /**
26 | Called when visiting the node for the first time
27 |
28 | @param node The node that is beaing visited for the first time.
29 | */
30 | - (void)enter:(HTMLNode *)node;
31 |
32 | /**
33 | Called when leaving a previously entered node, i.e. when all its child nodes are visited.
34 |
35 | @param node The node that beaing leaved.
36 | */
37 | - (void)leave:(HTMLNode *)node;
38 |
39 | @end
40 |
41 | #pragma mark - Block Node Visitor
42 |
43 | /**
44 | A concrete block-based HTML Node Visitor implementation.
45 | */
46 | @interface HTMLNodeVisitorBlock : NSObject
47 |
48 | /**
49 | Initializes and returns a new instance of this visitor.
50 |
51 | @param enterBlock The block to apply on entering a visited node.
52 | @param leaveBlock The block to apply on leaving a visited node.
53 | */
54 | + (instancetype)visitorWithEnterBlock:(void (^)(HTMLNode *node))enterBlock
55 | leaveBlock:(void (^)(HTMLNode *node))leaveBlock;
56 |
57 | @end
58 |
59 | NS_ASSUME_NONNULL_END
60 |
--------------------------------------------------------------------------------
/Sources/include/HTMLOrderedDictionary.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLOrderedDictionary.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 14/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | An ordered mutable dictionary, that preserves the order of its keys.
15 | */
16 | @interface HTMLOrderedDictionary : NSMutableDictionary
17 |
18 | /**
19 | Returns the object at the specified index.
20 |
21 | @param index An index within the bounds of the dictionary.
22 | @return The object located at index.
23 | */
24 | - (ObjectType)objectAtIndex:(NSUInteger)index;
25 |
26 | /**
27 | Sets the object for the given key at the specified index.
28 |
29 | @param anObject The object.
30 | @param aKey The key.
31 | @param index An index within the bounds of the dictionary.
32 | */
33 | - (void)setObject:(ObjectType)anObject forKey:(KeyType)aKey atIndex:(NSUInteger)index;
34 |
35 | /**
36 | Removes the key-value pair located at the specified index.
37 |
38 | @param index An index within the bounds of the dictionary.
39 | */
40 | - (void)removeObjectAtIndex:(NSUInteger)index;
41 |
42 | /**
43 | Replaces the key-value pair located at the specified index.
44 |
45 | @param index An index within the bounds of the dictionary.
46 | @param anObject The new object.
47 | @param aKey The new key.
48 | */
49 | - (void)replaceKeyValueAtIndex:(NSUInteger)index withObject:(ObjectType)anObject andKey:(KeyType)aKey;
50 |
51 | /**
52 | Replaces a key keeping the same object.
53 |
54 | @param aKey The old key to replace.
55 | @param newKey The new key.
56 | */
57 | - (void)replaceKey:(KeyType)aKey withKey:(KeyType)newKey;
58 |
59 | /**
60 | Returns the index of the given key in the dictionary.
61 |
62 | @param aKey The key.
63 | @return The index of the given key in the dictionary.
64 | */
65 | - (NSUInteger)indexOfKey:(KeyType)aKey;
66 |
67 | /**
68 | Returns the object at the specified index.
69 |
70 | @param index An index within the bounds of the dictionary.
71 | @return The object located at index.
72 | */
73 | - (ObjectType)objectAtIndexedSubscript:(NSUInteger)index;
74 |
75 | /**
76 | Replaces the object at the index with the new object.
77 |
78 | @param obj The obj with which to replace the object at given index in the dictionary.
79 | @param index The index of the object to be replaced.
80 | */
81 | - (void)setObject:(ObjectType)obj atIndexedSubscript:(NSUInteger)index;
82 |
83 | /**
84 | @return A reverse key enumerator.
85 | */
86 | - (NSEnumerator *)reverseKeyEnumerator;
87 |
88 | @end
89 |
90 | NS_ASSUME_NONNULL_END
91 |
--------------------------------------------------------------------------------
/Sources/include/HTMLParseErrorToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLParseErrorToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 |
16 | /**
17 | HTML Parse Error Token
18 | */
19 | @interface HTMLParseErrorToken : HTMLToken
20 |
21 | /** @brief The parse error's code as specified at https://html.spec.whatwg.org/multipage/parsing.html#parse-errors. */
22 | @property (nonatomic, strong, readonly) NSString *code;
23 |
24 | /** @brief Additional detailed error information. */
25 | @property (nonatomic, strong, readonly) NSString *details;
26 |
27 | /** @brief The error's location in the stream. */
28 | @property (nonatomic, assign, readonly) NSUInteger location;
29 |
30 | /**
31 | Initializes a new Parse Error token.
32 |
33 | @param code The parse error's as specified at https://html.spec.whatwg.org/multipage/parsing.html#parse-errors.
34 | @param location The error's location in the stream.
35 | @return A new instance of a parse error token.
36 | */
37 | - (instancetype)initWithCode:(NSString *)code details:(NSString *)details location:(NSUInteger)location;
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Sources/include/HTMLParser+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTLMLParser+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/11/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLParser.h"
10 | #import "HTMLElement.h"
11 |
12 | /**
13 | Private HTML Parser properties & methods which are not intended for public API.
14 | */
15 | @interface HTMLParser (Private)
16 |
17 | /**
18 | The adjusted current node in the context of HTML parsing as described in:
19 | https://html.spec.whatwg.org/#adjusted-current-node
20 | */
21 | @property (nonatomic, strong, readonly) HTMLElement *adjustedCurrentNode;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Sources/include/HTMLParser.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLParser.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 04/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLElement.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | The HTML Parser.
16 | Parses HTML strings to valid HTML documents and/or fragments. This parser implements the WHATWG specification:
17 | https://html.spec.whatwg.org/multipage/syntax.html#tree-construction
18 |
19 | @see HTMLDocument
20 | @see HTMLElement
21 | */
22 | @interface HTMLParser : NSObject
23 |
24 | /**
25 | An array of errors that occurred during document parsing.
26 | */
27 | @property (nonatomic, strong, readonly) NSArray *parseErrors;
28 |
29 | /**
30 | The parsed HTML Document.
31 |
32 | @see HTMLDocument
33 | */
34 | @property (nonatomic, strong, readonly) HTMLDocument *document;
35 |
36 | /**
37 | Intializes a new parser instance with a given HTML string.
38 |
39 | @discussion The parser assumes a UTF-8 encoded string and does not implement the encoding sniffing algorithm that is
40 | described under the following section of the specification:
41 | https://html.spec.whatwg.org/multipage/syntax.html#determining-the-character-encoding
42 |
43 | @param string The HTML string to parse
44 | @return A new instance of the HTML parser.
45 | */
46 | - (instancetype)initWithString:(NSString *)string;
47 |
48 | /**
49 | Runs the parsing algorithm and generates a valid HTML document object.
50 |
51 | @return A HTML document object that is the result of parsing the HTML string, with which this parser instance was
52 | initialized
53 |
54 | @see HTMLDocument
55 | */
56 | - (HTMLDocument *)parseDocument;
57 |
58 | /**
59 | Runs the HTML fragment parsing algorithm with the provided context element. The algorithm is sprecified under the
60 | following section: https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
61 |
62 | @discussion The fragment parsing algorithm can be run multiple times with different context elements on the same parser
63 | instance. In this case the parser will reset its internal state and re-run the parsing algorithm.
64 |
65 | @param contextElement A context element used for parsing a HTML fragment
66 | @return An array of HTML elements, that are the result of parsing the given HTML string with the given context element.
67 |
68 | @see HTMLElement
69 | */
70 | - (NSArray *)parseFragmentWithContextElement:(HTMLElement *)contextElement;
71 |
72 | @end
73 |
74 | NS_ASSUME_NONNULL_END
75 |
--------------------------------------------------------------------------------
/Sources/include/HTMLParserInsertionModes.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLParserInsertionMode.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 05/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #define INSERTION_MODES \
14 | MODE_ENTRY( HTMLInsertionModeInitial, = 0 ) \
15 | MODE_ENTRY( HTMLInsertionModeBeforeHTML, ) \
16 | MODE_ENTRY( HTMLInsertionModeBeforeHead, ) \
17 | MODE_ENTRY( HTMLInsertionModeInHead, ) \
18 | MODE_ENTRY( HTMLInsertionModeInHeadNoscript, ) \
19 | MODE_ENTRY( HTMLInsertionModeAfterHead, ) \
20 | MODE_ENTRY( HTMLInsertionModeInBody, ) \
21 | MODE_ENTRY( HTMLInsertionModeText, ) \
22 | MODE_ENTRY( HTMLInsertionModeInTable, ) \
23 | MODE_ENTRY( HTMLInsertionModeInTableText, ) \
24 | MODE_ENTRY( HTMLInsertionModeInCaption, ) \
25 | MODE_ENTRY( HTMLInsertionModeInColumnGroup, ) \
26 | MODE_ENTRY( HTMLInsertionModeInTableBody, ) \
27 | MODE_ENTRY( HTMLInsertionModeInRow, ) \
28 | MODE_ENTRY( HTMLInsertionModeInCell, ) \
29 | MODE_ENTRY( HTMLInsertionModeInSelect, ) \
30 | MODE_ENTRY( HTMLInsertionModeInSelectInTable, ) \
31 | MODE_ENTRY( HTMLInsertionModeInTemplate, ) \
32 | MODE_ENTRY( HTMLInsertionModeAfterBody, ) \
33 | MODE_ENTRY( HTMLInsertionModeInFrameset, ) \
34 | MODE_ENTRY( HTMLInsertionModeAfterFrameset, ) \
35 | MODE_ENTRY( HTMLInsertionModeAfterAfterBody, ) \
36 | MODE_ENTRY( HTMLInsertionModeAfterAfterFrameset, ) \
37 |
38 | typedef NS_ENUM(NSUInteger, HTMLInsertionMode)
39 | {
40 | #define MODE_ENTRY( name, value ) name value,
41 | INSERTION_MODES
42 | #undef MODE_ENTRY
43 | };
44 |
--------------------------------------------------------------------------------
/Sources/include/HTMLRange+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLRange+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 27/11/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLRange.h"
10 | #import "HTMLCharacterData.h"
11 |
12 | @interface HTMLRange ()
13 |
14 | /**
15 | Runs the necessary steps after removing data from a character data node that may be a range's boundary.
16 |
17 | @param node The character data node.
18 | @param offset The offset at which the data was removed.
19 | @param length The length of the data that was removed.
20 | */
21 | - (void)didRemoveCharacterDataInNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length;
22 |
23 | /**
24 | Runs the necessary steps after adding data to a character data node that may be a range's boundary.
25 |
26 | @param node The character data node.
27 | @param offset The offset at which the data was added.
28 | @param length The length of the data that was added.
29 | */
30 | - (void)didAddCharacterDataToNode:(HTMLCharacterData *)node atOffset:(NSUInteger)offset withLength:(NSUInteger)length;
31 |
32 | /**
33 | Runs the necessary steps after inserting a new text node when an old text node is split.
34 |
35 | @param newNode The new text node after splitting.
36 | @param parent The parent where newNode was inserted.
37 | @param node The old text node that was split.
38 | @param offset The offset of splitting.
39 | */
40 | - (void)didInsertNewTextNode:(HTMLText *)newNode intoParent:(HTMLNode *)parent afterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset;
41 |
42 | /**
43 | Runs the necessary steps to clamp the range whose end boundary is after the text node upon splitting it.
44 |
45 | @param node The text node that was split.
46 | @param offset The offset of splitting
47 | */
48 | - (void)clampRangesAfterSplittingTextNode:(HTMLText *)node atOffset:(NSUInteger)offset;
49 |
50 | /**
51 | Runs the necessary steps after removing a node from the DOM.
52 |
53 | @param oldNode The old node that was removed.
54 | @param oldParent The old parent of the node that was removed.
55 | @param oldPreviousSibling The old previous sibling node of the node that was removed.
56 | */
57 | - (void)runRemovingStepsForNode:(HTMLNode *)oldNode
58 | withOldParent:(HTMLNode *)oldParent
59 | andOldPreviousSibling:(HTMLNode *)oldPreviousSibling;
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/Sources/include/HTMLSerializer.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLSerializer.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 28.07.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @class HTMLNode;
14 |
15 | /**
16 | The scope for HTML Serialization.
17 | */
18 | typedef NS_ENUM(unsigned short, HTMLSerializationScope)
19 | {
20 | HTMLSerializationScopeIncludeRoot = 1,
21 | HTMLSerializationScopeChildrenOnly = 2
22 | };
23 |
24 | /**
25 | A HTML DOM Serializer. Used to serialize HTML Tree rooted at a given node with the desired scope:
26 |
27 | - IncludeRoot scope includes the given node into the serialized result, e.g. HTML Node's `outerHTML`
28 | - ChildrenOnly scope serializes only the child nodes of the given node, e.g. HTML Node's `innerHTML`
29 |
30 | https://html.spec.whatwg.org/multipage/parsing.html#serialising-html-fragments
31 | */
32 | @interface HTMLSerializer : NSObject
33 |
34 | /**
35 | Serializes the given node with the given scope.
36 |
37 | @param node The root node of the tree to serialize
38 | @param scope The scope for serialization
39 | */
40 | + (NSString *)serializeNode:(HTMLNode *)node scope:(HTMLSerializationScope)scope;
41 |
42 | @end
43 |
44 | NS_ASSUME_NONNULL_END
45 |
46 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTagToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTagToken.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 | #import "HTMLOrderedDictionary.h"
16 |
17 | /**
18 | HTML Tag Token
19 | */
20 | @interface HTMLTagToken : HTMLToken
21 |
22 | /** @brief The tag name. */
23 | @property (nonatomic, copy) NSString *tagName;
24 |
25 | /** @brief The tag's attributes. */
26 | @property (nonatomic, strong) HTMLOrderedDictionary *attributes;
27 |
28 | /** @brief Flag whether this tag is self-closing. */
29 | @property (nonatomic, assign, getter = isSelfClosing) BOOL selfClosing;
30 |
31 | /**
32 | Initializes a new tag token.
33 |
34 | @param tagName The tag's name.
35 | @return A new instance of a tag token.
36 | */
37 | - (instancetype)initWithTagName:(NSString *)tagName;
38 |
39 | /**
40 | Initializes a new tag token.
41 |
42 | @param tagName The tag's name.
43 | @param attributes The tag's attributes.
44 | @return A new instance of a tag token.
45 | */
46 | - (instancetype)initWithTagName:(NSString *)tagName attributes:(NSMutableDictionary *)attributes;
47 |
48 | /**
49 | Appends the given string to this token's name.
50 |
51 | @param string The string to append.
52 | */
53 | - (void)appendStringToTagName:(NSString *)string;
54 |
55 | @end
56 |
57 | /**
58 | HTML Start Tag Token
59 | */
60 | @interface HTMLStartTagToken : HTMLTagToken
61 |
62 | @end
63 |
64 | /**
65 | HTML End Tag Token
66 | */
67 | @interface HTMLEndTagToken : HTMLTagToken
68 |
69 | @end
70 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTemplate.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTemplate.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 12/04/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLElement.h"
10 | #import "HTMLDocumentFragment.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | /**
15 | A HTML Template node.
16 |
17 | https://html.spec.whatwg.org/multipage/scripting.html#the-template-element
18 | */
19 | @interface HTMLTemplate : HTMLElement
20 |
21 | /**
22 | Decalration override for `NS_UNAVAILABLE` declared in `HTMLNode`
23 | */
24 | - (instancetype)init;
25 |
26 | /**
27 | The content of the template.
28 |
29 | @see HTMLDocumentFragment
30 | */
31 | @property (nonatomic, strong) HTMLDocumentFragment *content;
32 |
33 | @end
34 |
35 | NS_ASSUME_NONNULL_END
36 |
--------------------------------------------------------------------------------
/Sources/include/HTMLText.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLText.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26/02/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLCharacterData.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | A HTML Text node
15 | */
16 | @interface HTMLText : HTMLCharacterData
17 |
18 | /**
19 | Decalration override for `NS_UNAVAILABLE` declared in `HTMLNode`
20 | */
21 | - (instancetype)init;
22 |
23 | /**
24 | Initializes a new HTML text node.
25 |
26 | @param data The text string.
27 | @return A new isntance of a HTML text node.
28 | */
29 | - (instancetype)initWithData:(NSString *)data;
30 |
31 | /**
32 | Appends the string to this text node.
33 |
34 | @param string The string to append.
35 | */
36 | - (void)appendString:(NSString *)string __attribute__((deprecated("Use `appendData:` instead.")));
37 |
38 | - (HTMLText *)splitTextAtOffset:(NSUInteger)offset;
39 |
40 | @end
41 |
42 | NS_ASSUME_NONNULL_END
43 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTokenizer.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTokenizer.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 19/09/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 | #import "HTMLToken.h"
15 | #import "HTMLTokenizerStates.h"
16 |
17 | @class HTMLParser;
18 |
19 | /**
20 | Typedef for the parse error callback block.
21 |
22 | @param token The parse error token.
23 | */
24 | typedef void (^ HTMLTokenizerParseErrorCallback)(HTMLParseErrorToken *token);
25 |
26 | /**
27 | * HTML Tokenizer
28 | * https://html.spec.whatwg.org/multipage/syntax.html#tokenization
29 | */
30 | @interface HTMLTokenizer : NSEnumerator
31 |
32 | /** @brief The underlying string with which this tokenizer was initialized. */
33 | @property (nonatomic, readonly) NSString *string;
34 |
35 | /**
36 | The current tokenizer state.
37 |
38 | @see HTMLTokenizerState
39 | */
40 | @property (nonatomic, assign) HTMLTokenizerState state;
41 |
42 | /**
43 | The associated HTML Parser instance.
44 |
45 | @see HTMLParser
46 | */
47 | @property (nonatomic, weak) HTMLParser *parser;
48 |
49 | /**
50 | An error callback block, which gets called when encountering parse errors while tokenizing the stream
51 |
52 | Parse error tokens are dropped if the callback is `nil`.
53 | */
54 | @property (nonatomic, copy) HTMLTokenizerParseErrorCallback parseErrorCallback;
55 |
56 | /**
57 | Initializes a new Tokenizer with the given string.
58 |
59 | @param string The HTML string
60 | @return A new instance of the Tokenizer.
61 | */
62 | - (instancetype)initWithString:(NSString *)string;
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTokenizerEntities.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTokenizerEntities.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 11/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 |
15 | /**
16 | HTML character reference entitites
17 | https://html.spec.whatwg.org/multipage/syntax.html#named-character-references
18 | */
19 | @interface HTMLTokenizerEntities : NSObject
20 |
21 | /** @brief All character reference entitites. */
22 | + (NSArray *)entities;
23 |
24 | /**
25 | Returns the replacement entity at the given index.
26 |
27 | @param index The index of the character reference.
28 | @return The replacement character reference entitiy.
29 | */
30 | + (NSString *)replacementAtIndex:(NSUInteger)index;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTokens.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTokens.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import "HTMLToken.h"
14 | #import "HTMLCharacterToken.h"
15 | #import "HTMLCommentToken.h"
16 | #import "HTMLDOCTYPEToken.h"
17 | #import "HTMLParseErrorToken.h"
18 | #import "HTMLTagToken.h"
19 | #import "HTMLEOFToken.h"
20 |
--------------------------------------------------------------------------------
/Sources/include/HTMLTreeVisitor.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLTreeVisitor.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30.07.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLNodeVisitor.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @class HTMLNode;
15 |
16 | /**
17 | A HTML Tree Visitor that walks the DOM in tree order. Nodes are visited exacly once
18 |
19 | The provided node visitor is called for each node twice, once when entering the node,
20 | and once again when leaving the node.
21 |
22 | @see HTMLNodeVisitor
23 | */
24 | @interface HTMLTreeVisitor : NSObject
25 |
26 | /**
27 | Initializes a new tree visitor with.
28 |
29 | @param node The root node.
30 |
31 | @return A new instance of a tree visitor.
32 | */
33 | - (instancetype)initWithNode:(HTMLNode *)node;
34 |
35 | /**
36 | Walks the DOM tree rooted at the provided node with the given node visitor.
37 |
38 | @param visitor A HTMLNodeVisitor implementation.
39 | */
40 | - (void)walkWithNodeVisitor:(id)visitor;
41 |
42 | @end
43 |
44 | NS_ASSUME_NONNULL_END
45 |
--------------------------------------------------------------------------------
/Sources/include/NSCharacterSet+HTMLKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSCharacterSet+HTMLKit.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 14/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | NSCharacterSet category for HTML-related methods.
15 | */
16 | @interface NSCharacterSet (HTMLKit)
17 |
18 | /**
19 | A character set for HTML whitespace characters: CHARACTER TABULATION U+0009, LINE FEED U+000A, FORM FEED U+000C,
20 | CARRIAGE RETURN U+000D, and SPACE U+0020.
21 | */
22 |
23 | + (instancetype)htmlkit_HTMLWhitespaceCharacterSet;
24 |
25 | /**
26 | A character set for HTML HEX-Number characters: The digits 0-9, latin small letters a-f, and latin capital letters A-F.
27 | */
28 | + (instancetype)htmlkit_HTMLHexNumberCharacterSet;
29 |
30 | /**
31 | A character set for CSS Nth-Expression: The digits 0-9, space, latin small n, latin capital N, plus sing and minus sign.
32 | */
33 | + (instancetype)htmlkit_CSSNthExpressionCharacterSet;
34 |
35 | @end
36 |
37 | NS_ASSUME_NONNULL_END
38 |
--------------------------------------------------------------------------------
/Sources/include/NSString+HTMLKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+HTMLKit.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 02/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /**
14 | NSStirng category for HTML-related methods.
15 | */
16 | @interface NSString (HTMLKit)
17 |
18 | /**
19 | Checks whether this string is a HTML whitespace string.
20 |
21 | @return `YES` if this string is a HTML whitespace string, `NO` otherwise.
22 | */
23 | - (BOOL)htmlkit_isHTMLWhitespaceString;
24 |
25 | /**
26 | @return The length of the leading HTML whitespace characters in this string.
27 | */
28 | - (NSUInteger)htmlkit_leadingHTMLWhitespaceLength;
29 |
30 | @end
31 |
32 | NS_ASSUME_NONNULL_END
33 |
--------------------------------------------------------------------------------
/Sources/include/NSString+Private.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Private.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 26.03.19.
6 | // Copyright © 2019 BrainCookie. All rights reserved.
7 | //
8 |
9 | ///------------------------------------------------------
10 | /// HTMLKit private header
11 | ///------------------------------------------------------
12 |
13 | #import
14 |
15 | /**
16 | NSStirng category for common helper methods.
17 | */
18 | @interface NSString (Private)
19 |
20 | /**
21 | Checks whether this string is equal to another ignoring the case.
22 |
23 | @return `YES` if the two string are equal ignroing the case, `NO` otherwise.
24 | */
25 | - (BOOL)isEqualToStringIgnoringCase:(NSString *)aString;
26 |
27 | /**
28 | Checks whether this string is equal to any of the given strings.
29 |
30 | @return `YES` if there is an equal string, `NO` otherwise.
31 | */
32 | - (BOOL)isEqualToAny:(NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
33 |
34 | /**
35 | Checks whether this string has a prefix ignoring the case.
36 |
37 | @return `YES` if this string has a given prefix ignroing the case, `NO` otherwise.
38 | */
39 | - (BOOL)hasPrefixIgnoringCase:(NSString *)aString;
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Sources/include/module.modulemap:
--------------------------------------------------------------------------------
1 | module HTMLKit {
2 | umbrella header "HTMLKit.h"
3 |
4 | module * { export * }
5 | export *
6 |
7 | explicit module Private {
8 | textual header "CSSCodePoints.h"
9 | header "CSSInputStream.h"
10 | header "HTMLCharacterToken.h"
11 | header "HTMLCommentToken.h"
12 | header "HTMLDOCTYPEToken.h"
13 | header "HTMLElementAdjustment.h"
14 | header "HTMLElementTypes.h"
15 | header "HTMLEOFToken.h"
16 | header "HTMLInputStreamReader.h"
17 | header "HTMLListOfActiveFormattingElements.h"
18 | header "HTMLMarker.h"
19 | header "HTMLParseErrorToken.h"
20 | header "HTMLParserInsertionModes.h"
21 | header "HTMLStackOfOpenElements.h"
22 | header "HTMLTagToken.h"
23 | header "HTMLToken.h"
24 | header "HTMLTokenizer.h"
25 | textual header "HTMLTokenizerCharacters.h"
26 | header "HTMLTokenizerEntities.h"
27 | header "HTMLTokenizerStates.h"
28 | header "HTMLTokens.h"
29 | header "HTMLNode+Private.h"
30 | header "HTMLDocument+Private.h"
31 | header "HTMLCharacterData+Private.h"
32 | header "HTMLRange+Private.h"
33 | header "HTMLNodeIterator+Private.h"
34 | header "HTMLParser+Private.h"
35 | header "HTMLNodeTraversal.h"
36 | header "HTMLDOMUtils.h"
37 | header "NSString+Private.h"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/CSSSelectorTest.h:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelectorTest.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 22/11/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HTMLElement;
12 |
13 | @interface CSSSelectorTest : NSObject
14 |
15 | @property (nonatomic, copy) NSString *testName;
16 | @property (nonatomic, strong) NSArray *selectors;
17 | @property (nonatomic, strong) HTMLElement *testDOM;
18 |
19 | + (NSArray *)loadCSSSelectorTests;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/CSSSelectorTest.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSSelectorTest.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 22/11/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "CSSSelectorTest.h"
10 | #import "HTMLParser.h"
11 | #import "HTMLDocument.h"
12 | #import "HTMLElement.h"
13 | #import "CSSSelectors.h"
14 | #import "HTMLKitTestUtil.h"
15 |
16 | static NSString * const CSSTests = @"css-tests";
17 |
18 | @implementation CSSSelectorTest
19 |
20 | + (NSArray *)loadCSSSelectorTests
21 | {
22 | NSString *path = [HTMLKitTestUtil pathForFixture:CSSTests ofType:nil inDirectory:nil];
23 |
24 | NSMutableArray *tests = [NSMutableArray array];
25 | NSArray *testFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
26 |
27 | for (NSString *testFile in testFiles) {
28 | if (![testFile.pathExtension isEqualToString:@"html"]) {
29 | continue;
30 | }
31 |
32 | NSString *testFilePath = [path stringByAppendingPathComponent:testFile];
33 | CSSSelectorTest *test = [CSSSelectorTest testWithFileAtPath:testFilePath];
34 | [tests addObject:test];
35 | }
36 |
37 | return tests;
38 | }
39 |
40 | + (instancetype)testWithFileAtPath:(NSString *)filePath
41 | {
42 | NSString *testName = filePath.lastPathComponent.stringByDeletingPathExtension;
43 |
44 | NSString *html = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
45 |
46 | HTMLDocument *document = [HTMLDocument documentWithString:html];
47 |
48 | HTMLElement *domElement = [document firstElementMatchingSelector:idSelector(@"testDOM")];
49 | HTMLElement *scriptElement = [document firstElementMatchingSelector:idSelector(@"selectors")];
50 | NSData *data = [scriptElement.textContent dataUsingEncoding:NSUTF8StringEncoding];
51 | NSArray *selectors = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
52 |
53 | CSSSelectorTest *instance = [CSSSelectorTest new];
54 | instance.testName = testName;
55 | instance.selectors = selectors;
56 | instance.testDOM = domElement;
57 | return instance;
58 | }
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/CSSStructuralPseudoSelectors.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSStructuralPseudoSelectors.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 18.04.18.
6 | // Copyright © 2018 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelectors.h"
11 | #import "HTMLParser.h"
12 | #import "HTMLDOM.h"
13 |
14 | @interface CSSStructuralPseudoSelectors : XCTestCase
15 |
16 | @end
17 |
18 | @implementation CSSStructuralPseudoSelectors
19 |
20 | #pragma mark - Bug Fixes
21 |
22 | - (void)testBugFix_Issue_25
23 | {
24 | NSString *html = @"";
25 | HTMLDocument *doc = [HTMLDocument documentWithString:html];
26 | NSArray *elements = [doc querySelectorAll:@"td:gt(0)"];
27 |
28 | XCTAssertEqual(elements.count, 3);
29 | XCTAssertEqualObjects(elements[0].textContent, @"TD #1");
30 | XCTAssertEqualObjects(elements[1].textContent, @"TD #2");
31 | XCTAssertEqualObjects(elements[2].textContent, @"TD #3");
32 |
33 | elements = [doc querySelectorAll:@"td:lt(0)"];
34 | XCTAssertEqual(elements.count, 0);
35 |
36 | elements = [doc querySelectorAll:@"td:eq(0)"];
37 | XCTAssertEqual(elements.count, 1);
38 | XCTAssertEqualObjects(elements[0].textContent, @"TD #0");
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/CSSTypeSelectorTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // CSSTypeSelectorTests.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 14/05/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "CSSSelectors.h"
11 | #import "HTMLDOM.h"
12 | #import "CSSSelectorParser.h"
13 |
14 | @interface CSSTypeSelectorTests : XCTestCase
15 |
16 | @end
17 |
18 | @implementation CSSTypeSelectorTests
19 |
20 | - (void)testUniversalSelector
21 | {
22 | CSSSelector *selector = universalSelector();
23 |
24 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@""]], YES);
25 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"div"]], YES);
26 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"p"]], YES);
27 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"any other name"]], YES);
28 | }
29 |
30 | - (void)testTypeSelector
31 | {
32 | CSSSelector *selector = typeSelector(@"div");
33 |
34 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@""]], NO);
35 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"p"]], NO);
36 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"any other name"]], NO);
37 |
38 | XCTAssertEqual([selector acceptElement:[[HTMLElement alloc] initWithTagName:@"div"]], YES);
39 | }
40 |
41 | @end
42 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTML5LibTokenizerTest.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTML5LibTest.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/10/14.
6 | // Copyright (c) 2014 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HTML5LibTokenizerTest : NSObject
12 |
13 | @property (nonatomic, copy) NSString *testFile;
14 | @property (nonatomic, copy) NSString *title;
15 | @property (nonatomic, copy) NSString *input;
16 | @property (nonatomic, strong) NSArray *output;
17 | @property (nonatomic, strong) NSArray *errors;
18 | @property (nonatomic, strong) NSArray *initialStates;
19 | @property (nonatomic, copy) NSString *lastStartTag;
20 |
21 | + (NSDictionary *)loadHTML5LibTokenizerTests;
22 |
23 | - (instancetype)initWithTestDictionary:(NSDictionary *)dictionary;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTML5LibTreeConstructionTest.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTML5LibTreeConstructionTest.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 25/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HTMLElement;
12 |
13 | @interface HTML5LibTreeConstructionTest : NSObject
14 |
15 | @property (nonatomic, copy) NSString *testFile;
16 | @property (nonatomic, copy) NSString *data;
17 | @property (nonatomic, strong) NSArray *errors;
18 | @property (nonatomic, strong) HTMLElement *documentFragment;
19 | @property (nonatomic, strong) NSArray *nodes;
20 |
21 | + (NSDictionary *)loadHTML5LibTreeConstructionTests;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLDOMTokenListTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitDOMTokenListTests.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 30/11/15.
6 | // Copyright © 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLElement.h"
11 | #import "HTMLDOMTokenList.h"
12 |
13 | @interface HTMLKitDOMTokenListTests : XCTestCase
14 |
15 | @end
16 |
17 | @implementation HTMLKitDOMTokenListTests
18 |
19 | - (void)testTokenList
20 | {
21 | HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"class": @"red"}];
22 |
23 | HTMLDOMTokenList *list = element.classList;
24 |
25 | XCTAssertEqual(list.length, 1);
26 | XCTAssertTrue([list contains:@"red"]);
27 | XCTAssertEqualObjects(list.stringify, @"red");
28 |
29 | [list add:@[@"green", @"blue"]];
30 |
31 | XCTAssertEqual(list.length, 3);
32 | XCTAssertTrue([list contains:@"green"]);
33 | XCTAssertTrue([list contains:@"blue"]);
34 | XCTAssertEqualObjects(list.stringify, @"red green blue");
35 |
36 | XCTAssertFalse([list toggle:@"green"]);
37 | XCTAssertFalse([list contains:@"green"]);
38 | XCTAssertEqual(list.length, 2);
39 | XCTAssertEqualObjects(list.stringify, @"red blue");
40 |
41 | XCTAssertTrue([list toggle:@"green"]);
42 | XCTAssertTrue([list contains:@"green"]);
43 | XCTAssertEqual(list.length, 3);
44 | XCTAssertEqualObjects(list.stringify, @"red blue green");
45 |
46 | [list remove:@[@"blue", @"red"]];
47 |
48 | XCTAssertEqual(list.length, 1);
49 | XCTAssertEqualObjects(list.stringify, @"green");
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitParserIssuesTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitParserTests.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 16.07.18.
6 | // Copyright © 2018 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLDOM.h"
11 |
12 | @interface HTMLKitParserIssuesTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation HTMLKitParserIssuesTests
17 |
18 | #pragma mark - Bug Fixes
19 |
20 | - (void)testBugFix_Issue_30 {
21 | NSString *html =
22 | @""
23 | " "
24 | " "
25 | " "
26 | "";
27 |
28 | HTMLDocument* document = [HTMLDocument documentWithString:html];
29 | HTMLElement *svg = [document querySelector:@"#draw_area"];
30 |
31 | XCTAssertNil(svg.attributes[@"xlink"]);
32 | XCTAssertEqualObjects(svg.attributes[@"xmlns"], @"http://www.w3.org/2000/svg");
33 | XCTAssertEqualObjects(svg.attributes[@"xmlns:xlink"], @"http://www.w3.org/1999/xlink");
34 |
35 | HTMLElement *image = [document querySelector:@"#overlay_img"];
36 |
37 | XCTAssertNil(image.attributes[@"xlink"]);
38 | XCTAssertNil(image.attributes[@"href"]);
39 | XCTAssertEqualObjects(image.attributes[@"xlink:href"], @"foo.png");
40 | XCTAssertEqualObjects(image.outerHTML, @" ");
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitParserPerformance.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitParserPerformance.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 11/04/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLParser.h"
11 | #import "HTMLKitTestUtil.h"
12 |
13 | @interface HTMLKitParserPerformance : XCTestCase
14 |
15 | @end
16 |
17 | @implementation HTMLKitParserPerformance
18 |
19 | #define HTMLKIT_NO_DOM_CHECKS
20 |
21 | - (void)_testParserPerformance
22 | {
23 | NSString *path = [HTMLKitTestUtil pathForFixture:@"HTML Standard" ofType:@"html" inDirectory:@"Fixtures"];
24 |
25 | NSString *string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
26 |
27 | [self measureBlock:^{
28 | HTMLParser *parser = [[HTMLParser alloc] initWithString:string];
29 | [parser parseDocument];
30 | }];
31 | }
32 |
33 | #undef HTMLKIT_NO_DOM_CHECKS
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTestObserver.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitTestObserver.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 10/04/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HTMLKitTestReport : NSObject
12 | @property (assign, readonly) NSUInteger totalCount;
13 | @property (assign, readonly) NSUInteger failureCount;
14 | @property (copy, readonly) NSString *failureReport;
15 | @end
16 |
17 | @interface HTMLKitTestObserver : NSObject
18 |
19 | - (instancetype)initWithName:(NSString *)name;
20 |
21 | - (void)addCaseForHTML5LibTestWithInput:(NSString *)input;
22 | - (HTMLKitTestReport *)generateReport;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTestObserver.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitTestObserver.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 10/04/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLKitTestObserver.h"
10 |
11 | #pragma mark - HTMLKitTestReport
12 |
13 | @interface HTMLKitTestReport ()
14 | @property (assign) NSUInteger totalCount;
15 | @property (assign) NSUInteger failureCount;
16 | @property (copy) NSString *failureReport;
17 | @end
18 |
19 | @implementation HTMLKitTestReport
20 | @synthesize totalCount, failureCount, failureReport;
21 | @end
22 |
23 | #pragma mark - HTMLKitTestObserver
24 |
25 | @interface HTMLKitTestObserver ()
26 | {
27 | NSString *_name;
28 | NSMutableArray *_cases;
29 | NSMutableDictionary *_currentCase;
30 | }
31 | @end
32 |
33 | @implementation HTMLKitTestObserver
34 |
35 | - (instancetype)initWithName:(NSString *)name
36 | {
37 | self = [super init];
38 | if (self) {
39 | _name = [name copy];
40 | _cases = [NSMutableArray new];
41 | }
42 | return self;
43 | }
44 |
45 |
46 | - (void)addCaseForHTML5LibTestWithInput:(NSString *)input
47 | {
48 | _currentCase = [NSMutableDictionary new];
49 | _currentCase[@"input"] = input;
50 | _currentCase[@"status"] = @"Passed";
51 | [_cases addObject:_currentCase];
52 | }
53 |
54 | - (void)testCase:(XCTestCase *)testCase didRecordIssue:(XCTIssue *)issue
55 | {
56 | _currentCase[@"status"] = @"Failed";
57 | }
58 |
59 | - (HTMLKitTestReport *)generateReport
60 | {
61 | NSMutableString *reportDescription = [NSMutableString string];
62 |
63 | NSIndexSet *failedIndexes = [_cases indexesOfObjectsPassingTest:^BOOL(NSDictionary *testCase, NSUInteger idx, BOOL * _Nonnull stop) {
64 | return [testCase[@"status"] isEqualToString:@"Failed"];
65 | }];
66 |
67 | NSArray *failedTests = [_cases objectsAtIndexes:failedIndexes];
68 |
69 | NSUInteger totalCount = _cases.count;
70 | NSUInteger failureCount = failedTests.count;
71 |
72 | [reportDescription appendFormat:@"HTML5Lib test %@ failed [%lu] out of [%lu] total tests\n", _name, (unsigned long)failureCount, (unsigned long)_cases.count];
73 |
74 | for (NSDictionary *testCase in failedTests) {
75 | [reportDescription appendFormat:@"Failed test for input: %@\n", testCase[@"input"]];
76 | }
77 |
78 | HTMLKitTestReport *report = [HTMLKitTestReport new];
79 | report.totalCount = totalCount;
80 | report.failureCount = failureCount;
81 | report.failureReport = reportDescription;
82 |
83 | return report;
84 | }
85 |
86 | @end
87 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTestUtil.h:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitTestUtil.h
3 | // HTMLKit
4 | //
5 | // Created by Iska on 11/04/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface HTMLKitTestUtil : NSObject
12 |
13 | + (NSInvocation *)addTestToClass:(Class)cls withName:(NSString *)name block:(id)block;
14 | + (id)ivarForInstacne:(id)instance name:(NSString *)name;
15 | + (NSString *)pathForFixture:(NSString *)fixture ofType:(NSString *)type inDirectory:(NSString *)directory;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTestUtil.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitTestUtil.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 11/04/16.
6 | // Copyright © 2016 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import "HTMLKitTestUtil.h"
10 | #import
11 |
12 | @implementation HTMLKitTestUtil
13 |
14 | + (NSInvocation *)addTestToClass:(Class)cls withName:(NSString *)name block:(id)block
15 | {
16 | IMP implementation = imp_implementationWithBlock(block);
17 | const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(id), @encode(id), @encode(SEL)] UTF8String];
18 |
19 | SEL selector = NSSelectorFromString(name);
20 | class_addMethod(cls, selector, implementation, types);
21 |
22 | NSMethodSignature *signature = [cls instanceMethodSignatureForSelector:selector];
23 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
24 | invocation.selector = selector;
25 |
26 | return invocation;
27 | }
28 |
29 | + (id)ivarForInstacne:(id)instance name:(NSString *)name
30 | {
31 | Ivar ivar = class_getInstanceVariable([instance class], [name UTF8String]);
32 | return object_getIvar(instance, ivar);
33 | }
34 |
35 | + (NSString *)pathForFixture:(NSString *)fixture ofType:(NSString *)type inDirectory:(NSString *)directory
36 | {
37 | // Try testing bundle first
38 | NSString *path = [[NSBundle bundleForClass:self.class] pathForResource:fixture ofType:type inDirectory:directory];
39 | if (path) {
40 | return path;
41 | }
42 |
43 | path = [[@(__FILE__) stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
44 | if (directory) {
45 | path = [path stringByAppendingPathComponent:directory];
46 | }
47 |
48 | NSString *resource = type ? [NSString stringWithFormat:@"%@.%@", fixture, type] : fixture;
49 | path = [path stringByAppendingPathComponent:resource];
50 |
51 | return path;
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | dev.iabudiab.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/HTMLKitTests/HTMLKitTokenizerPerformance.m:
--------------------------------------------------------------------------------
1 | //
2 | // HTMLKitTokenizerPerformance.m
3 | // HTMLKit
4 | //
5 | // Created by Iska on 23/03/15.
6 | // Copyright (c) 2015 BrainCookie. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "HTMLTokenizer.h"
11 | #import "HTMLTokenizerStates.h"
12 | #import "HTMLTokens.h"
13 | #import "HTMLKitTestUtil.h"
14 |
15 | @interface HTMLKitTokenizerPerformance : XCTestCase
16 |
17 | @end
18 |
19 | @implementation HTMLKitTokenizerPerformance
20 |
21 | - (void)_testTokenizerPerformance
22 | {
23 | NSString *path = [HTMLKitTestUtil pathForFixture:@"HTML Standard" ofType:@"html" inDirectory:@"Fixtures"];
24 |
25 | NSString *string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
26 |
27 | [self measureBlock:^{
28 | HTMLTokenizer *tokenizer = [[HTMLTokenizer alloc] initWithString:string];
29 | [tokenizer allObjects];
30 | }];
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Tests/css-tests/1.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | The background of this list item should be green
10 | The background of this second list item should be also green
11 |
12 |
The background of this paragraph should be green.
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/10.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background because its title attribute ends with "bar"
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/11.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background because its title attribute contains "bar"
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/13.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | This list item should have green background because its class is "t1"
18 | This list item should have green background because its class is "t2"
19 |
20 | This list item should have green background because the inner SPAN does not match SPAN.t3
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Tests/css-tests/14.html:
--------------------------------------------------------------------------------
1 |
27 |
28 |
This paragraph should have a green background and a green thick solid border because it carries both classes t1 and t2.
29 |
This line should be green.
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/144.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have a green background.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Tests/css-tests/148.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/149.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/14b.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
This line should be green.
21 |
This line should be green.
22 |
23 |
--------------------------------------------------------------------------------
/Tests/css-tests/14c.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
This line should be green.
17 |
This line should be green.
18 |
This line should be green.
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/14d.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
This line should be green.
21 |
22 |
--------------------------------------------------------------------------------
/Tests/css-tests/14e.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
This line should be green.
17 |
This line should be green.
18 |
This line should be green.
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/15.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 | This list item should have a green background. because its ID is "t1"
22 | This list item should have a green background. because its ID is "t2"
23 |
24 | This list item should have a green background. because the inner SPAN does not match "#t4"
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Tests/css-tests/150.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This line should have a green background.
10 |
(Note: This test is based on unpublished errata.)
11 |
12 |
--------------------------------------------------------------------------------
/Tests/css-tests/151.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/152.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/154.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/155.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/155a.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/155b.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/155c.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/155d.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/156.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/157.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/158.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/15b.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
This line should be green.
21 |
This line should be green.
22 |
23 |
--------------------------------------------------------------------------------
/Tests/css-tests/16.html:
--------------------------------------------------------------------------------
1 |
11 |
16 |
--------------------------------------------------------------------------------
/Tests/css-tests/160.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/175a.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
This line should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/175b.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should be green.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/175c.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should be green.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/176.html:
--------------------------------------------------------------------------------
1 |
27 |
28 |
This line should be green.
29 |
This line should be green.
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/177b.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
This line should be green.
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Tests/css-tests/181.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
This line should be green.
21 |
This line should be green.
22 |
This line should be green.
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Tests/css-tests/183.html:
--------------------------------------------------------------------------------
1 |
18 |
19 |
This text should be green.
20 |
This text should be green.
21 |
This text should be green.
22 |
This text should be green.
23 |
This text should be green.
24 |
This text should be green.
25 |
26 |
--------------------------------------------------------------------------------
/Tests/css-tests/184a.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/184b.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/184c.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/184d.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/184e.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/184f.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be green.
9 |
This text should be green.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/2.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This address element should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/23.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | A button (enabled) with green background
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Tests/css-tests/24.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | A button (disabled) with green background
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Tests/css-tests/25.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 | Everything in this paragraph should have a green background
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Tests/css-tests/27a.html:
--------------------------------------------------------------------------------
1 |
59 |
60 |
This line should be green (there should be no red on this page).
61 |
62 |
--------------------------------------------------------------------------------
/Tests/css-tests/27b.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This line should be green (there should be no red on this page).
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/3.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | This paragraph, and all textual contents in the document, should be green.
14 |
15 |
16 | This item should be green.
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Tests/css-tests/30.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph is here only to fill space in the DOM
13 |
And this address too..
14 |
So does this paragraph !
15 |
But this one should have green background
16 |
17 | First definition term that should have green background
18 | First definition that should have green background
19 | Second definition term
20 | Second definition
21 | Third definition term
22 | Third definition
23 | Fourth definition term that should have green background
24 | Fourth definition that should have green background
25 | Fifth definition term
26 | Fifth definition
27 | Sixth definition term
28 | Sixth definition
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/31.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph should have green background
13 |
But this address is here only to fill space in the dom..
14 |
So does this paragraph !
15 |
And so does this one too.
16 |
17 | First definition term
18 | First definition
19 | Second definition term
20 | Second definition
21 | Third definition term that should have green background
22 | Third definition that should have green background
23 | Fourth definition term
24 | Fourth definition
25 | Fifth definition term
26 | Fifth definition
27 | Sixth definition term that should have green background
28 | Sixth definition that should have green background
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/32.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 | green cell
16 | 1.2
17 | 1.3
18 |
19 |
20 | green cell
21 | 2.2
22 | 2.3
23 |
24 |
25 | green cell
26 | 3.2
27 | 3.3
28 |
29 |
30 |
31 |
This paragraph contains some text
32 | and a span that should have a green background
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Tests/css-tests/33.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 | 1.1
16 | 1.2
17 | green cell
18 |
19 |
20 | 2.1
21 | 2.2
22 | green cell
23 |
24 |
25 | 3.1
26 | 3.2
27 | green cell
28 |
29 |
30 |
31 |
32 | This paragraph contains a span that should
33 | have a green background and some text after it.
34 |
35 |
--------------------------------------------------------------------------------
/Tests/css-tests/34.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This div contains 3 addresses:
9 |
A first address that should have a green background
10 |
A second address with normal background
11 |
A third address with normal background
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/35.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
A first address with normal background
10 |
A second address with normal background
11 |
A third address that should have a green background
12 | This div contains 3 addresses above this sentence.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Tests/css-tests/36.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph should have normal background
13 |
This div contains only one paragraph
14 |
This paragraph should have green background
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Tests/css-tests/37.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have normal background
10 |
But this address should have green background
11 |
This paragraph should have normal background
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/4.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/43.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have a green background
10 |
11 |
12 |
13 |
14 | This paragraph should have a green background
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | This paragraph should be unstyled.
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Tests/css-tests/44.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have a green background
10 |
11 |
This paragraph should have a green background
12 |
13 |
14 |
15 |
16 |
17 |
18 | This paragraph should be unstyled.
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Tests/css-tests/44c.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This should be unstyled.
9 |
This should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/44d.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This should be unstyled.
9 |
This should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/45.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should be unstyled.
10 |
But this one should have a green background.
11 |
And this one should also have a green background.
12 |
This address is only here to fill some space between two paragraphs.
13 |
This paragraph should be unstyled.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Tests/css-tests/45c.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This should be unstyled.
9 |
This should have a green background.
10 |
11 |
--------------------------------------------------------------------------------
/Tests/css-tests/46.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should be unstyled.
10 |
But this one should have a green background
11 |
And this one should also have a green background
12 |
This address is only here to fill some space between two paragraphs
13 |
This paragraph should have a green background
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Tests/css-tests/5.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background because its TITLE attribute is set.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/54.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
This paragraph should be in green characters.
14 |
This paragraph should be in green characters.
15 |
16 | This paragraph should be in green characters.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/55.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
This paragraph should be in green characters.
14 |
This paragraph should be in green characters.
15 |
16 | This paragraph should be in green characters.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/56.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
This paragraph should be in green characters.
14 |
This paragraph should be in green characters.
15 |
16 | This paragraph should be in green characters.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/59.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
This paragraph should be in green characters.
14 |
This paragraph should be in green characters.
15 |
16 | This paragraph should be in green characters.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/6.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | This line should
18 | have a green background.
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Tests/css-tests/60.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
This paragraph should be in green characters.
14 |
This paragraph should be in green characters.
15 |
16 | This paragraph should be in green characters.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Tests/css-tests/68.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | A button (disabled) with green background
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Tests/css-tests/69.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | A button (enabled) with green background
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Tests/css-tests/7.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
This paragraph should have green background because CLASS contains "b"
17 |
18 | This address should also
19 | have green background because the selector in the last rule does not apply to the inner SPANs.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Tests/css-tests/70.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | Everything in this paragraph should have a green background
18 |
19 |
--------------------------------------------------------------------------------
/Tests/css-tests/72.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have a green background and there should be no red anywhere.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Tests/css-tests/72b.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have a green background and there should be no red anywhere.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Tests/css-tests/75.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph should have green background
13 |
And this address should be unstyled.
14 |
This paragraph should also have green background!
15 |
But this one should be unstyled again.
16 |
17 | First definition term
18 | First definition
19 | Second definition term that should have green background
20 | Second definition that should have green background
21 | Third definition term that should have green background
22 | Third definition that should have green background
23 | Fourth definition term
24 | Fourth definition
25 | Fifth definition term that should have green background
26 | Fifth definition that should have green background
27 | Sixth definition term that should have green background
28 | Sixth definition that should have green background
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/76.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph should be unstyled.
13 |
This address should be unstyled.
14 |
This paragraph should have green background.
15 |
This paragraph should have green background.
16 |
17 | First definition term that should have green background.
18 | First definition that should also have a green background.
19 | Second definition term that should have green background.
20 | Second definition that should have green background.
21 | Third definition term.
22 | Third definition.
23 | Fourth definition term that should have green background.
24 | Fourth definition that should have green background.
25 | Fifth definition term that should have green background.
26 | Fifth definition that should have green background.
27 | Sixth definition term.
28 | Sixth definition.
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Tests/css-tests/77.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 | 1.1
16 | green cell
17 | green cell
18 |
19 |
20 | 2.1
21 | green cell
22 | green cell
23 |
24 |
25 | 3.1
26 | green cell
27 | green cell
28 |
29 |
30 |
31 |
This paragraph should be unstyled.
32 |
33 |
--------------------------------------------------------------------------------
/Tests/css-tests/78.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 | green cell
16 | green cell
17 | 1.3
18 |
19 |
20 | green cell
21 | green cell
22 | 2.3
23 |
24 |
25 | green cell
26 | green cell
27 | 3.3
28 |
29 |
30 |
31 |
This paragraph should be unstyled.
32 |
33 |
--------------------------------------------------------------------------------
/Tests/css-tests/79.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This div contains 3 addresses :
9 |
A first address with normal background
10 |
A second address that should have a green background
11 |
A third address that should have a green background
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/7b.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This line should have a green background.
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/8.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
This paragraph should have green background because its language is "en-gb"
17 |
18 | This address should also
19 | have green background because the language of the inner SPANs id="" is not French.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Tests/css-tests/80.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
A first address that should have a green background
10 |
A second address that should have a green background
11 |
A third address with normal background
12 | This div should have three addresses above it.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Tests/css-tests/81.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
This paragraph should have a green background.
13 |
This div contains only one paragraph.
14 |
This paragraph should be unstyled.
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Tests/css-tests/82.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
This paragraph should have green background.
10 |
But this address should be unstyled.
11 |
This paragraph should have green background.
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests/css-tests/83.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/86.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
This text should be green.
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Tests/css-tests/87.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be unstyled.
9 |
This text should be unstyled.
10 |
This text should be unstyled.
11 |
This text should be green.
12 |
13 |
--------------------------------------------------------------------------------
/Tests/css-tests/88.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be unstyled.
9 |
10 |
11 |
This text should be green.
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Tests/css-tests/89.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
This text should be green.
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Tests/css-tests/9.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This paragraph should have a green background because its title attribute begins with "foo"
9 |
10 |
--------------------------------------------------------------------------------
/Tests/css-tests/90.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
This text should be unstyled.
9 |
This text should be unstyled.
10 |
This text should be unstyled.
11 |
This text should be green.
12 |
13 |
--------------------------------------------------------------------------------