Repository navigation
FAQ
Short answers to what people ask first about Parsec, each pointing at the page with the long one.
All 24 questions
- Can I use Parsec today?
- When is the first release?
- Is it a fork of Lexbor, or html5ever?
- Is it faster than Lexbor?
- How correct is it?
- Does it run JavaScript?
- Which
scriptingvalue should I use? - Can I parse bytes, or pages in other encodings?
- Why did my page parse in quirks mode?
- Why doesn't
.Foomatchclass="foo"? - Why doesn't
[href]find SVG'sxlink:href? - Why can't my selector see what's inside a
<template>? - Why is
:lang()(or:valid, or::before) an error? - How do I read one attribute?
- How do I set
innerHTML? - What happens to a node I remove?
- Can I share a
Documentbetween threads? - How do I protect a crawler from hostile pages?
- Can I get line and column numbers?
- Can I stream a page in as it downloads?
- Is there XPath?
- Can I use it from C, Python or JavaScript?
- Why does it need a CLA if it's Apache-2.0?
- Where do I ask something that isn't here?
Yes, from git; it isn't released. Add parsec-html = { git = "https://github.com/parsec-html/parsec" } to your dependencies and use parsec. The API can still change before 0.1.0, so pin a commit if that matters to you. Getting started has the details.
When milestones M1 to M4 are done and the benchmarks show Parsec ahead of Lexbor on every page in the corpus (#32). There's no date. Roadmap has what's in each milestone.
Neither. It's its own parser, written in Rust from the HTML Standard. It's developed inside Netweir as crates/netweir-html and synced here; Contributing explains how.
Not measured parser against parser yet; that's #2. The one published number is end-to-end from Python, Netweir against selectolax, and it includes the queries and Python itself. Benchmarks has it with its caveats.
It passes all 7,045 html5lib tokenizer runs it can be given and all 3,898 runs of the WPT tree-construction cases that don't need JavaScript. Conformance says exactly what's counted and skipped.
No. The scripting flag only changes how <noscript> is parsed, as a browser with JavaScript on or off would parse it. See Parsing.
false, usually. Then <noscript> fallbacks become ordinary elements your selectors can find. Use true if you want the tree a JavaScript-enabled browser builds.
Not yet. Parsec takes a &str, so decode first. Encoding sniffing is #5, and the encodings themselves are #25.
Either it has no doctype, or it has an old one, or it starts with a byte order mark before the doctype. A browser drops the BOM while decoding; Parsec sees it as text, so strip a leading \u{FEFF} yourself. Parsing shows how.
Class names and ids compare exactly, as in a browser, except in quirks-mode documents. A page with no doctype is in quirks mode, so there .foo would match. See Selectors.
Because xlink:href is in the XLink namespace and [href] means no namespace, as in a browser. Use [*|href].
The HTML Standard keeps template contents out of the tree, and Parsec follows it. Run the selector on doc.template_contents(id), or call doc.adopt_template_contents() once to move all contents into the tree, as lxml and Beautiful Soup show them. See The document tree.
Parsec refuses selectors it doesn't match yet, rather than parse them and silently match nothing. Each missing pseudo-class has an issue; pseudo-elements select parts of elements, not elements, so select can't return them. Selectors has the list.
let doc = parsec::parse("<a href=/x>x</a>", false);
let a = parsec::css::SelectorList::parse("a").unwrap().select(&doc, doc.root())[0];
let href = doc.attrs(a).find(|&(_, name, _)| name == "href").map(|(_, _, v)| v);
assert_eq!(href, Some("/x"));There's no single-call getter yet.
There's no setter. Parse the markup with parse_fragment in the element's context and copy the nodes in; Moving from Lexbor has a helper that does it.
It's unlinked from the tree but stays in the document, with its subtree, until the document is dropped. Its id stays valid and you can insert it again. See Editing.
Yes. It's Send and Sync today, so you can read it from many threads and move it between them; edits need &mut. That isn't a promise yet: #11 makes it one. See Thread safety and memory safety.
Use parse_with with a budget, and check sizes before you parse. Limits and hostile input explains what the budget covers and where Parsec is and isn't linear.
Not yet. Parse errors with positions are #7, and positions on nodes and attributes are #8.
Not yet; the whole input has to be in memory. Chunked input is #6.
Not yet: #31, which brings Netweir's XPath 1.0 engine over. There's no XML parser either; Ns::Xml is for trees you build yourself.
Not yet. The C API is #20, Python #23, WebAssembly #24.
Because the parser is shared with Netweir, which is AGPL-3.0 and also sold under a commercial licence, so contributions here may go there too. You keep your copyright. Contributing has the details.
Discussions. Bugs go to Issues, and security problems to the private form in SECURITY.md.
- Getting started, for a first program.
- Glossary, for the terms these answers use.
- Roadmap, for anything that says "not yet".
Parsec is Apache-2.0 and not yet released; these pages describe main. Found something wrong here? Open an issue or ask in Discussions.
Repository · Issues · Discussions · Roadmap · Security policy · Licence