Commit Graph

491 Commits

Author SHA1 Message Date
Yorick Peterse fa838154fc Flush Element#namespace cache
When setting a new namespace name using Element#namespace_name= the
cache used by Element#namespace is flushed properly.
2015-04-11 19:20:50 +02:00
Yorick Peterse b0359b37e5 Cache Node#html? and Node#root_node
The results of these methods is now cached until a Node is moved into
another NodeSet. This reduces the time spent in the
xpath/evaluator/big_xml_average_bench.rb benchmark from roughly 10
seconds to roughly 5 seconds per iteration.
2015-04-11 19:12:26 +02:00
Yorick Peterse 4bdc8a3fdc Don't convert entities in script/style elements
In HTML the text of a script/style tag should be left untouched, no
entities must be converted. Doing so would break Javascript such as the
following:

    foo&&bar;

Such code is often the result of minifiers doing their dirty business.
2015-04-08 14:32:09 +02:00
Yorick Peterse 6a1010c287 Fixed decoding entities in attribute values
This was broken by introducing the process of lazy decoding of XML/HTML
entities. The new setup works similar to how XML::Text#text decodes any
entities that may be present.

Fixes #91
2015-04-07 21:18:22 +02:00
Yorick Peterse ef7f50137a Added Oga::EntityDecoder
This module removes some of the code duplication needed to determine
what entity decoder to use.
2015-04-07 21:18:15 +02:00
Yorick Peterse 0800654c96 Support lexing or carriage returns
Fixes #89.
2015-04-03 00:46:37 +02:00
Yorick Peterse 3176459307 Ignore declared namespaces in HTML documents
The HTML spec states that any declared namespaces, including the default
namespace are to be ignored.

This fixes #85
2015-03-26 22:38:39 +01:00
Yorick Peterse 5adeae18d0 XPath queries match nodes in the default namespace
When querying an XML document that explicitly defines the default XML
namespace the XPath evaluator now correctly matches all nodes within
that namespace if no namespace prefix is given in the query. Previously
this would always return an empty set.
2015-03-26 01:13:55 +01:00
Yorick Peterse f175414917 Added XML::Element#default_namespace? 2015-03-26 01:10:20 +01:00
Yorick Peterse b6fcd326ef Added XML::Node#html? and XML::Node#xml?
The former has been moved over from XML::Text, the latter just inverts
html?.
2015-03-26 01:02:32 +01:00
Yorick Peterse 4ad502958d Added XML::Attribute#==
Overwriting this method makes it easier to check if a given namespace
equals the default XML (and soon HTML) namespace.
2015-03-26 00:53:16 +01:00
Yorick Peterse f2d69af33b Distinguish default attribute/element namespaces
The previous commit messed this up because I wasn't fully awake.
2015-03-26 00:43:50 +01:00
Yorick Peterse 68ada997a8 Moved default namespace into Oga::XML
The default namespace is now located at Oga::XML::DEFAULT_NAMESPACE
instead of Oga::XML::Attribute::DEFAULT_NAMESPACE.
2015-03-26 00:35:28 +01:00
Yorick Peterse 66fa9f62ef Added LRU#maximum=/maximum
This allows one to change the maximum amount of keys stored in the
XPath/CSS caches, for example:

    Oga::XPath::Parser::CACHE.maximum = 2056
2015-03-23 00:26:48 +01:00
Yorick Peterse 2c4e490614 Added CSS/XPath Parser.parse_with_cache
This method parses and caches ASTs using Oga::LRU. Currently the default
of 1024 keys is used.

See #71 for more information.
2015-03-23 00:22:59 +01:00
Yorick Peterse 67d7d9af88 Added thread-safe LRU class
This class will be used for storing parser XPath/CSS ASTs.

