nokolexbor 0.3.3 → 0.3.5
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/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);
|