better example text
[catagits/DOM-Tiny.git] / README.pod
index 01d617a..c827c68 100644 (file)
@@ -2,8 +2,6 @@
 
 =encoding utf8
 
-=for Pod::Coverage TO_JSON
-
 =head1 NAME
 
 DOM::Tiny - Minimalistic HTML/XML DOM parser with CSS selectors
@@ -37,10 +35,11 @@ DOM::Tiny - Minimalistic HTML/XML DOM parser with CSS selectors
 
 =head1 DESCRIPTION
 
-L<DOM::Tiny> is a minimalistic and relaxed pure-perl HTML/XML DOM parser with
-support for the L<HTML Living Standard|https://html.spec.whatwg.org/> and
-L<CSS3 selectors|http://www.w3.org/TR/selectors/> based on L<Mojo::DOM>. It
-will even try to interpret broken HTML and XML, so you should not use it for
+L<DOM::Tiny> is a minimalistic and relaxed pure-perl HTML/XML DOM parser based
+on L<Mojo::DOM>. It supports the L<HTML Living Standard|https://html.spec.whatwg.org/>
+and L<Extensible Markup Language (XML) 1.0|http://www.w3.org/TR/xml/>, and
+matching based on L<CSS3 selectors|http://www.w3.org/TR/selectors/>. It will
+even try to interpret broken HTML and XML, so you should not use it for
 validation.
 
 =head1 NODES AND ELEMENTS
@@ -95,6 +94,260 @@ XML detection can also be disabled with the L</"xml"> method.
   my $dom = DOM::Tiny->new->xml(0)->parse('<P ID="greeting">Hi!</P>');
   say $dom->at('p[id]')->text;
 
