rusteerio 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +73 -0
- package/Cargo.lock +1051 -0
- package/Cargo.toml +36 -0
- package/LICENSE +21 -0
- package/README.md +252 -2
- package/RELEASING.md +138 -0
- package/THIRD_PARTY_NOTICES.md +7443 -0
- package/build.rs +3 -0
- package/dist/chunk-DKULX6VO.mjs +3185 -0
- package/dist/chunk-DKULX6VO.mjs.map +1 -0
- package/dist/chunk-OHPGEY3E.mjs +32 -0
- package/dist/chunk-OHPGEY3E.mjs.map +1 -0
- package/dist/index.cjs +3230 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +113 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.mjs +38 -0
- package/dist/index.mjs.map +1 -0
- package/dist/slim.cjs +2441 -0
- package/dist/slim.cjs.map +1 -0
- package/dist/slim.d.mts +11 -0
- package/dist/slim.d.ts +11 -0
- package/dist/slim.mjs +19 -0
- package/dist/slim.mjs.map +1 -0
- package/dist/types-BP6TpxE5.d.mts +532 -0
- package/dist/types-BP6TpxE5.d.ts +532 -0
- package/dist/utils.cjs +61 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.mts +13 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.mjs +17 -0
- package/dist/utils.mjs.map +1 -0
- package/native/src/arena.rs +1781 -0
- package/native/src/attributes.rs +923 -0
- package/native/src/codec.rs +172 -0
- package/native/src/diagnostics.rs +1249 -0
- package/native/src/extraction.rs +226 -0
- package/native/src/gc.rs +166 -0
- package/native/src/hook_sink.rs +727 -0
- package/native/src/hook_stream.rs +513 -0
- package/native/src/lib.rs +2095 -0
- package/native/src/location.rs +392 -0
- package/native/src/runtime.rs +189 -0
- package/native/src/selector.rs +1287 -0
- package/native/src/sink.rs +261 -0
- package/native/src/stream.rs +334 -0
- package/native/src/tokenizer.rs +355 -0
- package/native/src/tracker.rs +232 -0
- package/native/vendor/README.md +25 -0
- package/native/vendor/html5ever-0.35.0/.cargo_vcs_info.json +6 -0
- package/native/vendor/html5ever-0.35.0/Cargo.lock +828 -0
- package/native/vendor/html5ever-0.35.0/Cargo.toml +85 -0
- package/native/vendor/html5ever-0.35.0/LICENSE-APACHE +201 -0
- package/native/vendor/html5ever-0.35.0/LICENSE-MIT +25 -0
- package/native/vendor/html5ever-0.35.0/README.md +60 -0
- package/native/vendor/html5ever-0.35.0/benches/html5ever.rs +86 -0
- package/native/vendor/html5ever-0.35.0/data/bench/lipsum-zh.html +19 -0
- package/native/vendor/html5ever-0.35.0/data/bench/lipsum.html +40 -0
- package/native/vendor/html5ever-0.35.0/data/bench/medium-fragment.html +24 -0
- package/native/vendor/html5ever-0.35.0/data/bench/small-fragment.html +7 -0
- package/native/vendor/html5ever-0.35.0/data/bench/strong.html +1 -0
- package/native/vendor/html5ever-0.35.0/data/bench/tiny-fragment.html +1 -0
- package/native/vendor/html5ever-0.35.0/examples/arena.rs +356 -0
- package/native/vendor/html5ever-0.35.0/examples/capi/tokenize.c +74 -0
- package/native/vendor/html5ever-0.35.0/examples/noop-tokenize.rs +47 -0
- package/native/vendor/html5ever-0.35.0/examples/noop-tree-builder.rs +132 -0
- package/native/vendor/html5ever-0.35.0/examples/print-tree-actions.rs +185 -0
- package/native/vendor/html5ever-0.35.0/examples/tokenize.rs +111 -0
- package/native/vendor/html5ever-0.35.0/src/driver.rs +148 -0
- package/native/vendor/html5ever-0.35.0/src/lib.rs +30 -0
- package/native/vendor/html5ever-0.35.0/src/macros.rs +34 -0
- package/native/vendor/html5ever-0.35.0/src/serialize/mod.rs +255 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/char_ref/mod.rs +451 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/interface.rs +99 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/mod.rs +2305 -0
- package/native/vendor/html5ever-0.35.0/src/tokenizer/states.rs +97 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/data.rs +170 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/mod.rs +1848 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/rules.rs +1494 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/tag_sets.rs +114 -0
- package/native/vendor/html5ever-0.35.0/src/tree_builder/types.rs +91 -0
- package/native/vendor/html5ever-0.35.0/src/util/str.rs +52 -0
- package/native/vendor/html5gum-0.8.4/Cargo.lock +1006 -0
- package/native/vendor/html5gum-0.8.4/Cargo.toml +109 -0
- package/native/vendor/html5gum-0.8.4/LICENSE +19 -0
- package/native/vendor/html5gum-0.8.4/README.md +110 -0
- package/native/vendor/html5gum-0.8.4/benches/files/0050.html +2131 -0
- package/native/vendor/html5gum-0.8.4/benches/files/6D30.html +1004 -0
- package/native/vendor/html5gum-0.8.4/benches/files.rs +32 -0
- package/native/vendor/html5gum-0.8.4/benches/patterns.rs +31 -0
- package/native/vendor/html5gum-0.8.4/src/arrayvec.rs +29 -0
- package/native/vendor/html5gum-0.8.4/src/char_validator.rs +134 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/callback.rs +676 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/default.rs +207 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/emitter.rs +344 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/html5ever.rs +306 -0
- package/native/vendor/html5gum-0.8.4/src/emitters/mod.rs +25 -0
- package/native/vendor/html5gum-0.8.4/src/entities.rs +3342 -0
- package/native/vendor/html5gum-0.8.4/src/error.rs +96 -0
- package/native/vendor/html5gum-0.8.4/src/htmlstring.rs +130 -0
- package/native/vendor/html5gum-0.8.4/src/lib.rs +66 -0
- package/native/vendor/html5gum-0.8.4/src/machine.rs +2136 -0
- package/native/vendor/html5gum-0.8.4/src/machine_helper.rs +277 -0
- package/native/vendor/html5gum-0.8.4/src/read_helper.rs +244 -0
- package/native/vendor/html5gum-0.8.4/src/reader.rs +440 -0
- package/native/vendor/html5gum-0.8.4/src/span.rs +98 -0
- package/native/vendor/html5gum-0.8.4/src/state.rs +16 -0
- package/native/vendor/html5gum-0.8.4/src/testutils.rs +71 -0
- package/native/vendor/html5gum-0.8.4/src/tokenizer.rs +189 -0
- package/native/vendor/html5gum-0.8.4/src/utils.rs +88 -0
- package/native/vendor/markup5ever-0.35.0/.cargo_vcs_info.json +6 -0
- package/native/vendor/markup5ever-0.35.0/Cargo.toml +45 -0
- package/native/vendor/markup5ever-0.35.0/LICENSE-APACHE +201 -0
- package/native/vendor/markup5ever-0.35.0/LICENSE-MIT +25 -0
- package/native/vendor/markup5ever-0.35.0/interface/mod.rs +422 -0
- package/native/vendor/markup5ever-0.35.0/interface/tree_builder.rs +280 -0
- package/native/vendor/markup5ever-0.35.0/lib.rs +59 -0
- package/native/vendor/markup5ever-0.35.0/serialize.rs +77 -0
- package/native/vendor/markup5ever-0.35.0/util/buffer_queue.rs +333 -0
- package/native/vendor/markup5ever-0.35.0/util/smallcharset.rs +88 -0
- package/package.json +137 -4
- package/rusteerio.darwin-arm64.node +0 -0
- package/rusteerio.darwin-x64.node +0 -0
- package/rusteerio.linux-arm64-gnu.node +0 -0
- package/rusteerio.linux-arm64-musl.node +0 -0
- package/rusteerio.linux-x64-gnu.node +0 -0
- package/rusteerio.linux-x64-musl.node +0 -0
- package/rusteerio.win32-arm64-msvc.node +0 -0
- package/rusteerio.win32-x64-msvc.node +0 -0
- package/scripts/check-native.mjs +15 -0
- package/scripts/check-release.mjs +235 -0
- package/scripts/fix-declarations.mjs +27 -0
- package/scripts/generate-notices.mjs +176 -0
- package/scripts/notices/README.md +13 -0
- package/scripts/notices/cheerio-MIT.txt +21 -0
- package/scripts/notices/html5ever-AUTHORS.txt +20 -0
- package/scripts/notices/html5ever-COPYRIGHT.txt +8 -0
- package/scripts/notices/html5ever-LICENSE-APACHE.txt +201 -0
- package/scripts/notices/html5ever-LICENSE-MIT.txt +25 -0
- package/scripts/notices/napi-rs-MIT.txt +43 -0
- package/scripts/notices/neon-MIT.txt +19 -0
- package/scripts/notices/runtime-01c266bced4a434da005.txt +3 -0
- package/scripts/notices/runtime-0a54e647fe54104658b5.txt +14 -0
- package/scripts/notices/runtime-0b74dfa0bcee5c420c6b.txt +25 -0
- package/scripts/notices/runtime-0d542e0c8804e39aa7f3.txt +177 -0
- package/scripts/notices/runtime-0f96a83840e146e43c0e.txt +21 -0
- package/scripts/notices/runtime-123a331b5dbf04c30097.txt +25 -0
- package/scripts/notices/runtime-172020dbfd5b53a226df.txt +34 -0
- package/scripts/notices/runtime-209fbbe0ad52d9235e37.txt +26 -0
- package/scripts/notices/runtime-23f18e03dc49df91622f.txt +23 -0
- package/scripts/notices/runtime-268872b9816f90fd8e85.txt +220 -0
- package/scripts/notices/runtime-35242e7a83f69875e6ed.txt +176 -0
- package/scripts/notices/runtime-378f5840b258e2779c39.txt +25 -0
- package/scripts/notices/runtime-4108245a1f2df9d4e94d.txt +25 -0
- package/scripts/notices/runtime-4455bf75a91154108304.txt +21 -0
- package/scripts/notices/runtime-553fffcd9b1cb158bc3e.txt +13 -0
- package/scripts/notices/runtime-62c7a1e35f56406896d7.txt +176 -0
- package/scripts/notices/runtime-6485b8ed310d3f0340bf.txt +25 -0
- package/scripts/notices/runtime-69fef7b0f322a6555415.txt +201 -0
- package/scripts/notices/runtime-6df43f6f4b5d4587f3d8.txt +187 -0
- package/scripts/notices/runtime-799e9ca9d179295ef372.txt +24 -0
- package/scripts/notices/runtime-7b63ecd5f1902af1b637.txt +25 -0
- package/scripts/notices/runtime-7bc7d5de2a0b793d4e1a.txt +21 -0
- package/scripts/notices/runtime-7e12e5df4bae12cb2158.txt +24 -0
- package/scripts/notices/runtime-861399f8c21c042b1105.txt +12 -0
- package/scripts/notices/runtime-8ada45cd9f843acf64e4.txt +201 -0
- package/scripts/notices/runtime-90eb64f0279b0d9432ac.txt +12 -0
- package/scripts/notices/runtime-a60eea817514531668d7.txt +201 -0
- package/scripts/notices/runtime-a7c936ff1ed8fa340172.txt +25 -0
- package/scripts/notices/runtime-ab6eec6caf0fa5775e41.txt +275 -0
- package/scripts/notices/runtime-b1181a40b2a7b25cf66f.txt +19 -0
- package/scripts/notices/runtime-b71bd43a069ca0641a9e.txt +25 -0
- package/scripts/notices/runtime-c16f8dcf1a368b83be78.txt +201 -0
- package/scripts/notices/runtime-c2cfccb812fe482101a8.txt +21 -0
- package/scripts/notices/runtime-e99d88d232bf57d70f0f.txt +25 -0
- package/scripts/notices/runtime-f32fb3b417a194167cfa.txt +9 -0
- package/scripts/notices/runtime-f5062c9a188d81dfe66b.txt +39 -0
- package/scripts/notices/runtime-f9070a832833fa7488fd.txt +4 -0
- package/scripts/notices/runtime-fab3dd6bdab226f1c086.txt +373 -0
- package/scripts/notices/runtime-fba3318d0c600380177e.txt +62 -0
- package/scripts/notices/runtime-ff8f68cb076caf8cefe7.txt +25 -0
- package/scripts/notices/runtime-ff92bed461f50338dd70.txt +74 -0
- package/scripts/notices/runtime.json +1632 -0
- package/scripts/notices/sources.json +555 -0
- package/scripts/notices/xray-MIT.txt +21 -0
- package/src/attributes.ts +271 -0
- package/src/codec.ts +74 -0
- package/src/dom.ts +87 -0
- package/src/extract-plan.ts +97 -0
- package/src/extract.ts +130 -0
- package/src/hooks.ts +220 -0
- package/src/index.ts +223 -0
- package/src/io.ts +491 -0
- package/src/native.ts +135 -0
- package/src/nodes.ts +290 -0
- package/src/parse.ts +53 -0
- package/src/parser-types.ts +157 -0
- package/src/router.ts +327 -0
- package/src/selection.ts +566 -0
- package/src/slim.ts +12 -0
- package/src/transport.ts +104 -0
- package/src/types.ts +186 -0
- package/src/utils.ts +29 -0
- package/src/workers.ts +21 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +16 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
//! See [`examples/scraper.rs`] for usage.
|
|
2
|
+
use std::convert::Infallible;
|
|
3
|
+
|
|
4
|
+
use crate::emitters::callback::{Callback, CallbackEmitter, CallbackEvent};
|
|
5
|
+
use crate::utils::trace_log;
|
|
6
|
+
use crate::{Emitter, ForwardingEmitter, Readable, Reader, Span, State, Tokenizer};
|
|
7
|
+
|
|
8
|
+
use html5ever::interface::{create_element, TreeSink};
|
|
9
|
+
use html5ever::tokenizer::states::State as Html5everState;
|
|
10
|
+
use html5ever::tokenizer::{
|
|
11
|
+
states::RawKind, Doctype, Tag, TagKind, Token as Html5everToken, TokenSink, TokenSinkResult,
|
|
12
|
+
};
|
|
13
|
+
use html5ever::tree_builder::TreeBuilder;
|
|
14
|
+
use html5ever::ParseOpts;
|
|
15
|
+
use html5ever::{Attribute, QualName};
|
|
16
|
+
|
|
17
|
+
const BOGUS_LINENO: u64 = 1;
|
|
18
|
+
|
|
19
|
+
#[derive(Debug)]
|
|
20
|
+
struct OurCallback<'a, S> {
|
|
21
|
+
sink: &'a mut S,
|
|
22
|
+
current_start_tag: Option<Tag>,
|
|
23
|
+
next_state: Option<State>,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl<'a, S: TokenSink> OurCallback<'a, S> {
|
|
27
|
+
fn handle_sink_result<H>(&mut self, result: TokenSinkResult<H>) {
|
|
28
|
+
match result {
|
|
29
|
+
TokenSinkResult::Continue => {}
|
|
30
|
+
TokenSinkResult::Script(_) => {
|
|
31
|
+
self.next_state = Some(State::Data);
|
|
32
|
+
// TODO: suspend tokenizer for script
|
|
33
|
+
}
|
|
34
|
+
TokenSinkResult::Plaintext => {
|
|
35
|
+
self.next_state = Some(State::PlainText);
|
|
36
|
+
}
|
|
37
|
+
TokenSinkResult::RawData(RawKind::Rcdata) => {
|
|
38
|
+
self.next_state = Some(State::RcData);
|
|
39
|
+
}
|
|
40
|
+
TokenSinkResult::RawData(RawKind::Rawtext) => {
|
|
41
|
+
self.next_state = Some(State::RawText);
|
|
42
|
+
}
|
|
43
|
+
TokenSinkResult::RawData(RawKind::ScriptData) => {
|
|
44
|
+
self.next_state = Some(State::ScriptData);
|
|
45
|
+
}
|
|
46
|
+
TokenSinkResult::RawData(RawKind::ScriptDataEscaped(_)) => {
|
|
47
|
+
todo!()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn sink_token(&mut self, token: Html5everToken) {
|
|
53
|
+
trace_log!("sink_token: {:?}", token);
|
|
54
|
+
let result = self.sink.process_token(token, BOGUS_LINENO);
|
|
55
|
+
self.handle_sink_result(result);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl<'a, S: TokenSink> Callback<Infallible, ()> for OurCallback<'a, S> {
|
|
60
|
+
fn handle_event(&mut self, event: CallbackEvent<'_>, _span: Span<()>) -> Option<Infallible> {
|
|
61
|
+
trace_log!("Html5everEmitter::handle_event: {:?}", event);
|
|
62
|
+
match event {
|
|
63
|
+
CallbackEvent::OpenStartTag { name } => {
|
|
64
|
+
self.current_start_tag = Some(Tag {
|
|
65
|
+
kind: TagKind::StartTag,
|
|
66
|
+
name: String::from_utf8_lossy(name).into_owned().into(),
|
|
67
|
+
self_closing: false,
|
|
68
|
+
attrs: Default::default(),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
CallbackEvent::AttributeName { name } => {
|
|
72
|
+
if let Some(ref mut tag) = self.current_start_tag {
|
|
73
|
+
tag.attrs.push(Attribute {
|
|
74
|
+
name: QualName::new(
|
|
75
|
+
None,
|
|
76
|
+
Default::default(),
|
|
77
|
+
String::from_utf8_lossy(name).into_owned().into(),
|
|
78
|
+
),
|
|
79
|
+
value: Default::default(),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
CallbackEvent::AttributeValue { value } => {
|
|
84
|
+
if let Some(ref mut tag) = self.current_start_tag {
|
|
85
|
+
if let Some(attr) = tag.attrs.last_mut() {
|
|
86
|
+
attr.value.push_slice(&String::from_utf8_lossy(value));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
CallbackEvent::CloseStartTag { self_closing } => {
|
|
91
|
+
if let Some(mut tag) = self.current_start_tag.take() {
|
|
92
|
+
tag.self_closing = self_closing;
|
|
93
|
+
self.sink_token(Html5everToken::TagToken(tag));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
CallbackEvent::EndTag { name } => {
|
|
97
|
+
self.sink_token(Html5everToken::TagToken(Tag {
|
|
98
|
+
kind: TagKind::EndTag,
|
|
99
|
+
name: String::from_utf8_lossy(name).into_owned().into(),
|
|
100
|
+
self_closing: false,
|
|
101
|
+
attrs: Default::default(),
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
CallbackEvent::String { value } => {
|
|
105
|
+
let mut first = true;
|
|
106
|
+
for part in String::from_utf8_lossy(value).split('\0') {
|
|
107
|
+
if !first {
|
|
108
|
+
self.sink_token(Html5everToken::NullCharacterToken);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
first = false;
|
|
112
|
+
self.sink_token(Html5everToken::CharacterTokens(part.to_owned().into()));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
CallbackEvent::Comment { value } => {
|
|
116
|
+
self.sink_token(Html5everToken::CommentToken(
|
|
117
|
+
String::from_utf8_lossy(value).into_owned().into(),
|
|
118
|
+
));
|
|
119
|
+
}
|
|
120
|
+
CallbackEvent::Doctype {
|
|
121
|
+
name,
|
|
122
|
+
public_identifier,
|
|
123
|
+
system_identifier,
|
|
124
|
+
force_quirks,
|
|
125
|
+
} => {
|
|
126
|
+
self.sink_token(Html5everToken::DoctypeToken(Doctype {
|
|
127
|
+
name: Some(name)
|
|
128
|
+
.filter(|x| !x.is_empty())
|
|
129
|
+
.map(|x| String::from_utf8_lossy(x).into_owned().into()),
|
|
130
|
+
public_id: public_identifier
|
|
131
|
+
.map(|x| String::from_utf8_lossy(x).into_owned().into()),
|
|
132
|
+
system_id: system_identifier
|
|
133
|
+
.map(|x| String::from_utf8_lossy(x).into_owned().into()),
|
|
134
|
+
force_quirks,
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
CallbackEvent::Error(error) => {
|
|
138
|
+
self.sink_token(Html5everToken::ParseError(error.as_str().into()));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
None
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// A compatibility layer that allows you to plug the TreeBuilder from html5ever into the tokenizer
|
|
147
|
+
/// from html5gum.
|
|
148
|
+
///
|
|
149
|
+
/// See [`examples/scraper.rs`] for usage.
|
|
150
|
+
#[derive(Debug)]
|
|
151
|
+
pub struct Html5everEmitter<'a, S: TokenSink> {
|
|
152
|
+
emitter_inner: CallbackEmitter<OurCallback<'a, S>>,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
impl<'a, S: TokenSink> Html5everEmitter<'a, S> {
|
|
156
|
+
/// Construct the compatibility layer.
|
|
157
|
+
pub fn new(sink: &'a mut S) -> Self {
|
|
158
|
+
Html5everEmitter {
|
|
159
|
+
emitter_inner: CallbackEmitter::new(OurCallback {
|
|
160
|
+
sink,
|
|
161
|
+
current_start_tag: None,
|
|
162
|
+
next_state: None,
|
|
163
|
+
}),
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
impl<'a, S: TokenSink> ForwardingEmitter for Html5everEmitter<'a, S> {
|
|
169
|
+
type Token = Infallible;
|
|
170
|
+
|
|
171
|
+
fn inner(&mut self) -> &mut impl Emitter<Token = Self::Token> {
|
|
172
|
+
&mut self.emitter_inner
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fn emit_eof(&mut self) {
|
|
176
|
+
self.emitter_inner.emit_eof();
|
|
177
|
+
let sink = &mut self.emitter_inner.callback_mut().sink;
|
|
178
|
+
let _ignored = sink.process_token(Html5everToken::EOFToken, BOGUS_LINENO);
|
|
179
|
+
sink.end();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fn emit_current_tag(&mut self) -> Option<State> {
|
|
183
|
+
assert!(self.emitter_inner.emit_current_tag().is_none());
|
|
184
|
+
self.emitter_inner.callback_mut().next_state.take()
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
fn adjusted_current_node_present_but_not_in_html_namespace(&mut self) -> bool {
|
|
188
|
+
self.emitter_inner
|
|
189
|
+
.callback_mut()
|
|
190
|
+
.sink
|
|
191
|
+
.adjusted_current_node_present_but_not_in_html_namespace()
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
fn map_tokenizer_state(input: Html5everState) -> State {
|
|
196
|
+
match input {
|
|
197
|
+
Html5everState::Data => State::Data,
|
|
198
|
+
Html5everState::Plaintext => State::PlainText,
|
|
199
|
+
Html5everState::RawData(RawKind::Rcdata) => State::RcData,
|
|
200
|
+
Html5everState::RawData(RawKind::Rawtext) => State::RawText,
|
|
201
|
+
Html5everState::RawData(RawKind::ScriptData) => State::ScriptData,
|
|
202
|
+
x => todo!("{:?}", x),
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Parse an HTML fragment
|
|
207
|
+
///
|
|
208
|
+
/// This is a convenience function for using [Html5everEmitter] together with html5ever. It is
|
|
209
|
+
/// equivalent to the same functions in [html5ever::driver].
|
|
210
|
+
///
|
|
211
|
+
/// ```
|
|
212
|
+
/// use html5ever::{local_name, interface::TreeSink, QualName, ns, namespace_url}; // extern crate html5ever;
|
|
213
|
+
/// use scraper::{HtmlTreeSink, Html}; // extern crate scraper;
|
|
214
|
+
///
|
|
215
|
+
/// let input = "<h1>hello world</h1>";
|
|
216
|
+
///
|
|
217
|
+
/// // equivalent to `Html::parse_fragment`
|
|
218
|
+
/// let dom = Html::new_fragment();
|
|
219
|
+
/// let tree_sink = HtmlTreeSink::new(dom);
|
|
220
|
+
/// let Ok(tree_sink) = html5gum::emitters::html5ever::parse_fragment(
|
|
221
|
+
/// input,
|
|
222
|
+
/// tree_sink,
|
|
223
|
+
/// Default::default(),
|
|
224
|
+
/// QualName::new(None, ns!(html), local_name!("body")),
|
|
225
|
+
/// Vec::new()
|
|
226
|
+
/// );
|
|
227
|
+
/// let dom: Html = tree_sink.finish();
|
|
228
|
+
/// ```
|
|
229
|
+
pub fn parse_fragment<'a, R, Sink>(
|
|
230
|
+
input: R,
|
|
231
|
+
sink: Sink,
|
|
232
|
+
opts: ParseOpts,
|
|
233
|
+
context_name: QualName,
|
|
234
|
+
context_attrs: Vec<Attribute>,
|
|
235
|
+
) -> Result<Sink, <R::Reader as Reader>::Error>
|
|
236
|
+
where
|
|
237
|
+
R: Readable<'a>,
|
|
238
|
+
Sink: TreeSink,
|
|
239
|
+
{
|
|
240
|
+
let context_elem = create_element(&sink, context_name, context_attrs);
|
|
241
|
+
parse_fragment_for_element(input, sink, opts, context_elem, None)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Like `parse_fragment`, but with an existing context element
|
|
245
|
+
/// and optionally a form element.
|
|
246
|
+
///
|
|
247
|
+
/// This is a convenience function for using [Html5everEmitter] together with html5ever. It is
|
|
248
|
+
/// equivalent to the same functions in [html5ever::driver].
|
|
249
|
+
pub fn parse_fragment_for_element<'a, R, Sink>(
|
|
250
|
+
input: R,
|
|
251
|
+
sink: Sink,
|
|
252
|
+
opts: ParseOpts,
|
|
253
|
+
context_element: Sink::Handle,
|
|
254
|
+
form_element: Option<Sink::Handle>,
|
|
255
|
+
) -> Result<Sink, <R::Reader as Reader>::Error>
|
|
256
|
+
where
|
|
257
|
+
R: Readable<'a>,
|
|
258
|
+
Sink: TreeSink,
|
|
259
|
+
{
|
|
260
|
+
let mut tree_builder =
|
|
261
|
+
TreeBuilder::new_for_fragment(sink, context_element, form_element, opts.tree_builder);
|
|
262
|
+
|
|
263
|
+
let initial_state = map_tokenizer_state(tree_builder.tokenizer_state_for_context_elem());
|
|
264
|
+
let token_emitter = Html5everEmitter::new(&mut tree_builder);
|
|
265
|
+
let mut tokenizer = Tokenizer::new_with_emitter(input, token_emitter);
|
|
266
|
+
tokenizer.set_state(initial_state);
|
|
267
|
+
tokenizer.finish()?;
|
|
268
|
+
Ok(tree_builder.sink)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Parse an HTML document.
|
|
272
|
+
///
|
|
273
|
+
/// This is a convenience function for using [Html5everEmitter] together with html5ever. It is
|
|
274
|
+
/// equivalent to the same functions in [html5ever::driver].
|
|
275
|
+
///
|
|
276
|
+
/// ```rust
|
|
277
|
+
/// use html5ever::interface::TreeSink; // extern crate html5ever;
|
|
278
|
+
/// use scraper::{HtmlTreeSink, Html}; // extern crate scraper;
|
|
279
|
+
///
|
|
280
|
+
/// let input = "<h1>hello world</h1>";
|
|
281
|
+
///
|
|
282
|
+
/// // equivalent to `Html::parse_document`
|
|
283
|
+
/// let dom = Html::new_document();
|
|
284
|
+
/// let tree_sink = HtmlTreeSink::new(dom);
|
|
285
|
+
/// let Ok(tree_sink) = html5gum::emitters::html5ever::parse_document(
|
|
286
|
+
/// input,
|
|
287
|
+
/// tree_sink,
|
|
288
|
+
/// Default::default()
|
|
289
|
+
/// );
|
|
290
|
+
/// let dom: Html = tree_sink.finish();
|
|
291
|
+
/// ```
|
|
292
|
+
pub fn parse_document<'a, R, Sink>(
|
|
293
|
+
input: R,
|
|
294
|
+
sink: Sink,
|
|
295
|
+
opts: ParseOpts,
|
|
296
|
+
) -> Result<Sink, <R::Reader as Reader>::Error>
|
|
297
|
+
where
|
|
298
|
+
R: Readable<'a>,
|
|
299
|
+
Sink: TreeSink,
|
|
300
|
+
{
|
|
301
|
+
let mut tree_builder = TreeBuilder::new(sink, opts.tree_builder);
|
|
302
|
+
let token_emitter = Html5everEmitter::new(&mut tree_builder);
|
|
303
|
+
let tokenizer = Tokenizer::new_with_emitter(input, token_emitter);
|
|
304
|
+
tokenizer.finish()?;
|
|
305
|
+
Ok(tree_builder.sink)
|
|
306
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//! [Emitter] is a "visitor" on the underlying token stream.
|
|
2
|
+
//!
|
|
3
|
+
//! When html5gum parses HTML, it (more specifically, the [crate::Tokenizer]) calls into emitters to keep
|
|
4
|
+
//! track of state and to produce output.
|
|
5
|
+
//!
|
|
6
|
+
//! Emitters can yield control to the _caller_ of the tokenizer by emitting tokens in
|
|
7
|
+
//! [Emitter::pop_token]. This is what powers the basic API where users just iterate over
|
|
8
|
+
//! [crate::Tokenizer] which is an iterator over [default::Token].
|
|
9
|
+
//!
|
|
10
|
+
//! Most performant implementations don't implement `pop_token` and instead hold internal mutable
|
|
11
|
+
//! state, or directly produce side effects.
|
|
12
|
+
//!
|
|
13
|
+
//! Emitters are "a way to consume parsing results." The following ways are available:
|
|
14
|
+
//!
|
|
15
|
+
//! * [default::DefaultEmitter], if you don't care about speed and only want convenience.
|
|
16
|
+
//! * [callback::CallbackEmitter], if you can deal with some lifetime problems in exchange for way fewer allocations.
|
|
17
|
+
//! * Implementing your own [Emitter] for maximum performance and maximum pain.
|
|
18
|
+
pub mod callback;
|
|
19
|
+
pub mod default;
|
|
20
|
+
#[cfg(feature = "html5ever")]
|
|
21
|
+
pub mod html5ever;
|
|
22
|
+
|
|
23
|
+
mod emitter;
|
|
24
|
+
|
|
25
|
+
pub use emitter::{naive_next_state, Emitter, ForwardingEmitter};
|