See #71 for more information.
2015-03-23 00:21:52 +01:00
Yorick Peterse 45d84d31da Renamed rspec helper files 2015-03-22 22:50:03 +01:00
Yorick Peterse 70e4942d3e CSS parser spec for "+ b" 2015-03-21 01:23:00 +01:00
Yorick Peterse 6039e1dbeb XPath parsing spec for axes with predicates 2015-03-21 01:23:00 +01:00
Yorick Peterse 62fa2a9cc5 Spec for XPath functions inside predicates. 2015-03-21 01:23:00 +01:00
Yorick Peterse 194d981996 XPath specs for paths with multiple members. 2015-03-21 01:22:59 +01:00
Yorick Peterse fdcd712ffe Don't use Array#uniq in NodeSet#initialize.
Removing this makes the process of parsing larger XML documents a bit faster.
The downside is that NodeSet#initialize will no longer filter out duplicate
nodes, though this is not something Oga itself relies upon.

Methods such as NodeSet#push still do ignore elements already present.
2015-03-21 01:22:59 +01:00
Yorick Peterse f83c03aaec Fixed typo in NodeSet spec. 2015-03-21 01:22:59 +01:00
Yorick Peterse 006ef4d51a Port over most of the old XML error handling.
Some messages are a bit different due to ruby-ll's error handling, other than
that it's largely the same stuff as before.
2015-03-21 01:22:59 +01:00
Yorick Peterse d8b9725b82 Fixed SAX parsing of XML attributes.
This was utterly broken, mainly due to me overlooking it. There are now 2 new
callbacks to handle this properly:

* on_attribute: to handle a single attribute/value pair
* on_attributes: to handle a collection of attributes (as returned by
  on_attribute)

By default on_attribut returns a Hash, on_attributes in turn merges all
attribute hashes into a single one. This ensures that on_element _actually_
receives the attributes as a Hash, instead of an Array with random
nil/XML::Attribute values.
2015-03-21 01:22:59 +01:00
Yorick Peterse 605d565104 Use sax_parse_html for HTML documents.
I suspect the only reason this test ever passed due to Racc's error handling.
Either way this was using the wrong method.
2015-03-21 01:22:59 +01:00
Yorick Peterse 2ec91f130f Lazy decoding of XML/HTML entities.
Instead of decoding entities in the lexer we'll do this whenever XML::Text#text
is called. This removes the overhead from the parsing phase and ensures the
process is only triggered when actually needed. Note that calling #to_xml and/or
the #inspect methods on a Text (or parent) instance will also trigger the entity
conversion process.

The new entity decoding API supports both regular entities (e.g. &) as well
as codepoint based entities (both regular and hexadecimal codepoints).

To allow safe read-only access to Text instances from multiple threads a mutex
is used. This mutex ensures that only 1 thread can trigger the conversion
process.

Fixes #68
2015-03-05 23:00:43 +01:00
Yorick Peterse 3b2055a30b Refactored handling of literal HTML elements.
This ensures newlines can appear in <style> / <script> tags when using IOs as
input.
2015-03-04 11:44:31 +01:00
Yorick Peterse 78e40b55c0 Handle parsing of HTML <style> tags.
This basically re-applies the technique used for HTML <script> tags. With this
extra addition I decided to rename/normalize a few things so it's easier to add
any extra tags in the future. One downside of this setup is that the following
will not be parsed by Oga:

    <style>
        </script>
    </style>

The same applies to script tags containing a literal </style> tag. Since this
particular case is rather unlikely to occur I'm OK with not supporting it as it
_does_ simplify the lexer quite a bit.

Fixes #80
2015-03-03 16:28:05 +01:00
Yorick Peterse 142b467277 Set parent of nodes set using Element#inner_text=
This ensures that any text nodes created using Element#inner_text= have their
parent node set correctly.
2015-03-03 13:13:05 +01:00
Yorick Peterse 874d7124af Don't convert <script> text to XML entities.
Fixes #79.
2015-03-02 17:32:19 +01:00
Yorick Peterse 9a586363e9 Added XML::Document#html? 2015-03-02 16:39:40 +01:00
Yorick Peterse 351b5ac004 Added spec for lexing inline HTML script tags.
Related issue: #70
2015-03-02 16:20:06 +01:00
Yorick Peterse 47a3c5e7f8 Use describe/it instead of context/example.
This keeps things consistent with the general testing guidelines in the Ruby
community. This in turn should hopefully make my life easier as I don't have to
tell people to use this rather odd stlye I was using before.
2015-01-08 23:01:53 +01:00
Yorick Peterse 746c8052dd Remove all nodes when calling Element#inner_text=
This fixes #64.
2014-12-14 23:32:43 +01:00
Dmitry Krasnoukhov 26baf89440 Add missing entities to the decode/encode lists 2014-11-21 01:53:11 +02:00
Yorick Peterse cbb2815146 Support for inline doctype rules plus newlines.
This adds support for lexing/parsing XML documents that use an IO as input _and_
contain doctype rules with newlines in them.

