@@ -10,7 +10,7 @@ use HTML::Selector::XPath qw/selector_to_xpath/;
10
10
use Carp qw/ confess / ;
11
11
use JSON qw/ decode_json / ;
12
12
13
- our $VERSION = " 0.01 " ;
13
+ our $VERSION = " 0.02 " ;
14
14
our @EXPORT = qw/ j / ;
15
15
16
16
use constant {
@@ -29,17 +29,15 @@ my $data = {};
29
29
30
30
sub new {
31
31
my ($class , $stuff , $before ) = @_ ;
32
- my $self ;
32
+ my ( $self , $existing_document , $nodes ) ;
33
33
34
+ # instance method, reuse document
34
35
if (ref $class ) {
35
36
$self = $class ;
36
37
$class = ref $self ;
38
+ $existing_document = $self -> {document };
37
39
}
38
40
39
- $class = ref $class if ref $class ;
40
-
41
- my $nodes ;
42
-
43
41
if (blessed $stuff ) {
44
42
45
43
if ($stuff -> isa(__PACKAGE__ )) {
@@ -65,27 +63,41 @@ sub new {
65
63
$nodes = [ _parse_html($stuff ) ];
66
64
}
67
65
66
+ # # if called as instance method, import nodes to our document
67
+ # if (ref $self && defined $self->{nodes}[0]) {
68
+ #
69
+ # my $doc = $self->{nodes}[0]->ownerDocument;
70
+ # $doc->adoptNode($_)
71
+ # for grep { $_->nodeType != XML_DOCUMENT_NODE } @$nodes;
72
+ # }
68
73
}
69
74
70
- # if called as instance method, import nodes to our document
71
- if ( ref $self && defined $self -> { nodes }[0]) {
75
+ # catch bugs :)
76
+ confess " undefined node " if grep { ! defined } @$nodes ;
72
77
73
- my $doc = $self -> {nodes }[0]-> ownerDocument;
74
- $doc -> adoptNode($_ )
75
- for grep { $_ -> nodeType != XML_DOCUMENT_NODE } @$nodes ;
76
- }
78
+ # adopt nodes to existing document
79
+ if ($existing_document ) {
77
80
81
+ my $doc_id = $existing_document -> unique_key;
82
+ $existing_document -> adoptNode($_ )
83
+ for grep { $_ -> ownerDocument-> unique_key != $doc_id }
84
+ grep { $_ -> nodeType != XML_DOCUMENT_NODE }
85
+ @$nodes ;
86
+ }
78
87
79
- if (@$nodes ) {
88
+ my $document = defined $nodes -> [0] ? $nodes -> [0]-> ownerDocument
89
+ : XML::LibXML-> createDocument;
80
90
81
- # increment document data refcount
82
- my $doc_id = $nodes -> [0]-> ownerDocument-> unique_key;
83
- $data -> {$doc_id }{refcount }++;
84
- # printf STDERR "[%s] incremented document %d data ref count: %d\n", __PACKAGE__, $doc_id, $data->{$doc_id}{refcount};
85
- }
91
+ # increment document data refcount
92
+ my $doc_id = $document -> unique_key;
93
+ $data -> {$doc_id }{refcount }++;
94
+ # printf STDERR "[%s] incremented document %d data ref count: %d\n", __PACKAGE__, $doc_id, $data->{$doc_id}{refcount};
86
95
87
- confess " undefined node" if grep { !defined } @$nodes ;
88
- bless ({ nodes => $nodes , before => $before }, $class );
96
+ bless {
97
+ document => $document ,
98
+ nodes => $nodes ,
99
+ before => $before
100
+ }, $class ;
89
101
}
90
102
91
103
@@ -159,7 +171,7 @@ sub end {
159
171
160
172
sub document {
161
173
my $self = shift ;
162
- $self -> new([ $self -> {nodes }[0] ? $self -> { nodes }[0] -> ownerDocument : () ], $self );
174
+ $self -> new([ $self -> {document } ], $self );
163
175
}
164
176
165
177
sub tagname {
@@ -199,16 +211,20 @@ sub as_html {
199
211
# TODO benchmark as_html() using can() vs nodeType to detect document nodes
200
212
# best method, but only document nodes can toStringHTML()
201
213
if ($_ -> can(' toStringHTML' )) {
214
+ # printf STDERR "%s: toStringHTML\n", ref $_;
202
215
$output .= $_ -> toStringHTML;
203
216
next ;
204
217
}
205
218
219
+
206
220
# second best is to call toStringC14N(1), which generates valid HTML (eg. no auto closed <div/>),
207
221
# but dies on some cases with "Failed to convert doc to string in doc->toStringC14N" error.
208
222
# so we fallback to toString()
223
+ # the most common case where toStringC14N fails is unbound nodes (getOwner returns a DocumentFragment)
209
224
{
210
225
local $@ ; # protect existing $@
211
226
my $html = eval { $_ -> toStringC14N(1) };
227
+ # printf STDERR "%s: %s\n", ref $_->getOwner, ($@ ? "toString: $@" : 'toStringC14N');
212
228
$output .= $@ ? $_ -> toString : $html ;
213
229
}
214
230
}
@@ -393,7 +409,7 @@ sub append {
393
409
394
410
sub append_to {
395
411
my $self = shift ;
396
- _append_to($self -> {nodes }, $self -> new(@_ )-> {nodes });
412
+ _append_to($self -> {nodes }, ( ref $self ) -> new(@_ )-> {nodes });
397
413
$self ;
398
414
}
399
415
@@ -430,7 +446,7 @@ sub prepend {
430
446
431
447
sub prepend_to {
432
448
my $self = shift ;
433
- _prepend_to($self -> {nodes }, $self -> new(@_ )-> {nodes });
449
+ _prepend_to($self -> {nodes }, ( ref $self ) -> new(@_ )-> {nodes });
434
450
$self ;
435
451
}
436
452
@@ -474,7 +490,7 @@ sub before {
474
490
475
491
sub insert_before {
476
492
my $self = shift ;
477
- _insert_before($self -> {nodes }, $self -> new(@_ )-> {nodes });
493
+ _insert_before($self -> {nodes }, ( ref $self ) -> new(@_ )-> {nodes });
478
494
$self ;
479
495
}
480
496
@@ -520,7 +536,7 @@ sub after {
520
536
521
537
sub insert_after {
522
538
my $self = shift ;
523
- _insert_after($self -> {nodes }, $self -> new(@_ )-> {nodes });
539
+ _insert_after($self -> {nodes }, ( ref $self ) -> new(@_ )-> {nodes });
524
540
$self ;
525
541
}
526
542
@@ -993,6 +1009,24 @@ Unless otherwise noted, all methods behave exactly like the javascript version.
993
1009
994
1010
=head2 add
995
1011
1012
+ Implemented signatures:
1013
+
1014
+ =over
1015
+
1016
+ =item B<add > (Str B<selector > )
1017
+
1018
+ =item B<add > (Str B<selector > , XML::LibXML::jQuery B<context > )
1019
+
1020
+ =item B<add > (Str B<html > )
1021
+
1022
+ =item B<add > (ArrayRef[L<XML::LibXML::Node> ] B<elements > )
1023
+
1024
+ =item B<add > (XML::LibXML::jQuery B<selection > )
1025
+
1026
+ =back
1027
+
1028
+ Documentation and examples at L<http://api.jquery.com/add/> .
1029
+
996
1030
=head2 add_class
997
1031
998
1032
=head2 after
@@ -1015,6 +1049,20 @@ Unless otherwise noted, all methods behave exactly like the javascript version.
1015
1049
1016
1050
=head2 data
1017
1051
1052
+ Implemented signatures:
1053
+
1054
+ =over
1055
+
1056
+ =item B<data > (Str B<key > , Any B<value > )
1057
+
1058
+ =item B<data > (Str B<key > )
1059
+
1060
+ =item B<data > (HashRef B<obj > )
1061
+
1062
+ =back
1063
+
1064
+ Documentation and examples at L<http://api.jquery.com/data/> .
1065
+
1018
1066
=head2 detach
1019
1067
1020
1068
=head2 document
0 commit comments