File Coverage

lib/HTML/Object/DOM/CharacterData.pm
Criterion Covered Total %
statement 20 145 13.7
branch 0 72 0.0
condition 0 49 0.0
subroutine 8 24 33.3
pod 13 13 100.0
total 41 303 13.5


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/DOM/CharacterData.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/20
7             ## Modified 2022/09/18
8             ## All rights reserved
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTML::Object::DOM::CharacterData;
15             BEGIN
16             {
17 29     29   13020 use strict;
  29         58  
  29         827  
18 29     29   191 use warnings;
  29         55  
  29         786  
19 29     29   140 use parent qw( HTML::Object::DOM::Node );
  29         75  
  29         172  
20 29     29   1900 use vars qw( $VERSION );
  29         58  
  29         1313  
21 29     29   489 our $VERSION = 'v0.2.0';
22             };
23              
24 29     29   155 use strict;
  29         58  
  29         496  
25 29     29   143 use warnings;
  29         50  
  29         42192  
26              
27             # There is no constructor, because this is just an abstract interface to be inherited from by HTML::Object::DOM::Text, HTML::Object::DOM::Comment or HTML::Object::DOM::Space
28              
29             sub after
30             {
31 0     0 1 0 my $self = shift( @_ );
32 0   0     0 my $parent = $self->parent || return;
33 0         0 my $pos = $parent->children->pos( $self );
34 0 0       0 return( $self->error({
35             message => "This CharacterData object cannot be found in its parent node.",
36             class => 'HTML::Object::HierarchyRequestError',
37             }) ) if( !defined( $pos ) );
38 0         0 my $list = $self->_get_from_list_of_elements_or_html( @_ );
39 0 0       0 $self->_sanity_check_for_before_after( $list ) ||
40             return( $self->pass_error );
41            
42 0         0 $parent->children->splice( $pos + 1, 0, $list->list );
43             $list->foreach(sub
44             {
45 0     0   0 $_->parent( $parent );
46 0         0 });
47 0         0 $parent->reset(1);
48 0         0 return( $self );
49             }
50              
51 0     0 1 0 sub appendData { return( shift->value->append( @_ ) ); }
52              
53             sub before
54             {
55 0     0 1 0 my $self = shift( @_ );
56 0   0     0 my $parent = $self->parent || return;
57 0         0 my $pos = $parent->children->pos( $self );
58 0 0       0 return( $self->error({
59             message => "This CharacterData object cannot be found in its parent node.",
60             class => 'HTML::Object::HierarchyRequestError',
61             }) ) if( !defined( $pos ) );
62 0         0 my $list = $self->_get_from_list_of_elements_or_html( @_ );
63 0 0       0 $self->_sanity_check_for_before_after( $list ) ||
64             return( $self->pass_error );
65            
66             $list->foreach(sub
67             {
68 0     0   0 $parent->children->splice( $pos, 0, $_ );
69 0         0 $_->parent( $parent );
70 0         0 $pos++;
71 0         0 });
72 0         0 $parent->reset(1);
73 0         0 return( $self );
74             }
75              
76             # Note: property
77 2     2 1 739 sub data : lvalue { return( shift->_set_get_lvalue( 'value', @_ ) ); }
78              
79             sub deleteData
80             {
81 0     0 1   my $self = shift( @_ );
82 0           my $offset = shift( @_ );
83 0           my $len = shift( @_ );
84 0 0 0       $offset = "$offset" if( ref( $offset ) && overload::Method( $offset, '""' ) );
85 0 0 0       $len = "$len" if( ref( $len ) && overload::Method( $len, '""' ) );
86 0 0         return( $self->error({
87             message => "Offset value provided \"$offset\" is not an integer.",
88             class => 'HTML::Object::TypeError',
89             }) ) if( !$self->_is_integer( $offset ) );
90 0 0         return( $self->error({
91             message => "Length value provided \"$len\" is not an integer.",
92             class => 'HTML::Object::TypeError',
93             }) ) if( !$self->_is_integer( $len ) );
94 0           $offset = int( $offset );
95 0           $len = int( $len );
96 0 0         return( $self->error({
97             message => "Offset value is greater than the size of the CharacterData object.",
98             class => 'HTML::Object::IndexSizeError',
99             }) ) if( $offset > $self->value->length );
100 0           $self->value->substr( $offset, $len, '' );
101 0           $self->reset(1);
102 0           return( $self );
103             }
104              
105             sub insertData
106             {
107 0     0 1   my $self = shift( @_ );
108 0           my $offset = shift( @_ );
109 0           my $str = shift( @_ );
110             # Nothing to do, stop here
111 0 0 0       return( $self ) if( !defined( $str ) || !CORE::length( "$str" ) );
112 0 0 0       $offset = "$offset" if( ref( $offset ) && overload::Method( $offset, '""' ) );
113 0           $str = "$str";
114 0 0         return( $self->error({
115             message => "Offset value provided \"$offset\" is not an integer.",
116             class => 'HTML::Object::TypeError',
117             }) ) if( !$self->_is_integer( $offset ) );
118 0           $offset = int( $offset );
119 0 0         return( $self->error({
120             message => "Offset value is greater than the size of the CharacterData object.",
121             class => 'HTML::Object::IndexSizeError',
122             }) ) if( $offset > $self->value->length );
123 0           $self->value->substr( $offset, 0, $str );
124 0           $self->reset(1);
125 0           return( $self );
126             }
127              
128             # Note: property
129 0     0 1   sub length { return( shift->value->length ); }
130              
131             # Note: property
132             sub nextElementSibling
133             {
134 0     0 1   my $self = shift( @_ );
135 0   0       my $parent = $self->parent || return;
136 0           my $pos = $parent->children->pos( $self );
137 0 0         return( $self->error({
138             message => "This CharacterData object cannot be found in its parent node.",
139             class => 'HTML::Object::HierarchyRequestError',
140             }) ) if( !defined( $pos ) );
141 0           return( $parent->children->index( $pos + 1 ) );
142             }
143              
144             # Note: property
145             sub previousElementSibling
146             {
147 0     0 1   my $self = shift( @_ );
148 0   0       my $parent = $self->parent || return;
149 0           my $pos = $parent->children->pos( $self );
150 0 0         return( $self->error({
151             message => "This CharacterData object cannot be found in its parent node.",
152             class => 'HTML::Object::HierarchyRequestError',
153             }) ) if( !defined( $pos ) );
154 0 0         return if( $pos <= 0 );
155 0           return( $parent->children->index( $pos - 1 ) );
156             }
157              
158             sub remove
159             {
160 0     0 1   my $self = shift( @_ );
161 0   0       my $parent = $self->parent || return;
162 0           my $pos = $parent->children->pos( $self );
163 0 0         return( $self->error({
164             message => "This CharacterData object cannot be found in its parent node.",
165             class => 'HTML::Object::HierarchyRequestError',
166             }) ) if( !defined( $pos ) );
167 0           $parent->children->splice( $pos, 1 );
168 0           $parent->reset(1);
169 0           return( $self );
170             }
171              
172             sub replaceData
173             {
174 0     0 1   my $self = shift( @_ );
175 0           my $offset = shift( @_ );
176 0           my $len = shift( @_ );
177 0           my $str = shift( @_ );
178             # It is ok to be provided an undefined value, but we convert it to an empty string
179             # to prevent perl from triggering warnings.
180 0   0       $str //= '';
181 0 0 0       $offset = "$offset" if( ref( $offset ) && overload::Method( $offset, '""' ) );
182 0 0 0       $len = "$len" if( ref( $len ) && overload::Method( $len, '""' ) );
183 0 0         return( $self->error({
184             message => "Offset value provided \"$offset\" is not an integer.",
185             class => 'HTML::Object::TypeError',
186             }) ) if( !$self->_is_integer( $offset ) );
187 0 0         return( $self->error({
188             message => "Length value provided \"$len\" is not an integer.",
189             class => 'HTML::Object::TypeError',
190             }) ) if( !$self->_is_integer( $len ) );
191 0           $offset = int( $offset );
192 0           $len = int( $len );
193 0           $str = "$str";
194 0 0         return( $self->error({
195             message => "Offset value is greater than the size of the CharacterData object.",
196             class => 'HTML::Object::IndexSizeError',
197             }) ) if( $offset > $self->value->length );
198 0           $self->value->substr( $offset, $len, $str );
199 0           $self->reset(1);
200 0           return( $self );
201             }
202              
203             sub replaceWith
204             {
205 0     0 1   my $self = shift( @_ );
206 0   0       my $parent = $self->parent || return( $self->error({
207             message => "This CharacterData has no parent.",
208             class => 'HTML::Object::HierarchyRequestError',
209             }) );
210 0           my $pos = $parent->children->pos( $self );
211 0           my $list = _get_from_list_of_elements_or_html( @_ );
212 0 0         return( $self->error({
213             message => "This CharacterData object cannot be found in its parent node.",
214             class => 'HTML::Object::HierarchyRequestError',
215             }) ) if( !defined( $pos ) );
216             # There is nothing to do
217 0 0         return( $self ) if( $list->is_empty );
218 0           $parent->children->splice( $pos, 1, $list->list );
219             $list->foreach(sub
220             {
221 0     0     $_->parent( $parent );
222 0           });
223 0           $parent->reset(1);
224 0           return( $self );
225             }
226              
227             sub substringData
228             {
229 0     0 1   my $self = shift( @_ );
230 0           my $offset = shift( @_ );
231 0           my $len = shift( @_ );
232 0 0 0       $offset = "$offset" if( ref( $offset ) && overload::Method( $offset, '""' ) );
233 0 0 0       $len = "$len" if( ref( $len ) && overload::Method( $len, '""' ) );
234 0 0         return( $self->error({
235             message => "Offset value provided \"$offset\" is not an integer.",
236             class => 'HTML::Object::TypeError',
237             }) ) if( !$self->_is_integer( $offset ) );
238 0 0         return( $self->error({
239             message => "Length value provided \"$len\" is not an integer.",
240             class => 'HTML::Object::TypeError',
241             }) ) if( !$self->_is_integer( $len ) );
242 0           $offset = int( $offset );
243 0           $len = int( $len );
244 0 0         return( $self->error({
245             message => "Offset value is greater than the size of the CharacterData object.",
246             class => 'HTML::Object::IndexSizeError',
247             }) ) if( $offset > $self->value->length );
248 0           return( $self->value->substr( $offset, $len ) );
249             }
250              
251             sub _sanity_check_for_before_after
252             {
253 0     0     my $self = shift( @_ );
254 0   0       my $list = shift( @_ ) || return( $self->error( "No list of nodes was provided." ) );
255 0 0         return( $self->error( "I was expecting an array object, but instead got '$list'." ) ) if( !$self->_is_a( $list => 'Module::Generic::Array' ) );
256 0           my $parent = $self->parent;
257 0           my $lineage = $self->lineage;
258 0 0         if( !$list->intersect( $lineage )->is_empty )
259             {
260 0           return( $self->error({
261             message => "One of the nodes provided is an ancestor of this CharacterData",
262             class => 'HTML::Object::HierarchyRequestError',
263             }) );
264             }
265 0           foreach( @$list )
266             {
267 0 0 0       if( !$self->_is_a( $_ => 'HTML::Object::DOM::DocumentFragment' ) &&
    0          
268             !$self->_is_a( $_ => 'HTML::Object::DOM::Element' ) &&
269             !$self->_is_a( $_ => 'HTML::Object::DOM::CharacterData' ) )
270             {
271 0           return( $self->error({
272             message => "A node provided (" . overload::StrVal( $_ ) . ") is neither a DocumentFragment, an Element nor a CharacterData object.",
273             class => 'HTML::Object::HierarchyRequestError',
274             }) );
275             }
276             elsif( $self->_is_a( $_ => 'HTML::Object::DOM::DocumentFragment' ) )
277             {
278 0           my $kids = $_->children;
279 0           my $count = 0;
280 0           foreach my $node ( @$kids )
281             {
282 0 0         ++$count if( $node->isa( 'HTML::Object::DOM::Element' ) );
283 0 0 0       if( $count > 1 || $node->isa( 'HTML::Object::DOM::Text' ) )
284             {
285 0           return( $self->error({
286             message => "More than one Element node was provided or a Text node was provided.",
287             class => 'HTML::Object::HierarchyRequestError',
288             }) );
289             }
290             }
291             }
292             }
293 0 0 0       if( $self->isa( 'HTML::Object::DOM::Text' ) && $self->_is_a( $parent => 'HTML::Object::DOM::Document' ) )
294             {
295 0           return( $self->error({
296             message => "This CharacterData object is a Text object, and our parent is a Document.",
297             class => 'HTML::Object::HierarchyRequestError',
298             }) );
299             }
300 0           return(1);
301             }
302              
303             1;
304             # NOTE: POD
305             __END__
306              
307             =encoding utf-8
308              
309             =head1 NAME
310              
311             HTML::Object::DOM::CharacterData - HTML Object Character Data Class
312              
313             =head1 SYNOPSIS
314              
315             use parent qw( HTML::Object::DOM::CharacterData );
316             # then implements additional properties and methods
317              
318             =head1 VERSION
319              
320             v0.2.0
321              
322             =head1 DESCRIPTION
323              
324             The C<CharacterData> abstract interface represents a L<Node object|HTML::Object::DOM::Node> that contains characters. This is an abstract interface, meaning there are not any objects of type CharacterData: it is implemented by other interfaces like L<Text|HTML::Object::DOM::Text>, L<Comment|HTML::Object::DOM::Comment>, L<Space|HTML::Object::DOM::Space> which are not abstract.
325              
326             It inherits from L<Node|HTML::Object::DOM::Node>
327              
328             =head1 INHERITANCE
329              
330             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------------+
331             | HTML::Object::Element | --> | HTML::Object::EventTarget | --> | HTML::Object::DOM::Node | --> | HTML::Object::DOM::CharacterData |
332             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------------+
333              
334             =head1 PROPERTIES
335              
336             This interface also inherits properties from its parents L<Node|HTML::Object::DOM::Node> and L<EventTarget|HTML::Object::EventTarget>.
337              
338             =head2 data
339              
340             Is a string representing the textual data contained in this object.
341              
342             Example:
343              
344             <!-- This is an html comment !-->
345             <output id="Result"></output>
346              
347             my $comment = $doc->body->childNodes->[1];
348             my $output = $doc->getElementById('Result');
349             $output->value = $comment->data;
350             # output content would now be: This is an html comment !
351              
352             Setting the content of a text node using data
353              
354             <span>Result: </span>Not set.
355              
356             my $span = $doc->getElementsByTagName('span')->[0];
357             my $textnode = $span->nextSibling;
358             $textnode->data = "This text has been set using textnode.data."
359              
360             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/data>
361              
362             =head2 length
363              
364             Read-only.
365              
366             Returns a L<number|Module::Generic::Number> representing the size of the string contained in the object.
367              
368             Example:
369              
370             Length of the string in the <code>Text</code> node: <output></output>
371              
372             use HTML::Object::DOM::Text;
373             my $output = $doc->getElementsByTagName('output')->[0];
374             my $textnode = HTML::Object::DOM::Text->new("This text has been set using textnode.data.");
375              
376             $output->value = $textnode->length;
377             # Length of the string in the Text node: 43
378              
379             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/length>
380              
381             =head2 nextElementSibling
382              
383             Read-only.
384              
385             Returns the first Element that follows this node, and is a sibling, or C<undef> if this node was the last one in its parent's children list.
386              
387             Example:
388              
389             TEXT
390             <div id="div-01">Here is div-01</div>
391             TEXT2
392             <div id="div-02">Here is div-02</div>
393             <pre>Here is the result area</pre>
394              
395             # Initially, set node to the Text node with `TEXT`
396             my $node = $doc->getElementById('div-01')->previousSibling;
397             my $result = "Next element siblings of TEXT:\n";
398             while( $node )
399             {
400             $result .= $node->nodeName + "\n";
401             # The first node is a CharacterData, the others Element objects
402             $node = $node->nextElementSibling;
403             }
404             $doc->getElementsByTagName('pre')->[0]->textContent = $result;
405              
406             would produce:
407              
408             TEXT
409             Here is div-01
410             TEXT2
411             Here is div-02
412              
413             Next element siblings of TEXT:
414             #text
415             DIV
416             DIV
417             PRE
418             SCRIPT
419              
420             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/nextElementSibling>
421              
422             =head2 previousElementSibling
423              
424             Read-only.
425              
426             Returns the first Element that precedes this node, and is a sibling, or C<undef> if this node was the first one in its parent's children list.
427              
428             Example:
429              
430             <div id="div-01">Here is div-01</div>
431             TEXT
432             <div id="div-02">Here is div-02</div>
433             SOME TEXT
434             <div id="div-03">Here is div-03</div>
435             <pre>Result</pre>
436              
437             # Initially set node to the Text node with `SOME TEXT`
438             my $node = $doc->getElementById('div-02')->nextSibling;
439             my $result = "Previous element siblings of SOME TEXT:\n";
440             while( $node )
441             {
442             $result .= $node->nodeName + "\n";
443             $node = $node->previousElementSibling;
444             }
445             $doc->getElementsByTagName('pre')->[0]->textContent = $result;
446              
447             would produce:
448              
449             Here is div-01
450             TEXT
451             Here is div-02
452             SOME TEXT
453             Here is div-03
454              
455             Previous element siblings of SOME TEXT:
456             #text
457             DIV
458             DIV
459              
460             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/previousElementSibling>
461              
462             =head1 METHODS
463              
464             This interface also inherits methods from its parents, L<Node|HTML::Object::DOM::Node> and L<EventTarget|HTML::Object::EventTarget>.
465              
466             =head2 after
467              
468             Inserts a set of L<Node objects|HTML::Object::DON::Node> or strings in the children list of the C<CharacterData>'s parent, just after the C<CharacterData> object.
469              
470             Strings are inserted as L<Text nodes|HTML::Object::DOM::Text>; the string is being passed as argument to the L<HTML::Object::DOM::Text> constructor.
471              
472             It returns an C<HTML::Object::HierarchyRequestError> error when the new nodes cannot be inserted at the specified point in the hierarchy, that is if one of the following conditions is met:
473              
474             =over 4
475              
476             =item * If the insertion of one of the added node would lead to a cycle, that is if one of them is an ancestor of this C<CharacterData> node.
477              
478             =item * If one of the added node is not a L<HTML::Object::DOM::DocumentFragment>, an L<HTML::Object::DOM::Element>, or a L<HTML::Object::DOM::CharacterData>.
479              
480             =item * If this L<CharacterData node|HTML::Object::DOM::CharacterData> is actually a L<Text|HTML::Object::DOM::Text> node, and its parent is a L<Document|HTML::Object::DOM::Document>.
481              
482             =item * If the parent of this L<CharacterData node|HTML::Object::DOM::CharacterData> is a L<Document|HTML::Object::DOM::Document> and one of the nodes to insert is a L<DocumentFragment|HTML::Object::DOM::DocumentFragment> with more than one L<Element|HTML::Object::DOM::Element> child, or that has a L<Text|HTML::Object::DOM::Text> child.
483              
484             =back
485              
486             Example:
487              
488             my $h1TextNode = $doc->getElementsByTagName('h1')->[0]->firstChild;
489             $h1TextNode->after(" #h1");
490              
491             $h1TextNode->parentElement->childNodes;
492             # NodeList [#text "CharacterData.after()", #text " #h1"]
493              
494             say $h1TextNode->data;
495             # "CharacterData.after()"
496              
497             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/after>
498              
499             =head2 appendData
500              
501             Provided with some string and this appends the given string to the L</data> string; when this method returns, data contains the concatenated string.
502              
503             Example:
504              
505             <span>Result: </span>A text
506              
507             my $span = $doc->getElementsByTagName("span")->[0];
508             my $textnode = $span->nextSibling;
509             $textnode->appendData(" - appended text.");
510             # span now contains:
511             # Result: A text - appended text.
512              
513             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/appendData>
514              
515             =head2 before
516              
517             Inserts a set of L<Node objects|HTML::Object::DON::Node> or strings in the children list of the C<CharacterData>'s parent, just before the C<CharacterData> object.
518              
519             It returns the same error as L</after>
520              
521             Example:
522              
523             my $h1TextNode = $doc->getElementsByTagName('h1')->[0]->firstChild;
524             $h1TextNode->before("h1# ");
525             $h1TextNode->parentElement->childNodes;
526             # NodeList [#text "h1# ", #text "CharacterData.before()"]
527              
528             say $h1TextNode.data;
529             # "CharacterData.before()"
530              
531             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/before>
532              
533             =head2 deleteData
534              
535             Provided with an C<offset> value as an integer and an C<amount> as a length, and this removes the specified C<amount> of characters, starting at the specified C<offset>, from the L</data> string; when this method returns, data contains the shortened string.
536              
537             Example:
538              
539             <span>Result: </span>A long string.
540              
541             my $span = $doc->getElementsByTagName("span")->[0];
542             my $textnode = $span->nextSibling;
543             $textnode->deleteData(1, 5);
544             # span now contains:
545             # Result: A string.
546              
547             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/deleteData>
548              
549             =head2 insertData
550              
551             Provided with an C<offset> value as an integer and a string, and this inserts the specified characters, at the specified C<offset>, in the L</data> string; when this method returns, data contains the modified string.
552              
553             <span>Result: </span>A string.
554              
555             my $span = $doc->getElementsByTagName("span")->[0];
556             my $textnode = $span->nextSibling;
557             $textnode->insertData(2, "long ");
558             # span now contains:
559             # Result: A long string.
560              
561             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/insertData>
562              
563             =head2 remove
564              
565             Removes the object from its parent children list.
566              
567             <span>Result: </span>A long string.
568              
569             my $span = $doc->getElementsByTagName("span")->[0];
570             my $textnode = $span->nextSibling;
571             # Removes the text
572             $textnode->remove();
573             # span now contains:
574             # Result:
575              
576             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/remove>
577              
578             =head2 replaceData
579              
580             $e->replaceData($offset, $count, $data);
581              
582             Provided with an C<offset> value as an integer, an C<amount> as a length, and a string, and this replaces the specified C<amount> of characters, starting at the specified C<offset>, with the specified C<string>; when this method returns, data contains the modified string.
583              
584             <span>Result: </span>A long string.
585              
586             my $span = $doc->getElementsByTagName("span")->[0];
587             my $textnode = $span->nextSibling;
588              
589             $textnode->replaceData(2, 4, "replaced");
590             # span now contains:
591             # Result: A replaced string.
592              
593             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/replaceData>
594              
595             =head2 replaceWith
596              
597             $e->replaceWith( $node1, 'some text', $node2 );
598              
599             Provided with a list of L<node objects|HTML::Object::DOM::Node> or strings and this replaces the characters in the children list of its parent with the supplied set of L<node objects|HTML::Object::DOM::Node> or strings.
600              
601             This returns an C<HTML::Object::HierarchyRequestError> when the node cannot be inserted at the specified point in the hierarchy.
602              
603             Example:
604              
605             <p id="myText">Some text</p>
606              
607             my $text = $doc->getElementById('myText')->firstChild;
608             my $em = $doc->createElement("em");
609             $em->textContent = "Italic text";
610             # Replace `Some text` by `Italic text`
611             $text->replaceWith( $em );
612              
613             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/replaceWith>
614              
615             =head2 substringData
616              
617             Provided with an C<offset> value as an integer, an C<amount> as a length, and this returns a string containing the part of L</data> of the specified C<length> and starting at the specified C<offset>.
618              
619             This is effectively similar to perl's L<perlfunc/substr>
620              
621             Returns a new L<scalar object|Module::Generic::Scalar>
622              
623             It returns a C<HTML::Object::IndexSizeError> error if C<offset> + C<amount> is larger than the length of the contained data.
624              
625             See L<for more information|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/substringData>
626              
627             =head1 AUTHOR
628              
629             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
630              
631             =head1 SEE ALSO
632              
633             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/CharacterData>
634              
635             =head1 COPYRIGHT & LICENSE
636              
637             Copyright(c) 2021 DEGUEST Pte. Ltd.
638              
639             All rights reserved
640              
641             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
642              
643             =cut