aboutsummaryrefslogtreecommitdiff
path: root/src/tokenizer.rs
AgeCommit message (Collapse)Author
2023-09-28chore: rename internal states as wellMartin Fischer
See the previous commit.
2023-09-28break!: rename State variantsMartin Fischer
The spec refers to them only as RCDATA, RAWTEXT and PLAINTEXT. See https://rust-lang.github.io/api-guidelines/naming.html.
2023-09-28break!: remove CdataActionMartin Fischer
Which action the tokenizer takes depending on whether or not an adjusted current node is present but not in the HTML namespace, is an implementation detail and shouldn't be exposed in the API.
2023-09-28feat: add offset to Trace::EndOfFileMartin Fischer
2023-09-28feat: implement BasicEmitterMartin Fischer
2023-09-28break!: move offsets out of TokenMartin Fischer
Previously the Token enum contained the offsets using the O generic type parameter, which could be a usize if you're tracking offsets or a zero-sized type if you didn't care about offsets. This commit moves all the byte offset and syntax information to a new Trace enum, which has several advantages: * Traces can now easily be stored separately, while the tokens are fed to the tree builder. (The tree builder only has to keep track of which tree nodes originate from which tokens.) * No needless generics for functions that take a token but don't care about offsets (a tree construction implementation is bound to have many of such functions). * The FromIterator<(String, String)> impl for AttributeMap no longer has to specify arbitrary values for the spans and the value_syntax). * The PartialEq implementation of Token is now much more useful (since it no longer includes all the offsets). * The Debug formatting of Token is now more readable (since it no longer includes all the offsets). * Function pointers to functions accepting tokens are possible. (Since function pointer types may not have generic parameters.)
2023-09-28break!: rename DefaultEmitter to TracingEmitterMartin Fischer
2023-09-28refactor: move machine impl details to machine moduleMartin Fischer
This commit separates the public API (the "Tokenizer") from the internal implementation (the "Machine") to make the code more readable.
2023-09-28refactor: move utils module under tokenizer::machineMartin Fischer
2023-09-28refactor: only use InternalState re-export for feature-gated internal APIMartin Fischer
2023-09-28refactor: move machine module under tokenizerMartin Fischer
2023-09-28break!: remove Token::ErrorMartin Fischer
An error isn't a token (in general and also according to the spec). You shouldn't have to filter out errors when you're just interested in tokens but most importantly having errors in the Token enum is annoying when implementing tree construction (since the spec conditions exhaustively cover all Token variants except Token::Error).
2023-09-28break!: rename Emitter::emit_error to report_errorMartin Fischer
2023-09-27break!: remove Emitter::pop_token, use Iterator insteadMartin Fischer
2023-09-12docs: move warning from DefaultEmitter to TokenizerMartin Fischer
2023-09-03fix!: make comment data spans encoding-independentMartin Fischer
2023-09-03fix!: make start/end tag name spans encoding-independentMartin Fischer
2023-09-03fix: don't assume UTF-8 in machine/tokenizerMartin Fischer
2023-09-03refactor: inline internal method only used onceMartin Fischer
2023-09-03refactor: also use some_offset for start/end tagsMartin Fischer
2023-09-03fix!: calculate tag offsets in Tokenizer instead of Emitter implMartin Fischer
2023-09-03fix: too small char ref error spansMartin Fischer
2023-09-03chore: rename doctype_offset field to some_offsetMartin Fischer
We'll reuse the field for another offset in the next commit.
2023-09-03fix: off-by-one missing-semicolon-after-character-reference spanMartin Fischer
2023-09-03fix: most error spans mistakenly being emptyMartin Fischer
With codespan_reporting an empty span shows up exactly like a one-byte span, which is why I didn't notice this mistake earlier.
2023-09-03fix: off-by-one eof error spansMartin Fischer
2023-09-03break!: make Emitter::emit_error take spanMartin Fischer
2023-09-03fix!: remove adjusted_current_node_present_and_not_in_html_namespaceMartin Fischer
Conceptually the tokenizer emits tokens, which are then handled in the tree construction stage (which this crate doesn't yet implement). While the tokenizer can operate almost entirely based on its state (which may be changed via Tokenizer::set_state) and its internal state, there is the exception of the 'Markup declaration open state'[1], the third condition of which depends on the "adjusted current node", which in turn depends on the "stack of open elements" only known to the tree constructor. In 82898967320f90116bbc686ab7ffc2f61ff456c4 I tried to address this by adding the adjusted_current_node_present_and_not_in_html_namespace method to the Emitter trait. What I missed was that adding this method to the Emitter trait effectively crippled the composability of the API. You should be able to do the following: struct TreeConstructor<R, O> { tokenizer: Tokenizer<R, O, SomeEmitter<O>>, stack_of_open_elements: Vec<NodeId>, // ... } However this doesn't work if the implementation of SomeEmitter depends on the stack_of_open_elements field. This commits remedies this oversight by removing this method and instead making the Tokenizer yield values of a new Event enum: enum Event<T> { Token(T), CdataOpen } Event::CdataOpen signals that the new Tokenizer::handle_cdata_open method has to be called, which accepts a CdataAction: enum CdataAction { Cdata, BogusComment } the variants of which correspond exactly to the possible outcomes of the third condition of the 'Markup declaration open state'. Removing this method also has the added benefit that the DefaultEmitter is now again spec-compliant, which lets us expose it again in the next commit in good conscience (previously it just hard-coded the method implementation to return false, which is why I had removed the DefaultEmitter from the public API in the last release). [1]: https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state
2023-09-03refactor: simplify Iterator impl for TokenizerMartin Fischer
2023-09-03chore: use `return` instead of `break`Martin Fischer
2023-09-03chore: move ControlToken enum definition to machineMartin Fischer
2023-09-03fix!: add missing `R: Position<O>` boundsMartin Fischer
It doesn't make sense that you're able to construct a Tokenizer/NaiveParser that you're unable to iterate over.
2023-08-19feat: introduce NaiveParserMartin Fischer
2023-08-19break!: remove type param defaults from TokenizerMartin Fischer
2023-08-19docs: correct `a HTML` to `an HTML` and fix 2 typosMartin Fischer
2023-08-19docs: link multipage version of HTML specMartin Fischer
2023-08-19chore: use link reference definitions in MarkdownMartin Fischer
2023-08-19feat!: add span and offsets to DoctypeMartin Fischer
2023-08-19feat!: add all-inclusive spans to tagsMartin Fischer
Also more performant since we no longer have to update the name span on every Emitter::push_tag_name call.
2023-08-19fix: fix lots of position off-by-onesMartin Fischer
Previously the PosTrackingReader always mysteriously subtracted 1 from the current position ... this wasn't sound at all ... the machine just happens to often call `Tokenizer::unread_char` ... but not always. E.g. for proper comments it didn't which resulted in their offset and spans being off-by-one, which is fixed by this commit (see test_spans.rs).
2023-08-19refactor!: make Emitter generic over offset instead of readerMartin Fischer
Emitters should not have access to the reader at all. Also the current position of the reader, at the time an Emitted method is called, very much depends on machine implementation details such as if `Tokenizer::unread_char` is used. Having the Emitter methods take offsets lets the machine take care of providing the right offsets, as evidenced by the next commit.
2023-08-19chore: move type param bounds to where clauseMartin Fischer
2023-08-19refactor!: remove Span trait, just use RangeMartin Fischer
`std::mem::size_of::<Range<NoopOffset>>()` is 0 so there's no need to abstract over Range.
2023-08-19refactor!: make Position generic over offset typeMartin Fischer
Previously Span was generic over R just so that it could provide the method: fn from_reader(reader: &R) -> Self; and properly implementing that method again relied on R implementing the Position trait: impl<P: Position> Span<P> for Range<usize> { .. } which was a very roundabout and awkward way of doing things. It makes much more sense to make the Position trait generic over the return type of its method (which previously always had to be usize). Which lets us provide a blanket implementation: impl<R: Reader> Position<NoopOffset> for R { .. }
2023-08-19refactor!: remove current_is_appropriate_end_tag_token from EmitterMartin Fischer
2023-08-19refactor: proxy essential Emitter methods through TokenizerMartin Fischer
2023-08-19break!: stop re-exporting reader traits & typesMartin Fischer
This is primarily done to make the rustdoc more readable (by grouping Reader, IntoReader, StringReader and BufReadReader in the reader module). Ideally IntoReader is already implemented for your input type and you don't have to concern yourself with these traits / types at all.
2023-08-19break!: merge Tokenizer::new_with_emitter into Tokenizer::newMartin Fischer
The Tokenizer does not perform any state switching, since proper state switching requires a feedback loop between tokenization and DOM tree building. Using the Tokenizer directly therefore is a bit of a pitfall, since you might not expect it to e.g. tokenize `<script><b>` as: StartTag(StartTag { name: "script", .. }) StartTag(StartTag { name: "b", .. }) Since we don't want to make walking into pitfalls particularly easy, this commit changes the Tokenizer::new method so that you have to specify the Emitter. Since this makes new_with_emitter redundant it is removed.
2023-08-19docs: move note about Reader impls to Reader traitMartin Fischer
2023-08-19break!: remove InfallibleTokenizer in favor of Iterator::flattenMartin Fischer