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,356 @@
|
|
|
1
|
+
// Copyright 2014-2017 The html5ever Project Developers. See the
|
|
2
|
+
// COPYRIGHT file at the top-level directory of this distribution.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
5
|
+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
6
|
+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
7
|
+
// option. This file may not be copied, modified, or distributed
|
|
8
|
+
// except according to those terms.
|
|
9
|
+
|
|
10
|
+
extern crate html5ever;
|
|
11
|
+
extern crate typed_arena;
|
|
12
|
+
|
|
13
|
+
use html5ever::interface::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
|
|
14
|
+
use html5ever::tendril::{StrTendril, TendrilSink};
|
|
15
|
+
use html5ever::{parse_document, Attribute, QualName};
|
|
16
|
+
use std::borrow::Cow;
|
|
17
|
+
use std::cell::{Cell, RefCell};
|
|
18
|
+
use std::collections::HashSet;
|
|
19
|
+
use std::io::{self, Read};
|
|
20
|
+
use std::ptr;
|
|
21
|
+
|
|
22
|
+
/// By using our Sink type, the arena is filled with parsed HTML.
|
|
23
|
+
fn html5ever_parse_slice_into_arena<'a>(bytes: &[u8], arena: Arena<'a>) -> Ref<'a> {
|
|
24
|
+
let sink = Sink {
|
|
25
|
+
arena,
|
|
26
|
+
document: arena.alloc(Node::new(NodeData::Document)),
|
|
27
|
+
quirks_mode: Cell::new(QuirksMode::NoQuirks),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
parse_document(sink, Default::default())
|
|
31
|
+
.from_utf8()
|
|
32
|
+
.one(bytes)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type Arena<'arena> = &'arena typed_arena::Arena<Node<'arena>>;
|
|
36
|
+
type Ref<'arena> = &'arena Node<'arena>;
|
|
37
|
+
type Link<'arena> = Cell<Option<Ref<'arena>>>;
|
|
38
|
+
|
|
39
|
+
/// Sink struct is responsible for handling how the data that comes out of the HTML parsing
|
|
40
|
+
/// unit (TreeBuilder in our case) is handled.
|
|
41
|
+
struct Sink<'arena> {
|
|
42
|
+
arena: Arena<'arena>,
|
|
43
|
+
document: Ref<'arena>,
|
|
44
|
+
quirks_mode: Cell<QuirksMode>,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// DOM node which contains links to other nodes in the tree.
|
|
48
|
+
pub struct Node<'arena> {
|
|
49
|
+
parent: Link<'arena>,
|
|
50
|
+
next_sibling: Link<'arena>,
|
|
51
|
+
previous_sibling: Link<'arena>,
|
|
52
|
+
first_child: Link<'arena>,
|
|
53
|
+
last_child: Link<'arena>,
|
|
54
|
+
data: NodeData<'arena>,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// HTML node data which can be an element, a comment, a string, a DOCTYPE, etc...
|
|
58
|
+
pub enum NodeData<'arena> {
|
|
59
|
+
Document,
|
|
60
|
+
Doctype {
|
|
61
|
+
name: StrTendril,
|
|
62
|
+
public_id: StrTendril,
|
|
63
|
+
system_id: StrTendril,
|
|
64
|
+
},
|
|
65
|
+
Text {
|
|
66
|
+
contents: RefCell<StrTendril>,
|
|
67
|
+
},
|
|
68
|
+
Comment {
|
|
69
|
+
contents: StrTendril,
|
|
70
|
+
},
|
|
71
|
+
Element {
|
|
72
|
+
name: QualName,
|
|
73
|
+
attrs: RefCell<Vec<Attribute>>,
|
|
74
|
+
template_contents: Option<Ref<'arena>>,
|
|
75
|
+
mathml_annotation_xml_integration_point: bool,
|
|
76
|
+
},
|
|
77
|
+
ProcessingInstruction {
|
|
78
|
+
target: StrTendril,
|
|
79
|
+
contents: StrTendril,
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
impl<'arena> Node<'arena> {
|
|
84
|
+
fn new(data: NodeData<'arena>) -> Self {
|
|
85
|
+
Node {
|
|
86
|
+
parent: Cell::new(None),
|
|
87
|
+
previous_sibling: Cell::new(None),
|
|
88
|
+
next_sibling: Cell::new(None),
|
|
89
|
+
first_child: Cell::new(None),
|
|
90
|
+
last_child: Cell::new(None),
|
|
91
|
+
data,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn detach(&self) {
|
|
96
|
+
let parent = self.parent.take();
|
|
97
|
+
let previous_sibling = self.previous_sibling.take();
|
|
98
|
+
let next_sibling = self.next_sibling.take();
|
|
99
|
+
|
|
100
|
+
if let Some(next_sibling) = next_sibling {
|
|
101
|
+
next_sibling.previous_sibling.set(previous_sibling);
|
|
102
|
+
} else if let Some(parent) = parent {
|
|
103
|
+
parent.last_child.set(previous_sibling);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if let Some(previous_sibling) = previous_sibling {
|
|
107
|
+
previous_sibling.next_sibling.set(next_sibling);
|
|
108
|
+
} else if let Some(parent) = parent {
|
|
109
|
+
parent.first_child.set(next_sibling);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fn append(&'arena self, new_child: &'arena Self) {
|
|
114
|
+
new_child.detach();
|
|
115
|
+
new_child.parent.set(Some(self));
|
|
116
|
+
if let Some(last_child) = self.last_child.take() {
|
|
117
|
+
new_child.previous_sibling.set(Some(last_child));
|
|
118
|
+
debug_assert!(last_child.next_sibling.get().is_none());
|
|
119
|
+
last_child.next_sibling.set(Some(new_child));
|
|
120
|
+
} else {
|
|
121
|
+
debug_assert!(self.first_child.get().is_none());
|
|
122
|
+
self.first_child.set(Some(new_child));
|
|
123
|
+
}
|
|
124
|
+
self.last_child.set(Some(new_child));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
fn insert_before(&'arena self, new_sibling: &'arena Self) {
|
|
128
|
+
new_sibling.detach();
|
|
129
|
+
new_sibling.parent.set(self.parent.get());
|
|
130
|
+
new_sibling.next_sibling.set(Some(self));
|
|
131
|
+
if let Some(previous_sibling) = self.previous_sibling.take() {
|
|
132
|
+
new_sibling.previous_sibling.set(Some(previous_sibling));
|
|
133
|
+
debug_assert!(ptr::eq::<Node>(
|
|
134
|
+
previous_sibling.next_sibling.get().unwrap(),
|
|
135
|
+
self
|
|
136
|
+
));
|
|
137
|
+
previous_sibling.next_sibling.set(Some(new_sibling));
|
|
138
|
+
} else if let Some(parent) = self.parent.get() {
|
|
139
|
+
debug_assert!(ptr::eq::<Node>(parent.first_child.get().unwrap(), self));
|
|
140
|
+
parent.first_child.set(Some(new_sibling));
|
|
141
|
+
}
|
|
142
|
+
self.previous_sibling.set(Some(new_sibling));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
impl<'arena> Sink<'arena> {
|
|
147
|
+
fn new_node(&self, data: NodeData<'arena>) -> Ref<'arena> {
|
|
148
|
+
self.arena.alloc(Node::new(data))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
fn append_common<P, A>(&self, child: NodeOrText<Ref<'arena>>, previous: P, append: A)
|
|
152
|
+
where
|
|
153
|
+
P: FnOnce() -> Option<Ref<'arena>>,
|
|
154
|
+
A: FnOnce(Ref<'arena>),
|
|
155
|
+
{
|
|
156
|
+
let new_node = match child {
|
|
157
|
+
NodeOrText::AppendText(text) => {
|
|
158
|
+
// Append to an existing Text node if we have one.
|
|
159
|
+
if let Some(&Node {
|
|
160
|
+
data: NodeData::Text { ref contents },
|
|
161
|
+
..
|
|
162
|
+
}) = previous()
|
|
163
|
+
{
|
|
164
|
+
contents.borrow_mut().push_tendril(&text);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
self.new_node(NodeData::Text {
|
|
168
|
+
contents: RefCell::new(text),
|
|
169
|
+
})
|
|
170
|
+
},
|
|
171
|
+
NodeOrText::AppendNode(node) => node,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
append(new_node)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/// By implementing the TreeSink trait we determine how the data from the tree building step
|
|
179
|
+
/// is processed. In our case, our data is allocated in the arena and added to the Node data
|
|
180
|
+
/// structure.
|
|
181
|
+
///
|
|
182
|
+
/// For deeper understating of each function go to the TreeSink declaration.
|
|
183
|
+
impl<'arena> TreeSink for Sink<'arena> {
|
|
184
|
+
type Handle = Ref<'arena>;
|
|
185
|
+
type Output = Ref<'arena>;
|
|
186
|
+
type ElemName<'a>
|
|
187
|
+
= &'a QualName
|
|
188
|
+
where
|
|
189
|
+
Self: 'a;
|
|
190
|
+
|
|
191
|
+
fn finish(self) -> Ref<'arena> {
|
|
192
|
+
self.document
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
fn parse_error(&self, _: Cow<'static, str>) {}
|
|
196
|
+
|
|
197
|
+
fn get_document(&self) -> Ref<'arena> {
|
|
198
|
+
self.document
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fn set_quirks_mode(&self, mode: QuirksMode) {
|
|
202
|
+
self.quirks_mode.set(mode);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
fn same_node(&self, x: &Ref<'arena>, y: &Ref<'arena>) -> bool {
|
|
206
|
+
ptr::eq::<Node>(*x, *y)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
fn elem_name(&self, target: &Ref<'arena>) -> Self::ElemName<'_> {
|
|
210
|
+
match target.data {
|
|
211
|
+
NodeData::Element { ref name, .. } => name,
|
|
212
|
+
_ => panic!("not an element!"),
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
fn get_template_contents(&self, target: &Ref<'arena>) -> Ref<'arena> {
|
|
217
|
+
if let NodeData::Element {
|
|
218
|
+
template_contents: Some(contents),
|
|
219
|
+
..
|
|
220
|
+
} = target.data
|
|
221
|
+
{
|
|
222
|
+
contents
|
|
223
|
+
} else {
|
|
224
|
+
panic!("not a template element!")
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
fn is_mathml_annotation_xml_integration_point(&self, target: &Ref<'arena>) -> bool {
|
|
229
|
+
if let NodeData::Element {
|
|
230
|
+
mathml_annotation_xml_integration_point,
|
|
231
|
+
..
|
|
232
|
+
} = target.data
|
|
233
|
+
{
|
|
234
|
+
mathml_annotation_xml_integration_point
|
|
235
|
+
} else {
|
|
236
|
+
panic!("not an element!")
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
fn create_element(
|
|
241
|
+
&self,
|
|
242
|
+
name: QualName,
|
|
243
|
+
attrs: Vec<Attribute>,
|
|
244
|
+
flags: ElementFlags,
|
|
245
|
+
) -> Ref<'arena> {
|
|
246
|
+
self.new_node(NodeData::Element {
|
|
247
|
+
name,
|
|
248
|
+
attrs: RefCell::new(attrs),
|
|
249
|
+
template_contents: if flags.template {
|
|
250
|
+
Some(self.new_node(NodeData::Document))
|
|
251
|
+
} else {
|
|
252
|
+
None
|
|
253
|
+
},
|
|
254
|
+
mathml_annotation_xml_integration_point: flags.mathml_annotation_xml_integration_point,
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
fn create_comment(&self, text: StrTendril) -> Ref<'arena> {
|
|
259
|
+
self.new_node(NodeData::Comment { contents: text })
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
fn create_pi(&self, target: StrTendril, data: StrTendril) -> Ref<'arena> {
|
|
263
|
+
self.new_node(NodeData::ProcessingInstruction {
|
|
264
|
+
target,
|
|
265
|
+
contents: data,
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
fn append(&self, parent: &Ref<'arena>, child: NodeOrText<Ref<'arena>>) {
|
|
270
|
+
self.append_common(
|
|
271
|
+
child,
|
|
272
|
+
|| parent.last_child.get(),
|
|
273
|
+
|new_node| parent.append(new_node),
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
fn append_before_sibling(&self, sibling: &Ref<'arena>, child: NodeOrText<Ref<'arena>>) {
|
|
278
|
+
self.append_common(
|
|
279
|
+
child,
|
|
280
|
+
|| sibling.previous_sibling.get(),
|
|
281
|
+
|new_node| sibling.insert_before(new_node),
|
|
282
|
+
)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
fn append_based_on_parent_node(
|
|
286
|
+
&self,
|
|
287
|
+
element: &Ref<'arena>,
|
|
288
|
+
prev_element: &Ref<'arena>,
|
|
289
|
+
child: NodeOrText<Ref<'arena>>,
|
|
290
|
+
) {
|
|
291
|
+
if element.parent.get().is_some() {
|
|
292
|
+
self.append_before_sibling(element, child)
|
|
293
|
+
} else {
|
|
294
|
+
self.append(prev_element, child)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
fn append_doctype_to_document(
|
|
299
|
+
&self,
|
|
300
|
+
name: StrTendril,
|
|
301
|
+
public_id: StrTendril,
|
|
302
|
+
system_id: StrTendril,
|
|
303
|
+
) {
|
|
304
|
+
self.document.append(self.new_node(NodeData::Doctype {
|
|
305
|
+
name,
|
|
306
|
+
public_id,
|
|
307
|
+
system_id,
|
|
308
|
+
}))
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
fn add_attrs_if_missing(&self, target: &Ref<'arena>, attrs: Vec<Attribute>) {
|
|
312
|
+
let mut existing = if let NodeData::Element { ref attrs, .. } = target.data {
|
|
313
|
+
attrs.borrow_mut()
|
|
314
|
+
} else {
|
|
315
|
+
panic!("not an element")
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
let existing_names = existing
|
|
319
|
+
.iter()
|
|
320
|
+
.map(|e| e.name.clone())
|
|
321
|
+
.collect::<HashSet<_>>();
|
|
322
|
+
existing.extend(
|
|
323
|
+
attrs
|
|
324
|
+
.into_iter()
|
|
325
|
+
.filter(|attr| !existing_names.contains(&attr.name)),
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
fn remove_from_parent(&self, target: &Ref<'arena>) {
|
|
330
|
+
target.detach()
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fn reparent_children(&self, node: &Ref<'arena>, new_parent: &Ref<'arena>) {
|
|
334
|
+
let mut next_child = node.first_child.get();
|
|
335
|
+
while let Some(child) = next_child {
|
|
336
|
+
debug_assert!(ptr::eq::<Node>(child.parent.get().unwrap(), *node));
|
|
337
|
+
next_child = child.next_sibling.get();
|
|
338
|
+
new_parent.append(child)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/// In this example an "arena" is created and filled with the DOM nodes.
|
|
344
|
+
/// "Arena" is a type of allocation in which a block of memory is allocated
|
|
345
|
+
/// and later filled with data, DOM nodes in this case. When the arena is deallocated
|
|
346
|
+
/// it is destroyed with all of its items.
|
|
347
|
+
///
|
|
348
|
+
/// Further info about arena: https://docs.rs/typed-arena/latest/typed_arena/
|
|
349
|
+
fn main() {
|
|
350
|
+
// Read HTML from the standard input
|
|
351
|
+
let mut bytes = Vec::new();
|
|
352
|
+
io::stdin().read_to_end(&mut bytes).unwrap();
|
|
353
|
+
|
|
354
|
+
let arena = typed_arena::Arena::new();
|
|
355
|
+
html5ever_parse_slice_into_arena(&bytes, &arena);
|
|
356
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Copyright 2014-2017 The html5ever Project Developers. See the
|
|
2
|
+
// COPYRIGHT file at the top-level directory of this distribution.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
5
|
+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
6
|
+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
7
|
+
// option. This file may not be copied, modified, or distributed
|
|
8
|
+
// except according to those terms.
|
|
9
|
+
|
|
10
|
+
#include <stdio.h>
|
|
11
|
+
|
|
12
|
+
#include "html5ever.h"
|
|
13
|
+
|
|
14
|
+
void put_str(const char *x) {
|
|
15
|
+
fputs(x, stdout);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void put_buf(struct h5e_buf text) {
|
|
19
|
+
fwrite(text.data, text.len, 1, stdout);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void do_chars(void *user, struct h5e_buf text) {
|
|
23
|
+
put_str("CHARS : ");
|
|
24
|
+
put_buf(text);
|
|
25
|
+
put_str("\n");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void do_start_tag(void *user, struct h5e_buf name, int self_closing, size_t num_attrs) {
|
|
29
|
+
put_str("TAG : <");
|
|
30
|
+
put_buf(name);
|
|
31
|
+
if (self_closing) {
|
|
32
|
+
putchar('/');
|
|
33
|
+
}
|
|
34
|
+
put_str(">\n");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void do_tag_attr(void *user, struct h5e_buf name, struct h5e_buf value) {
|
|
38
|
+
put_str(" ATTR: ");
|
|
39
|
+
put_buf(name);
|
|
40
|
+
put_str("=\"");
|
|
41
|
+
put_buf(value);
|
|
42
|
+
put_str("\"\n");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void do_end_tag(void *user, struct h5e_buf name) {
|
|
46
|
+
put_str("TAG : </");
|
|
47
|
+
put_buf(name);
|
|
48
|
+
put_str(">\n");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
struct h5e_token_ops ops = {
|
|
52
|
+
.do_chars = do_chars,
|
|
53
|
+
.do_start_tag = do_start_tag,
|
|
54
|
+
.do_tag_attr = do_tag_attr,
|
|
55
|
+
.do_end_tag = do_end_tag,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
struct h5e_token_sink sink = {
|
|
59
|
+
.ops = &ops,
|
|
60
|
+
.user = NULL,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
int main(int argc, char *argv[]) {
|
|
64
|
+
if (argc < 2) {
|
|
65
|
+
printf("Usage: %s 'HTML fragment'\n", argv[0]);
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
struct h5e_tokenizer *tok = h5e_tokenizer_new(&sink);
|
|
70
|
+
h5e_tokenizer_feed(tok, h5e_buf_from_cstr(argv[1]));
|
|
71
|
+
h5e_tokenizer_end(tok);
|
|
72
|
+
h5e_tokenizer_free(tok);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright 2014-2017 The html5ever Project Developers. See the
|
|
2
|
+
// COPYRIGHT file at the top-level directory of this distribution.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
5
|
+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
6
|
+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
7
|
+
// option. This file may not be copied, modified, or distributed
|
|
8
|
+
// except according to those terms.
|
|
9
|
+
|
|
10
|
+
// Run a single benchmark once. For use with profiling tools.
|
|
11
|
+
|
|
12
|
+
extern crate html5ever;
|
|
13
|
+
|
|
14
|
+
use std::cell::RefCell;
|
|
15
|
+
use std::io;
|
|
16
|
+
|
|
17
|
+
use html5ever::tendril::*;
|
|
18
|
+
use html5ever::tokenizer::{BufferQueue, Token, TokenSink, TokenSinkResult, Tokenizer};
|
|
19
|
+
|
|
20
|
+
/// In our case, our sink only contains a tokens vector
|
|
21
|
+
struct Sink(RefCell<Vec<Token>>);
|
|
22
|
+
|
|
23
|
+
impl TokenSink for Sink {
|
|
24
|
+
type Handle = ();
|
|
25
|
+
|
|
26
|
+
/// Each processed token will be handled by this method
|
|
27
|
+
fn process_token(&self, token: Token, _line_number: u64) -> TokenSinkResult<()> {
|
|
28
|
+
self.0.borrow_mut().push(token);
|
|
29
|
+
TokenSinkResult::Continue
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// In this example we implement the TokenSink trait which lets us implement how each
|
|
34
|
+
/// parsed token is treated. In our example we take each token and insert it into a vector.
|
|
35
|
+
fn main() {
|
|
36
|
+
// Read HTML from standard input
|
|
37
|
+
let mut chunk = ByteTendril::new();
|
|
38
|
+
io::stdin().read_to_tendril(&mut chunk).unwrap();
|
|
39
|
+
|
|
40
|
+
let input = BufferQueue::default();
|
|
41
|
+
input.push_back(chunk.try_reinterpret().unwrap());
|
|
42
|
+
|
|
43
|
+
let tok = Tokenizer::new(Sink(RefCell::new(Vec::new())), Default::default());
|
|
44
|
+
let _ = tok.feed(&input);
|
|
45
|
+
assert!(input.is_empty());
|
|
46
|
+
tok.end();
|
|
47
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Copyright 2014-2017 The html5ever Project Developers. See the
|
|
2
|
+
// COPYRIGHT file at the top-level directory of this distribution.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
5
|
+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
6
|
+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
7
|
+
// option. This file may not be copied, modified, or distributed
|
|
8
|
+
// except according to those terms.
|
|
9
|
+
|
|
10
|
+
#[macro_use]
|
|
11
|
+
extern crate html5ever;
|
|
12
|
+
|
|
13
|
+
use std::borrow::Cow;
|
|
14
|
+
use std::cell::{Cell, RefCell};
|
|
15
|
+
use std::collections::HashMap;
|
|
16
|
+
use std::io;
|
|
17
|
+
|
|
18
|
+
use html5ever::parse_document;
|
|
19
|
+
use html5ever::tendril::*;
|
|
20
|
+
use html5ever::tree_builder::{ElementFlags, NodeOrText, QuirksMode, TreeSink};
|
|
21
|
+
use html5ever::{Attribute, ExpandedName, QualName};
|
|
22
|
+
|
|
23
|
+
struct Sink {
|
|
24
|
+
next_id: Cell<usize>,
|
|
25
|
+
names: RefCell<HashMap<usize, &'static QualName>>,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl Sink {
|
|
29
|
+
fn get_id(&self) -> usize {
|
|
30
|
+
let id = self.next_id.get();
|
|
31
|
+
self.next_id.set(id + 2);
|
|
32
|
+
id
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// By implementing the TreeSink trait we determine how the data from the tree building step
|
|
37
|
+
/// is processed. In this case the DOM elements are written into the "names" hashmap.
|
|
38
|
+
///
|
|
39
|
+
/// For deeper understating of each function go to the TreeSink declaration.
|
|
40
|
+
impl TreeSink for Sink {
|
|
41
|
+
type Handle = usize;
|
|
42
|
+
type Output = Self;
|
|
43
|
+
type ElemName<'a> = ExpandedName<'a>;
|
|
44
|
+
fn finish(self) -> Self {
|
|
45
|
+
self
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fn get_document(&self) -> usize {
|
|
49
|
+
0
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn get_template_contents(&self, target: &usize) -> usize {
|
|
53
|
+
if let Some(expanded_name!(html "template")) =
|
|
54
|
+
self.names.borrow().get(target).map(|n| n.expanded())
|
|
55
|
+
{
|
|
56
|
+
target + 1
|
|
57
|
+
} else {
|
|
58
|
+
panic!("not a template element")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fn same_node(&self, x: &usize, y: &usize) -> bool {
|
|
63
|
+
x == y
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fn elem_name(&self, target: &usize) -> ExpandedName {
|
|
67
|
+
self.names
|
|
68
|
+
.borrow()
|
|
69
|
+
.get(target)
|
|
70
|
+
.expect("not an element")
|
|
71
|
+
.expanded()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fn create_element(&self, name: QualName, _: Vec<Attribute>, _: ElementFlags) -> usize {
|
|
75
|
+
let id = self.get_id();
|
|
76
|
+
// N.B. We intentionally leak memory here to minimize the implementation complexity
|
|
77
|
+
// of this example code. A real implementation would either want to use a real
|
|
78
|
+
// real DOM tree implentation, or else use an arena as the backing store for
|
|
79
|
+
// memory used by the parser.
|
|
80
|
+
self.names
|
|
81
|
+
.borrow_mut()
|
|
82
|
+
.insert(id, Box::leak(Box::new(name)));
|
|
83
|
+
id
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn create_comment(&self, _text: StrTendril) -> usize {
|
|
87
|
+
self.get_id()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[allow(unused_variables)]
|
|
91
|
+
fn create_pi(&self, target: StrTendril, value: StrTendril) -> usize {
|
|
92
|
+
unimplemented!()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fn append_before_sibling(&self, _sibling: &usize, _new_node: NodeOrText<usize>) {}
|
|
96
|
+
|
|
97
|
+
fn append_based_on_parent_node(
|
|
98
|
+
&self,
|
|
99
|
+
_element: &usize,
|
|
100
|
+
_prev_element: &usize,
|
|
101
|
+
_new_node: NodeOrText<usize>,
|
|
102
|
+
) {
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn parse_error(&self, _msg: Cow<'static, str>) {}
|
|
106
|
+
fn set_quirks_mode(&self, _mode: QuirksMode) {}
|
|
107
|
+
fn append(&self, _parent: &usize, _child: NodeOrText<usize>) {}
|
|
108
|
+
|
|
109
|
+
fn append_doctype_to_document(&self, _: StrTendril, _: StrTendril, _: StrTendril) {}
|
|
110
|
+
fn add_attrs_if_missing(&self, target: &usize, _attrs: Vec<Attribute>) {
|
|
111
|
+
assert!(self.names.borrow().contains_key(target), "not an element");
|
|
112
|
+
}
|
|
113
|
+
fn remove_from_parent(&self, _target: &usize) {}
|
|
114
|
+
fn reparent_children(&self, _node: &usize, _new_parent: &usize) {}
|
|
115
|
+
fn mark_script_already_started(&self, _node: &usize) {}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// In this example we implement the TreeSink trait which takes each parsed elements and insert
|
|
119
|
+
/// it to a hashmap, while each element is given a numeric id.
|
|
120
|
+
fn main() {
|
|
121
|
+
let sink = Sink {
|
|
122
|
+
next_id: Cell::new(1),
|
|
123
|
+
names: RefCell::new(HashMap::new()),
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Read HTML from the standard input and parse it
|
|
127
|
+
let stdin = io::stdin();
|
|
128
|
+
parse_document(sink, Default::default())
|
|
129
|
+
.from_utf8()
|
|
130
|
+
.read_from(&mut stdin.lock())
|
|
131
|
+
.unwrap();
|
|
132
|
+
}
|