+=head1 SELECTORS
+
+L<DOM::Tiny> uses a CSS selector engine based on L<Mojo::DOM::CSS>. All CSS
+selectors that make sense for a standalone parser are supported.
+
+=head2 *
+
+Any element.
+
+  my $all = $dom->find('*');
+
+=head2 E
+
+An element of type C<E>.
+
+  my $title = $dom->at('title');
+
+=head2 E[foo]
+
+An C<E> element with a C<foo> attribute.
+
+  my $links = $dom->find('a[href]');
+
+=head2 E[foo="bar"]
+
+An C<E> element whose C<foo> attribute value is exactly equal to C<bar>.
+
+  my $case_sensitive = $dom->find('input[type="hidden"]');
+  my $case_sensitive = $dom->find('input[type=hidden]');
+
+=head2 E[foo="bar" i]
+
+An C<E> element whose C<foo> attribute value is exactly equal to any
+(ASCII-range) case-permutation of C<bar>. Note that this selector is
+EXPERIMENTAL and might change without warning!
+
+  my $case_insensitive = $dom->find('input[type="hidden" i]');
+  my $case_insensitive = $dom->find('input[type=hidden i]');
+  my $case_insensitive = $dom->find('input[class~="foo" i]');
+
+This selector is part of
+L<Selectors Level 4|http://dev.w3.org/csswg/selectors-4>, which is still a work
+in progress.
+
+=head2 E[foo~="bar"]
+
+An C<E> element whose C<foo> attribute value is a list of whitespace-separated
+values, one of which is exactly equal to C<bar>.
+
+  my $foo = $dom->find('input[class~="foo"]');
+  my $foo = $dom->find('input[class~=foo]');
+
+=head2 E[foo^="bar"]
+
+An C<E> element whose C<foo> attribute value begins exactly with the string
+C<bar>.
+
+  my $begins_with = $dom->find('input[name^="f"]');
+  my $begins_with = $dom->find('input[name^=f]');
+
+=head2 E[foo$="bar"]
+
+An C<E> element whose C<foo> attribute value ends exactly with the string
+C<bar>.
+
+  my $ends_with = $dom->find('input[name$="o"]');
+  my $ends_with = $dom->find('input[name$=o]');
+
+=head2 E[foo*="bar"]
+
+An C<E> element whose C<foo> attribute value contains the substring C<bar>.
+
+  my $contains = $dom->find('input[name*="fo"]');
+  my $contains = $dom->find('input[name*=fo]');
+
+=head2 E:root
+
+An C<E> element, root of the document.
+
+  my $root = $dom->at(':root');
+
+=head2 E:nth-child(n)
+
+An C<E> element, the C<n-th> child of its parent.
+
+  my $third = $dom->find('div:nth-child(3)');
+  my $odd   = $dom->find('div:nth-child(odd)');
+  my $even  = $dom->find('div:nth-child(even)');
+  my $top3  = $dom->find('div:nth-child(-n+3)');
+
+=head2 E:nth-last-child(n)
+
+An C<E> element, the C<n-th> child of its parent, counting from the last one.
+
+  my $third    = $dom->find('div:nth-last-child(3)');
+  my $odd      = $dom->find('div:nth-last-child(odd)');
+  my $even     = $dom->find('div:nth-last-child(even)');
+  my $bottom3  = $dom->find('div:nth-last-child(-n+3)');
+
+=head2 E:nth-of-type(n)
+
+An C<E> element, the C<n-th> sibling of its type.
+
+  my $third = $dom->find('div:nth-of-type(3)');
+  my $odd   = $dom->find('div:nth-of-type(odd)');
+  my $even  = $dom->find('div:nth-of-type(even)');
+  my $top3  = $dom->find('div:nth-of-type(-n+3)');
+
+=head2 E:nth-last-of-type(n)
+
+An C<E> element, the C<n-th> sibling of its type, counting from the last one.
+
+  my $third    = $dom->find('div:nth-last-of-type(3)');
+  my $odd      = $dom->find('div:nth-last-of-type(odd)');
+  my $even     = $dom->find('div:nth-last-of-type(even)');
+  my $bottom3  = $dom->find('div:nth-last-of-type(-n+3)');
+
+=head2 E:first-child
+
+An C<E> element, first child of its parent.
+
+  my $first = $dom->find('div p:first-child');
+
+=head2 E:last-child
+
+An C<E> element, last child of its parent.
+
+  my $last = $dom->find('div p:last-child');
+
+=head2 E:first-of-type
+
+An C<E> element, first sibling of its type.
+
+  my $first = $dom->find('div p:first-of-type');
+
+=head2 E:last-of-type
+
+An C<E> element, last sibling of its type.
+
+  my $last = $dom->find('div p:last-of-type');
+
+=head2 E:only-child
+
+An C<E> element, only child of its parent.
+
+  my $lonely = $dom->find('div p:only-child');
+
+=head2 E:only-of-type
+
+An C<E> element, only sibling of its type.
+
+  my $lonely = $dom->find('div p:only-of-type');
+
+=head2 E:empty
+
+An C<E> element that has no children (including text nodes).
+
+  my $empty = $dom->find(':empty');
+
+=head2 E:checked
+
+A user interface element C<E> which is checked (for instance a radio-button or
+checkbox).
+
+  my $input = $dom->find(':checked');
+
+=head2 E.warning
+
+An C<E> element whose class is "warning".
+
+  my $warning = $dom->find('div.warning');
+
+=head2 E#myid
+
+An C<E> element with C<ID> equal to "myid".
+
+  my $foo = $dom->at('div#foo');
+
+=head2 E:not(s)
+
+An C<E> element that does not match simple selector C<s>.
+
+  my $others = $dom->find('div p:not(:first-child)');
+
+=head2 E F
+
+An C<F> element descendant of an C<E> element.
+
+  my $headlines = $dom->find('div h1');
+
+=head2 E E<gt> F
+
+An C<F> element child of an C<E> element.
+
+  my $headlines = $dom->find('html > body > div > h1');
+
+=head2 E + F
+
+An C<F> element immediately preceded by an C<E> element.
+
+  my $second = $dom->find('h1 + h2');
+
+=head2 E ~ F
+
+An C<F> element preceded by an C<E> element.
+
+  my $second = $dom->find('h1 ~ h2');
+
+=head2 E, F, G
+
+Elements of type C<E>, C<F> and C<G>.
+
+  my $headlines = $dom->find('h1, h2, h3');
+
+=head2 E[foo=bar][bar=baz]
+
+An C<E> element whose attributes match all following attribute selectors.
+
+  my $links = $dom->find('a[foo^=b][foo$=ar]');
+
+=head1 OPERATORS
+
+L<DOM::Tiny> overloads the following operators.
+
+=head2 array
+
+  my @nodes = @$dom;
+
+Alias for L</"child_nodes">.
+
+  # "<!-- Test -->"
+  $dom->parse('<!-- Test --><b>123</b>')->[0];
+
+=head2 bool
+
+  my $bool = !!$dom;
+
+Always true.
+
+=head2 hash
+
+  my %attrs = %$dom;
+
+Alias for L</"attr">.
+
+  # "test"
+  $dom->parse('<div id="test">Test</div>')->at('div')->{id};
+
+=head2 stringify
+
+  my $str = "$dom";
+
+Alias for L</"to_string">.
+
 =head1 METHODS
 
 L<DOM::Tiny> implements the following methods.