This fixes #63.
2014-11-18 20:02:55 +01:00
Yorick Peterse ad4f650c5d Fixed XML entity encoding/decoding ordering.
Thanks to @krasnoukhov for providing the initial patch, which this commit is
largely based on.

This fixes #49.
2014-11-17 22:39:43 +01:00
Yorick Peterse cd86d5d294 Allow removal of element attributes. 2014-11-17 09:00:40 +01:00
Yorick Peterse 804646cc5e Don't modify raw namespaces.
When calling Element#available_namespaces the list of namespaces returned by
Element#namespaces must not be modified.
2014-11-17 00:01:16 +01:00
Yorick Peterse 57adabc068 Ensure SAX after_element receives meaningful args
This changes the behaviour of after_element when parsing documents using the SAX
parsing API. Previously it would always receive a nil argument, which is kinda
pointless. This commit changes that by making sure it receives a namespace name
(if any) and the element name.

This fixes #54.
2014-11-16 23:32:32 +01:00
Yorick Peterse 448ff56e38 Fixed CSS eval specs for nth-(first|last)-of-type. 2014-11-15 18:27:26 +01:00
Yorick Peterse b464815577 Fixed AST generation for nth-(first|last)-of-type. 2014-11-15 18:27:15 +01:00
Yorick Peterse 9eead81a7c Fixed AST for :only-of-type 2014-11-15 18:08:26 +01:00
Yorick Peterse 1c301d40e2 Properly fixed AST for first-of-type/last-of-type
This requires keeping track of the current element being processed. This in turn
allows the usage of count() + preceding-sibling/following-sibling.
2014-11-15 17:58:56 +01:00
Yorick Peterse e559b4b89b Corrected :first-of-type eval spec. 2014-11-15 17:20:17 +01:00
Yorick Peterse f1d574f342 Evaluate XPath predicates for every context node.
Instead of evaluating a predicate once for all context nodes, they should
instead be evaluated separately per context node.
2014-11-15 00:31:44 +01:00
Yorick Peterse 6daa3e7a00 Reverted AST changes for first-of-type
Functions can't be used in combination with axes, so I'll just need to fix the
position() function to work properly.
2014-11-14 23:51:46 +01:00
Yorick Peterse 2d6a2be2e8 Revert "Fixed XPath AST for :last-of-type"
Axes can't be used in combination with functions.

This reverts commit b0b572a584.
2014-11-14 23:49:49 +01:00
Yorick Peterse 8f3553f8f1 Fixed eval specs of :first-of-type & :last-of-type 2014-11-14 23:27:52 +01:00
Yorick Peterse b0b572a584 Fixed XPath AST for :last-of-type
This should count following nodes, not merely the position.
2014-11-14 23:27:15 +01:00
Yorick Peterse 0128dc50ae Fixed CSS evaluation of :first-of-type
The old XPath "position() = 1" would work in Nokogiri due to the way they
retrieve descendants. In Oga however this would simply always return the first
node.

