line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
###################################################################################################
|
2
|
|
|
|
|
|
|
# Copyright 2013/2014 by Marcel Greter
|
3
|
|
|
|
|
|
|
# This file is part of OCBNET-CSS3 (GPL3)
|
4
|
|
|
|
|
|
|
####################################################################################################
|
5
|
|
|
|
|
|
|
package OCBNET::CSS3::Styles;
|
6
|
|
|
|
|
|
|
####################################################################################################
|
7
|
|
|
|
|
|
|
our $VERSION = '0.2.5';
|
8
|
|
|
|
|
|
|
####################################################################################################
|
9
|
|
|
|
|
|
|
|
10
|
11
|
|
|
11
|
|
61
|
use strict;
|
|
11
|
|
|
|
|
85
|
|
|
11
|
|
|
|
|
353
|
|
11
|
11
|
|
|
11
|
|
50
|
use warnings;
|
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
271
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
####################################################################################################
|
14
|
11
|
|
|
11
|
|
58
|
use Scalar::Util 'blessed';
|
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
16131
|
|
15
|
|
|
|
|
|
|
####################################################################################################
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our %matcher;
|
18
|
|
|
|
|
|
|
our %default;
|
19
|
|
|
|
|
|
|
our %setter;
|
20
|
|
|
|
|
|
|
our %getter;
|
21
|
|
|
|
|
|
|
our %list;
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
####################################################################################################
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# static function only
|
26
|
|
|
|
|
|
|
# never call as method
|
27
|
|
|
|
|
|
|
sub register
|
28
|
|
|
|
|
|
|
{
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# get input arguments of static call
|
31
|
62
|
|
|
62
|
0
|
107
|
my ($key, $matcher, $default, $list) = @_;
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# store the matcher by key
|
34
|
62
|
|
|
|
|
139
|
$matcher{$key} = $matcher;
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# store the defaults by key
|
37
|
62
|
|
|
|
|
107
|
$default{$key} = $default;
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# store list attribute
|
40
|
|
|
|
|
|
|
# means we store as array
|
41
|
|
|
|
|
|
|
# and can parse comma lists
|
42
|
62
|
|
|
|
|
162
|
$list{$key} = $list;
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
}
|
45
|
|
|
|
|
|
|
# EO fn register
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# static function only
|
48
|
|
|
|
|
|
|
# never call as method
|
49
|
|
|
|
|
|
|
sub setter
|
50
|
|
|
|
|
|
|
{
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# get input arguments of static call
|
53
|
0
|
|
|
0
|
0
|
0
|
my ($key, $setter) = @_;
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# store the matcher by key
|
56
|
0
|
|
|
|
|
0
|
$setter{$key} = $setter;
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
}
|
59
|
|
|
|
|
|
|
# EO setter
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# static function only
|
62
|
|
|
|
|
|
|
# never call as method
|
63
|
|
|
|
|
|
|
sub getter
|
64
|
|
|
|
|
|
|
{
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# get input arguments of static call
|
67
|
2
|
|
|
2
|
0
|
4
|
my ($key, $getter) = @_;
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# store the matcher by key
|
70
|
2
|
|
|
|
|
6
|
$getter{$key} = $getter;
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
}
|
73
|
|
|
|
|
|
|
# EO getter
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
####################################################################################################
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# create a new object
|
78
|
|
|
|
|
|
|
# ***************************************************************************************
|
79
|
|
|
|
|
|
|
sub new
|
80
|
|
|
|
|
|
|
{
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# package name
|
83
|
211
|
|
|
211
|
0
|
1076
|
my ($pckg, $node) = @_;
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# create a new instance
|
86
|
211
|
|
|
|
|
550
|
my $self = { 'node' => $node, 'ids' => {} };
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# bless instance into package
|
89
|
211
|
|
|
|
|
1092
|
return bless $self, $pckg;
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
}
|
92
|
|
|
|
|
|
|
# EO constructor
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
####################################################################################################
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# basic getter
|
97
|
|
|
|
|
|
|
# ***************************************************************************************
|
98
|
72
|
|
|
72
|
0
|
279
|
sub node { $_[0]->{'node'} }
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
####################################################################################################
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# set key/value pair
|
103
|
|
|
|
|
|
|
# ***************************************************************************************
|
104
|
|
|
|
|
|
|
sub set
|
105
|
|
|
|
|
|
|
{
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# list variable
|
108
|
|
|
|
|
|
|
# parse optional
|
109
|
136
|
|
|
136
|
0
|
172
|
my %longhands;
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# get input arguments
|
112
|
136
|
|
|
|
|
284
|
my ($self, $key, $value) = @_;
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# check if we have a matcher
|
115
|
136
|
100
|
|
|
|
293
|
if (exists $matcher{$key})
|
116
|
|
|
|
|
|
|
{
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# get the configured matcher
|
119
|
|
|
|
|
|
|
# might be a shorthand value
|
120
|
113
|
|
|
|
|
172
|
my $matcher = $matcher{$key};
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# rewrite longhand to shorthand
|
123
|
113
|
100
|
|
|
|
280
|
if (ref($matcher) eq 'Regexp')
|
124
|
|
|
|
|
|
|
{
|
125
|
|
|
|
|
|
|
# must only match that single keys regex
|
126
|
82
|
|
|
|
|
313
|
$matcher = { 'ordered' => [ [ $key ] ] };
|
127
|
|
|
|
|
|
|
}
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# matcher is a shorthand
|
130
|
113
|
100
|
|
|
|
245
|
if (ref($matcher) eq 'HASH')
|
131
|
|
|
|
|
|
|
{
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# create arrays for all longhands
|
134
|
112
|
100
|
|
|
|
116
|
$longhands{$_} = [] foreach @{$matcher->{'prefix'} || []};
|
|
112
|
|
|
|
|
617
|
|
135
|
112
|
100
|
|
|
|
139
|
$longhands{$_->[0]} = [] foreach @{$matcher->{'ordered'} || []};
|
|
112
|
|
|
|
|
633
|
|
136
|
|
|
|
|
|
|
# $longhands{$_} = [] foreach @{$matcher->{'postfix'} || []};
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# parse list
|
139
|
|
|
|
|
|
|
# exit if not
|
140
|
112
|
|
|
|
|
380
|
while (1)
|
141
|
|
|
|
|
|
|
{
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# declare variables
|
144
|
121
|
|
|
|
|
131
|
my ($prop);
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# get optional options from shorthand
|
147
|
|
|
|
|
|
|
# create a copy of the array, so we can
|
148
|
|
|
|
|
|
|
# manipulate them later for loop control
|
149
|
121
|
100
|
|
|
|
116
|
my $prefix = [ @{$matcher->{'prefix'} || []} ];
|
|
121
|
|
|
|
|
468
|
|
150
|
121
|
100
|
|
|
|
153
|
my $ordered = [ @{$matcher->{'ordered'} || []} ];
|
|
121
|
|
|
|
|
377
|
|
151
|
|
|
|
|
|
|
# my $postfix = [ @{$matcher->{'postfix'} || []} ];
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# set defaults for all optional longhands
|
154
|
121
|
|
|
|
|
166
|
push @{$longhands{$_}}, $default{$_} foreach @{$prefix};
|
|
121
|
|
|
|
|
252
|
|
|
58
|
|
|
|
|
239
|
|
155
|
121
|
|
|
|
|
131
|
push @{$longhands{$_->[0]}}, $default{$_->[0]} foreach @{$ordered};
|
|
121
|
|
|
|
|
186
|
|
|
154
|
|
|
|
|
533
|
|
156
|
|
|
|
|
|
|
# push @{$longhands{$_}}, $default{$_} foreach @{$postfix};
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# optional prefixes (can occur in any order)
|
159
|
121
|
|
|
|
|
201
|
for (my $i = 0; $i < scalar(@{$prefix}); $i++)
|
|
194
|
|
|
|
|
495
|
|
160
|
|
|
|
|
|
|
{
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# get property name
|
163
|
73
|
|
|
|
|
119
|
my $prop = $prefix->[$i];
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# get the configured matcher
|
166
|
|
|
|
|
|
|
# might be a shorthand value
|
167
|
73
|
|
|
|
|
129
|
my $regex = $matcher{$prop};
|
168
|
|
|
|
|
|
|
|
169
|
73
|
100
|
|
|
|
183
|
if (ref($regex) eq 'HASH')
|
170
|
13
|
|
|
|
|
33
|
{ $regex = $regex->{'matcher'} }
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# test if we have found this property
|
173
|
73
|
100
|
|
|
|
22753
|
if ($value =~ s/\A\s*($regex)\s*//s)
|
174
|
|
|
|
|
|
|
{
|
175
|
|
|
|
|
|
|
# matches this property
|
176
|
30
|
|
|
|
|
116
|
$longhands{$prop}->[-1] = $1;
|
177
|
|
|
|
|
|
|
# remove from search and
|
178
|
30
|
|
|
|
|
39
|
splice(@{$prefix}, $i, 1);
|
|
30
|
|
|
|
|
66
|
|
179
|
|
|
|
|
|
|
# restart loop
|
180
|
30
|
|
|
|
|
45
|
$i = -1; next;
|
|
30
|
|
|
|
|
382
|
|
181
|
|
|
|
|
|
|
}
|
182
|
|
|
|
|
|
|
# EO match regex
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
# EO each prefix
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# mandatory longhands
|
188
|
121
|
|
|
|
|
125
|
foreach $prop (@{$ordered})
|
|
121
|
|
|
|
|
194
|
|
189
|
|
|
|
|
|
|
{
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# get property name
|
192
|
154
|
|
|
|
|
194
|
my $name = $prop->[0];
|
193
|
|
|
|
|
|
|
# get optinal alternative
|
194
|
|
|
|
|
|
|
# string: eval to this if nothing set
|
195
|
|
|
|
|
|
|
# regexp: is optionally fallowed by this
|
196
|
154
|
|
|
|
|
177
|
my $alt = $prop->[1];
|
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# get the configured matcher
|
199
|
|
|
|
|
|
|
# might be a shorthand value
|
200
|
154
|
|
|
|
|
216
|
my $regex = $matcher{$name};
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# optional alternative
|
203
|
|
|
|
|
|
|
# delimited from property
|
204
|
154
|
100
|
|
|
|
324
|
if (ref($alt) eq 'Regexp')
|
205
|
|
|
|
|
|
|
{
|
206
|
|
|
|
|
|
|
# test if we found the delimiter
|
207
|
|
|
|
|
|
|
# if not the value is not mandatory
|
208
|
1
|
50
|
|
|
|
22
|
next unless ($value =~ s/\A\s*($alt)\s*//s)
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
# test if we have found this property
|
212
|
154
|
100
|
33
|
|
|
14018
|
if ($value =~ s/\A\s*($regex)\s*//s)
|
|
|
50
|
|
|
|
|
|
213
|
|
|
|
|
|
|
{
|
214
|
|
|
|
|
|
|
# matches this property
|
215
|
120
|
|
|
|
|
829
|
$longhands{$name}->[-1] = $1;
|
216
|
|
|
|
|
|
|
}
|
217
|
|
|
|
|
|
|
# EO match regex
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# has another alternative (string)
|
220
|
|
|
|
|
|
|
elsif (defined $alt && ref($alt) eq '')
|
221
|
|
|
|
|
|
|
{
|
222
|
|
|
|
|
|
|
# eval to another longhand property
|
223
|
|
|
|
|
|
|
# this property should be parsed already
|
224
|
34
|
|
|
|
|
122
|
$longhands{$name}->[-1] = $longhands{$alt}->[-1];
|
225
|
|
|
|
|
|
|
}
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
}
|
228
|
|
|
|
|
|
|
# EO each longhand
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
# # optional postfixes (can occur in any order)
|
231
|
|
|
|
|
|
|
# for (my $i = 0; $i < scalar(@{$postfix}); $i++)
|
232
|
|
|
|
|
|
|
# {
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# # get property name
|
235
|
|
|
|
|
|
|
# my $prop = $postfix->[$i];
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# # get the configured matcher
|
238
|
|
|
|
|
|
|
# # might be a shorthand value
|
239
|
|
|
|
|
|
|
# my $regex = $matcher{$prop};
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# # test if we have found this property
|
242
|
|
|
|
|
|
|
# if ($value =~ s/\A\s*($regex)\s*//s)
|
243
|
|
|
|
|
|
|
# {
|
244
|
|
|
|
|
|
|
# # matches this property
|
245
|
|
|
|
|
|
|
# $longhands{$prop}->[-1] = $1;
|
246
|
|
|
|
|
|
|
# # remove from search and
|
247
|
|
|
|
|
|
|
# splice(@{$postfix}, $i, 1);
|
248
|
|
|
|
|
|
|
# # restart loop
|
249
|
|
|
|
|
|
|
# $i = -1; next;
|
250
|
|
|
|
|
|
|
# }
|
251
|
|
|
|
|
|
|
# # EO match regex
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# }
|
254
|
|
|
|
|
|
|
# # EO each postfix
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# check if we should parse in list mode
|
257
|
|
|
|
|
|
|
# if we find a comma we will parse again
|
258
|
121
|
100
|
100
|
|
|
571
|
next if $list{$key} && $value =~ s/\A\s*,\s*//s;
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
# end loop
|
261
|
112
|
|
|
|
|
325
|
last;
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
}
|
264
|
|
|
|
|
|
|
# EO while 1
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
}
|
268
|
|
|
|
|
|
|
# EO if HASH
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# assertion for hash type
|
271
|
1
|
|
|
|
|
8
|
else { die "unknown type"; }
|
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
}
|
274
|
|
|
|
|
|
|
# EO if matcher
|
275
|
|
|
|
|
|
|
else
|
276
|
|
|
|
|
|
|
{
|
277
|
|
|
|
|
|
|
# trim whitespace for value
|
278
|
23
|
|
|
|
|
110
|
$value =~ s/(?:\A\s+|\s+\z)//g;
|
279
|
|
|
|
|
|
|
# store the original value
|
280
|
23
|
|
|
|
|
83
|
$longhands{$key} = [ $value ];
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# check if we have a new id
|
284
|
135
|
100
|
|
|
|
303
|
if ($longhands{'css-id'})
|
285
|
|
|
|
|
|
|
{
|
286
|
|
|
|
|
|
|
# store all ids in our global hash
|
287
|
36
|
|
|
|
|
43
|
foreach my $id (@{$longhands{'css-id'}})
|
|
36
|
|
|
|
|
93
|
|
288
|
36
|
|
|
|
|
93
|
{ $self->root->{'ids'}->{$id} = $self->node; }
|
289
|
|
|
|
|
|
|
}
|
290
|
|
|
|
|
|
|
# EO if css-id
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
#####################################################
|
293
|
|
|
|
|
|
|
# implement action to setup styles
|
294
|
|
|
|
|
|
|
#####################################################
|
295
|
|
|
|
|
|
|
# print "x" x 40, "\n";
|
296
|
|
|
|
|
|
|
# foreach my $name (keys %longhands)
|
297
|
|
|
|
|
|
|
# { printf "%s => %s\n", $name, join(", ", @{$longhands{$name}}); }
|
298
|
|
|
|
|
|
|
#####################################################
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# overwrite styles with longhands
|
301
|
135
|
|
|
|
|
382
|
foreach my $name (keys %longhands)
|
302
|
|
|
|
|
|
|
{
|
303
|
|
|
|
|
|
|
# check if key is another shorthand
|
304
|
216
|
100
|
|
|
|
493
|
if (ref($matcher{$name}) eq 'HASH')
|
305
|
|
|
|
|
|
|
{
|
306
|
|
|
|
|
|
|
# pass this "shorthand" value to parse longhands
|
307
|
11
|
|
|
|
|
21
|
$self->set($name, join(',', @{$longhands{$name}}));
|
|
11
|
|
|
|
|
67
|
|
308
|
|
|
|
|
|
|
}
|
309
|
|
|
|
|
|
|
# it's a longhand
|
310
|
|
|
|
|
|
|
else
|
311
|
|
|
|
|
|
|
{
|
312
|
|
|
|
|
|
|
# just store the parsed value
|
313
|
205
|
|
|
|
|
356
|
$self->{$name} = $longhands{$name};
|
314
|
|
|
|
|
|
|
# call setter hook if one was defined
|
315
|
205
|
50
|
|
|
|
531
|
$setter{$name}->($self) if $setter{$name};
|
316
|
|
|
|
|
|
|
}
|
317
|
|
|
|
|
|
|
}
|
318
|
|
|
|
|
|
|
# EO each longhand
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# return results
|
321
|
135
|
|
|
|
|
803
|
return \ %longhands;
|
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
}
|
324
|
|
|
|
|
|
|
# EO sub set
|
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
####################################################################################################
|
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# get value of a longhand
|
329
|
|
|
|
|
|
|
# ***************************************************************************************
|
330
|
|
|
|
|
|
|
sub get
|
331
|
|
|
|
|
|
|
{
|
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# get input arguments
|
334
|
0
|
|
|
0
|
0
|
0
|
my ($self, $key, $idx) = @_;
|
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
# check if found in current styles
|
337
|
0
|
0
|
0
|
|
|
0
|
if (exists $self->{$key}->[$idx || 0])
|
338
|
0
|
|
0
|
|
|
0
|
{ return $self->{$key}->[$idx || 0]; }
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# nothing found
|
341
|
0
|
|
|
|
|
0
|
return undef;
|
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
}
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
####################################################################################################
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# get list of all longhands
|
348
|
|
|
|
|
|
|
# ***************************************************************************************
|
349
|
|
|
|
|
|
|
sub list
|
350
|
|
|
|
|
|
|
{
|
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# get input arguments
|
353
|
72
|
|
|
72
|
0
|
113
|
my ($self, $key) = @_;
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# check if found in current styles
|
356
|
72
|
100
|
|
|
|
165
|
if (exists $self->{$key})
|
357
|
62
|
|
|
|
|
73
|
{ return @{$self->{$key}}; }
|
|
62
|
|
|
|
|
247
|
|
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# nothing found
|
360
|
10
|
|
|
|
|
37
|
return ();
|
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
}
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
####################################################################################################
|
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# access helper for node root
|
367
|
|
|
|
|
|
|
# ***************************************************************************************
|
368
|
36
|
|
|
36
|
0
|
76
|
sub root { shift->node->root(@_) }
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
####################################################################################################
|
371
|
|
|
|
|
|
|
####################################################################################################
|
372
|
|
|
|
|
|
|
1;
|
373
|
|
|
|
|
|
|
|