@@ -127,8 +380,8 @@ whitespace trimming is enabled by default.
   my $collection = $dom->ancestors('div ~ p');
 
 Find all ancestor elements of this node matching the CSS selector and return a
-L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
-objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+L<collection|/"COLLECTION METHODS"> containing these elements as L<DOM::Tiny>
+objects. All selectors listed in L</"SELECTORS"> are supported.
 
   # List tag names of ancestor elements
   say $dom->ancestors->map('tag')->join("\n");
@@ -171,7 +424,7 @@ node's content.
 
 Find first descendant element of this element matching the CSS selector and
 return it as a L<DOM::Tiny> object or return C<undef> if none could be found.
-All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+All selectors listed in L</"SELECTORS"> are supported.
 
   # Find first element with "svg" namespace definition
   my $namespace = $dom->at('[xmlns\:svg]')->{'xmlns:svg'};
@@ -198,7 +451,7 @@ This element's attributes.
 
   my $collection = $dom->child_nodes;
 
-Return a L<DOM::Tiny::Collection> object containing all child nodes of this
+Return a L<collection|/"COLLECTION METHODS"> containing all child nodes of this
 element as L<DOM::Tiny> objects.
 
   # "<p><b>123</b></p>"
@@ -216,8 +469,8 @@ element as L<DOM::Tiny> objects.
   my $collection = $dom->children('div ~ p');
 
 Find all child elements of this element matching the CSS selector and return a
-L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
-objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+L<collection|/"COLLECTION METHODS"> containing these elements as L<DOM::Tiny>
+objects. All selectors listed in L</"SELECTORS"> are supported.
 
   # Show tag name of random child element
   say $dom->children->shuffle->first->tag;
@@ -253,7 +506,7 @@ and C<tag> nodes) or raw content.
 
   my $collection = $dom->descendant_nodes;
 
-Return a L<DOM::Tiny::Collection> object containing all descendant nodes of
+Return a L<collection|/"COLLECTION METHODS"> containing all descendant nodes of
 this element as L<DOM::Tiny> objects.
 
   # "<p><b>123</b></p>"
@@ -271,9 +524,8 @@ this element as L<DOM::Tiny> objects.
   my $collection = $dom->find('div ~ p');
 
 Find all descendant elements of this element matching the CSS selector and
-return a L<DOM::Tiny::Collection> object containing these elements as
-L<DOM::Tiny> objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are
-supported.
+return a L<collection|/"COLLECTION METHODS"> containing these elements as
+L<DOM::Tiny> objects. All selectors listed in L</"SELECTORS"> are supported.
 
   # Find a specific element and extract information
   my $id = $dom->find('div')->[23]{id};
@@ -293,8 +545,8 @@ supported.
   my $collection = $dom->following('div ~ p');
 
 Find all sibling elements after this node matching the CSS selector and return
-a L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
-objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+a L<collection|/"COLLECTION METHODS"> containing these elements as L<DOM::Tiny>
+objects. All selectors listen in L</"SELECTORS"> are supported.
 
   # List tags of sibling elements after this node
   say $dom->following->map('tag')->join("\n");
@@ -303,7 +555,7 @@ objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
 
   my $collection = $dom->following_nodes;
 
-Return a L<DOM::Tiny::Collection> object containing all sibling nodes after
+Return a L<collection|/"COLLECTION METHODS"> containing all sibling nodes after
 this node as L<DOM::Tiny> objects.
 
   # "C"
@@ -313,8 +565,8 @@ this node as L<DOM::Tiny> objects.
 
   my $bool = $dom->matches('div ~ p');
 
-Check if this element matches the CSS selector. All selectors from
-L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+Check if this element matches the CSS selector. All selectors listed in
+L</"SELECTORS"> are supported.
 
   # True
   $dom->parse('<p class="a">A</p>')->at('p')->matches('.a');
@@ -372,7 +624,7 @@ no parent.
 
   $dom = $dom->parse('<foo bar="baz">I ♥ DOM::Tiny!</foo>');
 