To fix this Oga now counts the amount of preceding siblings that match the same
full name.
2014-11-14 01:25:03 +01:00
Yorick Peterse e3a26c5d15 Allow querying of nodes using CSS. 2014-11-14 01:05:29 +01:00
Yorick Peterse d47ca19ffa Remaining CSS evaluation specs. 2014-11-14 00:24:54 +01:00
Yorick Peterse 518bedc3a1 CSS evaluator specs for :nth-of-type 2014-11-14 00:16:35 +01:00
Yorick Peterse abfe6e3d61 CSS evaluator specs for nth-last-of-type 2014-11-14 00:13:11 +01:00
Yorick Peterse c874ceabb9 CSS evaluator specs for :nth-last-child 2014-11-13 23:54:47 +01:00
Yorick Peterse 5964a2cda4 CSS evaluator specs for :nth-child(n) 2014-11-13 22:50:04 +01:00
Yorick Peterse 3237617bf5 CSS eval specs for various pseudo classes.
This includes the following pseudos:

* :empty
* :first-child
* :first-of-type
* :last-child
* :last-of-type
2014-11-13 10:10:31 +01:00
Yorick Peterse 27ffa4d3d5 Added various failing following/preceding specs. 2014-11-13 01:11:13 +01:00
Yorick Peterse 97a9a11db1 Failing CSS evaluation specs for the axes.
These currently fail due to the ~ and + axes not being evaluated properly.
2014-11-12 23:38:17 +01:00
Yorick Peterse 817a5e075b Wrap predicate AST nodes _around_ other nodes.
This means that "foo[1]" uses this AST:

    (predicate (test nil "foo") (int 1))

Instead of this AST:

    (test nil "foo" (int 1))

This makes it easier for the XPath evaluator to process predicates correctly.
2014-11-12 22:59:38 +01:00
Yorick Peterse 24350fa457 Added various predicate specs for XPath axes. 2014-11-12 09:40:22 +01:00
Yorick Peterse c15604a86f CSS evaluator specs for IDs. 2014-11-11 00:21:28 +01:00
Yorick Peterse b9e1b51270 CSS evaluator specs for classes. 2014-11-11 00:18:44 +01:00
Yorick Peterse 43200238c5 CSS evaluator specs for predicates and operators. 2014-11-10 23:21:00 +01:00
Yorick Peterse d5002010fe Removed RSpec shared examples. 2014-11-10 00:06:26 +01:00
Yorick Peterse 1f855dc982 Rewrote CSS evaluator paths spec. 2014-11-09 23:51:23 +01:00
Yorick Peterse fb1927a7c7 Removed use of shared examples in Element specs. 2014-11-09 23:44:14 +01:00
Yorick Peterse ccbb19a42d Rewrote all XPath evaluator type specs. 2014-11-09 23:43:01 +01:00
Yorick Peterse c5c3c5dbc3 Rewrote all XPath evaluator type test specs. 2014-11-09 23:39:47 +01:00
Yorick Peterse ca5da3f9c9 Rewrote all XPath evaluator operator tests. 2014-11-09 23:31:05 +01:00
Yorick Peterse 28a1f1b8a9 Rewrote all XPath evaluator call specs. 2014-11-09 23:23:52 +01:00
Yorick Peterse 58209cbad0 Rewrote all XPath axis specs. 2014-11-09 22:53:47 +01:00
Yorick Peterse 5f13cc9d73 Rewrote XPath evaluator wildcards spec. 2014-11-09 18:56:49 +01:00
Yorick Peterse ceed3a6046 Rewrote XPath evaluator predicates spec. 2014-11-09 18:52:04 +01:00
Yorick Peterse 3893e56ca8 Rewrote XPath evaluator paths spec.
This is the first spec of many that will be re-written. Eventually this will
remove the need of the shared examples as well as removing lots of code
duplication and odd context blocks.
2014-11-09 18:47:20 +01:00
Yorick Peterse 857ac517d5 Added XML::NodeSet#==
This method can be used to compare two NodeSet instances. By using
XML::NodeSet#equal_nodes?() the need for exposing the "nodes" instance variable
is also removed.
2014-11-09 18:33:16 +01:00
Yorick Peterse 7e38e20586 Use "include" vs "return" in CSS path spec. 2014-11-07 09:28:18 +01:00
Yorick Peterse a586a512b8 Removed support for CSS such as "|X"
This expression could be used to get all elements that _don't_ have any
namespace. The problem is that this can't be expressed as just a node test,
instead the resulting XPath would have to look something like the following:

    X[local-name() = name()]

