nokolexbor 0.3.3 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/nokolexbor/nl_attribute.c +201 -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 +317 -48
- 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.c +1 -0
- data/ext/nokolexbor/nokolexbor.h +2 -0
- data/lib/nokolexbor/document.rb +52 -5
- data/lib/nokolexbor/document_fragment.rb +11 -0
- data/lib/nokolexbor/node.rb +370 -24
- data/lib/nokolexbor/node_set.rb +56 -0
- data/lib/nokolexbor/version.rb +1 -1
- data/lib/nokolexbor.rb +0 -1
- metadata +3 -25
- data/lib/nokolexbor/attribute.rb +0 -18
- 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
@@ -12,6 +12,7 @@ extern VALUE cNokolexborComment;
|
|
12
12
|
extern VALUE cNokolexborProcessingInstruction;
|
13
13
|
extern VALUE cNokolexborNodeSet;
|
14
14
|
extern VALUE cNokolexborDocumentFragment;
|
15
|
+
extern VALUE cNokolexborAttribute;
|
15
16
|
extern VALUE eLexborError;
|
16
17
|
VALUE cNokolexborNode;
|
17
18
|
VALUE cNokolexborElement;
|
@@ -31,8 +32,9 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
|
|
31
32
|
case LXB_DOM_NODE_TYPE_ELEMENT:
|
32
33
|
rb_class = cNokolexborElement;
|
33
34
|
break;
|
34
|
-
|
35
|
-
|
35
|
+
case LXB_DOM_NODE_TYPE_ATTRIBUTE:
|
36
|
+
rb_class = cNokolexborAttribute;
|
37
|
+
break;
|
36
38
|
case LXB_DOM_NODE_TYPE_TEXT:
|
37
39
|
rb_class = cNokolexborText;
|
38
40
|
break;
|
@@ -49,8 +51,11 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
|
|
49
51
|
case LXB_DOM_NODE_TYPE_COMMENT:
|
50
52
|
rb_class = cNokolexborComment;
|
51
53
|
break;
|
52
|
-
|
53
|
-
|
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;
|
54
59
|
// case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
|
55
60
|
// break;
|
56
61
|
case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
|
@@ -79,6 +84,23 @@ nl_rb_node_unwrap(VALUE rb_node)
|
|
79
84
|
return node;
|
80
85
|
}
|
81
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
|
+
*/
|
82
104
|
static VALUE
|
83
105
|
nl_node_new(int argc, VALUE *argv, VALUE klass)
|
84
106
|
{
|
@@ -111,6 +133,68 @@ nl_node_new(int argc, VALUE *argv, VALUE klass)
|
|
111
133
|
return rb_node;
|
112
134
|
}
|
113
135
|
|
136
|
+
/**
|
137
|
+
* call-seq: attribute(name) → Attribute
|
138
|
+
*
|
139
|
+
* @return [Attribute] The attribute belonging to this node with name +name+.
|
140
|
+
*/
|
141
|
+
static VALUE
|
142
|
+
nl_node_attribute(VALUE self, VALUE rb_name)
|
143
|
+
{
|
144
|
+
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
145
|
+
|
146
|
+
const char *c_name = StringValuePtr(rb_name);
|
147
|
+
size_t name_len = RSTRING_LEN(rb_name);
|
148
|
+
|
149
|
+
if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
|
150
|
+
return Qnil;
|
151
|
+
}
|
152
|
+
|
153
|
+
lxb_dom_attr_t *attr = lxb_dom_element_attr_by_name(lxb_dom_interface_element(node), (const lxb_char_t *)c_name, name_len);
|
154
|
+
if (attr == NULL) {
|
155
|
+
return Qnil;
|
156
|
+
}
|
157
|
+
if (attr->owner == NULL) {
|
158
|
+
attr->owner = lxb_dom_interface_element(node);
|
159
|
+
}
|
160
|
+
return nl_rb_node_create(attr, nl_rb_document_get(self));
|
161
|
+
}
|
162
|
+
|
163
|
+
/**
|
164
|
+
* @return [Array<Attribute>] An array of {Attribute} belonging to this node.
|
165
|
+
*/
|
166
|
+
static VALUE
|
167
|
+
nl_node_attribute_nodes(VALUE self)
|
168
|
+
{
|
169
|
+
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
170
|
+
VALUE ary = rb_ary_new();
|
171
|
+
if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
|
172
|
+
return ary;
|
173
|
+
}
|
174
|
+
|
175
|
+
lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_dom_interface_element(node));
|
176
|
+
|
177
|
+
if (attr == NULL) {
|
178
|
+
return ary;
|
179
|
+
}
|
180
|
+
|
181
|
+
VALUE rb_doc = nl_rb_document_get(self);
|
182
|
+
while (attr != NULL) {
|
183
|
+
if (attr->owner == NULL) {
|
184
|
+
attr->owner = lxb_dom_interface_element(node);
|
185
|
+
}
|
186
|
+
rb_ary_push(ary, nl_rb_node_create(attr, rb_doc));
|
187
|
+
attr = attr->next;
|
188
|
+
}
|
189
|
+
|
190
|
+
return ary;
|
191
|
+
}
|
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
|
+
*/
|
114
198
|
static VALUE
|
115
199
|
nl_node_content(VALUE self)
|
116
200
|
{
|
@@ -127,6 +211,12 @@ nl_node_content(VALUE self)
|
|
127
211
|
return rb_str;
|
128
212
|
}
|
129
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
|
+
*/
|
130
220
|
static VALUE
|
131
221
|
nl_node_content_set(VALUE self, VALUE content)
|
132
222
|
{
|
@@ -141,6 +231,15 @@ nl_node_content_set(VALUE self, VALUE content)
|
|
141
231
|
return content;
|
142
232
|
}
|
143
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
|
+
*/
|
144
243
|
static VALUE
|
145
244
|
nl_node_get_attr(VALUE self, VALUE rb_attr)
|
146
245
|
{
|
@@ -166,6 +265,16 @@ nl_node_get_attr(VALUE self, VALUE rb_attr)
|
|
166
265
|
return rb_utf8_str_new((const char *)attr_value, attr_value_len);
|
167
266
|
}
|
168
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
|
+
*/
|
169
278
|
static VALUE
|
170
279
|
nl_node_set_attr(VALUE self, VALUE rb_attr, VALUE rb_value)
|
171
280
|
{
|
@@ -190,13 +299,22 @@ nl_node_set_attr(VALUE self, VALUE rb_attr, VALUE rb_value)
|
|
190
299
|
return rb_value;
|
191
300
|
}
|
192
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
|
+
*/
|
193
311
|
static VALUE
|
194
312
|
nl_node_remove_attr(VALUE self, VALUE rb_attr)
|
195
313
|
{
|
196
314
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
197
315
|
|
198
316
|
if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
|
199
|
-
return
|
317
|
+
return Qfalse;
|
200
318
|
}
|
201
319
|
|
202
320
|
VALUE rb_attr_s = rb_String(rb_attr);
|
@@ -206,7 +324,12 @@ nl_node_remove_attr(VALUE self, VALUE rb_attr)
|
|
206
324
|
|
207
325
|
lxb_dom_element_t *element = lxb_dom_interface_element(node);
|
208
326
|
|
209
|
-
|
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;
|
210
333
|
}
|
211
334
|
|
212
335
|
lxb_status_t
|
@@ -333,6 +456,11 @@ void nl_sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_
|
|
333
456
|
}
|
334
457
|
}
|
335
458
|
|
459
|
+
/**
|
460
|
+
* Internal implementation of {#at_css}
|
461
|
+
*
|
462
|
+
* @see #at_css
|
463
|
+
*/
|
336
464
|
static VALUE
|
337
465
|
nl_node_at_css(VALUE self, VALUE selector)
|
338
466
|
{
|
@@ -360,6 +488,11 @@ nl_node_at_css(VALUE self, VALUE selector)
|
|
360
488
|
return ret;
|
361
489
|
}
|
362
490
|
|
491
|
+
/**
|
492
|
+
* Internal implementation of {#css}
|
493
|
+
*
|
494
|
+
* @see #css
|
495
|
+
*/
|
363
496
|
static VALUE
|
364
497
|
nl_node_css(VALUE self, VALUE selector)
|
365
498
|
{
|
@@ -377,6 +510,11 @@ nl_node_css(VALUE self, VALUE selector)
|
|
377
510
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
378
511
|
}
|
379
512
|
|
513
|
+
/**
|
514
|
+
* Get the inner_html of this Node.
|
515
|
+
*
|
516
|
+
* @return [String]
|
517
|
+
*/
|
380
518
|
static VALUE
|
381
519
|
nl_node_inner_html(int argc, VALUE *argv, VALUE self)
|
382
520
|
{
|
@@ -414,6 +552,11 @@ nl_node_inner_html(int argc, VALUE *argv, VALUE self)
|
|
414
552
|
return Qnil;
|
415
553
|
}
|
416
554
|
|
555
|
+
/**
|
556
|
+
* Serialize this Node to HTML, also known as outer_html.
|
557
|
+
*
|
558
|
+
* @return [String]
|
559
|
+
*/
|
417
560
|
static VALUE
|
418
561
|
nl_node_outer_html(int argc, VALUE *argv, VALUE self)
|
419
562
|
{
|
@@ -451,6 +594,11 @@ nl_node_outer_html(int argc, VALUE *argv, VALUE self)
|
|
451
594
|
return Qnil;
|
452
595
|
}
|
453
596
|
|
597
|
+
/**
|
598
|
+
* call-seq: key?(name) -> Boolean
|
599
|
+
*
|
600
|
+
* @return true if +name+ is set.
|
601
|
+
*/
|
454
602
|
static VALUE
|
455
603
|
nl_node_has_key(VALUE self, VALUE rb_attr)
|
456
604
|
{
|
@@ -469,6 +617,11 @@ nl_node_has_key(VALUE self, VALUE rb_attr)
|
|
469
617
|
return lxb_dom_element_has_attribute(element, (const lxb_char_t *)attr_c, attr_len) ? Qtrue : Qfalse;
|
470
618
|
}
|
471
619
|
|
620
|
+
/**
|
621
|
+
* Get the attribute names of this Node.
|
622
|
+
*
|
623
|
+
* @return [Array<String>] An array of attribute names.
|
624
|
+
*/
|
472
625
|
static VALUE
|
473
626
|
nl_node_keys(VALUE self)
|
474
627
|
{
|
@@ -492,6 +645,11 @@ nl_node_keys(VALUE self)
|
|
492
645
|
return ary_keys;
|
493
646
|
}
|
494
647
|
|
648
|
+
/**
|
649
|
+
* Get the attribute values of this Node.
|
650
|
+
*
|
651
|
+
* @return [Array<String>] An array of attribute values.
|
652
|
+
*/
|
495
653
|
static VALUE
|
496
654
|
nl_node_values(VALUE self)
|
497
655
|
{
|
@@ -519,6 +677,11 @@ nl_node_values(VALUE self)
|
|
519
677
|
return ary_values;
|
520
678
|
}
|
521
679
|
|
680
|
+
/**
|
681
|
+
* Get a hash of attribute names and values of this Node.
|
682
|
+
*
|
683
|
+
* @return [Hash{String => String}] A hash whose keys are attribute names and values are attribute values.
|
684
|
+
*/
|
522
685
|
static VALUE
|
523
686
|
nl_node_attrs(VALUE self)
|
524
687
|
{
|
@@ -547,6 +710,11 @@ nl_node_attrs(VALUE self)
|
|
547
710
|
return rb_hash;
|
548
711
|
}
|
549
712
|
|
713
|
+
/**
|
714
|
+
* Get the parent node.
|
715
|
+
*
|
716
|
+
* @return [Node,nil] The parent node
|
717
|
+
*/
|
550
718
|
static VALUE
|
551
719
|
nl_node_parent(VALUE self)
|
552
720
|
{
|
@@ -554,6 +722,11 @@ nl_node_parent(VALUE self)
|
|
554
722
|
return node->parent ? nl_rb_node_create(node->parent, nl_rb_document_get(self)) : Qnil;
|
555
723
|
}
|
556
724
|
|
725
|
+
/**
|
726
|
+
* Get the previous sibling node.
|
727
|
+
*
|
728
|
+
* @return [Node,nil] The previous sibling node
|
729
|
+
*/
|
557
730
|
static VALUE
|
558
731
|
nl_node_previous(VALUE self)
|
559
732
|
{
|
@@ -561,6 +734,11 @@ nl_node_previous(VALUE self)
|
|
561
734
|
return node->prev ? nl_rb_node_create(node->prev, nl_rb_document_get(self)) : Qnil;
|
562
735
|
}
|
563
736
|
|
737
|
+
/**
|
738
|
+
* Get the previous sibling element.
|
739
|
+
*
|
740
|
+
* @return [Element,nil] The previous sibling element
|
741
|
+
*/
|
564
742
|
static VALUE
|
565
743
|
nl_node_previous_element(VALUE self)
|
566
744
|
{
|
@@ -574,6 +752,11 @@ nl_node_previous_element(VALUE self)
|
|
574
752
|
return Qnil;
|
575
753
|
}
|
576
754
|
|
755
|
+
/**
|
756
|
+
* Get the next sibling node.
|
757
|
+
*
|
758
|
+
* @return [Node,nil] The previous sibling node
|
759
|
+
*/
|
577
760
|
static VALUE
|
578
761
|
nl_node_next(VALUE self)
|
579
762
|
{
|
@@ -581,6 +764,11 @@ nl_node_next(VALUE self)
|
|
581
764
|
return node->next ? nl_rb_node_create(node->next, nl_rb_document_get(self)) : Qnil;
|
582
765
|
}
|
583
766
|
|
767
|
+
/**
|
768
|
+
* Get the next sibling element.
|
769
|
+
*
|
770
|
+
* @return [Element,nil] The previous sibling element
|
771
|
+
*/
|
584
772
|
static VALUE
|
585
773
|
nl_node_next_element(VALUE self)
|
586
774
|
{
|
@@ -594,6 +782,11 @@ nl_node_next_element(VALUE self)
|
|
594
782
|
return Qnil;
|
595
783
|
}
|
596
784
|
|
785
|
+
/**
|
786
|
+
* Get the children of this node.
|
787
|
+
*
|
788
|
+
* @return [NodeSet] The set of this node's children.
|
789
|
+
*/
|
597
790
|
static VALUE
|
598
791
|
nl_node_children(VALUE self)
|
599
792
|
{
|
@@ -609,6 +802,11 @@ nl_node_children(VALUE self)
|
|
609
802
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
610
803
|
}
|
611
804
|
|
805
|
+
/**
|
806
|
+
* Get the first child of this node.
|
807
|
+
*
|
808
|
+
* @return [Node,nil] The first child.
|
809
|
+
*/
|
612
810
|
static VALUE
|
613
811
|
nl_node_child(VALUE self)
|
614
812
|
{
|
@@ -617,14 +815,26 @@ nl_node_child(VALUE self)
|
|
617
815
|
return child ? nl_rb_node_create(child, nl_rb_document_get(self)) : Qnil;
|
618
816
|
}
|
619
817
|
|
818
|
+
/**
|
819
|
+
* Remove this node from its current context.
|
820
|
+
*
|
821
|
+
* @return [Node] +self+, to support chaining of calls.
|
822
|
+
*/
|
620
823
|
static VALUE
|
621
824
|
nl_node_remove(VALUE self)
|
622
825
|
{
|
623
826
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
624
827
|
lxb_dom_node_remove(node);
|
625
|
-
return
|
828
|
+
return self;
|
626
829
|
}
|
627
830
|
|
831
|
+
/**
|
832
|
+
* Remove this node from its current context and free its allocated memory.
|
833
|
+
*
|
834
|
+
* @return [nil]
|
835
|
+
*
|
836
|
+
* @see #remove
|
837
|
+
*/
|
628
838
|
static VALUE
|
629
839
|
nl_node_destroy(VALUE self)
|
630
840
|
{
|
@@ -633,6 +843,9 @@ nl_node_destroy(VALUE self)
|
|
633
843
|
return Qnil;
|
634
844
|
}
|
635
845
|
|
846
|
+
/**
|
847
|
+
* @return [Boolean] true if this Node is equal to +other+.
|
848
|
+
*/
|
636
849
|
static VALUE
|
637
850
|
nl_node_equals(VALUE self, VALUE other)
|
638
851
|
{
|
@@ -651,6 +864,11 @@ lxb_dom_node_name_qualified(lxb_dom_node_t *node, size_t *len)
|
|
651
864
|
return lxb_dom_node_name(node, len);
|
652
865
|
}
|
653
866
|
|
867
|
+
/**
|
868
|
+
* Get the name of this Node
|
869
|
+
*
|
870
|
+
* @return [String] The name of this Node
|
871
|
+
*/
|
654
872
|
static VALUE
|
655
873
|
nl_node_name(VALUE self)
|
656
874
|
{
|
@@ -682,6 +900,13 @@ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_dom_element_t *element, lxb_
|
|
682
900
|
return frag_root;
|
683
901
|
}
|
684
902
|
|
903
|
+
/**
|
904
|
+
* Parse +html+ as a document fragment within the context of
|
905
|
+
* *this* node.
|
906
|
+
*
|
907
|
+
* @param html [String] The fragment to be parsed.
|
908
|
+
* @return [NodeSet] The {NodeSet} containing the parsed nodes.
|
909
|
+
*/
|
685
910
|
static VALUE
|
686
911
|
nl_node_parse(VALUE self, VALUE html)
|
687
912
|
{
|
@@ -701,38 +926,48 @@ nl_node_parse(VALUE self, VALUE html)
|
|
701
926
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
702
927
|
}
|
703
928
|
|
929
|
+
typedef void (*lxb_dom_node_add_nodes_to_f)(lxb_dom_node_t *, lxb_dom_node_t *);
|
930
|
+
|
704
931
|
static VALUE
|
705
|
-
|
932
|
+
nl_node_add_nodes(VALUE self, VALUE new, lxb_dom_node_add_nodes_to_f add_to, bool operate_on_new_node)
|
706
933
|
{
|
707
934
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
708
935
|
lxb_dom_document_t *doc = node->owner_document;
|
709
936
|
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
} else if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("previous"))) {
|
714
|
-
insert_after = 0;
|
715
|
-
} else {
|
716
|
-
rb_raise(rb_eArgError, "Unsupported inserting position");
|
717
|
-
}
|
718
|
-
|
719
|
-
if (TYPE(new) == T_STRING) {
|
720
|
-
lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
|
937
|
+
if (TYPE(new) == T_STRING || rb_obj_is_kind_of(new, cNokolexborDocumentFragment)) {
|
938
|
+
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))
|
939
|
+
: nl_rb_node_unwrap(new);
|
721
940
|
lexbor_array_t *array = lexbor_array_create();
|
722
941
|
|
942
|
+
lxb_dom_node_t *last_node = node;
|
723
943
|
while (frag_root->first_child != NULL) {
|
724
944
|
lxb_dom_node_t *child = frag_root->first_child;
|
725
945
|
lxb_dom_node_remove(child);
|
726
|
-
|
946
|
+
operate_on_new_node ? add_to(last_node, child) : add_to(node, child);
|
947
|
+
last_node = child;
|
727
948
|
lexbor_array_push(array, child);
|
728
949
|
}
|
729
|
-
|
950
|
+
if (TYPE(new) == T_STRING) {
|
951
|
+
lxb_dom_node_destroy(frag_root);
|
952
|
+
}
|
730
953
|
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
731
954
|
|
955
|
+
} else if (rb_obj_is_kind_of(new, cNokolexborNodeSet)) {
|
956
|
+
lexbor_array_t *node_array = nl_rb_node_set_unwrap(new);
|
957
|
+
|
958
|
+
lxb_dom_node_t *last_node = node;
|
959
|
+
for (size_t i = 0; i < node_array->length; i++) {
|
960
|
+
lxb_dom_node_t *child = (lxb_dom_node_t *)node_array->list[i];
|
961
|
+
lxb_dom_node_remove(child);
|
962
|
+
operate_on_new_node ? add_to(last_node, child) : add_to(node, child);
|
963
|
+
last_node = child;
|
964
|
+
}
|
965
|
+
return new;
|
966
|
+
|
732
967
|
} else if (rb_obj_is_kind_of(new, cNokolexborNode)) {
|
733
968
|
lxb_dom_node_t *node_new = nl_rb_node_unwrap(new);
|
734
969
|
lxb_dom_node_remove(node_new);
|
735
|
-
|
970
|
+
add_to(node, node_new);
|
736
971
|
return new;
|
737
972
|
|
738
973
|
} else {
|
@@ -741,43 +976,57 @@ nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
|
|
741
976
|
return Qnil;
|
742
977
|
}
|
743
978
|
|
979
|
+
/**
|
980
|
+
* Insert +node_or_tags+ before or after this Node (as a sibling).
|
981
|
+
*
|
982
|
+
* @see #add_previous_sibling
|
983
|
+
* @see #add_next_sibling
|
984
|
+
*
|
985
|
+
* @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}).
|
986
|
+
*/
|
744
987
|
static VALUE
|
745
|
-
|
988
|
+
nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
|
746
989
|
{
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
if (
|
751
|
-
|
752
|
-
lexbor_array_t *array = lexbor_array_create();
|
753
|
-
|
754
|
-
while (frag_root->first_child != NULL) {
|
755
|
-
lxb_dom_node_t *child = frag_root->first_child;
|
756
|
-
lxb_dom_node_remove(child);
|
757
|
-
lxb_dom_node_insert_child(node, child);
|
758
|
-
lexbor_array_push(array, child);
|
759
|
-
}
|
760
|
-
lxb_dom_node_destroy(frag_root);
|
761
|
-
return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
|
762
|
-
|
763
|
-
} else if (rb_obj_is_kind_of(new, cNokolexborNode)) {
|
764
|
-
lxb_dom_node_t *node_new = nl_rb_node_unwrap(new);
|
765
|
-
lxb_dom_node_remove(node_new);
|
766
|
-
lxb_dom_node_insert_child(node, node_new);
|
767
|
-
return new;
|
768
|
-
|
990
|
+
bool insert_after;
|
991
|
+
if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("next"))) {
|
992
|
+
insert_after = true;
|
993
|
+
} else if (rb_eql(rb_String(next_or_previous), rb_str_new_literal("previous"))) {
|
994
|
+
insert_after = false;
|
769
995
|
} else {
|
770
|
-
rb_raise(rb_eArgError, "Unsupported
|
996
|
+
rb_raise(rb_eArgError, "Unsupported inserting position");
|
771
997
|
}
|
772
|
-
|
998
|
+
|
999
|
+
return insert_after ? nl_node_add_nodes(self, new, lxb_dom_node_insert_after, true)
|
1000
|
+
: nl_node_add_nodes(self, new, lxb_dom_node_insert_before, false);
|
773
1001
|
}
|
774
1002
|
|
1003
|
+
/**
|
1004
|
+
* Add +new+ as a child of this Node.
|
1005
|
+
*
|
1006
|
+
* @param new [Node, DocumentFragment, NodeSet, String] The node to be added.
|
1007
|
+
*
|
1008
|
+
* @return [Node,NodeSet] The reparented {Node} (if +new+ is a {Node}), or {NodeSet} (if +new+ is a {DocumentFragment}, {NodeSet}, or {String}).
|
1009
|
+
*/
|
1010
|
+
static VALUE
|
1011
|
+
nl_node_add_child(VALUE self, VALUE new)
|
1012
|
+
{
|
1013
|
+
return nl_node_add_nodes(self, new, lxb_dom_node_insert_child, false);
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
/**
|
1017
|
+
* Get the type of this Node
|
1018
|
+
*
|
1019
|
+
* @return {Integer}
|
1020
|
+
*/
|
775
1021
|
static VALUE
|
776
1022
|
nl_node_get_type(VALUE self)
|
777
1023
|
{
|
778
1024
|
return INT2NUM(nl_rb_node_unwrap(self)->type);
|
779
1025
|
}
|
780
1026
|
|
1027
|
+
/**
|
1028
|
+
* @return [Element] The first child Node that is an element.
|
1029
|
+
*/
|
781
1030
|
static VALUE
|
782
1031
|
nl_node_first_element_child(VALUE self)
|
783
1032
|
{
|
@@ -805,6 +1054,9 @@ nl_node_first_element_child(VALUE self)
|
|
805
1054
|
return Qnil;
|
806
1055
|
}
|
807
1056
|
|
1057
|
+
/**
|
1058
|
+
* @return [Element] The last child Node that is an element.
|
1059
|
+
*/
|
808
1060
|
static VALUE
|
809
1061
|
nl_node_last_element_child(VALUE self)
|
810
1062
|
{
|
@@ -832,11 +1084,26 @@ nl_node_last_element_child(VALUE self)
|
|
832
1084
|
return Qnil;
|
833
1085
|
}
|
834
1086
|
|
1087
|
+
/**
|
1088
|
+
* Copy this node.
|
1089
|
+
*
|
1090
|
+
* @return [Node] The new {Node}.
|
1091
|
+
*/
|
835
1092
|
static VALUE
|
836
1093
|
nl_node_clone(VALUE self)
|
837
1094
|
{
|
838
1095
|
lxb_dom_node_t *node = nl_rb_node_unwrap(self);
|
839
|
-
lxb_dom_node_t *clone
|
1096
|
+
lxb_dom_node_t *clone;
|
1097
|
+
|
1098
|
+
switch (node->type) {
|
1099
|
+
case LXB_DOM_NODE_TYPE_ATTRIBUTE:
|
1100
|
+
clone = (lxb_dom_node_t *)lxb_dom_attr_interface_clone(node->owner_document, lxb_dom_interface_attr(node));
|
1101
|
+
case LXB_DOM_NODE_TYPE_CDATA_SECTION:
|
1102
|
+
clone = (lxb_dom_node_t *)lxb_dom_cdata_section_interface_clone(node->owner_document, lxb_dom_interface_cdata_section(node));
|
1103
|
+
default:
|
1104
|
+
clone = lxb_dom_node_clone(node, true);
|
1105
|
+
break;
|
1106
|
+
}
|
840
1107
|
return nl_rb_node_create(clone, nl_rb_document_get(self));
|
841
1108
|
}
|
842
1109
|
|
@@ -849,6 +1116,8 @@ void Init_nl_node(void)
|
|
849
1116
|
cNokolexborCharacterData = rb_define_class_under(mNokolexbor, "CharacterData", cNokolexborNode);
|
850
1117
|
|
851
1118
|
rb_define_singleton_method(cNokolexborNode, "new", nl_node_new, -1);
|
1119
|
+
rb_define_method(cNokolexborNode, "attribute", nl_node_attribute, 1);
|
1120
|
+
rb_define_method(cNokolexborNode, "attribute_nodes", nl_node_attribute_nodes, 0);
|
852
1121
|
rb_define_method(cNokolexborNode, "content", nl_node_content, 0);
|
853
1122
|
rb_define_method(cNokolexborNode, "content=", nl_node_content_set, 1);
|
854
1123
|
rb_define_method(cNokolexborNode, "[]", nl_node_get_attr, 1);
|