-Parse HTML/XML fragment with L<DOM::Tiny::HTML>.
+Parse HTML/XML fragment.
 
   # Parse XML
   my $dom = DOM::Tiny->new->xml(1)->parse($xml);
@@ -383,8 +635,8 @@ Parse HTML/XML fragment with L<DOM::Tiny::HTML>.
   my $collection = $dom->preceding('div ~ p');
 
 Find all sibling elements before this node matching the CSS selector and return
-a L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
-objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
+a L<collection|/"COLLECTION METHODS"> containing these elements as L<DOM::Tiny>
+objects. All selectors listed in L</"SELECTORS"> are supported.
 
   # List tags of sibling elements before this node
   say $dom->preceding->map('tag')->join("\n");
@@ -393,8 +645,8 @@ objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
 
   my $collection = $dom->preceding_nodes;
 
-Return a L<DOM::Tiny::Collection> object containing all sibling nodes before
-this node as L<DOM::Tiny> objects.
+Return a L<collection|/"COLLECTION METHODS"> containing all sibling nodes
+before this node as L<DOM::Tiny> objects.
 
   # "A"
   $dom->parse('A<!-- B --><p>C</p>')->at('p')->preceding_nodes->first->content;
@@ -643,45 +895,11 @@ children of the first innermost element.
 Disable HTML semantics in parser and activate case-sensitivity, defaults to
 auto detection based on processing instructions.
 
-=head1 OPERATORS
-
-L<DOM::Tiny> overloads the following operators.
-
-=head2 array
-
-  my @nodes = @$dom;
-
-Alias for L</"child_nodes">.
-
-  # "<!-- Test -->"
-  $dom->parse('<!-- Test --><b>123</b>')->[0];
-
-=head2 bool
-
-  my $bool = !!$dom;
-
-Always true.
-
-=head2 hash
-
-  my %attrs = %$dom;
-
-Alias for L</"attr">.
-
-  # "test"
-  $dom->parse('<div id="test">Test</div>')->at('div')->{id};
-
-=head2 stringify
-
-  my $str = "$dom";
-
-Alias for L</"to_string">.
-
 =head1 COLLECTION METHODS
 
-Some L<DOM::Tiny> methods return an array-based collection object, which can
-either be accessed directly as an array reference, or with the following
-methods.
+Some L<DOM::Tiny> methods return an array-based collection object based on
+L<Mojo::Collection>, which can either be accessed directly as an array
+reference, or with the following methods.
 
   # Chain methods
   $collection->map(sub { ucfirst })->shuffle->each(sub {
@@ -734,8 +952,8 @@ passed to the callback and is also available as C<$_>.
   # Longer version
   my $first = $collection->first(sub { $_->$method(@args) });
 
-  # Find first value that contains the word "dom"
-  my $interesting = $collection->first(qr/dom/i);
+  # Find first value that contains the word "tiny"
+  my $interesting = $collection->first(qr/tiny/i);
 
   # Find first value that is greater than 5
   my $greater = $collection->first(sub { $_ > 5 });
@@ -766,8 +984,8 @@ C<$_>.
   # Longer version
   my $new = $collection->grep(sub { $_->$method(@args) });
 
-  # Find all values that contain the word "dom"
-  my $interesting = $collection->grep(qr/dom/i);
+  # Find all values that contain the word "tiny"
+  my $interesting = $collection->grep(qr/tiny/i);
 
   # Find all values that are greater than 5
   my $greater = $collection->grep(sub { $_ > 5 });
@@ -801,8 +1019,8 @@ passed to the callback and is also available as C<$_>.
   # Longer version
   my $new = $collection->map(sub { $_->$method(@args) });
 
-  # Append the word "dom" to all values
-  my $domified = $collection->map(sub { $_ . 'dom' });
+  # Append the word "tiny" to all values
+  my $domified = $collection->map(sub { $_ . 'tiny' });
 
 =head2 reduce
 
@@ -906,6 +1124,8 @@ This is free software, licensed under:
 
 =head1 SEE ALSO
 
-L<Mojo::DOM>, L<XML::LibXML>, L<XML::Twig>, L<HTML::TreeBuilder>, L<XML::Smart>
+L<Mojo::DOM>, L<HTML::TreeBuilder>, L<XML::LibXML>, L<XML::Twig>, L<XML::Smart>
+
+=for Pod::Coverage TO_JSON
 
 =cut