y-rb 0.3.2-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/lib/y/xml.rb ADDED
@@ -0,0 +1,870 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Y
4
+ # rubocop:disable Metrics/ClassLength
5
+
6
+ # A XMLElement
7
+ #
8
+ # Someone should not instantiate an element directly, but use
9
+ # {Y::Doc#get_xml_element} instead
10
+ #
11
+ # @example
12
+ # doc = Y::Doc.new
13
+ # xml_element = doc.get_xml_element("my xml")
14
+ #
15
+ # puts xml_element.to_s
16
+ class XMLElement
17
+ # @!attribute [r] document
18
+ #
19
+ # @return [Y::Doc] The document this array belongs to
20
+ attr_accessor :document
21
+
22
+ # Create a new XMLElement instance
23
+ #
24
+ # @param [Y::Doc] doc
25
+ def initialize(doc = nil)
26
+ @document = doc || Y::Doc.new
27
+
28
+ super()
29
+ end
30
+
31
+ # Retrieve node at index
32
+ #
33
+ # @param [Integer] index
34
+ # @return [Y::XMLElement|nil]
35
+ def [](index)
36
+ node = yxml_element_get(index)
37
+ node&.document = document
38
+ node
39
+ end
40
+
41
+ # Create a node at index
42
+ #
43
+ # @param [Integer] index
44
+ # @param [String] name Name of node, e.g. `<p />`
45
+ # @return [Y::XMLElement]
46
+ # rubocop:disable Lint/Void
47
+ def []=(index, name)
48
+ node = yxml_element_insert_element(transaction, index, name)
49
+ node.document = document
50
+ node
51
+ end
52
+ # rubocop:enable Lint/Void
53
+
54
+ # Returns first child in list or nil if no child exists
55
+ #
56
+ # @return [Hash]
57
+ def attrs
58
+ yxml_element_attributes
59
+ end
60
+
61
+ alias attributes attrs
62
+
63
+ # Returns first child in list or nil if no child exists
64
+ #
65
+ # @return [Y::XMLElement]
66
+ def first_child
67
+ child = yxml_element_first_child
68
+ child&.document = document
69
+ child
70
+ end
71
+
72
+ # Insert text into element at given index
73
+ #
74
+ # Optional input is pushed to the text if provided
75
+ #
76
+ # @param [Integer] index
77
+ # @param [String|nil] input
78
+ # @return [Y::XMLText]
79
+ def insert_text(index, input = nil)
80
+ text = yxml_element_insert_text(transaction, index)
81
+ text.document = document
82
+ text << input unless input.nil?
83
+ text
84
+ end
85
+
86
+ # Retrieve element or text adjacent (next) to this element
87
+ #
88
+ # @return [Y::XMLElement|Y::XMLText|nil]
89
+ def next_sibling
90
+ node = yxml_element_next_sibling
91
+ node&.document = document
92
+ node
93
+ end
94
+
95
+ # Attach listener to get notified about changes to the element
96
+ #
97
+ # This supports either a `Proc` or a `Block`.
98
+ #
99
+ # @example Receive changes via Proc
100
+ # doc = Y::Doc.new
101
+ # xml_element = doc.get_xml_element("my xml element")
102
+ # xml_element.attach ->(changes) { … }
103
+ #
104
+ # @example Receive changes via Block
105
+ # doc = Y::Doc.new
106
+ # xml_element = doc.get_xml_element("my xml element")
107
+ # xml_element.attach { |changes| … }
108
+ #
109
+ # @param [Proc] callback
110
+ # @param [Block] block
111
+ # @return [Integer] The subscription ID
112
+ def attach(callback = nil, &block)
113
+ return yxml_element_observe(callback) unless callback.nil?
114
+
115
+ yxml_element_observe(block.to_proc) unless block.nil?
116
+ end
117
+
118
+ # Retrieve parent element
119
+ #
120
+ # @return [Y::XMLElement|nil]
121
+ def parent
122
+ node = yxml_element_parent
123
+ node.document = document
124
+ node
125
+ end
126
+
127
+ # Retrieve element or text adjacent (previous) to this element
128
+ #
129
+ # @return [Y::XMLElement|Y::XMLText|nil]
130
+ def prev_sibling
131
+ node = yxml_element_prev_sibling
132
+ node&.document = document
133
+ node
134
+ end
135
+
136
+ # Creates a new child an inserts at the end of the children list
137
+ #
138
+ # @param [String] name
139
+ # @return [Y::XMLElement]
140
+ def <<(name)
141
+ xml_element = yxml_element_push_elem_back(transaction, name)
142
+ xml_element.document = document
143
+ xml_element
144
+ end
145
+
146
+ alias push_child <<
147
+
148
+ # Insert new text at the end of this elements child list
149
+ #
150
+ # The optional str argument initializes the text node with its value
151
+ #
152
+ # @param [String] str
153
+ # @return [Y::XMLText]
154
+ def push_text(str = nil)
155
+ text = yxml_element_push_text_back(transaction)
156
+ text.document = document
157
+ text << str unless str.nil?
158
+ text
159
+ end
160
+
161
+ # Number of children
162
+ #
163
+ # @return [Integer]
164
+ def size
165
+ yxml_element_size
166
+ end
167
+
168
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
169
+
170
+ # Removes one or more children from XML Element
171
+ #
172
+ # @example Removes a single element
173
+ # doc = Y::Doc.new
174
+ #
175
+ # xml_element = doc.get_xml_element("my xml")
176
+ # xml_element << "A"
177
+ # xml_element << "B"
178
+ # xml_element << "C"
179
+ #
180
+ # xml_element.slice!(1)
181
+ #
182
+ # xml_element.to_s # <UNDEFINED><A></A><C></C></UNDEFINED>
183
+ #
184
+ # @overload slice!(n)
185
+ # Removes nth node from child list
186
+ #
187
+ # @overload slice!(start, length)
188
+ # Removes a range of nodes
189
+ #
190
+ # @overload slice!(range)
191
+ # Removes a range of nodes
192
+ #
193
+ # @return [void]
194
+ def slice!(*args)
195
+ if args.size.zero?
196
+ raise ArgumentError,
197
+ "Provide one of `index`, `range`, `start, length` as arguments"
198
+ end
199
+
200
+ if args.size == 1
201
+ arg = args.first
202
+
203
+ if arg.is_a?(Range)
204
+ if arg.exclude_end?
205
+ yxml_element_remove_range(transaction, arg.first,
206
+ arg.last - arg.first)
207
+ end
208
+ unless arg.exclude_end?
209
+ yxml_element_remove_range(transaction, arg.first,
210
+ arg.last + 1 - arg.first)
211
+ end
212
+ return nil
213
+ end
214
+
215
+ if arg.is_a?(Numeric)
216
+ yxml_element_remove_range(transaction, arg.to_int, 1)
217
+ return nil
218
+ end
219
+ end
220
+
221
+ if args.size == 2
222
+ first, second = args
223
+
224
+ if first.is_a?(Numeric) && second.is_a?(Numeric)
225
+ yxml_element_remove_range(transaction, first, second)
226
+ return nil
227
+ end
228
+ end
229
+
230
+ raise ArgumentError, "Please check your arguments, can't slice."
231
+ end
232
+
233
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
234
+
235
+ # Tag name
236
+ #
237
+ # @return [String]
238
+ def tag
239
+ yxml_element_tag
240
+ end
241
+
242
+ # String representation of this node and all its children
243
+ #
244
+ # @return [String]
245
+ def to_s
246
+ yxml_element_to_s
247
+ end
248
+
249
+ # Detach a listener
250
+ #
251
+ # @param [Integer] subscription_id
252
+ # @return [void]
253
+ def detach(subscription_id)
254
+ yxml_element_unobserve(subscription_id)
255
+ end
256
+
257
+ # Creates a new node and puts it in front of the child list
258
+ #
259
+ # @param [String] name
260
+ # @return [Y::XMLElement]
261
+ def unshift_child(name)
262
+ xml_element = yxml_element_push_elem_front(transaction, name)
263
+ xml_element.document = document
264
+ xml_element
265
+ end
266
+
267
+ # Insert new text at the front of this elements child list
268
+ #
269
+ # The optional str argument initializes the text node with its value
270
+ #
271
+ # @param [String] str
272
+ # @return [Y::XMLText]
273
+ def unshift_text(str = nil)
274
+ text = yxml_element_push_text_front(transaction)
275
+ text.document = document
276
+ text << args.first unless str.nil?
277
+ text
278
+ end
279
+
280
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
281
+
282
+ # make attributes just work on an element in the form of `attr_name` and
283
+ # `attr_name=`
284
+ #
285
+ # @example Set and get an attribute
286
+ # doc = Y::Doc.new
287
+ # xml_element = doc.get_xml_element("my xml")
288
+ # xml_element.attr_name = "Hello"
289
+ #
290
+ # puts xml_element.attr_name # "Hello"
291
+ #
292
+ # @!visibility private
293
+ def method_missing(method_name, *args, &block)
294
+ is_setter = method_name.to_s.end_with?("=")
295
+
296
+ setter = method_name
297
+ setter += "=" unless is_setter
298
+ getter = method_name
299
+ getter = getter.to_s.slice(0...-1)&.to_sym if is_setter
300
+
301
+ define_singleton_method(setter.to_sym) do |new_val|
302
+ yxml_element_insert_attribute(transaction,
303
+ method_name.to_s
304
+ .delete_suffix("=")
305
+ .delete_prefix("attr_"),
306
+ new_val)
307
+ end
308
+
309
+ define_singleton_method(getter) do
310
+ yxml_element_get_attribute(method_name.to_s.delete_prefix("attr_"))
311
+ end
312
+
313
+ if is_setter
314
+ value = args[0]
315
+ send(setter, value)
316
+ end
317
+ rescue StandardError
318
+ super(method_name, *args, &block)
319
+ end
320
+
321
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
322
+
323
+ # Make sure we only respond to attributes
324
+ # @!visibility private
325
+ def respond_to_missing?(method_name, include_private = false)
326
+ method_name.to_s.start_with?("attr_") || super
327
+ end
328
+
329
+ private
330
+
331
+ # @!method yxml_element_attributes
332
+ #
333
+ # @return [Hash]
334
+
335
+ # @!method yxml_element_first_child
336
+ #
337
+ # @return [Y::XMLElement|Y::XMLText]
338
+
339
+ # @!method yxml_element_get_attribute(name)
340
+ #
341
+ # @param [String] name
342
+ # @return [String|nil]
343
+
344
+ # @!method yxml_element_get(index)
345
+ #
346
+ # @param [Integer] index
347
+ # @return [Y::XMLElement|Y::XMLText|nil]
348
+
349
+ # @!method yxml_element_insert_attribute(transaction, name, value)
350
+ #
351
+ # @param [Y::Transaction] transaction
352
+ # @param [String] name
353
+ # @param [String] value
354
+ # @return [String|nil]
355
+
356
+ # @!method yxml_element_insert_element(transaction, index, name)
357
+ # Insert XML element into this XML element
358
+ # @!visibility private
359
+ # @param [Y::Transaction] transaction
360
+ # @param [Integer] index
361
+ # @param [String] name
362
+ # @return [Y::XMLElement]
363
+
364
+ # @!method yxml_element_insert_text(transaction, index)
365
+ #
366
+ # @param [Y::Transaction] transaction
367
+ # @param [Integer] index
368
+ # @return [Y::XMLText]
369
+
370
+ # @!method yxml_element_next_sibling()
371
+ #
372
+ # @return [Y::XMLElement|XMLText|nil]
373
+
374
+ # @!method yxml_element_observe(callback)
375
+ #
376
+ # @param [Proc] callback
377
+ # @return [Integer] The subscription ID
378
+
379
+ # @!method yxml_element_parent()
380
+ #
381
+ # @return [Y::XMLElement|nil]
382
+
383
+ # @!method yxml_element_prev_sibling()
384
+ #
385
+ # @return [Y::XMLElement|XMLText|nil]
386
+
387
+ # @!method yxml_element_push_elem_back(transaction, name)
388
+ #
389
+ # @param [Y::Transaction] transaction
390
+ # @param [String] name
391
+ # @return [Y::XMLElement]
392
+
393
+ # @!method yxml_element_push_elem_front(transaction, name)
394
+ #
395
+ # @param [Y::Transaction] transaction
396
+ # @param [String] name
397
+ # @return [Y::XMLElement]
398
+
399
+ # @!method yxml_element_push_text_back(transaction)
400
+ #
401
+ # @param [Y::Transaction] transaction
402
+ # @return [Y::XMLText]
403
+
404
+ # @!method yxml_element_push_text_front(transaction)
405
+ #
406
+ # @param [Y::Transaction] transaction
407
+ # @return [Y::XMLText]
408
+
409
+ # @!method yxml_element_remove_attribute(transaction, name)
410
+ #
411
+ # @param [Y::Transaction] transaction
412
+ # @param [String] name
413
+ #
414
+ # @return [void]
415
+
416
+ # @!method yxml_element_remove_range(transaction, index, length)
417
+ #
418
+ # @param [Y::Transaction] transaction
419
+ # @param [Integer] index
420
+ # @param [Integer] length
421
+ #
422
+ # @return [void]
423
+
424
+ # @!method yxml_element_size()
425
+ #
426
+ # @return [Integer]
427
+
428
+ # @!method yxml_element_tag()
429
+ #
430
+ # @return [String]
431
+
432
+ # @!method yxml_element_to_s()
433
+ #
434
+ # @return [String]
435
+
436
+ # @!method yxml_element_unobserve(subscription_id)
437
+ #
438
+ # @param [Integer] subscription_id
439
+ # @return [void]
440
+
441
+ # A reference to the current active transaction of the document this element
442
+ # belongs to.
443
+ #
444
+ # @return [Y::Transaction] A transaction object
445
+ def transaction
446
+ document.current_transaction
447
+ end
448
+ end
449
+
450
+ # A XMLText
451
+ #
452
+ # Someone should not instantiate a text directly, but use
453
+ # {Y::Doc#get_text_element}, {Y::XMLElement#insert_text},
454
+ # {Y::XMLElement#push_text}, {Y::XMLElement#unshift_text} instead.
455
+ #
456
+ # The XMLText API is similar to {Y::Text}, but adds a few methods to make it
457
+ # easier to work in structured XML documents.
458
+ #
459
+ # @example
460
+ # doc = Y::Doc.new
461
+ # xml_text = doc.get_xml_text("my xml text")
462
+ #
463
+ # puts xml_text.to_s
464
+ class XMLText
465
+ # @!attribute [r] document
466
+ #
467
+ # @return [Y::Doc] The document this array belongs to
468
+ attr_accessor :document
469
+
470
+ # Create a new XMLText instance
471
+ #
472
+ # @param [Y::Doc] doc
473
+ def initialize(doc = nil)
474
+ @document = doc || Y::Doc.new
475
+
476
+ super()
477
+ end
478
+
479
+ # Push a string to the end of the text node
480
+ #
481
+ # @param [String] str
482
+ # @return {void}
483
+ def <<(str)
484
+ yxml_text_push(transaction, str)
485
+ end
486
+
487
+ alias push <<
488
+
489
+ # Attach a listener to get notified about changes
490
+ #
491
+ # @param [Proc] callback
492
+ # @return [Integer] subscription_id
493
+ def attach(callback = nil, &block)
494
+ yxml_text_observe(callback) unless callback.nil?
495
+ yxml_text_observe(block.to_proc) unless block.nil?
496
+ end
497
+
498
+ # Return text attributes
499
+ #
500
+ # @return [Hash]
501
+ def attrs
502
+ yxml_text_attributes
503
+ end
504
+
505
+ # Detach a listener
506
+ #
507
+ # @param [Integer] subscription_id
508
+ # @return [void]
509
+ def detach(subscription_id)
510
+ yxml_text_unobserve(subscription_id)
511
+ end
512
+
513
+ # Format text
514
+ #
515
+ # @param [Integer] index
516
+ # @param [Integer] length
517
+ # @param [Hash] attrs
518
+ # @return [void]
519
+ def format(index, length, attrs)
520
+ yxml_text_format(transaction, index, length, attrs)
521
+ end
522
+
523
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
524
+
525
+ # Insert a value at position and with optional attributes. This method is
526
+ # similar to [String#insert](https://ruby-doc.org/core-3.1.2/String.html),
527
+ # except for the optional third `attrs` argument.
528
+ #
529
+ # @example Insert a string at position
530
+ # doc = Y::Doc.new
531
+ # text = doc.get_text("my text")
532
+ # text << "Hello, "
533
+ #
534
+ # text.insert(7, "World!")
535
+ #
536
+ # puts text.to_s == "Hello, World!" # true
537
+ #
538
+ # The value can be any of the supported types:
539
+ # - Boolean
540
+ # - String
541
+ # - Numeric
542
+ # - Array (where element types must be supported)
543
+ # - Hash (where the the types of key and values must be supported)
544
+ #
545
+ # @param [Integer] index
546
+ # @param [String, Float, Array, Hash, Boolean] value
547
+ # @param [Hash|nil] attrs
548
+ # @return [void]
549
+ def insert(index, value, attrs = nil)
550
+ if value.is_a?(String)
551
+ yxml_text_insert(transaction, index, value) if attrs.nil?
552
+ unless attrs.nil?
553
+ yxml_text_insert_with_attrs(transaction, index, value,
554
+ attrs)
555
+ end
556
+
557
+ return nil
558
+ end
559
+
560
+ if can_insert?(value)
561
+ yxml_text_insert_embed(transaction, index, value) if attrs.nil?
562
+ unless attrs.nil?
563
+ yxml_text_insert_embed_with_attrs(transaction, index, value,
564
+ attrs)
565
+ end
566
+
567
+ return nil
568
+ end
569
+
570
+ raise ArgumentError,
571
+ "Can't insert value. `#{value.class.name}` isn't supported."
572
+ end
573
+
574
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
575
+
576
+ # Return length of string
577
+ #
578
+ # @return [void]
579
+ def length
580
+ yxml_text_length
581
+ end
582
+
583
+ alias size length
584
+
585
+ # Return adjacent XMLElement or XMLText node (next)
586
+ #
587
+ # @return [Y::XMLElement|Y::XMLText|nil]
588
+ def next_sibling
589
+ node = yxml_text_next_sibling
590
+ node.document = document
591
+ node
592
+ end
593
+
594
+ # Return parent XMLElement
595
+ #
596
+ # @return [Y::XMLElement|nil]
597
+ def parent
598
+ node = yxml_text_parent
599
+ node.document = document
600
+ node
601
+ end
602
+
603
+ # Return adjacent XMLElement or XMLText node (prev)
604
+ #
605
+ # @return [Y::XMLElement|Y::XMLText|nil]
606
+ def prev_sibling
607
+ node = yxml_text_prev_sibling
608
+ node&.document = document
609
+ node
610
+ end
611
+
612
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
613
+
614
+ # Removes a part from text
615
+ #
616
+ # **Attention:** In comparison to String#slice, {XMLText#slice!} will not
617
+ # return the substring that gets removed. Even this being technically
618
+ # possible, it requires us to read the substring before removing it, which
619
+ # is not desirable in most situations.
620
+ #
621
+ # @example Removes a single character
622
+ # doc = Y::Doc.new
623
+ #
624
+ # text = doc.get_xml_text("my xml text")
625
+ # text << "Hello"
626
+ #
627
+ # text.slice!(0)
628
+ #
629
+ # text.to_s == "ello" # true
630
+ #
631
+ # @example Removes a range of characters
632
+ # doc = Y::Doc.new
633
+ #
634
+ # text = doc.get_xml_text("my xml text")
635
+ # text << "Hello"
636
+ #
637
+ # text.slice!(1..2)
638
+ # text.to_s == "Hlo" # true
639
+ #
640
+ # text.slice!(1...2)
641
+ # text.to_s == "Ho" # true
642
+ #
643
+ # @example Removes a range of chars from start and for given length
644
+ # doc = Y::Doc.new
645
+ #
646
+ # text = doc.get_xml_text("my xml text")
647
+ # text << "Hello"
648
+ #
649
+ # text.slice!(0, 3)
650
+ #
651
+ # text.to_s == "lo" # true
652
+ #
653
+ # @overload slice!(index)
654
+ # Removes a single character at index
655
+ #
656
+ # @overload slice!(start, length)
657
+ # Removes a range of characters
658
+ #
659
+ # @overload slice!(range)
660
+ # Removes a range of characters
661
+ #
662
+ # @return [void]
663
+ def slice!(*args)
664
+ if args.size.zero?
665
+ raise ArgumentError,
666
+ "Provide one of `index`, `range`, `start, length` as arguments"
667
+ end
668
+
669
+ if args.size == 1
670
+ arg = args.first
671
+
672
+ if arg.is_a?(Range)
673
+ yxml_text_remove_range(transaction, arg.first, arg.last - arg.first)
674
+ return nil
675
+ end
676
+
677
+ if arg.is_a?(Numeric)
678
+ yxml_text_remove_range(transaction, arg.to_int, 1)
679
+ return nil
680
+ end
681
+ end
682
+
683
+ if args.size == 2
684
+ first, second = args
685
+
686
+ if first.is_a?(Numeric) && second.is_a?(Numeric)
687
+ yxml_text_remove_range(transaction, first, second)
688
+ return nil
689
+ end
690
+ end
691
+
692
+ raise ArgumentError, "Please check your arguments, can't slice."
693
+ end
694
+
695
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
696
+
697
+ # Returns string representation of XMLText
698
+ #
699
+ # @return [String]
700
+ def to_s
701
+ yxml_text_to_s
702
+ end
703
+
704
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
705
+
706
+ # make attributes just work on an element in the form of `attr_name` and
707
+ # `attr_name=`
708
+ #
709
+ # @example Set and get an attribute
710
+ # doc = Y::Doc.new
711
+ # xml_element = doc.get_xml_element("my xml")
712
+ # xml_element.attr_name = "Hello"
713
+ #
714
+ # puts xml_element.attr_name # "Hello"
715
+ #
716
+ # @!visibility private
717
+ def method_missing(method_name, *args, &block)
718
+ is_setter = method_name.to_s.end_with?("=")
719
+
720
+ setter = method_name
721
+ setter += "=" unless is_setter
722
+ getter = method_name
723
+ getter = getter.to_s.slice(0...-1).to_sym if is_setter
724
+
725
+ define_singleton_method(setter.to_sym) do |new_val|
726
+ yxml_text_insert_attribute(transaction,
727
+ method_name.to_s
728
+ .delete_suffix("=")
729
+ .delete_prefix("attr_"),
730
+ new_val)
731
+ end
732
+
733
+ define_singleton_method(getter) do
734
+ yxml_text_get_attribute(method_name.to_s.delete_prefix("attr_"))
735
+ end
736
+
737
+ if is_setter
738
+ value = args[0]
739
+ send(setter, value)
740
+ end
741
+ rescue StandardError
742
+ super(method_name, *args, &block)
743
+ end
744
+
745
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
746
+
747
+ # Make sure we only respond to attributes
748
+ # @!visibility private
749
+ def respond_to_missing?(method_name, include_private = false)
750
+ method_name.to_s.start_with?("attr_") || super
751
+ end
752
+
753
+ private
754
+
755
+ def can_insert?(value)
756
+ value.is_a?(NilClass) ||
757
+ value.is_a?(Symbol) ||
758
+ [true, false].include?(value) ||
759
+ value.is_a?(Numeric) ||
760
+ value.is_a?(Enumerable) ||
761
+ value.is_a?(Hash)
762
+ end
763
+
764
+ # @!method yxml_text_attributes
765
+ #
766
+ # @return [Hash]
767
+
768
+ # @!method yxml_text_format(transaction, index, length, attrs)
769
+ #
770
+ # @param [Integer] index
771
+ # @param [Integer] length
772
+ # @param [Hash] attrs
773
+ # @return [void]
774
+
775
+ # @!method yxml_text_get_attribute(name)
776
+ #
777
+ # @param [String] name
778
+ # @return [String|nil]
779
+
780
+ # @!method yxml_text_insert(transaction, index, str)
781
+ #
782
+ # @param [Y::Transaction] transaction
783
+ # @param [Integer] index
784
+ # @param [String] str
785
+ # @return [void]
786
+
787
+ # @!method yxml_text_insert_attribute(transaction, name, value)
788
+ #
789
+ # @param [Y::Transaction] transaction
790
+ # @param [String] name
791
+ # @param [String] value
792
+ # @return [void]
793
+
794
+ # @!method yxml_text_insert_with_attrs(transaction, index, value, attrs)
795
+ #
796
+ # @param [Y::Transaction] transaction
797
+ # @param [Integer] index
798
+ # @param [String] value
799
+ # @param [Hash] attrs
800
+ # @return [void]
801
+
802
+ # @!method yxml_text_insert_embed(transaction, index, value)
803
+ #
804
+ # @param [Y::Transaction] transaction
805
+ # @param [Integer] index
806
+ # @param [String] value
807
+ # @return [void]
808
+
809
+ # @!method yxml_text_insert_embed_with_attrs(txn, index, value, attrs)
810
+ #
811
+ # @param [Y::Transaction] txn
812
+ # @param [Integer] index
813
+ # @param [true|false|Float|Integer|Array|Hash] value
814
+ # @param [Hash] attrs
815
+ # @return [void]
816
+
817
+ # @!method yxml_text_length
818
+ #
819
+ # @return [Integer]
820
+
821
+ # @!method yxml_text_next_sibling
822
+ #
823
+ # @return [Y::XMLElement|Y::XMLText|nil]
824
+
825
+ # @!method yxml_text_observe(callback)
826
+ #
827
+ # @param [Proc] callback
828
+ # @return [Integer] A subscription ID
829
+
830
+ # @!method yxml_text_parent
831
+ #
832
+ # @return [Y::XMLElement|nil]
833
+
834
+ # @!method yxml_text_prev_sibling
835
+ #
836
+ # @return [Y::XMLElement|Y::XMLText|nil]
837
+
838
+ # @!method yxml_text_push(transaction, str)
839
+ #
840
+ # @param [Y::Transaction] transaction
841
+ # @param [String] str
842
+ # @return [void]
843
+
844
+ # @!method yxml_text_remove_range(transaction, index, length)
845
+ #
846
+ # @param [Y::Transaction] transaction
847
+ # @param [Integer] index
848
+ # @param [Integer] length
849
+ # @return [void]
850
+
851
+ # @!method yxml_text_to_s()
852
+ #
853
+ # @return [void]
854
+
855
+ # @!method yxml_text_unobserve(subscription_id)
856
+ #
857
+ # @param [Integer] subscription_id
858
+ # @return [void]
859
+
860
+ # A reference to the current active transaction of the document this text
861
+ # belongs to.
862
+ #
863
+ # @return [Y::Transaction] A transaction object
864
+ def transaction
865
+ document.current_transaction
866
+ end
867
+ end
868
+
869
+ # rubocop:enable Metrics/ClassLength
870
+ end