move collection documentation to main module
[catagits/DOM-Tiny.git] / README.pod
1 =pod
2
3 =encoding utf8
4
5 =for Pod::Coverage TO_JSON
6
7 =head1 NAME
8
9 DOM::Tiny - Minimalistic HTML/XML DOM parser with CSS selectors
10
11 =head1 SYNOPSIS
12
13   use DOM::Tiny;
14
15   # Parse
16   my $dom = DOM::Tiny->new('<div><p id="a">Test</p><p id="b">123</p></div>');
17
18   # Find
19   say $dom->at('#b')->text;
20   say $dom->find('p')->map('text')->join("\n");
21   say $dom->find('[id]')->map(attr => 'id')->join("\n");
22
23   # Iterate
24   $dom->find('p[id]')->reverse->each(sub { say $_->{id} });
25
26   # Loop
27   for my $e ($dom->find('p[id]')->each) {
28     say $e->{id}, ':', $e->text;
29   }
30
31   # Modify
32   $dom->find('div p')->last->append('<p id="c">456</p>');
33   $dom->find(':not(p)')->map('strip');
34
35   # Render
36   say "$dom";
37
38 =head1 DESCRIPTION
39
40 L<DOM::Tiny> is a minimalistic and relaxed pure-perl HTML/XML DOM parser with
41 support for the L<HTML Living Standard|https://html.spec.whatwg.org/> and
42 L<CSS3 selectors|http://www.w3.org/TR/selectors/> based on L<Mojo::DOM>. It
43 will even try to interpret broken HTML and XML, so you should not use it for
44 validation.
45
46 =head1 NODES AND ELEMENTS
47
48 When we parse an HTML/XML fragment, it gets turned into a tree of nodes.
49
50   <!DOCTYPE html>
51   <html>
52     <head><title>Hello</title></head>
53     <body>World!</body>
54   </html>
55
56 There are currently eight different kinds of nodes, C<cdata>, C<comment>,
57 C<doctype>, C<pi>, C<raw>, C<root>, C<tag> and C<text>. Elements are nodes of
58 the type C<tag>.
59
60   root
61   |- doctype (html)
62   +- tag (html)
63      |- tag (head)
64      |  +- tag (title)
65      |     +- raw (Hello)
66      +- tag (body)
67         +- text (World!)
68
69 While all node types are represented as L<DOM::Tiny> objects, some methods like
70 L</"attr"> and L</"namespace"> only apply to elements.
71
72 =head1 CASE-SENSITIVITY
73
74 L<DOM::Tiny> defaults to HTML semantics, that means all tags and attribute
75 names are lowercased and selectors need to be lowercase as well.
76
77   # HTML semantics
78   my $dom = DOM::Tiny->new('<P ID="greeting">Hi!</P>');
79   say $dom->at('p[id]')->text;
80
81 If XML processing instructions are found, the parser will automatically switch
82 into XML mode and everything becomes case-sensitive.
83
84   # XML semantics
85   my $dom = DOM::Tiny->new('<?xml version="1.0"?><P ID="greeting">Hi!</P>');
86   say $dom->at('P[ID]')->text;
87
88 XML detection can also be disabled with the L</"xml"> method.
89
90   # Force XML semantics
91   my $dom = DOM::Tiny->new->xml(1)->parse('<P ID="greeting">Hi!</P>');
92   say $dom->at('P[ID]')->text;
93
94   # Force HTML semantics
95   my $dom = DOM::Tiny->new->xml(0)->parse('<P ID="greeting">Hi!</P>');
96   say $dom->at('p[id]')->text;
97
98 =head1 METHODS
99
100 L<DOM::Tiny> implements the following methods.
101
102 =head2 new
103
104   my $dom = DOM::Tiny->new;
105   my $dom = DOM::Tiny->new('<foo bar="baz">I ♥ DOM::Tiny!</foo>');
106
107 Construct a new scalar-based L<DOM::Tiny> object and L</"parse"> HTML/XML
108 fragment if necessary.
109
110 =head2 all_text
111
112   my $trimmed   = $dom->all_text;
113   my $untrimmed = $dom->all_text(0);
114
115 Extract text content from all descendant nodes of this element, smart
116 whitespace trimming is enabled by default.
117
118   # "foo bar baz"
119   $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->all_text;
120
121   # "foo\nbarbaz\n"
122   $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->all_text(0);
123
124 =head2 ancestors
125
126   my $collection = $dom->ancestors;
127   my $collection = $dom->ancestors('div ~ p');
128
129 Find all ancestor elements of this node matching the CSS selector and return a
130 L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
131 objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
132
133   # List tag names of ancestor elements
134   say $dom->ancestors->map('tag')->join("\n");
135
136 =head2 append
137
138   $dom = $dom->append('<p>I ♥ DOM::Tiny!</p>');
139
140 Append HTML/XML fragment to this node.
141
142   # "<div><h1>Test</h1><h2>123</h2></div>"
143   $dom->parse('<div><h1>Test</h1></div>')
144     ->at('h1')->append('<h2>123</h2>')->root;
145
146   # "<p>Test 123</p>"
147   $dom->parse('<p>Test</p>')->at('p')
148     ->child_nodes->first->append(' 123')->root;
149
150 =head2 append_content
151
152   $dom = $dom->append_content('<p>I ♥ DOM::Tiny!</p>');
153
154 Append HTML/XML fragment (for C<root> and C<tag> nodes) or raw content to this
155 node's content.
156
157   # "<div><h1>Test123</h1></div>"
158   $dom->parse('<div><h1>Test</h1></div>')
159     ->at('h1')->append_content('123')->root;
160
161   # "<!-- Test 123 --><br>"
162   $dom->parse('<!-- Test --><br>')
163     ->child_nodes->first->append_content('123 ')->root;
164
165   # "<p>Test<i>123</i></p>"
166   $dom->parse('<p>Test</p>')->at('p')->append_content('<i>123</i>')->root;
167
168 =head2 at
169
170   my $result = $dom->at('div ~ p');
171
172 Find first descendant element of this element matching the CSS selector and
173 return it as a L<DOM::Tiny> object or return C<undef> if none could be found.
174 All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
175
176   # Find first element with "svg" namespace definition
177   my $namespace = $dom->at('[xmlns\:svg]')->{'xmlns:svg'};
178
179 =head2 attr
180
181   my $hash = $dom->attr;
182   my $foo  = $dom->attr('foo');
183   $dom     = $dom->attr({foo => 'bar'});
184   $dom     = $dom->attr(foo => 'bar');
185
186 This element's attributes.
187
188   # Remove an attribute
189   delete $dom->attr->{id};
190
191   # Attribute without value
192   $dom->attr(selected => undef);
193
194   # List id attributes
195   say $dom->find('*')->map(attr => 'id')->compact->join("\n");
196
197 =head2 child_nodes
198
199   my $collection = $dom->child_nodes;
200
201 Return a L<DOM::Tiny::Collection> object containing all child nodes of this
202 element as L<DOM::Tiny> objects.
203
204   # "<p><b>123</b></p>"
205   $dom->parse('<p>Test<b>123</b></p>')->at('p')->child_nodes->first->remove;
206
207   # "<!DOCTYPE html>"
208   $dom->parse('<!DOCTYPE html><b>123</b>')->child_nodes->first;
209
210   # " Test "
211   $dom->parse('<b>123</b><!-- Test -->')->child_nodes->last->content;
212
213 =head2 children
214
215   my $collection = $dom->children;
216   my $collection = $dom->children('div ~ p');
217
218 Find all child elements of this element matching the CSS selector and return a
219 L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
220 objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
221
222   # Show tag name of random child element
223   say $dom->children->shuffle->first->tag;
224
225 =head2 content
226
227   my $str = $dom->content;
228   $dom    = $dom->content('<p>I ♥ DOM::Tiny!</p>');
229
230 Return this node's content or replace it with HTML/XML fragment (for C<root>
231 and C<tag> nodes) or raw content.
232
233   # "<b>Test</b>"
234   $dom->parse('<div><b>Test</b></div>')->at('div')->content;
235
236   # "<div><h1>123</h1></div>"
237   $dom->parse('<div><h1>Test</h1></div>')->at('h1')->content('123')->root;
238
239   # "<p><i>123</i></p>"
240   $dom->parse('<p>Test</p>')->at('p')->content('<i>123</i>')->root;
241
242   # "<div><h1></h1></div>"
243   $dom->parse('<div><h1>Test</h1></div>')->at('h1')->content('')->root;
244
245   # " Test "
246   $dom->parse('<!-- Test --><br>')->child_nodes->first->content;
247
248   # "<div><!-- 123 -->456</div>"
249   $dom->parse('<div><!-- Test -->456</div>')
250     ->at('div')->child_nodes->first->content(' 123 ')->root;
251
252 =head2 descendant_nodes
253
254   my $collection = $dom->descendant_nodes;
255
256 Return a L<DOM::Tiny::Collection> object containing all descendant nodes of
257 this element as L<DOM::Tiny> objects.
258
259   # "<p><b>123</b></p>"
260   $dom->parse('<p><!-- Test --><b>123<!-- 456 --></b></p>')
261     ->descendant_nodes->grep(sub { $_->type eq 'comment' })
262     ->map('remove')->first;
263
264   # "<p><b>test</b>test</p>"
265   $dom->parse('<p><b>123</b>456</p>')
266     ->at('p')->descendant_nodes->grep(sub { $_->type eq 'text' })
267     ->map(content => 'test')->first->root;
268
269 =head2 find
270
271   my $collection = $dom->find('div ~ p');
272
273 Find all descendant elements of this element matching the CSS selector and
274 return a L<DOM::Tiny::Collection> object containing these elements as
275 L<DOM::Tiny> objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are
276 supported.
277
278   # Find a specific element and extract information
279   my $id = $dom->find('div')->[23]{id};
280
281   # Extract information from multiple elements
282   my @headers = $dom->find('h1, h2, h3')->map('text')->each;
283
284   # Count all the different tags
285   my $hash = $dom->find('*')->reduce(sub { $a->{$b->tag}++; $a }, {});
286
287   # Find elements with a class that contains dots
288   my @divs = $dom->find('div.foo\.bar')->each;
289
290 =head2 following
291
292   my $collection = $dom->following;
293   my $collection = $dom->following('div ~ p');
294
295 Find all sibling elements after this node matching the CSS selector and return
296 a L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
297 objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
298
299   # List tags of sibling elements after this node
300   say $dom->following->map('tag')->join("\n");
301
302 =head2 following_nodes
303
304   my $collection = $dom->following_nodes;
305
306 Return a L<DOM::Tiny::Collection> object containing all sibling nodes after
307 this node as L<DOM::Tiny> objects.
308
309   # "C"
310   $dom->parse('<p>A</p><!-- B -->C')->at('p')->following_nodes->last->content;
311
312 =head2 matches
313
314   my $bool = $dom->matches('div ~ p');
315
316 Check if this element matches the CSS selector. All selectors from
317 L<DOM::Tiny::CSS/"SELECTORS"> are supported.
318
319   # True
320   $dom->parse('<p class="a">A</p>')->at('p')->matches('.a');
321   $dom->parse('<p class="a">A</p>')->at('p')->matches('p[class]');
322
323   # False
324   $dom->parse('<p class="a">A</p>')->at('p')->matches('.b');
325   $dom->parse('<p class="a">A</p>')->at('p')->matches('p[id]');
326
327 =head2 namespace
328
329   my $namespace = $dom->namespace;
330
331 Find this element's namespace or return C<undef> if none could be found.
332
333   # Find namespace for an element with namespace prefix
334   my $namespace = $dom->at('svg > svg\:circle')->namespace;
335
336   # Find namespace for an element that may or may not have a namespace prefix
337   my $namespace = $dom->at('svg > circle')->namespace;
338
339 =head2 next
340
341   my $sibling = $dom->next;
342
343 Return L<DOM::Tiny> object for next sibling element or C<undef> if there are no
344 more siblings.
345
346   # "<h2>123</h2>"
347   $dom->parse('<div><h1>Test</h1><h2>123</h2></div>')->at('h1')->next;
348
349 =head2 next_node
350
351   my $sibling = $dom->next_node;
352
353 Return L<DOM::Tiny> object for next sibling node or C<undef> if there are no
354 more siblings.
355
356   # "456"
357   $dom->parse('<p><b>123</b><!-- Test -->456</p>')
358     ->at('b')->next_node->next_node;
359
360   # " Test "
361   $dom->parse('<p><b>123</b><!-- Test -->456</p>')
362     ->at('b')->next_node->content;
363
364 =head2 parent
365
366   my $parent = $dom->parent;
367
368 Return L<DOM::Tiny> object for parent of this node or C<undef> if this node has
369 no parent.
370
371 =head2 parse
372
373   $dom = $dom->parse('<foo bar="baz">I ♥ DOM::Tiny!</foo>');
374
375 Parse HTML/XML fragment with L<DOM::Tiny::HTML>.
376
377   # Parse XML
378   my $dom = DOM::Tiny->new->xml(1)->parse($xml);
379
380 =head2 preceding
381
382   my $collection = $dom->preceding;
383   my $collection = $dom->preceding('div ~ p');
384
385 Find all sibling elements before this node matching the CSS selector and return
386 a L<DOM::Tiny::Collection> object containing these elements as L<DOM::Tiny>
387 objects. All selectors from L<DOM::Tiny::CSS/"SELECTORS"> are supported.
388
389   # List tags of sibling elements before this node
390   say $dom->preceding->map('tag')->join("\n");
391
392 =head2 preceding_nodes
393
394   my $collection = $dom->preceding_nodes;
395
396 Return a L<DOM::Tiny::Collection> object containing all sibling nodes before
397 this node as L<DOM::Tiny> objects.
398
399   # "A"
400   $dom->parse('A<!-- B --><p>C</p>')->at('p')->preceding_nodes->first->content;
401
402 =head2 prepend
403
404   $dom = $dom->prepend('<p>I ♥ DOM::Tiny!</p>');
405
406 Prepend HTML/XML fragment to this node.
407
408   # "<div><h1>Test</h1><h2>123</h2></div>"
409   $dom->parse('<div><h2>123</h2></div>')
410     ->at('h2')->prepend('<h1>Test</h1>')->root;
411
412   # "<p>Test 123</p>"
413   $dom->parse('<p>123</p>')
414     ->at('p')->child_nodes->first->prepend('Test ')->root;
415
416 =head2 prepend_content
417
418   $dom = $dom->prepend_content('<p>I ♥ DOM::Tiny!</p>');
419
420 Prepend HTML/XML fragment (for C<root> and C<tag> nodes) or raw content to this
421 node's content.
422
423   # "<div><h2>Test123</h2></div>"
424   $dom->parse('<div><h2>123</h2></div>')
425     ->at('h2')->prepend_content('Test')->root;
426
427   # "<!-- Test 123 --><br>"
428   $dom->parse('<!-- 123 --><br>')
429     ->child_nodes->first->prepend_content(' Test')->root;
430
431   # "<p><i>123</i>Test</p>"
432   $dom->parse('<p>Test</p>')->at('p')->prepend_content('<i>123</i>')->root;
433
434 =head2 previous
435
436   my $sibling = $dom->previous;
437
438 Return L<DOM::Tiny> object for previous sibling element or C<undef> if there
439 are no more siblings.
440
441   # "<h1>Test</h1>"
442   $dom->parse('<div><h1>Test</h1><h2>123</h2></div>')->at('h2')->previous;
443
444 =head2 previous_node
445
446   my $sibling = $dom->previous_node;
447
448 Return L<DOM::Tiny> object for previous sibling node or C<undef> if there are
449 no more siblings.
450
451   # "123"
452   $dom->parse('<p>123<!-- Test --><b>456</b></p>')
453     ->at('b')->previous_node->previous_node;
454
455   # " Test "
456   $dom->parse('<p>123<!-- Test --><b>456</b></p>')
457     ->at('b')->previous_node->content;
458
459 =head2 remove
460
461   my $parent = $dom->remove;
462
463 Remove this node and return L</"root"> (for C<root> nodes) or L</"parent">.
464
465   # "<div></div>"
466   $dom->parse('<div><h1>Test</h1></div>')->at('h1')->remove;
467
468   # "<p><b>456</b></p>"
469   $dom->parse('<p>123<b>456</b></p>')
470     ->at('p')->child_nodes->first->remove->root;
471
472 =head2 replace
473
474   my $parent = $dom->replace('<div>I ♥ DOM::Tiny!</div>');
475
476 Replace this node with HTML/XML fragment and return L</"root"> (for C<root>
477 nodes) or L</"parent">.
478
479   # "<div><h2>123</h2></div>"
480   $dom->parse('<div><h1>Test</h1></div>')->at('h1')->replace('<h2>123</h2>');
481
482   # "<p><b>123</b></p>"
483   $dom->parse('<p>Test</p>')
484     ->at('p')->child_nodes->[0]->replace('<b>123</b>')->root;
485
486 =head2 root
487
488   my $root = $dom->root;
489
490 Return L<DOM::Tiny> object for C<root> node.
491
492 =head2 strip
493
494   my $parent = $dom->strip;
495
496 Remove this element while preserving its content and return L</"parent">.
497
498   # "<div>Test</div>"
499   $dom->parse('<div><h1>Test</h1></div>')->at('h1')->strip;
500
501 =head2 tag
502
503   my $tag = $dom->tag;
504   $dom    = $dom->tag('div');
505
506 This element's tag name.
507
508   # List tag names of child elements
509   say $dom->children->map('tag')->join("\n");
510
511 =head2 tap
512
513   $dom = $dom->tap(sub {...});
514
515 Equivalent to L<Mojo::Base/"tap">.
516
517 =head2 text
518
519   my $trimmed   = $dom->text;
520   my $untrimmed = $dom->text(0);
521
522 Extract text content from this element only (not including child elements),
523 smart whitespace trimming is enabled by default.
524
525   # "foo baz"
526   $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->text;
527
528   # "foo\nbaz\n"
529   $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->text(0);
530
531 =head2 to_string
532
533   my $str = $dom->to_string;
534
535 Render this node and its content to HTML/XML.
536
537   # "<b>Test</b>"
538   $dom->parse('<div><b>Test</b></div>')->at('div b')->to_string;
539
540 =head2 tree
541
542   my $tree = $dom->tree;
543   $dom     = $dom->tree(['root']);
544
545 Document Object Model. Note that this structure should only be used very
546 carefully since it is very dynamic.
547
548 =head2 type
549
550   my $type = $dom->type;
551
552 This node's type, usually C<cdata>, C<comment>, C<doctype>, C<pi>, C<raw>,
553 C<root>, C<tag> or C<text>.
554
555   # "cdata"
556   $dom->parse('<![CDATA[Test]]>')->child_nodes->first->type;
557
558   # "comment"
559   $dom->parse('<!-- Test -->')->child_nodes->first->type;
560
561   # "doctype"
562   $dom->parse('<!DOCTYPE html>')->child_nodes->first->type;
563
564   # "pi"
565   $dom->parse('<?xml version="1.0"?>')->child_nodes->first->type;
566
567   # "raw"
568   $dom->parse('<title>Test</title>')->at('title')->child_nodes->first->type;
569
570   # "root"
571   $dom->parse('<p>Test</p>')->type;
572
573   # "tag"
574   $dom->parse('<p>Test</p>')->at('p')->type;
575
576   # "text"
577   $dom->parse('<p>Test</p>')->at('p')->child_nodes->first->type;
578
579 =head2 val
580
581   my $value = $dom->val;
582
583 Extract value from form element (such as C<button>, C<input>, C<option>,
584 C<select> and C<textarea>) or return C<undef> if this element has no value. In
585 the case of C<select> with C<multiple> attribute, find C<option> elements with
586 C<selected> attribute and return an array reference with all values or C<undef>
587 if none could be found.
588
589   # "a"
590   $dom->parse('<input name="test" value="a">')->at('input')->val;
591
592   # "b"
593   $dom->parse('<textarea>b</textarea>')->at('textarea')->val;
594
595   # "c"
596   $dom->parse('<option value="c">Test</option>')->at('option')->val;
597
598   # "d"
599   $dom->parse('<select><option selected>d</option></select>')
600     ->at('select')->val;
601
602   # "e"
603   $dom->parse('<select multiple><option selected>e</option></select>')
604     ->at('select')->val->[0];
605
606 =head2 wrap
607
608   $dom = $dom->wrap('<div></div>');
609
610 Wrap HTML/XML fragment around this node, placing it as the last child of the
611 first innermost element.
612
613   # "<p>123<b>Test</b></p>"
614   $dom->parse('<b>Test</b>')->at('b')->wrap('<p>123</p>')->root;
615
616   # "<div><p><b>Test</b></p>123</div>"
617   $dom->parse('<b>Test</b>')->at('b')->wrap('<div><p></p>123</div>')->root;
618
619   # "<p><b>Test</b></p><p>123</p>"
620   $dom->parse('<b>Test</b>')->at('b')->wrap('<p></p><p>123</p>')->root;
621
622   # "<p><b>Test</b></p>"
623   $dom->parse('<p>Test</p>')->at('p')->child_nodes->first->wrap('<b>')->root;
624
625 =head2 wrap_content
626
627   $dom = $dom->wrap_content('<div></div>');
628
629 Wrap HTML/XML fragment around this node's content, placing it as the last
630 children of the first innermost element.
631
632   # "<p><b>123Test</b></p>"
633   $dom->parse('<p>Test<p>')->at('p')->wrap_content('<b>123</b>')->root;
634
635   # "<p><b>Test</b></p><p>123</p>"
636   $dom->parse('<b>Test</b>')->wrap_content('<p></p><p>123</p>');
637
638 =head2 xml
639
640   my $bool = $dom->xml;
641   $dom     = $dom->xml($bool);
642
643 Disable HTML semantics in parser and activate case-sensitivity, defaults to
644 auto detection based on processing instructions.
645
646 =head1 OPERATORS
647
648 L<DOM::Tiny> overloads the following operators.
649
650 =head2 array
651
652   my @nodes = @$dom;
653
654 Alias for L</"child_nodes">.
655
656   # "<!-- Test -->"
657   $dom->parse('<!-- Test --><b>123</b>')->[0];
658
659 =head2 bool
660
661   my $bool = !!$dom;
662
663 Always true.
664
665 =head2 hash
666
667   my %attrs = %$dom;
668
669 Alias for L</"attr">.
670
671   # "test"
672   $dom->parse('<div id="test">Test</div>')->at('div')->{id};
673
674 =head2 stringify
675
676   my $str = "$dom";
677
678 Alias for L</"to_string">.
679
680 =head1 COLLECTION METHODS
681
682 Some L<DOM::Tiny> methods return an array-based collection object, which can
683 either be accessed directly as an array reference, or with the following
684 methods.
685
686   # Chain methods
687   $collection->map(sub { ucfirst })->shuffle->each(sub {
688     my ($word, $num) = @_;
689     say "$num: $word";
690   });
691
692   # Access array directly to manipulate collection
693   $collection->[23] += 100;
694   say for @$collection;
695
696 =head2 compact
697
698   my $new = $collection->compact;
699
700 Create a new collection with all elements that are defined and not an empty
701 string.
702
703   # $collection contains (0, 1, undef, 2, '', 3)
704   $collection->compact->join(', '); # "0, 1, 2, 3"
705
706 =head2 each
707
708   my @elements = $collection->each;
709   $collection  = $collection->each(sub {...});
710
711 Evaluate callback for each element in collection or return all elements as a
712 list if none has been provided. The element will be the first argument passed
713 to the callback and is also available as C<$_>.
714
715   # Make a numbered list
716   $collection->each(sub {
717     my ($e, $num) = @_;
718     say "$num: $e";
719   });
720
721 =head2 first
722
723   my $first = $collection->first;
724   my $first = $collection->first(qr/foo/);
725   my $first = $collection->first(sub {...});
726   my $first = $collection->first($method);
727   my $first = $collection->first($method, @args);
728
729 Evaluate regular expression/callback for, or call method on, each element in
730 collection and return the first one that matched the regular expression, or for
731 which the callback/method returned true. The element will be the first argument
732 passed to the callback and is also available as C<$_>.
733
734   # Longer version
735   my $first = $collection->first(sub { $_->$method(@args) });
736
737   # Find first value that contains the word "dom"
738   my $interesting = $collection->first(qr/dom/i);
739
740   # Find first value that is greater than 5
741   my $greater = $collection->first(sub { $_ > 5 });
742
743 =head2 flatten
744
745   my $new = $collection->flatten;
746
747 Flatten nested collections/arrays recursively and create a new collection with
748 all elements.
749
750   # $collection contains (1, [2, [3, 4], 5, [6]], 7)
751   $collection->flatten->join(', '); # "1, 2, 3, 4, 5, 6, 7"
752
753 =head2 grep
754
755   my $new = $collection->grep(qr/foo/);
756   my $new = $collection->grep(sub {...});
757   my $new = $collection->grep($method);
758   my $new = $collection->grep($method, @args);
759
760 Evaluate regular expression/callback for, or call method on, each element in
761 collection and create a new collection with all elements that matched the
762 regular expression, or for which the callback/method returned true. The element
763 will be the first argument passed to the callback and is also available as
764 C<$_>.
765
766   # Longer version
767   my $new = $collection->grep(sub { $_->$method(@args) });
768
769   # Find all values that contain the word "dom"
770   my $interesting = $collection->grep(qr/dom/i);
771
772   # Find all values that are greater than 5
773   my $greater = $collection->grep(sub { $_ > 5 });
774
775 =head2 join
776
777   my $stream = $collection->join;
778   my $stream = $collection->join("\n");
779
780 Turn collection into string.
781
782   # Join all values with commas
783   $collection->join(', ');
784
785 =head2 last
786
787   my $last = $collection->last;
788
789 Return the last element in collection.
790
791 =head2 map
792
793   my $new = $collection->map(sub {...});
794   my $new = $collection->map($method);
795   my $new = $collection->map($method, @args);
796
797 Evaluate callback for, or call method on, each element in collection and create
798 a new collection from the results. The element will be the first argument
799 passed to the callback and is also available as C<$_>.
800
801   # Longer version
802   my $new = $collection->map(sub { $_->$method(@args) });
803
804   # Append the word "dom" to all values
805   my $domified = $collection->map(sub { $_ . 'dom' });
806
807 =head2 reduce
808
809   my $result = $collection->reduce(sub {...});
810   my $result = $collection->reduce(sub {...}, $initial);
811
812 Reduce elements in collection with callback, the first element will be used as
813 initial value if none has been provided.
814
815   # Calculate the sum of all values
816   my $sum = $collection->reduce(sub { $a + $b });
817
818   # Count how often each value occurs in collection
819   my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {});
820
821 =head2 reverse
822
823   my $new = $collection->reverse;
824
825 Create a new collection with all elements in reverse order.
826
827 =head2 slice
828
829   my $new = $collection->slice(4 .. 7);
830
831 Create a new collection with all selected elements.
832
833   # $collection contains ('A', 'B', 'C', 'D', 'E')
834   $collection->slice(1, 2, 4)->join(' '); # "B C E"
835
836 =head2 shuffle
837
838   my $new = $collection->shuffle;
839
840 Create a new collection with all elements in random order.
841
842 =head2 size
843
844   my $size = $collection->size;
845
846 Number of elements in collection.
847
848 =head2 sort
849
850   my $new = $collection->sort;
851   my $new = $collection->sort(sub {...});
852
853 Sort elements based on return value of callback and create a new collection
854 from the results.
855
856   # Sort values case-insensitive
857   my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) });
858
859 =head2 tap
860
861   $collection = $collection->tap(sub {...});
862
863 Equivalent to L<Mojo::Base/"tap">.
864
865 =head2 to_array
866
867   my $array = $collection->to_array;
868
869 Turn collection into array reference.
870
871 =head2 uniq
872
873   my $new = $collection->uniq;
874   my $new = $collection->uniq(sub {...});
875   my $new = $collection->uniq($method);
876   my $new = $collection->uniq($method, @args);
877
878 Create a new collection without duplicate elements, using the string
879 representation of either the elements or the return value of the
880 callback/method.
881
882   # Longer version
883   my $new = $collection->uniq(sub { $_->$method(@args) });
884
885   # $collection contains ('foo', 'bar', 'bar', 'baz')
886   $collection->uniq->join(' '); # "foo bar baz"
887
888   # $collection contains ([1, 2], [2, 1], [3, 2])
889   $collection->uniq(sub{ $_->[1] })->to_array; # "[[1, 2], [2, 1]]"
890
891 =head1 BUGS
892
893 Report any issues on the public bugtracker.
894
895 =head1 AUTHOR
896
897 Dan Book <dbook@cpan.org>
898
899 =head1 COPYRIGHT AND LICENSE
900
901 This software is Copyright (c) 2015 by Dan Book.
902
903 This is free software, licensed under:
904
905   The Artistic License 2.0 (GPL Compatible)
906
907 =head1 SEE ALSO
908
909 L<Mojo::DOM>, L<XML::LibXML>, L<XML::Twig>, L<HTML::TreeBuilder>, L<XML::Smart>
910
911 =cut