However, since the XPath predicates are already created for pseudo classes and
such, also injecting the above into it would be a real big pain. As such I've
decided not to support it.
2014-11-05 00:45:40 +01:00
Yorick Peterse 661741268a CSS parser tests for paths with namespaces. 2014-11-05 00:44:23 +01:00
Yorick Peterse 61801fe562 Allow CSS identifiers to start with an underscore. 2014-11-05 00:37:40 +01:00
Yorick Peterse f1316c50fb Allow XPath idents to start with an underscore.
This is valid in XML so XPath should support it as well.
2014-11-05 00:35:47 +01:00
Yorick Peterse eb3a3e7630 Use the descendant axis for CSS selectors.
Instead of using "descendant-or-self" Oga will use "descendant". This ensures
that expressions such as "foo *" don't return a set also including the "foo"
element.

Nokogiri solves this problem in a somewhat different way by using //foo//* for
the CSS expression "foo *". While this works in Nokogiri the expression
"descendant-or-self::node()" is slow as a snail in Oga (due to its nature of
retrieving _all_ nodes first). By using "descendant" we can work around this
problem.
2014-11-05 00:22:09 +01:00
Yorick Peterse 602f2fe8bb Apply node() type tests to the document too.
When running XPath queries such as "self::node()" the result should be a set
containing the document itself. This in turn fixes expressions such as
descendant-or-self::node()/a.
2014-11-04 23:41:45 +01:00
Yorick Peterse 1f3b4cb2fb Added initial CSS evaluation tests. 2014-11-04 23:34:01 +01:00
Yorick Peterse f6319ed0c7 Added failing descendant-or-self XPath specs.
These currently fail due to the child:: selector not working entirely as it
should be. Consider the following XML:

    <a><b><b><c class="x"></c></b></b></a>

And the following XPath:

    descendant-or-self::node()/a

In Nokogiri/libxml this will return a node set containing the <a> node. In Oga
however this will return an empty node set. This will require some further
investigation to see what exactly is going on, and in particular what is the
correct behaviour.
2014-11-04 23:34:01 +01:00
Yorick Peterse de04c61df9 Parsing support for the :empty pseudo. 2014-11-04 00:00:23 +01:00
Yorick Peterse 1b870406de Parsing support for the :only-of-type pseudo. 2014-11-03 23:47:25 +01:00
Yorick Peterse 2cf058457d Parsing support for the :only-child pseudo. 2014-11-03 23:27:56 +01:00
Yorick Peterse 759bb71d17 Parsing support for the :last-of-type pseudo. 2014-11-03 23:01:44 +01:00
Yorick Peterse 10632eafd4 Parsing support for the :first-of-type pseudo. 2014-11-03 23:00:15 +01:00
Yorick Peterse 7a606a11d3 Parsing support for the :last-child pseudo class. 2014-11-03 22:58:08 +01:00
Yorick Peterse b4fec3cc8c Parsing support for the :first-child pseudo class. 2014-11-03 22:45:00 +01:00
Yorick Peterse 020d979fba Parsing support for :nth-last-of-type(). 2014-11-03 22:15:21 +01:00
Yorick Peterse ab8b451dc3 Parsing support for :nth-of-type() 2014-11-02 19:29:39 +01:00
Yorick Peterse 0faceffacb Parsing support for nth-child(n+X) 2014-11-02 19:29:09 +01:00
Yorick Peterse 8d8d74ec41 Drop nth-child support of all negative sequences
This removes parsing support for selectors such as :nth-child(-n-6). According
to the CSS spec this isn't valid anyway (confirmed by testing it in Chromium).
As a result there's no point in supporting it in any way.
2014-11-02 19:19:05 +01:00
Yorick Peterse b31288b7d2 Use correct modulo for nth-child and negatives. 2014-11-02 18:53:23 +01:00
Yorick Peterse 9cce93fc4a Parsing support for :nth-last-child. 2014-11-01 20:58:28 +01:00