nokolexbor 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/nokolexbor/extconf.rb +9 -5
- data/ext/nokolexbor/nl_attribute.c +46 -0
- data/ext/nokolexbor/nl_cdata.c +8 -0
- data/ext/nokolexbor/nl_comment.c +6 -0
- data/ext/nokolexbor/nl_document.c +53 -7
- data/ext/nokolexbor/nl_document_fragment.c +9 -0
- data/ext/nokolexbor/nl_error.c +21 -19
- data/ext/nokolexbor/nl_node.c +255 -50
- data/ext/nokolexbor/nl_node_set.c +56 -1
- data/ext/nokolexbor/nl_processing_instruction.c +6 -0
- data/ext/nokolexbor/nl_text.c +6 -0
- data/ext/nokolexbor/nokolexbor.h +1 -0
- data/lib/nokolexbor/document.rb +52 -5
- data/lib/nokolexbor/document_fragment.rb +11 -0
- data/lib/nokolexbor/node.rb +367 -18
- data/lib/nokolexbor/node_set.rb +56 -0
- data/lib/nokolexbor/version.rb +1 -1
- metadata +2 -24
- data/vendor/lexbor/source/lexbor/encoding/base.h +0 -218
- data/vendor/lexbor/source/lexbor/encoding/big5.c +0 -42839
- data/vendor/lexbor/source/lexbor/encoding/config.cmake +0 -12
- data/vendor/lexbor/source/lexbor/encoding/const.h +0 -65
- data/vendor/lexbor/source/lexbor/encoding/decode.c +0 -3193
- data/vendor/lexbor/source/lexbor/encoding/decode.h +0 -370
- data/vendor/lexbor/source/lexbor/encoding/encode.c +0 -1931
- data/vendor/lexbor/source/lexbor/encoding/encode.h +0 -377
- data/vendor/lexbor/source/lexbor/encoding/encoding.c +0 -252
- data/vendor/lexbor/source/lexbor/encoding/encoding.h +0 -475
- data/vendor/lexbor/source/lexbor/encoding/euc_kr.c +0 -53883
- data/vendor/lexbor/source/lexbor/encoding/gb18030.c +0 -47905
- data/vendor/lexbor/source/lexbor/encoding/iso_2022_jp_katakana.c +0 -159
- data/vendor/lexbor/source/lexbor/encoding/jis0208.c +0 -22477
- data/vendor/lexbor/source/lexbor/encoding/jis0212.c +0 -15787
- data/vendor/lexbor/source/lexbor/encoding/multi.h +0 -53
- data/vendor/lexbor/source/lexbor/encoding/range.c +0 -71
- data/vendor/lexbor/source/lexbor/encoding/range.h +0 -34
- data/vendor/lexbor/source/lexbor/encoding/res.c +0 -222
- data/vendor/lexbor/source/lexbor/encoding/res.h +0 -34
- data/vendor/lexbor/source/lexbor/encoding/single.c +0 -13748
- data/vendor/lexbor/source/lexbor/encoding/single.h +0 -116
data/ext/nokolexbor/nl_node.c
CHANGED
@@ -51,8 +51,11 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
|
|
51
51
|
case LXB_DOM_NODE_TYPE_COMMENT:
|
52
52
|
rb_class = cNokolexborComment;
|
53
53
|
break;
|
54
|
-
|
55
|
-
|
54
|
+
case LXB_DOM_NODE_TYPE_DOCUMENT:
|
55
|
+
if (nl_rb_node_unwrap(rb_document) != node) {
|
56
|
+
rb_raise(rb_eRuntimeError, "Unexpected node type: Document");
|
57
|
+
}
|
58
|
+
return rb_document;
|
56
59
|
// case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
|
57
60
|
// break;
|
58
61
|
case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
|
@@ -81,6 +84,23 @@ nl_rb_node_unwrap(VALUE rb_node)
|
|
81
84
|
return node;
|
82
85
|
}
|
83
86
|
|
87
|
+
/**
|
88
|
+
* call-seq:
|
89
|
+
* new(name, document) { |Node| ... } -> Node
|
90
|
+
*
|
91
|
+
* Create a new node with +name+ that belongs to +document+.
|
92
|
+
*
|
93
|
+
* If you intend to add a node to a document tree, it's likely that you will prefer one of the
|
94
|
+
* {Node} methods like {#add_child}, {#add_next_sibling}, {#replace}, etc. which will
|
95
|
+
* both create an element (or subtree) and place it in the document tree.
|
96
|
+
*
|
97
|
+
* Another alternative, if you are concerned about performance, is
|
98
|
+
* {Document#create_element} which accepts additional arguments for contents or
|
99
|
+
* attributes but (like this method) avoids parsing markup.
|
100
|
+
*
|
101
|
+
* @param name [String]
|
102
|
+
* @param document [Document] The document to which the the returned node will belong.
|
103
|
+
*/
|
84
104
|
static VALUE
|
85
105
|
nl_node_new(int argc, VALUE *argv, VALUE klass)
|
86
106
|
{
|
@@ -113,6 +133,11 @@ nl_node_new(int argc, VALUE *argv, VALUE klass)
|
|
113
133
|
return rb_node;
|
114
134
|
}
|
115
135
|
|
136
|
+
/**
|
137
|
+
* call-seq: attribute(name) → Attribute
|
138
|
+
*
|
139
|
+
* @return [Attribute] The attribute belonging to this node with name +name+.
|
140
|
+
*/
|
116
141
|
static VALUE
|
117
142
|
nl_node_attribute(VALUE self, VALUE rb_name)
|
118
143
|
{
|
@@ -130,11 +155,14 @@ nl_node_attribute(VALUE self, VALUE rb_name)
|
|
130
155
|
return Qnil;
|
131
156
|
}
|
132
157
|
if (attr->owner == NULL) {
|
133
|
-
attr->owner = node;
|
158
|
+
attr->owner = lxb_dom_interface_element(node);
|
134
159
|
}
|
135
160
|
return nl_rb_node_create(attr, nl_rb_document_get(self));
|
136
161
|
}
|
137
162
|
|
163
|
+
/**
|
164
|
+
* @return [Array<Attribute>] An array of {Attribute} belonging to this node.
|
165
|
+
*/
|
138
166
|
static VALUE
|
139
167
|
nl_node_attribute_nodes(VALUE self)
|
140
168
|
{
|
@@ -153,7 +181,7 @@ nl_node_attribute_nodes(VALUE self)
|
|
153
181
|
VALUE rb_doc = nl_rb_document_get(self);
|
154
182
|
while (attr != NULL) {
|
155
183
|
if (attr->owner == NULL) {
|
156
|
-
attr->owner = node;
|
184
|
+
attr->owner = lxb_dom_interface_element(node);
|
157
185
|
}
|
158
186
|
rb_ary_push(ary, nl_rb_node_create(attr, rb_doc));
|
159
187
|
attr = attr->next;
|
@@ -162,6 +190,11 @@ nl_node_attribute_nodes(VALUE self)
|
|
162
190
|
return ary;
|
163
191
|
}
|
164
192
|
|
193
|
+
/**
|
194
|
+
* @return [String]
|
195
|
+
* Contents of all the text nodes in this node's subtree, concatenated together into a single
|
196
|
+
* String.
|
197
|
+
*/
|
165
198
|
static VALUE
|
166
199
|
nl_node_content(VALUE self)
|
167
200
|
{
|
@@ -178,6 +211,12 @@ nl_node_content(VALUE self)
|
|
178
211
|
return rb_str;
|
179
212
|
}
|
180
213
|
|
214
|
+
/**
|
215
|
+
* Set the Node's content to a Text node containing +content+. The string gets XML escaped, not
|
216
|
+
* interpreted as markup.
|
217
|
+
*
|
218
|
+
* @return [String] +content+
|
219
|
+
*/
|
181
220
|
static VALUE
|
182
221
|
nl_node_content_set(VALUE self, VALUE content)
|
183
222
|
{
|
@@ -192,6 +231,15 @@ nl_node_content_set(VALUE self, VALUE content)
|
|
192
231
|
return content;
|
193
232
|
}
|
194
233
|
|
234
|
+
/**
|
235
|
+
* call-seq: [](name) -> String,nil
|
236
|
+
*
|
237
|
+
* Fetch an attribute from this node.
|
238
|
+
*
|
239
|
+
* @param name The name of the attribute.
|
240
|
+
*
|
241
|
+
* @return (String, nil) The value of the attribute +name+, or +nil+ if no matching attribute exists.
|
242
|
+
*/
|
195
243
|
static VALUE
|
196
244
|
nl_node_get_attr(VALUE self, VALUE rb_attr)
|
197
245
|
{
|
@@ -217,6 +265,16 @@ nl_node_get_attr(VALUE self, VALUE rb_attr)
|
|
217
265
|
return rb_utf8_str_new((const char *)attr_value, attr_value_len);
|
218
266
|
}
|
219
267
|
|
268
|
+
/**
|
269
|
+
* call-seq: []=(name, value) -> String,nil
|
270
|
+
*
|
271
|
+
* Update the attribute +name+ to +value+, or create the attribute if it does not exist.
|
272
|
+
*
|
273
|
+
* @param name The name of the attribute.
|
274
|
+
* @param value The value of the attribute.
|
275
|
+
*
|
276
|
+
* @return [String] +value+
|
277
|
+
*/
|
220
278
|
static VALUE
|
221
279
|
nl_node_set_attr(VALUE self, VALUE rb_attr, VALUE rb_value)
|
222
280
|
{
|
@@ -241,13 +299,22 @@ nl_node_set_attr(VALUE self, VALUE rb_attr, VALUE rb_value)
|
|
241
299
|
return rb_value;
|
242
300
|
}
|
243
301
|
|
302
|
+
/**
|
303
|
+
* call-seq: remove_attr(name) -> Boolean
|
304
|
+
*
|
305
|
+
* Remove the attribute named +name+.
|
306
|
+
*
|
307
|
+
* @param name [String]
|
308
|
+
*
|
309
|
+
* @return [Boolean] +true+ if removal success, +false+ if node is not an {Element}.
|
310
|
+
*/
|
244
311
|
static VALUE
|
245
312
|
nl_node_remove_attr(VALUE self, VALUE rb_attr)
|
246
313
|
{
|
247
314
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
248
315
|
|
249
316
|
if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
|
250
|
-
return
|
317
|
+
return Qfalse;
|
251
318
|
}
|
252
319
|
|
253
320
|
VALUE rb_attr_s = rb_String(rb_attr);
|
@@ -257,7 +324,12 @@ nl_node_remove_attr(VALUE self, VALUE rb_attr)
|
|
257
324
|
|
258
325
|
lxb_dom_element_t *element = lxb_dom_interface_element(node);
|
259
326
|
|
260
|
-
|
327
|
+
lxb_status_t status = lxb_dom_element_remove_attribute(element, (const lxb_char_t *)attr_c, attr_len);
|
328
|
+
if (status != LXB_STATUS_OK) {
|
329
|
+
nl_raise_lexbor_error(status);
|
330
|
+
}
|
331
|
+
|
332
|
+
return Qtrue;
|
261
333
|
}
|
262
334
|
|
263
335
|
lxb_status_t
|
@@ -311,7 +383,6 @@ nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
|
|
311
383
|
}
|
312
384
|
|
313
385
|
/* Parse and get the log. */
|
314
|
-
// TODO: Cache the list for reuse, improves performance
|
315
386
|
list = lxb_css_selectors_parse_relative_list(parser, (const lxb_char_t *)selector_c, selector_len);
|
316
387
|
if (parser->status != LXB_STATUS_OK) {
|
317
388
|
status = parser->status;
|
@@ -384,6 +455,11 @@ void nl_sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_
|
|
384
455
|
}
|
385
456
|
}
|
386
457
|
|
458
|
+
/**
|
459
|
+
* Internal implementation of {#at_css}
|
460
|
+
*
|
461
|
+
* @see #at_css
|
462
|
+
*/
|
387
463
|
static VALUE
|
388
464
|
nl_node_at_css(VALUE self, VALUE selector)
|
389
465
|
{
|
@@ -411,6 +487,11 @@ nl_node_at_css(VALUE self, VALUE selector)
|
|
411
487
|
return ret;
|
412
488
|
}
|
413
489
|
|
490
|
+
/**
|
491
|
+
* Internal implementation of {#css}
|
492
|
+
*
|
493
|
+
* @see #css
|
494
|
+
*/
|
414
495
|
static VALUE
|
415
496
|
nl_node_css(VALUE self, VALUE selector)
|
416
497
|
{
|
@@ -428,6 +509,11 @@ nl_node_css(VALUE self, VALUE selector)
|
|
428
509
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
429
510
|
}
|
430
511
|
|
512
|
+
/**
|
513
|
+
* Get the inner_html of this Node.
|
514
|
+
*
|
515
|
+
* @return [String]
|
516
|
+
*/
|
431
517
|
static VALUE
|
432
518
|
nl_node_inner_html(int argc, VALUE *argv, VALUE self)
|
433
519
|
{
|
@@ -465,6 +551,11 @@ nl_node_inner_html(int argc, VALUE *argv, VALUE self)
|
|
465
551
|
return Qnil;
|
466
552
|
}
|
467
553
|
|
554
|
+
/**
|
555
|
+
* Serialize this Node to HTML, also known as outer_html.
|
556
|
+
*
|
557
|
+
* @return [String]
|
558
|
+
*/
|
468
559
|
static VALUE
|
469
560
|
nl_node_outer_html(int argc, VALUE *argv, VALUE self)
|
470
561
|
{
|
@@ -502,6 +593,11 @@ nl_node_outer_html(int argc, VALUE *argv, VALUE self)
|
|
502
593
|
return Qnil;
|
503
594
|
}
|
504
595
|
|
596
|
+
/**
|
597
|
+
* call-seq: key?(name) -> Boolean
|
598
|
+
*
|
599
|
+
* @return true if +name+ is set.
|
600
|
+
*/
|
505
601
|
static VALUE
|
506
602
|
nl_node_has_key(VALUE self, VALUE rb_attr)
|
507
603
|
{
|
@@ -520,6 +616,11 @@ nl_node_has_key(VALUE self, VALUE rb_attr)
|
|
520
616
|
return lxb_dom_element_has_attribute(element, (const lxb_char_t *)attr_c, attr_len) ? Qtrue : Qfalse;
|
521
617
|
}
|
522
618
|
|
619
|
+
/**
|
620
|
+
* Get the attribute names of this Node.
|
621
|
+
*
|
622
|
+
* @return [Array<String>] An array of attribute names.
|
623
|
+
*/
|
523
624
|
static VALUE
|
524
625
|
nl_node_keys(VALUE self)
|
525
626
|
{
|
@@ -543,6 +644,11 @@ nl_node_keys(VALUE self)
|
|
543
644
|
return ary_keys;
|
544
645
|
}
|
545
646
|
|
647
|
+
/**
|
648
|
+
* Get the attribute values of this Node.
|
649
|
+
*
|
650
|
+
* @return [Array<String>] An array of attribute values.
|
651
|
+
*/
|
546
652
|
static VALUE
|
547
653
|
nl_node_values(VALUE self)
|
548
654
|
{
|
@@ -570,6 +676,11 @@ nl_node_values(VALUE self)
|
|
570
676
|
return ary_values;
|
571
677
|
}
|
572
678
|
|
679
|
+
/**
|
680
|
+
* Get a hash of attribute names and values of this Node.
|
681
|
+
*
|
682
|
+
* @return [Hash{String => String}] A hash whose keys are attribute names and values are attribute values.
|
683
|
+
*/
|
573
684
|
static VALUE
|
574
685
|
nl_node_attrs(VALUE self)
|
575
686
|
{
|
@@ -598,6 +709,11 @@ nl_node_attrs(VALUE self)
|
|
598
709
|
return rb_hash;
|
599
710
|
}
|
600
711
|
|
712
|
+
/**
|
713
|
+
* Get the parent node.
|
714
|
+
*
|
715
|
+
* @return [Node,nil] The parent node
|
716
|
+
*/
|
601
717
|
static VALUE
|
602
718
|
nl_node_parent(VALUE self)
|
603
719
|
{
|
@@ -605,6 +721,11 @@ nl_node_parent(VALUE self)
|
|
605
721
|
return node->parent ? nl_rb_node_create(node->parent, nl_rb_document_get(self)) : Qnil;
|
606
722
|
}
|
607
723
|
|
724
|
+
/**
|
725
|
+
* Get the previous sibling node.
|
726
|
+
*
|
727
|
+
* @return [Node,nil] The previous sibling node
|
728
|
+
*/
|
608
729
|
static VALUE
|
609
730
|
nl_node_previous(VALUE self)
|
610
731
|
{
|
@@ -612,6 +733,11 @@ nl_node_previous(VALUE self)
|
|
612
733
|
return node->prev ? nl_rb_node_create(node->prev, nl_rb_document_get(self)) : Qnil;
|
613
734
|
}
|
614
735
|
|
736
|
+
/**
|
737
|
+
* Get the previous sibling element.
|
738
|
+
*
|
739
|
+
* @return [Element,nil] The previous sibling element
|
740
|
+
*/
|
615
741
|
static VALUE
|
616
742
|
nl_node_previous_element(VALUE self)
|
617
743
|
{
|
@@ -625,6 +751,11 @@ nl_node_previous_element(VALUE self)
|
|
625
751
|
return Qnil;
|
626
752
|
}
|
627
753
|
|
754
|
+
/**
|
755
|
+
* Get the next sibling node.
|
756
|
+
*
|
757
|
+
* @return [Node,nil] The previous sibling node
|
758
|
+
*/
|
628
759
|
static VALUE
|
629
760
|
nl_node_next(VALUE self)
|
630
761
|
{
|
@@ -632,6 +763,11 @@ nl_node_next(VALUE self)
|
|
632
763
|
return node->next ? nl_rb_node_create(node->next, nl_rb_document_get(self)) : Qnil;
|
633
764
|
}
|
634
765
|
|
766
|
+
/**
|
767
|
+
* Get the next sibling element.
|
768
|
+
*
|
769
|
+
* @return [Element,nil] The previous sibling element
|
770
|
+
*/
|
635
771
|
static VALUE
|
636
772
|
nl_node_next_element(VALUE self)
|
637
773
|
{
|
@@ -645,6 +781,11 @@ nl_node_next_element(VALUE self)
|
|
645
781
|
return Qnil;
|
646
782
|
}
|
647
783
|
|
784
|
+
/**
|
785
|
+
* Get the children of this node.
|
786
|
+
*
|
787
|
+
* @return [NodeSet] The set of this node's children.
|
788
|
+
*/
|
648
789
|
static VALUE
|
649
790
|
nl_node_children(VALUE self)
|
650
791
|
{
|
@@ -660,6 +801,11 @@ nl_node_children(VALUE self)
|
|
660
801
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
661
802
|
}
|
662
803
|
|
804
|
+
/**
|
805
|
+
* Get the first child of this node.
|
806
|
+
*
|
807
|
+
* @return [Node,nil] The first child.
|
808
|
+
*/
|
663
809
|
static VALUE
|
664
810
|
nl_node_child(VALUE self)
|
665
811
|
{
|
@@ -668,14 +814,26 @@ nl_node_child(VALUE self)
|
|
668
814
|
return child ? nl_rb_node_create(child, nl_rb_document_get(self)) : Qnil;
|
669
815
|
}
|
670
816
|
|
817
|
+
/**
|
818
|
+
* Remove this node from its current context.
|
819
|
+
*
|
820
|
+
* @return [Node] +self+, to support chaining of calls.
|
821
|
+
*/
|
671
822
|
static VALUE
|
672
823
|
nl_node_remove(VALUE self)
|
673
824
|
{
|
674
825
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
675
826
|
lxb_dom_node_remove(node);
|
676
|
-
return
|
827
|
+
return self;
|
677
828
|
}
|
678
829
|
|
830
|
+
/**
|
831
|
+
* Remove this node from its current context and free its allocated memory.
|
832
|
+
*
|
833
|
+
* @return [nil]
|
834
|
+
*
|
835
|
+
* @see #remove
|
836
|
+
*/
|
679
837
|
static VALUE
|
680
838
|
nl_node_destroy(VALUE self)
|
681
839
|
{
|
@@ -684,6 +842,9 @@ nl_node_destroy(VALUE self)
|
|
684
842
|
return Qnil;
|
685
843
|
}
|
686
844
|
|
845
|
+
/**
|
846
|
+
* @return [Boolean] true if this Node is equal to +other+.
|
847
|
+
*/
|
687
848
|
static VALUE
|
688
849
|
nl_node_equals(VALUE self, VALUE other)
|
689
850
|
{
|
@@ -702,6 +863,11 @@ lxb_dom_node_name_qualified(lxb_dom_node_t *node, size_t *len)
|
|
702
863
|
return lxb_dom_node_name(node, len);
|
703
864
|
}
|
704
865
|
|
866
|
+
/**
|
867
|
+
* Get the name of this Node
|
868
|
+
*
|
869
|
+
* @return [String] The name of this Node
|
870
|
+
*/
|
705
871
|
static VALUE
|
706
872
|
nl_node_name(VALUE self)
|
707
873
|
{
|
@@ -733,6 +899,13 @@ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_dom_element_t *element, lxb_
|
|
733
899
|
return frag_root;
|
734
900
|
}
|
735
901
|
|
902
|
+
/**
|
903
|
+
* Parse +html+ as a document fragment within the context of
|
904
|
+
* *this* node.
|
905
|
+
*
|
906
|
+
* @param html [String] The fragment to be parsed.
|
907
|
+
* @return [NodeSet] The {NodeSet} containing the parsed nodes.
|
908
|
+
*/
|
736
909
|
static VALUE
|
737
910
|
nl_node_parse(VALUE self, VALUE html)
|
738
911
|
{
|
@@ -752,38 +925,48 @@ nl_node_parse(VALUE self, VALUE html)
|
|
752
925
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
753
926
|
}
|
754
927
|
|
928
|
+
typedef void (*lxb_dom_node_add_nodes_to_f)(lxb_dom_node_t *, lxb_dom_node_t *);
|
929
|
+
|
755
930
|
static VALUE
|
756
|
-
|
931
|
+
nl_node_add_nodes(VALUE self, VALUE new, lxb_dom_node_add_nodes_to_f add_to, bool operate_on_new_node)
|
757
932
|
{
|
758
933
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
759
934
|
lxb_dom_document_t *doc = node->owner_document;
|
760
935
|
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
} else if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("previous"))) {
|
765
|
-
insert_after = 0;
|
766
|
-
} else {
|
767
|
-
rb_raise(rb_eArgError, "Unsupported inserting position");
|
768
|
-
}
|
769
|
-
|
770
|
-
if (TYPE(new) == T_STRING) {
|
771
|
-
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
936
|
+
if (TYPE(new) == T_STRING || rb_obj_is_kind_of(new, cNokolexborDocumentFragment)) {
|
937
|
+
lxb_dom_node_t *frag_root = (TYPE(new) == T_STRING) ? nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new))
|
938
|
+
: nl_rb_node_unwrap(new);
|
772
939
|
lexbor_array_t *array = lexbor_array_create();
|
773
940
|
|
941
|
+
lxb_dom_node_t *last_node = node;
|
774
942
|
while (frag_root->first_child != NULL) {
|
775
943
|
lxb_dom_node_t *child = frag_root->first_child;
|
776
944
|
lxb_dom_node_remove(child);
|
777
|
-
|
945
|
+
operate_on_new_node ? add_to(last_node, child) : add_to(node, child);
|
946
|
+
last_node = child;
|
778
947
|
lexbor_array_push(array, child);
|
779
948
|
}
|
780
|
-
|
949
|
+
if (TYPE(new) == T_STRING) {
|
950
|
+
lxb_dom_node_destroy(frag_root);
|
951
|
+
}
|
781
952
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
782
953
|
|
954
|
+
} else if (rb_obj_is_kind_of(new, cNokolexborNodeSet)) {
|
955
|
+
lexbor_array_t *node_array = nl_rb_node_set_unwrap(new);
|
956
|
+
|
957
|
+
lxb_dom_node_t *last_node = node;
|
958
|
+
for (size_t i = 0; i < node_array->length; i++) {
|
959
|
+
lxb_dom_node_t *child = (lxb_dom_node_t *)node_array->list[i];
|
960
|
+
lxb_dom_node_remove(child);
|
961
|
+
operate_on_new_node ? add_to(last_node, child) : add_to(node, child);
|
962
|
+
last_node = child;
|
963
|
+
}
|
964
|
+
return new;
|
965
|
+
|
783
966
|
} else if (rb_obj_is_kind_of(new, cNokolexborNode)) {
|
784
967
|
lxb_dom_node_t *node_new = nl_rb_node_unwrap(new);
|
785
968
|
lxb_dom_node_remove(node_new);
|
786
|
-
|
969
|
+
add_to(node, node_new);
|
787
970
|
return new;
|
788
971
|
|
789
972
|
} else {
|
@@ -792,43 +975,57 @@ nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
|
|
792
975
|
return Qnil;
|
793
976
|
}
|
794
977
|
|
978
|
+
/**
|
979
|
+
* Insert +node_or_tags+ before or after this Node (as a sibling).
|
980
|
+
*
|
981
|
+
* @see #add_previous_sibling
|
982
|
+
* @see #add_next_sibling
|
983
|
+
*
|
984
|
+
* @return [Node,NodeSet] The reparented {Node} (if +node_or_tags+ is a {Node}), or {NodeSet} (if +node_or_tags+ is a {DocumentFragment}, {NodeSet}, or {String}).
|
985
|
+
*/
|
795
986
|
static VALUE
|
796
|
-
|
987
|
+
nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
|
797
988
|
{
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
if (
|
802
|
-
|
803
|
-
lexbor_array_t *array = lexbor_array_create();
|
804
|
-
|
805
|
-
while (frag_root->first_child != NULL) {
|
806
|
-
lxb_dom_node_t *child = frag_root->first_child;
|
807
|
-
lxb_dom_node_remove(child);
|
808
|
-
lxb_dom_node_insert_child(node, child);
|
809
|
-
lexbor_array_push(array, child);
|
810
|
-
}
|
811
|
-
lxb_dom_node_destroy(frag_root);
|
812
|
-
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
813
|
-
|
814
|
-
} else if (rb_obj_is_kind_of(new, cNokolexborNode)) {
|
815
|
-
lxb_dom_node_t *node_new = nl_rb_node_unwrap(new);
|
816
|
-
lxb_dom_node_remove(node_new);
|
817
|
-
lxb_dom_node_insert_child(node, node_new);
|
818
|
-
return new;
|
819
|
-
|
989
|
+
bool insert_after;
|
990
|
+
if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("next"))) {
|
991
|
+
insert_after = true;
|
992
|
+
} else if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("previous"))) {
|
993
|
+
insert_after = false;
|
820
994
|
} else {
|
821
|
-
rb_raise(rb_eArgError, "Unsupported
|
995
|
+
rb_raise(rb_eArgError, "Unsupported inserting position");
|
822
996
|
}
|
823
|
-
|
997
|
+
|
998
|
+
return insert_after ? nl_node_add_nodes(self, new, lxb_dom_node_insert_after, true)
|
999
|
+
: nl_node_add_nodes(self, new, lxb_dom_node_insert_before, false);
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
/**
|
1003
|
+
* Add +new+ as a child of this Node.
|
1004
|
+
*
|
1005
|
+
* @param new [Node, DocumentFragment, NodeSet, String] The node to be added.
|
1006
|
+
*
|
1007
|
+
* @return [Node,NodeSet] The reparented {Node} (if +new+ is a {Node}), or {NodeSet} (if +new+ is a {DocumentFragment}, {NodeSet}, or {String}).
|
1008
|
+
*/
|
1009
|
+
static VALUE
|
1010
|
+
nl_node_add_child(VALUE self, VALUE new)
|
1011
|
+
{
|
1012
|
+
return nl_node_add_nodes(self, new, lxb_dom_node_insert_child, false);
|
824
1013
|
}
|
825
1014
|
|
1015
|
+
/**
|
1016
|
+
* Get the type of this Node
|
1017
|
+
*
|
1018
|
+
* @return {Integer}
|
1019
|
+
*/
|
826
1020
|
static VALUE
|
827
1021
|
nl_node_get_type(VALUE self)
|
828
1022
|
{
|
829
1023
|
return INT2NUM(nl_rb_node_unwrap(self)->type);
|
830
1024
|
}
|
831
1025
|
|
1026
|
+
/**
|
1027
|
+
* @return [Element] The first child Node that is an element.
|
1028
|
+
*/
|
832
1029
|
static VALUE
|
833
1030
|
nl_node_first_element_child(VALUE self)
|
834
1031
|
{
|
@@ -856,6 +1053,9 @@ nl_node_first_element_child(VALUE self)
|
|
856
1053
|
return Qnil;
|
857
1054
|
}
|
858
1055
|
|
1056
|
+
/**
|
1057
|
+
* @return [Element] The last child Node that is an element.
|
1058
|
+
*/
|
859
1059
|
static VALUE
|
860
1060
|
nl_node_last_element_child(VALUE self)
|
861
1061
|
{
|
@@ -883,6 +1083,11 @@ nl_node_last_element_child(VALUE self)
|
|
883
1083
|
return Qnil;
|
884
1084
|
}
|
885
1085
|
|
1086
|
+
/**
|
1087
|
+
* Copy this node.
|
1088
|
+
*
|
1089
|
+
* @return [Node] The new {Node}.
|
1090
|
+
*/
|
886
1091
|
static VALUE
|
887
1092
|
nl_node_clone(VALUE self)
|
888
1093
|
{
|
@@ -891,9 +1096,9 @@ nl_node_clone(VALUE self)
|
|
891
1096
|
|
892
1097
|
switch (node->type) {
|
893
1098
|
case LXB_DOM_NODE_TYPE_ATTRIBUTE:
|
894
|
-
clone = lxb_dom_attr_interface_clone(node->owner_document, lxb_dom_interface_attr(node));
|
1099
|
+
clone = (lxb_dom_node_t *)lxb_dom_attr_interface_clone(node->owner_document, lxb_dom_interface_attr(node));
|
895
1100
|
case LXB_DOM_NODE_TYPE_CDATA_SECTION:
|
896
|
-
clone = lxb_dom_cdata_section_interface_clone(node->owner_document, lxb_dom_interface_cdata_section(node));
|
1101
|
+
clone = (lxb_dom_node_t *)lxb_dom_cdata_section_interface_clone(node->owner_document, lxb_dom_interface_cdata_section(node));
|
897
1102
|
default:
|
898
1103
|
clone = lxb_dom_node_clone(node, true);
|
899
1104
|
break;
|
@@ -63,12 +63,27 @@ nl_rb_node_set_create_with_data(lexbor_array_t *array, VALUE rb_document)
|
|
63
63
|
return ret;
|
64
64
|
}
|
65
65
|
|
66
|
+
/**
|
67
|
+
* Get the length of this NodeSet.
|
68
|
+
*
|
69
|
+
* @return [Integer]
|
70
|
+
*/
|
66
71
|
static VALUE
|
67
72
|
nl_node_set_length(VALUE self)
|
68
73
|
{
|
69
74
|
return INT2NUM(nl_rb_node_set_unwrap(self)->length);
|
70
75
|
}
|
71
76
|
|
77
|
+
/**
|
78
|
+
* call-seq:
|
79
|
+
* push(node)
|
80
|
+
*
|
81
|
+
* Append +node+ to the NodeSet.
|
82
|
+
*
|
83
|
+
* @param node [Node]
|
84
|
+
*
|
85
|
+
* @return [NodeSet] +self+, to support chaining of calls.
|
86
|
+
*/
|
72
87
|
static VALUE
|
73
88
|
nl_node_set_push(VALUE self, VALUE rb_node)
|
74
89
|
{
|
@@ -83,6 +98,16 @@ nl_node_set_push(VALUE self, VALUE rb_node)
|
|
83
98
|
return self;
|
84
99
|
}
|
85
100
|
|
101
|
+
/**
|
102
|
+
* call-seq:
|
103
|
+
* delete(node)
|
104
|
+
*
|
105
|
+
* Delete +node+ from the NodeSet.
|
106
|
+
*
|
107
|
+
* @param node [Node]
|
108
|
+
*
|
109
|
+
* @return [Node,nil] The deleted node if found, otherwise returns nil.
|
110
|
+
*/
|
86
111
|
static VALUE
|
87
112
|
nl_node_set_delete(VALUE self, VALUE rb_node)
|
88
113
|
{
|
@@ -103,6 +128,12 @@ nl_node_set_delete(VALUE self, VALUE rb_node)
|
|
103
128
|
return rb_node;
|
104
129
|
}
|
105
130
|
|
131
|
+
/**
|
132
|
+
* call-seq:
|
133
|
+
* include?(node)
|
134
|
+
*
|
135
|
+
* @return true if any member of this NodeSet equals +node+.
|
136
|
+
*/
|
106
137
|
static VALUE
|
107
138
|
nl_node_set_is_include(VALUE self, VALUE rb_node)
|
108
139
|
{
|
@@ -166,6 +197,18 @@ nl_node_set_subseq(VALUE self, long beg, long len)
|
|
166
197
|
return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
|
167
198
|
}
|
168
199
|
|
200
|
+
/**
|
201
|
+
* call-seq:
|
202
|
+
* [](index) -> Node,nil
|
203
|
+
* [](start, length) -> NodeSet,nil
|
204
|
+
* [](range) -> NodeSet,nil
|
205
|
+
*
|
206
|
+
* @return [Node,NodeSet,nil] the {Node} at +index+, or returns a {NodeSet}
|
207
|
+
* containing nodes starting at +start+ and continuing for +length+ elements, or
|
208
|
+
* returns a {NodeSet} containing nodes specified by +range+. Negative +indices+
|
209
|
+
* count backward from the end of the +node_set+ (-1 is the last node). Returns
|
210
|
+
* nil if the +index+ (or +start+) are out of range.
|
211
|
+
*/
|
169
212
|
static VALUE
|
170
213
|
nl_node_set_slice(int argc, VALUE *argv, VALUE self)
|
171
214
|
{
|
@@ -205,6 +248,9 @@ nl_node_set_slice(int argc, VALUE *argv, VALUE self)
|
|
205
248
|
return nl_node_set_index_at(self, NUM2LONG(arg));
|
206
249
|
}
|
207
250
|
|
251
|
+
/**
|
252
|
+
* @return [Array<Node>] This list as an Array
|
253
|
+
*/
|
208
254
|
static VALUE
|
209
255
|
nl_node_set_to_array(VALUE self)
|
210
256
|
{
|
@@ -221,6 +267,9 @@ nl_node_set_to_array(VALUE self)
|
|
221
267
|
return list;
|
222
268
|
}
|
223
269
|
|
270
|
+
/**
|
271
|
+
* @return [NodeSet] A new set built by merging the +other+ set, excluding duplicates.
|
272
|
+
*/
|
224
273
|
static VALUE
|
225
274
|
nl_node_set_union(VALUE self, VALUE other)
|
226
275
|
{
|
@@ -301,6 +350,9 @@ nl_node_set_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
|
|
301
350
|
return status;
|
302
351
|
}
|
303
352
|
|
353
|
+
/**
|
354
|
+
* (see Node#at_css)
|
355
|
+
*/
|
304
356
|
static VALUE
|
305
357
|
nl_node_set_at_css(VALUE self, VALUE selector)
|
306
358
|
{
|
@@ -328,6 +380,9 @@ nl_node_set_at_css(VALUE self, VALUE selector)
|
|
328
380
|
return ret;
|
329
381
|
}
|
330
382
|
|
383
|
+
/**
|
384
|
+
* (see Node#css)
|
385
|
+
*/
|
331
386
|
static VALUE
|
332
387
|
nl_node_set_css(VALUE self, VALUE selector)
|
333
388
|
{
|
@@ -353,7 +408,6 @@ void Init_nl_node_set(void)
|
|
353
408
|
|
354
409
|
rb_define_method(cNokolexborNodeSet, "length", nl_node_set_length, 0);
|
355
410
|
rb_define_method(cNokolexborNodeSet, "[]", nl_node_set_slice, -1);
|
356
|
-
rb_define_method(cNokolexborNodeSet, "slice", nl_node_set_slice, -1);
|
357
411
|
rb_define_method(cNokolexborNodeSet, "push", nl_node_set_push, 1);
|
358
412
|
rb_define_method(cNokolexborNodeSet, "|", nl_node_set_union, 1);
|
359
413
|
rb_define_method(cNokolexborNodeSet, "to_a", nl_node_set_to_array, 0);
|
@@ -362,6 +416,7 @@ void Init_nl_node_set(void)
|
|
362
416
|
rb_define_method(cNokolexborNodeSet, "at_css", nl_node_set_at_css, 1);
|
363
417
|
rb_define_method(cNokolexborNodeSet, "css", nl_node_set_css, 1);
|
364
418
|
|
419
|
+
rb_define_alias(cNokolexborNodeSet, "slice", "[]");
|
365
420
|
rb_define_alias(cNokolexborNodeSet, "<<", "push");
|
366
421
|
rb_define_alias(cNokolexborNodeSet, "size", "length");
|
367
422
|
rb_define_alias(cNokolexborNodeSet, "+", "|");
|