Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Render.pm |
Statements | Executed 10737 statements in 102ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1954 | 88 | 1 | 20.5ms | 20.5ms | CORE:subst (opcode) | Foswiki::Render::
5 | 1 | 1 | 16.5ms | 191ms | getRenderedVersion | Foswiki::Render::
759 | 16 | 1 | 9.43ms | 9.43ms | CORE:substcont (opcode) | Foswiki::Render::
234 | 3 | 1 | 6.66ms | 7.06ms | _addListItem | Foswiki::Render::
34 | 1 | 1 | 5.05ms | 34.5ms | _handleSquareBracketedLink | Foswiki::Render::
72 | 2 | 1 | 4.30ms | 49.9ms | internalLink | Foswiki::Render::
1339 | 23 | 1 | 3.25ms | 3.25ms | CORE:match (opcode) | Foswiki::Render::
749 | 35 | 1 | 2.62ms | 2.62ms | CORE:regcomp (opcode) | Foswiki::Render::
72 | 1 | 1 | 2.61ms | 42.0ms | _renderWikiWord | Foswiki::Render::
50 | 1 | 1 | 2.46ms | 16.7ms | _renderExistingWikiWord | Foswiki::Render::
40 | 1 | 1 | 2.19ms | 30.0ms | _handleWikiWord | Foswiki::Render::
4 | 1 | 1 | 1.42ms | 3.16ms | forEachLine | Foswiki::Render::
1 | 1 | 1 | 1.41ms | 1.54ms | BEGIN@19 | Foswiki::Render::
6 | 1 | 1 | 1.08ms | 4.66ms | renderRevisionInfo | Foswiki::Render::
25 | 5 | 1 | 1.07ms | 1.71ms | _putBackProtected | Foswiki::Render::
7 | 1 | 1 | 899µs | 9.48ms | renderFORMFIELD | Foswiki::Render::
25 | 5 | 1 | 888µs | 2.13ms | _takeOutProtected | Foswiki::Render::
34 | 2 | 1 | 849µs | 1.45ms | _escapeAutoLinks | Foswiki::Render::
32 | 1 | 1 | 712µs | 980µs | _isImageLink | Foswiki::Render::
50 | 1 | 1 | 684µs | 966µs | _linkToolTipInfo | Foswiki::Render::
14 | 1 | 1 | 377µs | 420µs | protectFormFieldValue | Foswiki::Render::
15 | 1 | 1 | 258µs | 258µs | _replaceBlock | Foswiki::Render::
4 | 1 | 1 | 217µs | 10.3ms | _renderNonExistingWikiWord | Foswiki::Render::
6 | 1 | 1 | 166µs | 2.41ms | _makeAnchorHeading | Foswiki::Render::
5 | 1 | 1 | 149µs | 240µs | getAnchorNames | Foswiki::Render::
27 | 7 | 1 | 137µs | 137µs | CORE:qr (opcode) | Foswiki::Render::
17 | 1 | 1 | 103µs | 103µs | _filterLiteral | Foswiki::Render::
1 | 1 | 1 | 85µs | 121µs | renderParent | Foswiki::Render::
12 | 1 | 1 | 83µs | 83µs | _filterScript | Foswiki::Render::
1 | 1 | 1 | 68µs | 593µs | _fixedFontText | Foswiki::Render::
2 | 1 | 1 | 63µs | 77µs | _externalLink | Foswiki::Render::
4 | 1 | 1 | 59µs | 182µs | _newLinkFormat | Foswiki::Render::
1 | 1 | 1 | 35µs | 45µs | BEGIN@1772 | Foswiki::Render::
1 | 1 | 1 | 28µs | 98µs | BEGIN@14 | Foswiki::Render::
1 | 1 | 1 | 27µs | 172µs | BEGIN@72 | Foswiki::Render::
1 | 1 | 1 | 26µs | 34µs | BEGIN@12 | Foswiki::Render::
1 | 1 | 1 | 26µs | 564µs | BEGIN@15 | Foswiki::Render::
1 | 1 | 1 | 25µs | 25µs | new | Foswiki::Render::
1 | 1 | 1 | 20µs | 20µs | finish | Foswiki::Render::
1 | 1 | 1 | 19µs | 27µs | BEGIN@1774 | Foswiki::Render::
1 | 1 | 1 | 17µs | 35µs | BEGIN@13 | Foswiki::Render::
1 | 1 | 1 | 10µs | 10µs | BEGIN@17 | Foswiki::Render::
1 | 1 | 1 | 10µs | 10µs | BEGIN@76 | Foswiki::Render::
1 | 1 | 1 | 9µs | 9µs | BEGIN@18 | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | TML2PlainText | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | _addTHEADandTFOOT | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | _emitTR | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | _escape | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | _mailLink | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | breakName | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | getReferenceRE | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | makeTopicSummary | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | protectPlainText | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | renderIconImage | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | renderMoved | Foswiki::Render::
0 | 0 | 0 | 0s | 0s | verbatimCallBack | Foswiki::Render::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | package Foswiki::Render; | ||||
3 | |||||
4 | =begin TML | ||||
5 | |||||
6 | ---+ package Foswiki::Render | ||||
7 | |||||
8 | This module provides most of the actual HTML rendering code in Foswiki. | ||||
9 | |||||
10 | =cut | ||||
11 | |||||
12 | 2 | 50µs | 2 | 42µs | # spent 34µs (26+8) within Foswiki::Render::BEGIN@12 which was called:
# once (26µs+8µs) by Foswiki::renderer at line 12 # spent 34µs making 1 call to Foswiki::Render::BEGIN@12
# spent 8µs making 1 call to strict::import |
13 | 2 | 45µs | 2 | 53µs | # spent 35µs (17+18) within Foswiki::Render::BEGIN@13 which was called:
# once (17µs+18µs) by Foswiki::renderer at line 13 # spent 35µs making 1 call to Foswiki::Render::BEGIN@13
# spent 18µs making 1 call to warnings::import |
14 | 2 | 57µs | 2 | 169µs | # spent 98µs (28+71) within Foswiki::Render::BEGIN@14 which was called:
# once (28µs+71µs) by Foswiki::renderer at line 14 # spent 98µs making 1 call to Foswiki::Render::BEGIN@14
# spent 71µs making 1 call to Assert::import |
15 | 2 | 62µs | 2 | 1.10ms | # spent 564µs (26+538) within Foswiki::Render::BEGIN@15 which was called:
# once (26µs+538µs) by Foswiki::renderer at line 15 # spent 564µs making 1 call to Foswiki::Render::BEGIN@15
# spent 538µs making 1 call to Error::import |
16 | |||||
17 | 2 | 39µs | 1 | 10µs | # spent 10µs within Foswiki::Render::BEGIN@17 which was called:
# once (10µs+0s) by Foswiki::renderer at line 17 # spent 10µs making 1 call to Foswiki::Render::BEGIN@17 |
18 | 2 | 46µs | 1 | 9µs | # spent 9µs within Foswiki::Render::BEGIN@18 which was called:
# once (9µs+0s) by Foswiki::renderer at line 18 # spent 9µs making 1 call to Foswiki::Render::BEGIN@18 |
19 | 2 | 394µs | 1 | 1.54ms | # spent 1.54ms (1.41+130µs) within Foswiki::Render::BEGIN@19 which was called:
# once (1.41ms+130µs) by Foswiki::renderer at line 19 # spent 1.54ms making 1 call to Foswiki::Render::BEGIN@19 |
20 | |||||
21 | # Counter used to generate unique placeholders for when we lift blocks | ||||
22 | # (such as <verbatim> out of the text during rendering. | ||||
23 | 1 | 2µs | our $placeholderMarker = 0; | ||
24 | |||||
25 | # Limiting lookbehind and lookahead for wikiwords and emphasis. | ||||
26 | # use like \b | ||||
27 | 1 | 22µs | 1 | 6µs | our $STARTWW = qr/^|(?<=[\s\(])/m; # spent 6µs making 1 call to Foswiki::Render::CORE:qr |
28 | 1 | 8µs | 1 | 3µs | our $ENDWW = qr/$|(?=[\s,.;:!?)])/m; # spent 3µs making 1 call to Foswiki::Render::CORE:qr |
29 | |||||
30 | # Note: the following marker sequences are used in text to mark things that | ||||
31 | # have been hoisted or need to be marked for further processing. The strings | ||||
32 | # are carefully chosen so that they (1) are not normally present in written | ||||
33 | # text and (2) they do not combine with other characters to form valid | ||||
34 | # wide-byte characters. A subset of the 7-bit control characters is used | ||||
35 | # (codepoint < 0x07). Warning: the RENDERZONE_MARKER in Foswiki.pm uses \3 | ||||
36 | |||||
37 | # Marker used to indicate the start of a table | ||||
38 | 1 | 2µs | our $TABLEMARKER = "\0\1\2TABLE\2\1\0"; | ||
39 | |||||
40 | # Marker used to indicate table rows that are valid header/footer rows | ||||
41 | 1 | 2µs | our $TRMARK = "is\1all\1th"; | ||
42 | |||||
43 | # General purpose marker used to mark escapes inthe text; for example, we | ||||
44 | # use it to mark hoisted blocks, such as verbatim blocks. | ||||
45 | 1 | 1µs | our $REMARKER = "\0"; | ||
46 | |||||
47 | # Optional End marker for escapes where the default end character ; also | ||||
48 | # must be removed. Used for email anti-spam encoding. | ||||
49 | 1 | 1µs | our $REEND = "\1"; | ||
50 | |||||
51 | # Characters that need to be %XX escaped in mailto URIs. | ||||
52 | 1 | 28µs | our %ESCAPED = ( | ||
53 | '<' => '%3C', | ||||
54 | '>' => '%3E', | ||||
55 | '#' => '%23', | ||||
56 | '"' => '%22', | ||||
57 | '%' => '%25', | ||||
58 | "'" => '%27', | ||||
59 | '{' => '%7B', | ||||
60 | '}' => '%7D', | ||||
61 | '|' => '%7C', | ||||
62 | '\\' => '%5C', | ||||
63 | '^' => '%5E', | ||||
64 | '~' => '%7E', | ||||
65 | '`' => '%60', | ||||
66 | '?' => '%3F', | ||||
67 | '&' => '%26', | ||||
68 | '=' => '%3D', | ||||
69 | ); | ||||
70 | |||||
71 | # Default format for a link to a non-existant topic | ||||
72 | 1 | 145µs | # spent 172µs (27+145) within Foswiki::Render::BEGIN@72 which was called:
# once (27µs+145µs) by Foswiki::renderer at line 74 # spent 145µs making 1 call to constant::import | ||
73 | <span class="foswikiNewLink">$text<a href="%SCRIPTURLPATH{"edit"}%/$web/$topic?topicparent=%WEB%.%TOPIC%" rel="nofollow" title="%MAKETEXT{"Create this topic"}%">?</a></span> | ||||
74 | 2 | 102µs | 1 | 172µs | NLF # spent 172µs making 1 call to Foswiki::Render::BEGIN@72 |
75 | |||||
76 | # spent 10µs within Foswiki::Render::BEGIN@76 which was called:
# once (10µs+0s) by Foswiki::renderer at line 83 | ||||
77 | |||||
78 | # Do a dynamic 'use locale' for this module | ||||
79 | 1 | 9µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
80 | require locale; | ||||
81 | import locale(); | ||||
82 | } | ||||
83 | 1 | 13.8ms | 1 | 10µs | } # spent 10µs making 1 call to Foswiki::Render::BEGIN@76 |
84 | |||||
85 | =begin TML | ||||
86 | |||||
87 | ---++ ClassMethod new ($session) | ||||
88 | |||||
89 | Creates a new renderer | ||||
90 | |||||
91 | =cut | ||||
92 | |||||
93 | # spent 25µs within Foswiki::Render::new which was called:
# once (25µs+0s) by Foswiki::renderer at line 1916 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm | ||||
94 | 3 | 27µs | my ( $class, $session ) = @_; | ||
95 | my $this = bless( { session => $session }, $class ); | ||||
96 | |||||
97 | return $this; | ||||
98 | } | ||||
99 | |||||
100 | =begin TML | ||||
101 | |||||
102 | ---++ ObjectMethod finish() | ||||
103 | Break circular references. | ||||
104 | |||||
105 | =cut | ||||
106 | |||||
107 | # Note to developers; please undef *all* fields in the object explicitly, | ||||
108 | # whether they are references or not. That way this method is "golden | ||||
109 | # documentation" of the live fields in the object. | ||||
110 | # spent 20µs within Foswiki::Render::finish which was called:
# once (20µs+0s) by Foswiki::finish at line 2100 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm | ||||
111 | 6 | 25µs | my $this = shift; | ||
112 | undef $this->{NEWLINKFORMAT}; | ||||
113 | undef $this->{LINKTOOLTIPINFO}; | ||||
114 | undef $this->{LIST}; | ||||
115 | undef $this->{ffCache}; | ||||
116 | undef $this->{session}; | ||||
117 | } | ||||
118 | |||||
119 | # spent 182µs (59+123) within Foswiki::Render::_newLinkFormat which was called 4 times, avg 46µs/call:
# 4 times (59µs+123µs) by Foswiki::Render::_renderNonExistingWikiWord at line 698, avg 46µs/call | ||||
120 | 13 | 61µs | my $this = shift; | ||
121 | unless ( $this->{NEWLINKFORMAT} ) { | ||||
122 | 1 | 123µs | $this->{NEWLINKFORMAT} = # spent 123µs making 1 call to Foswiki::Prefs::getPreference | ||
123 | $this->{session}->{prefs}->getPreference('NEWLINKFORMAT') | ||||
124 | || DEFAULT_NEWLINKFORMAT; | ||||
125 | } | ||||
126 | return $this->{NEWLINKFORMAT}; | ||||
127 | } | ||||
128 | |||||
129 | =begin TML | ||||
130 | |||||
131 | ---++ ObjectMethod renderParent($topicObject, $params) -> $text | ||||
132 | |||||
133 | Render parent meta-data | ||||
134 | |||||
135 | =cut | ||||
136 | |||||
137 | # spent 121µs (85+36) within Foswiki::Render::renderParent which was called:
# once (85µs+36µs) by Foswiki::META at line 41 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/META.pm | ||||
138 | 25 | 70µs | my ( $this, $topicObject, $ah ) = @_; | ||
139 | my $dontRecurse = $ah->{dontrecurse} || 0; | ||||
140 | my $depth = $ah->{depth} || 0; | ||||
141 | my $noWebHome = $ah->{nowebhome} || 0; | ||||
142 | my $prefix = $ah->{prefix} || ''; | ||||
143 | my $suffix = $ah->{suffix} || ''; | ||||
144 | my $usesep = $ah->{separator} || ' > '; | ||||
145 | my $format = $ah->{format} || '[[$web.$topic][$topic]]'; | ||||
146 | |||||
147 | 2 | 14µs | my ( $web, $topic ) = ( $topicObject->web, $topicObject->topic ); # spent 7µs making 1 call to Foswiki::Meta::topic
# spent 7µs making 1 call to Foswiki::Meta::web | ||
148 | return '' unless $web && $topic; | ||||
149 | |||||
150 | my %visited; | ||||
151 | $visited{ $web . '.' . $topic } = 1; | ||||
152 | |||||
153 | my $pWeb = $web; | ||||
154 | my $pTopic; | ||||
155 | my $text = ''; | ||||
156 | 1 | 22µs | my $parentMeta = $topicObject->get('TOPICPARENT'); # spent 22µs making 1 call to Foswiki::Meta::get | ||
157 | my $parent; | ||||
158 | |||||
159 | $parent = $parentMeta->{name} if $parentMeta; | ||||
160 | |||||
161 | my @stack; | ||||
162 | my $currentDepth = 0; | ||||
163 | $depth = 1 if $dontRecurse; | ||||
164 | |||||
165 | while ($parent) { | ||||
166 | $currentDepth++; | ||||
167 | ( $pWeb, $pTopic ) = | ||||
168 | $this->{session}->normalizeWebTopicName( $pWeb, $parent ); | ||||
169 | $parent = $pWeb . '.' . $pTopic; | ||||
170 | last | ||||
171 | if ( $noWebHome && ( $pTopic eq $Foswiki::cfg{HomeTopicName} ) | ||||
172 | || $visited{$parent} ); | ||||
173 | $visited{$parent} = 1; | ||||
174 | $text = $format; | ||||
175 | $text =~ s/\$web/$pWeb/g; | ||||
176 | $text =~ s/\$topic/$pTopic/g; | ||||
177 | |||||
178 | if ( !$depth or $currentDepth == $depth ) { | ||||
179 | unshift( @stack, $text ); | ||||
180 | } | ||||
181 | last if $currentDepth == $depth; | ||||
182 | |||||
183 | # Compromise; rather than supporting a hack in the store to support | ||||
184 | # rapid access to parent meta (as in TWiki) accept the hit | ||||
185 | # of reading the whole topic. | ||||
186 | my $topicObject = | ||||
187 | Foswiki::Meta->load( $this->{session}, $pWeb, $pTopic ); | ||||
188 | my $parentMeta = $topicObject->get('TOPICPARENT'); | ||||
189 | $parent = $parentMeta->{name} if $parentMeta; | ||||
190 | } | ||||
191 | $text = join( $usesep, @stack ); | ||||
192 | |||||
193 | if ($text) { | ||||
194 | $text = $prefix . $text if ($prefix); | ||||
195 | $text .= $suffix if ($suffix); | ||||
196 | } | ||||
197 | |||||
198 | return $text; | ||||
199 | } | ||||
200 | |||||
201 | =begin TML | ||||
202 | |||||
203 | ---++ ObjectMethod renderMoved($topicObject, $params) -> $text | ||||
204 | |||||
205 | Render moved meta-data | ||||
206 | |||||
207 | =cut | ||||
208 | |||||
209 | sub renderMoved { | ||||
210 | my ( $this, $topicObject, $params ) = @_; | ||||
211 | my $text = ''; | ||||
212 | my $moved = $topicObject->get('TOPICMOVED'); | ||||
213 | my $prefix = $params->{prefix} || ''; | ||||
214 | my $suffix = $params->{suffix} || ''; | ||||
215 | |||||
216 | if ($moved) { | ||||
217 | my ( $fromWeb, $fromTopic ) = | ||||
218 | $this->{session} | ||||
219 | ->normalizeWebTopicName( $topicObject->web, $moved->{from} ); | ||||
220 | my ( $toWeb, $toTopic ) = | ||||
221 | $this->{session} | ||||
222 | ->normalizeWebTopicName( $topicObject->web, $moved->{to} ); | ||||
223 | my $by = $moved->{by}; | ||||
224 | my $u = $by; | ||||
225 | my $users = $this->{session}->{users}; | ||||
226 | $by = $users->webDotWikiName($u) if $u; | ||||
227 | my $date = Foswiki::Time::formatTime( $moved->{date}, '', 'gmtime' ); | ||||
228 | |||||
229 | # Only allow put back if current web and topic match | ||||
230 | # stored information | ||||
231 | my $putBack = ''; | ||||
232 | if ( $topicObject->web eq $toWeb && $topicObject->topic eq $toTopic ) { | ||||
233 | $putBack = ' - ' | ||||
234 | . CGI::a( | ||||
235 | { | ||||
236 | title => ( | ||||
237 | $this->{session}->i18n->maketext( | ||||
238 | 'Click to move topic back to previous location, with option to change references.' | ||||
239 | ) | ||||
240 | ), | ||||
241 | href => $this->{session}->getScriptUrl( | ||||
242 | 0, 'rename', $topicObject->web, $topicObject->topic | ||||
243 | ), | ||||
244 | rel => 'nofollow' | ||||
245 | }, | ||||
246 | $this->{session}->i18n->maketext('Put it back...') | ||||
247 | ); | ||||
248 | } | ||||
249 | $text = $this->{session}->i18n->maketext( | ||||
250 | "[_1] was renamed or moved from [_2] on [_3] by [_4]", | ||||
251 | "<nop>$toWeb.<nop>$toTopic", "<nop>$fromWeb.<nop>$fromTopic", | ||||
252 | $date, $by | ||||
253 | ) . $putBack; | ||||
254 | } | ||||
255 | $text = "$prefix$text$suffix" if $text; | ||||
256 | return $text; | ||||
257 | } | ||||
258 | |||||
259 | # Add a list item, of the given type and indent depth. The list item may | ||||
260 | # cause the opening or closing of lists currently being handled. | ||||
261 | # spent 7.06ms (6.66+400µs) within Foswiki::Render::_addListItem which was called 234 times, avg 30µs/call:
# 195 times (5.27ms+279µs) by Foswiki::Render::getRenderedVersion at line 1364, avg 28µs/call
# 34 times (1.25ms+114µs) by Foswiki::Render::getRenderedVersion at line 1319, avg 40µs/call
# 5 times (140µs+7µs) by Foswiki::Render::getRenderedVersion at line 1375, avg 29µs/call | ||||
262 | 2496 | 7.26ms | my ( $this, $result, $type, $element, $css, $indent ) = @_; | ||
263 | |||||
264 | 234 | 400µs | $indent =~ s/ /\t/g; # spent 400µs making 234 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
265 | my $depth = length($indent); | ||||
266 | |||||
267 | my $size = scalar( @{ $this->{LIST} } ); | ||||
268 | |||||
269 | # The whitespaces either side of the tags are required for the | ||||
270 | # emphasis REs to work. | ||||
271 | if ( $size < $depth ) { | ||||
272 | my $firstTime = 1; | ||||
273 | while ( $size < $depth ) { | ||||
274 | push( @{ $this->{LIST} }, { type => $type, element => $element } ); | ||||
275 | push( @$result, " <$element" . ($css ? " class='$css'" : "") .">\n" ) | ||||
276 | unless ($firstTime); | ||||
277 | push( @$result, ' <' . $type . ">\n" ) if $type; | ||||
278 | $firstTime = 0; | ||||
279 | $size++; | ||||
280 | } | ||||
281 | } | ||||
282 | else { | ||||
283 | while ( $size > $depth ) { | ||||
284 | my $tags = pop( @{ $this->{LIST} } ); | ||||
285 | my $r = "\n</" . $tags->{element} . '>'; | ||||
286 | $r .= '</' . $tags->{type} . '> ' if $tags->{type}; | ||||
287 | push( @$result, $r ); | ||||
288 | $size--; | ||||
289 | } | ||||
290 | if ($size) { | ||||
291 | push( @$result, | ||||
292 | "\n</" . $this->{LIST}->[ $size - 1 ]->{element} . '> ' ); | ||||
293 | } | ||||
294 | else { | ||||
295 | push( @$result, "\n" ); | ||||
296 | } | ||||
297 | } | ||||
298 | |||||
299 | if ($size) { | ||||
300 | my $oldt = $this->{LIST}->[ $size - 1 ]; | ||||
301 | if ( $oldt->{type} ne $type ) { | ||||
302 | my $r = ''; | ||||
303 | $r .= ' </' . $oldt->{type} . '>' if $oldt->{type}; | ||||
304 | $r .= '<' . $type . ">\n" if $type; | ||||
305 | push( @$result, $r ) if $r; | ||||
306 | pop( @{ $this->{LIST} } ); | ||||
307 | push( @{ $this->{LIST} }, { | ||||
308 | type => $type, element => $element } ); | ||||
309 | } | ||||
310 | } | ||||
311 | } | ||||
312 | |||||
313 | # Given that we have just seen the end of a table, work out the thead, | ||||
314 | # tbody and tfoot sections | ||||
315 | sub _addTHEADandTFOOT { | ||||
316 | my ($lines) = @_; | ||||
317 | |||||
318 | # scan back to the head of the table | ||||
319 | my $i = scalar(@$lines) - 1; | ||||
320 | my @thRows; | ||||
321 | my $inFoot = 1; | ||||
322 | my $footLines = 0; | ||||
323 | my $headLines = 0; | ||||
324 | |||||
325 | while ( $i >= 0 && $lines->[$i] ne $TABLEMARKER ) { | ||||
326 | if ( $lines->[$i] =~ /^\s*$/ ) { | ||||
327 | |||||
328 | # Remove blank lines in tables; they generate spurious <p>'s | ||||
329 | splice( @$lines, $i, 1 ); | ||||
330 | } | ||||
331 | elsif ( $lines->[$i] =~ s/$TRMARK=(["'])(.*?)\1//i ) { | ||||
332 | if ($2) { | ||||
333 | |||||
334 | # In head or foot | ||||
335 | if ($inFoot) { | ||||
336 | |||||
337 | #print STDERR "FOOT: $lines->[$i]\n"; | ||||
338 | $footLines++; | ||||
339 | } | ||||
340 | else { | ||||
341 | |||||
342 | #print STDERR "HEAD: $lines->[$i]\n"; | ||||
343 | $headLines++; | ||||
344 | } | ||||
345 | } | ||||
346 | else { | ||||
347 | |||||
348 | # In body | ||||
349 | #print STDERR "BODY: $lines->[$i]\n"; | ||||
350 | $inFoot = 0; | ||||
351 | $headLines = 0; | ||||
352 | } | ||||
353 | } | ||||
354 | $i--; | ||||
355 | } | ||||
356 | $lines->[ $i++ ] = CGI::start_table( | ||||
357 | { | ||||
358 | class => 'foswikiTable', | ||||
359 | border => 1, | ||||
360 | cellspacing => 0, | ||||
361 | cellpadding => 0 | ||||
362 | } | ||||
363 | ); | ||||
364 | |||||
365 | if ($headLines) { | ||||
366 | splice( @$lines, $i++, 0, '<thead>' ); | ||||
367 | splice( @$lines, $i + $headLines, 0, '</thead>' ); | ||||
368 | $i += $headLines + 1; | ||||
369 | } | ||||
370 | |||||
371 | if ($footLines) { | ||||
372 | |||||
373 | # Extract the foot and stick it in the table after the head (if any) | ||||
374 | # WRC says browsers prefer this | ||||
375 | my $firstFoot = scalar(@$lines) - $footLines; | ||||
376 | my @foot = splice( @$lines, $firstFoot, $footLines ); | ||||
377 | unshift( @foot, '<tfoot>' ); | ||||
378 | push( @foot, '</tfoot>' ); | ||||
379 | splice( @$lines, $i, 0, @foot ); | ||||
380 | $i += scalar(@foot); | ||||
381 | } | ||||
382 | splice( @$lines, $i, 0, '<tbody>' ); | ||||
383 | push( @$lines, '</tbody>' ); | ||||
384 | } | ||||
385 | |||||
386 | sub _emitTR { | ||||
387 | my ( $this, $row ) = @_; | ||||
388 | |||||
389 | $row =~ s/\t/ /g; # change tabs to space | ||||
390 | $row =~ s/\s*$//; # remove trailing spaces | ||||
391 | # calc COLSPAN | ||||
392 | $row =~ s/(\|\|+)/ | ||||
393 | 'colspan'.$REMARKER.length($1).'|'/ge; | ||||
394 | my $cells = ''; | ||||
395 | my $containsTableHeader; | ||||
396 | my $isAllTH = 1; | ||||
397 | foreach ( split( /\|/, $row ) ) { | ||||
398 | my %attr; | ||||
399 | |||||
400 | # Avoid matching single columns | ||||
401 | if (s/colspan$REMARKER([0-9]+)//o) { | ||||
402 | $attr{colspan} = $1; | ||||
403 | } | ||||
404 | s/^\s+$/ /; | ||||
405 | my ( $l1, $l2 ) = ( 0, 0 ); | ||||
406 | if (/^(\s*).*?(\s*)$/) { | ||||
407 | $l1 = length($1); | ||||
408 | $l2 = length($2); | ||||
409 | } | ||||
410 | if ( $l1 >= 2 ) { | ||||
411 | if ( $l2 <= 1 ) { | ||||
412 | $attr{align} = 'right'; | ||||
413 | } | ||||
414 | else { | ||||
415 | $attr{align} = 'center'; | ||||
416 | } | ||||
417 | } | ||||
418 | |||||
419 | # implicit untaint is OK, because we are just taking topic data | ||||
420 | # and rendering it; no security step is bypassed. | ||||
421 | if (/^\s*\*(.*)\*\s*$/) { | ||||
422 | $cells .= CGI::th( \%attr, CGI::strong( {}, " $1 " ) ) . "\n"; | ||||
423 | } | ||||
424 | else { | ||||
425 | $cells .= CGI::td( \%attr, " $_ " ) . "\n"; | ||||
426 | $isAllTH = 0; | ||||
427 | } | ||||
428 | } | ||||
429 | return CGI::Tr( { $TRMARK => $isAllTH }, $cells ); | ||||
430 | } | ||||
431 | |||||
432 | # spent 593µs (68+525) within Foswiki::Render::_fixedFontText which was called:
# once (68µs+525µs) by Foswiki::Render::getRenderedVersion at line 1388 | ||||
433 | 5 | 66µs | my ( $text, $embolden ) = @_; | ||
434 | |||||
435 | # preserve white space, so replace it by ' ' patterns | ||||
436 | 1 | 4µs | $text =~ s/\t/ /g; # spent 4µs making 1 call to Foswiki::Render::CORE:subst | ||
437 | 1 | 6µs | $text =~ s|((?:[\s]{2})+)([^\s])|' ' x (length($1) / 2) . $2|eg; # spent 6µs making 1 call to Foswiki::Render::CORE:subst | ||
438 | $text = CGI->b($text) if $embolden; | ||||
439 | 1 | 474µs | return CGI->code($text); # spent 474µs making 1 call to CGI::AUTOLOAD | ||
440 | } | ||||
441 | |||||
442 | # Build an HTML <Hn> element with suitable anchor for linking | ||||
443 | # from %<nop>TOC% | ||||
444 | # spent 2.41ms (166µs+2.25) within Foswiki::Render::_makeAnchorHeading which was called 6 times, avg 402µs/call:
# 6 times (166µs+2.25ms) by Foswiki::Render::getRenderedVersion at line 1251, avg 402µs/call | ||||
445 | 24 | 212µs | my ( $this, $text, $level, $anchors ) = @_; | ||
446 | |||||
447 | # - Build '<nop><h1><a name='atext'></a> heading </h1>' markup | ||||
448 | # - Initial '<nop>' is needed to prevent subsequent matches. | ||||
449 | # filter '!!', '%NOTOC%' | ||||
450 | 12 | 48µs | $text =~ s/$Foswiki::regex{headerPatternNoTOC}//o; # spent 27µs making 6 calls to Foswiki::Render::CORE:regcomp, avg 5µs/call
# spent 21µs making 6 calls to Foswiki::Render::CORE:subst, avg 4µs/call | ||
451 | |||||
452 | 6 | 2.20ms | my $html = # spent 2.20ms making 6 calls to Foswiki::Render::Anchors::makeHTMLTarget, avg 366µs/call | ||
453 | '<nop><h' | ||||
454 | . $level . '>' | ||||
455 | . $anchors->makeHTMLTarget($text) . ' ' | ||||
456 | . $text . ' </h' | ||||
457 | . $level . '>'; | ||||
458 | |||||
459 | return $html; | ||||
460 | } | ||||
461 | |||||
462 | # Returns =title='...'= tooltip info if the LINKTOOLTIPINFO preference | ||||
463 | # is set. Warning: Slower performance if enabled. | ||||
464 | # spent 966µs (684+283) within Foswiki::Render::_linkToolTipInfo which was called 50 times, avg 19µs/call:
# 50 times (684µs+283µs) by Foswiki::Render::_renderExistingWikiWord at line 683, avg 19µs/call | ||||
465 | 202 | 869µs | my ( $this, $web, $topic ) = @_; | ||
466 | unless ( defined( $this->{LINKTOOLTIPINFO} ) ) { | ||||
467 | 1 | 140µs | $this->{LINKTOOLTIPINFO} = # spent 140µs making 1 call to Foswiki::Prefs::getPreference | ||
468 | $this->{session}->{prefs}->getPreference('LINKTOOLTIPINFO') | ||||
469 | || ''; | ||||
470 | $this->{LINKTOOLTIPINFO} = '$username - $date - r$rev: $summary' | ||||
471 | if ( 'on' eq lc( $this->{LINKTOOLTIPINFO} ) ); | ||||
472 | } | ||||
473 | return '' unless ( $this->{LINKTOOLTIPINFO} ); | ||||
474 | 50 | 142µs | return '' if ( $this->{LINKTOOLTIPINFO} =~ /^off$/i ); # spent 142µs making 50 calls to Foswiki::Render::CORE:match, avg 3µs/call | ||
475 | return '' unless ( $this->{session}->inContext('view') ); | ||||
476 | |||||
477 | # These are safe to untaint blindly because this method is only | ||||
478 | # called when a regex matches a valid wikiword | ||||
479 | $web = Foswiki::Sandbox::untaintUnchecked($web); | ||||
480 | $topic = Foswiki::Sandbox::untaintUnchecked($topic); | ||||
481 | |||||
482 | # FIXME: This is slow, it can be improved by caching topic rev | ||||
483 | # info and summary | ||||
484 | my $users = $this->{session}->{users}; | ||||
485 | |||||
486 | my $topicObject = Foswiki::Meta->new( $this->{session}, $web, $topic ); | ||||
487 | my $info = $topicObject->getRevisionInfo(); | ||||
488 | my $tooltip = $this->{LINKTOOLTIPINFO}; | ||||
489 | $tooltip =~ s/\$web/<nop>$web/g; | ||||
490 | $tooltip =~ s/\$topic/<nop>$topic/g; | ||||
491 | $tooltip =~ s/\$rev/1.$info->{version}/g; | ||||
492 | $tooltip =~ s/\$date/Foswiki::Time::formatTime( $info->{date} )/ge; | ||||
493 | $tooltip =~ s/\$username/ | ||||
494 | $users->getLoginName($info->{author}) || $info->{author}/ge; | ||||
495 | $tooltip =~ s/\$wikiname/ | ||||
496 | $users->getWikiName($info->{author}) || $info->{author}/ge; | ||||
497 | $tooltip =~ s/\$wikiusername/ | ||||
498 | $users->webDotWikiName($info->{author}) || $info->{author}/ge; | ||||
499 | |||||
500 | if ( $tooltip =~ /\$summary/ ) { | ||||
501 | my $summary; | ||||
502 | if ( $topicObject->haveAccess('VIEW') ) { | ||||
503 | $summary = $topicObject->text || ''; | ||||
504 | } | ||||
505 | else { | ||||
506 | $summary = | ||||
507 | $this->{session} | ||||
508 | ->inlineAlert( 'alerts', 'access_denied', "$web.$topic" ); | ||||
509 | } | ||||
510 | $summary = $topicObject->summariseText(); | ||||
511 | $summary =~ | ||||
512 | s/[\"\']//g; # remove quotes (not allowed in title attribute) | ||||
513 | $tooltip =~ s/\$summary/$summary/g; | ||||
514 | } | ||||
515 | return $tooltip; | ||||
516 | } | ||||
517 | |||||
518 | =begin TML | ||||
519 | |||||
520 | ---++ ObjectMethod internalLink ( $web, $topic, $linkText, $anchor, $linkIfAbsent, $keepWebPrefix, $hasExplicitLinkLabel ) -> $html | ||||
521 | |||||
522 | Generate a link. | ||||
523 | |||||
524 | Note: Topic names may be spaced out. Spaced out names are converted | ||||
525 | to <nop>WikWords, for example, "spaced topic name" points to "SpacedTopicName". | ||||
526 | * =$web= - the web containing the topic | ||||
527 | * =$topic= - the topic to be link | ||||
528 | * =$linkText= - text to use for the link | ||||
529 | * =$anchor= - the link anchor, if any | ||||
530 | * =$linkIfAbsent= - boolean: false means suppress link for | ||||
531 | non-existing pages | ||||
532 | * =$keepWebPrefix= - boolean: true to keep web prefix (for | ||||
533 | non existing Web.TOPIC) | ||||
534 | * =$hasExplicitLinkLabel= - boolean: true if | ||||
535 | [[link][explicit link label]] | ||||
536 | |||||
537 | Called from outside the package by Func::internalLink | ||||
538 | |||||
539 | Calls _renderWikiWord, which in turn will use Plurals.pm to match fold | ||||
540 | plurals to equivalency with their singular form | ||||
541 | |||||
542 | SMELL: why is this available to Func? | ||||
543 | |||||
544 | =cut | ||||
545 | |||||
546 | sub internalLink { | ||||
547 | 866 | 5.57ms | my ( $this, $web, $topic, $linkText, $anchor, $linkIfAbsent, $keepWebPrefix, | ||
548 | $hasExplicitLinkLabel, $params ) | ||||
549 | = @_; | ||||
550 | |||||
551 | # SMELL - shouldn't it be callable by Foswiki::Func as well? | ||||
552 | |||||
553 | #PN: Webname/Subweb/ -> Webname/Subweb | ||||
554 | 72 | 121µs | $web =~ s/\/\Z//o; # spent 121µs making 72 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
555 | |||||
556 | if ( $linkText eq $web ) { | ||||
557 | 2 | 3µs | $linkText =~ s/\//\./go; # spent 3µs making 2 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
558 | } | ||||
559 | |||||
560 | #WebHome links to tother webs render as the WebName | ||||
561 | if ( ( $linkText eq $Foswiki::cfg{HomeTopicName} ) | ||||
562 | && ( $web ne $this->{session}->{webName} ) ) | ||||
563 | { | ||||
564 | $linkText = $web; | ||||
565 | } | ||||
566 | |||||
567 | # Get rid of leading/trailing spaces in topic name | ||||
568 | 72 | 203µs | $topic =~ s/^\s*//o; # spent 203µs making 72 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
569 | 72 | 324µs | $topic =~ s/\s*$//o; # spent 324µs making 72 calls to Foswiki::Render::CORE:subst, avg 5µs/call | ||
570 | |||||
571 | # Allow spacing out, etc. | ||||
572 | # Plugin authors use $hasExplicitLinkLabel to determine if the link label | ||||
573 | # should be rendered differently even if the topic author has used a | ||||
574 | # specific link label. | ||||
575 | 72 | 1.01ms | $linkText = # spent 1.01ms making 72 calls to Foswiki::Plugins::dispatch, avg 14µs/call | ||
576 | $this->{session}->{plugins} | ||||
577 | ->dispatch( 'renderWikiWordHandler', $linkText, $hasExplicitLinkLabel, | ||||
578 | $web, $topic ) | ||||
579 | || $linkText; | ||||
580 | |||||
581 | # Turn spaced-out names into WikiWords - upper case first letter of | ||||
582 | # whole link, and first of each word. TODO: Try to turn this off, | ||||
583 | # avoiding spaces being stripped elsewhere | ||||
584 | $topic = ucfirst($topic); | ||||
585 | 144 | 235µs | $topic =~ s/\s([$Foswiki::regex{mixedAlphaNum}])/\U$1/go; # spent 131µs making 72 calls to Foswiki::Render::CORE:subst, avg 2µs/call
# spent 104µs making 72 calls to Foswiki::Render::CORE:regcomp, avg 1µs/call | ||
586 | |||||
587 | # If locales are in effect, the above conversions will taint the topic | ||||
588 | # name (Foswiki:Tasks:Item2091) | ||||
589 | 72 | 1.12ms | $topic = Foswiki::Sandbox::untaintUnchecked($topic); # spent 1.12ms making 72 calls to Foswiki::Sandbox::untaintUnchecked, avg 16µs/call | ||
590 | |||||
591 | # Add <nop> before WikiWord inside link text to prevent double links | ||||
592 | 182 | 552µs | $linkText =~ s/(?<=[\s\(])([$Foswiki::regex{upperAlpha}])/<nop>$1/go; # spent 325µs making 72 calls to Foswiki::Render::CORE:subst, avg 5µs/call
# spent 121µs making 38 calls to Foswiki::Render::CORE:substcont, avg 3µs/call
# spent 105µs making 72 calls to Foswiki::Render::CORE:regcomp, avg 1µs/call | ||
593 | 72 | 42.0ms | return _renderWikiWord( $this, $web, $topic, $linkText, $anchor, # spent 42.0ms making 72 calls to Foswiki::Render::_renderWikiWord, avg 583µs/call | ||
594 | $linkIfAbsent, $keepWebPrefix, $params ); | ||||
595 | } | ||||
596 | |||||
597 | # TODO: this should be overridable by plugins. | ||||
598 | # spent 42.0ms (2.61+39.4) within Foswiki::Render::_renderWikiWord which was called 72 times, avg 583µs/call:
# 72 times (2.61ms+39.4ms) by Foswiki::Render::internalLink at line 593, avg 583µs/call | ||||
599 | 666 | 2.13ms | my ( $this, $web, $topic, $linkText, $anchor, $linkIfAbsent, $keepWebPrefix, | ||
600 | $params ) | ||||
601 | = @_; | ||||
602 | my $session = $this->{session}; | ||||
603 | 72 | 11.5ms | my $topicExists = $session->topicExists( $web, $topic ); # spent 11.5ms making 72 calls to Foswiki::topicExists, avg 159µs/call | ||
604 | |||||
605 | my $singular = ''; | ||||
606 | unless ($topicExists) { | ||||
607 | |||||
608 | # topic not found - try to singularise | ||||
609 | require Foswiki::Plurals; | ||||
610 | 22 | 519µs | $singular = Foswiki::Plurals::singularForm( $web, $topic ); # spent 519µs making 22 calls to Foswiki::Plurals::singularForm, avg 24µs/call | ||
611 | if ($singular) { | ||||
612 | 1 | 163µs | $topicExists = $session->topicExists( $web, $singular ); # spent 163µs making 1 call to Foswiki::topicExists | ||
613 | $topic = $singular if $topicExists; | ||||
614 | } | ||||
615 | } | ||||
616 | |||||
617 | if ($topicExists) { | ||||
618 | |||||
619 | # add a dependency so that the page gets invalidated as soon as the | ||||
620 | # topic is deleted | ||||
621 | $this->{session}->{cache}->addDependency( $web, $topic ) | ||||
622 | if $Foswiki::cfg{Cache}{Enabled}; | ||||
623 | |||||
624 | 50 | 16.7ms | return _renderExistingWikiWord( $this, $web, $topic, $linkText, $anchor, # spent 16.7ms making 50 calls to Foswiki::Render::_renderExistingWikiWord, avg 335µs/call | ||
625 | $params ); | ||||
626 | } | ||||
627 | if ($linkIfAbsent) { | ||||
628 | |||||
629 | # CDot: disabled until SuggestSingularNotPlural is resolved | ||||
630 | # if ($singular && $singular ne $topic) { | ||||
631 | # #unshift( @topics, $singular); | ||||
632 | # } | ||||
633 | |||||
634 | # add a dependency so that the page gets invalidated as soon as the | ||||
635 | # WikiWord comes into existance | ||||
636 | # Note we *ignore* the params if the target topic does not exist | ||||
637 | $this->{session}->{cache}->addDependency( $web, $topic ) | ||||
638 | if $Foswiki::cfg{Cache}{Enabled}; | ||||
639 | |||||
640 | 4 | 10.3ms | return _renderNonExistingWikiWord( $this, $web, $topic, $linkText ); # spent 10.3ms making 4 calls to Foswiki::Render::_renderNonExistingWikiWord, avg 2.57ms/call | ||
641 | } | ||||
642 | if ($keepWebPrefix) { | ||||
643 | return $web . '.' . $linkText; | ||||
644 | } | ||||
645 | |||||
646 | return $linkText; | ||||
647 | } | ||||
648 | |||||
649 | # spent 16.7ms (2.46+14.3) within Foswiki::Render::_renderExistingWikiWord which was called 50 times, avg 335µs/call:
# 50 times (2.46ms+14.3ms) by Foswiki::Render::_renderWikiWord at line 624, avg 335µs/call | ||||
650 | 800 | 2.42ms | my ( $this, $web, $topic, $text, $anchor, $params ) = @_; | ||
651 | |||||
652 | my @cssClasses; | ||||
653 | push( @cssClasses, 'foswikiCurrentWebHomeLink' ) | ||||
654 | if ( ( $web eq $this->{session}->{webName} ) | ||||
655 | && ( $topic eq $Foswiki::cfg{HomeTopicName} ) ); | ||||
656 | |||||
657 | my $inCurrentTopic = 0; | ||||
658 | |||||
659 | if ( ( $web eq $this->{session}->{webName} ) | ||||
660 | && ( $topic eq $this->{session}->{topicName} ) ) | ||||
661 | { | ||||
662 | push( @cssClasses, 'foswikiCurrentTopicLink' ); | ||||
663 | $inCurrentTopic = 1; | ||||
664 | } | ||||
665 | |||||
666 | my %attrs; | ||||
667 | 50 | 6.90ms | my $href = $this->{session}->getScriptUrl( 0, 'view', $web, $topic ); # spent 6.90ms making 50 calls to Foswiki::getScriptUrl, avg 138µs/call | ||
668 | if ($params) { | ||||
669 | $href .= $params; | ||||
670 | } | ||||
671 | |||||
672 | if ($anchor) { | ||||
673 | $anchor = Foswiki::Render::Anchors::make($anchor); | ||||
674 | $anchor = Foswiki::urlEncode($anchor); | ||||
675 | |||||
676 | # No point in trying to make it unique; just aim at the first | ||||
677 | # occurrence | ||||
678 | # Item8556 - drop path if same topic | ||||
679 | $href = $inCurrentTopic ? "#$anchor" : "$href#$anchor"; | ||||
680 | } | ||||
681 | $attrs{class} = join( ' ', @cssClasses ) if ( $#cssClasses >= 0 ); | ||||
682 | $attrs{href} = $href; | ||||
683 | 50 | 966µs | my $tooltip = _linkToolTipInfo( $this, $web, $topic ); # spent 966µs making 50 calls to Foswiki::Render::_linkToolTipInfo, avg 19µs/call | ||
684 | $attrs{title} = $tooltip if $tooltip; | ||||
685 | |||||
686 | 50 | 6.33ms | my $link = CGI::a( \%attrs, $text ); # spent 6.33ms making 50 calls to CGI::a, avg 127µs/call | ||
687 | |||||
688 | # When we pass the tooltip text to CGI::a it may contain | ||||
689 | # <nop>s, and CGI::a will convert the < to <. This is a | ||||
690 | # basic problem with <nop>. | ||||
691 | 50 | 89µs | $link =~ s/<nop>/<nop>/g; # spent 89µs making 50 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
692 | return $link; | ||||
693 | } | ||||
694 | |||||
695 | # spent 10.3ms (217µs+10.1) within Foswiki::Render::_renderNonExistingWikiWord which was called 4 times, avg 2.57ms/call:
# 4 times (217µs+10.1ms) by Foswiki::Render::_renderWikiWord at line 640, avg 2.57ms/call | ||||
696 | 28 | 268µs | my ( $this, $web, $topic, $text ) = @_; | ||
697 | |||||
698 | 4 | 182µs | my $ans = $this->_newLinkFormat; # spent 182µs making 4 calls to Foswiki::Render::_newLinkFormat, avg 46µs/call | ||
699 | 4 | 32µs | $ans =~ s/\$web/$web/g; # spent 32µs making 4 calls to Foswiki::Render::CORE:subst, avg 8µs/call | ||
700 | 4 | 21µs | $ans =~ s/\$topic/$topic/g; # spent 21µs making 4 calls to Foswiki::Render::CORE:subst, avg 5µs/call | ||
701 | 4 | 18µs | $ans =~ s/\$text/$text/g; # spent 18µs making 4 calls to Foswiki::Render::CORE:subst, avg 4µs/call | ||
702 | 4 | 238µs | my $topicObject = Foswiki::Meta->new( # spent 238µs making 4 calls to Foswiki::Meta::new, avg 59µs/call | ||
703 | $this->{session}, | ||||
704 | $this->{session}->{webName}, | ||||
705 | $this->{session}->{topicName} | ||||
706 | ); | ||||
707 | 4 | 9.57ms | return $topicObject->expandMacros($ans); # spent 9.57ms making 4 calls to Foswiki::Meta::expandMacros, avg 2.39ms/call | ||
708 | } | ||||
709 | |||||
710 | # _handleWikiWord is called for a wiki word that needs linking. | ||||
711 | # Handle the various link constructions. e.g.: | ||||
712 | # WikiWord | ||||
713 | # Web.WikiWord | ||||
714 | # Web.WikiWord#anchor | ||||
715 | # | ||||
716 | # This routine adds missing parameters before passing off to internallink | ||||
717 | # spent 30.0ms (2.19+27.8) within Foswiki::Render::_handleWikiWord which was called 40 times, avg 749µs/call:
# 40 times (2.19ms+27.8ms) by Foswiki::Render::getRenderedVersion at line 1415, avg 749µs/call | ||||
718 | 520 | 2.42ms | my ( $this, $topicObject, $web, $topic, $anchor ) = @_; | ||
719 | |||||
720 | my $linkIfAbsent = 1; | ||||
721 | my $keepWeb = 0; | ||||
722 | my $text; | ||||
723 | |||||
724 | # For some strange reason, $web doesn't get untainted by the regex | ||||
725 | # that invokes this function. We can untaint it safely, because it's | ||||
726 | # validated by the RE. | ||||
727 | 40 | 339µs | $web = Foswiki::Sandbox::untaintUnchecked($web); # spent 339µs making 40 calls to Foswiki::Sandbox::untaintUnchecked, avg 8µs/call | ||
728 | |||||
729 | 33 | 246µs | $web = $topicObject->web() unless ( defined($web) ); # spent 246µs making 33 calls to Foswiki::Meta::web, avg 7µs/call | ||
730 | if ( defined($anchor) ) { | ||||
731 | ASSERT( ( $anchor =~ m/\#.*/ ) ) if DEBUG; # must include a hash. | ||||
732 | } | ||||
733 | else { | ||||
734 | $anchor = ''; | ||||
735 | } | ||||
736 | |||||
737 | if ( defined($anchor) ) { | ||||
738 | |||||
739 | # 'Web.TopicName#anchor' or 'Web.ABBREV#anchor' link | ||||
740 | $text = $topic . $anchor; | ||||
741 | } | ||||
742 | else { | ||||
743 | $anchor = ''; | ||||
744 | |||||
745 | # 'Web.TopicName' or 'Web.ABBREV' link: | ||||
746 | if ( $topic eq $Foswiki::cfg{HomeTopicName} | ||||
747 | && $web ne $this->{session}->{webName} ) | ||||
748 | { | ||||
749 | $text = $web; | ||||
750 | } | ||||
751 | else { | ||||
752 | $text = $topic; | ||||
753 | } | ||||
754 | } | ||||
755 | |||||
756 | # true to keep web prefix for non-existing Web.TOPIC | ||||
757 | # Have to leave "web part" of ABR.ABR.ABR intact if topic not found | ||||
758 | 80 | 210µs | $keepWeb = # spent 140µs making 40 calls to Foswiki::Render::CORE:match, avg 3µs/call
# spent 71µs making 40 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
759 | ( $topic =~ /^$Foswiki::regex{abbrevRegex}$/o | ||||
760 | && $web ne $this->{session}->{webName} ); | ||||
761 | |||||
762 | # false means suppress link for non-existing pages | ||||
763 | 80 | 157µs | $linkIfAbsent = ( $topic !~ /^$Foswiki::regex{abbrevRegex}$/o ); # spent 95µs making 40 calls to Foswiki::Render::CORE:match, avg 2µs/call
# spent 63µs making 40 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
764 | |||||
765 | 40 | 26.8ms | return $this->internalLink( $web, $topic, $text, $anchor, $linkIfAbsent, # spent 26.8ms making 40 calls to Foswiki::Render::internalLink, avg 671µs/call | ||
766 | $keepWeb, undef ); | ||||
767 | } | ||||
768 | |||||
769 | # Protect WikiWords, TLAs and URLs from further rendering with <nop> | ||||
770 | # spent 1.45ms (849µs+604µs) within Foswiki::Render::_escapeAutoLinks which was called 34 times, avg 43µs/call:
# 32 times (796µs+586µs) by Foswiki::Render::_handleSquareBracketedLink at line 812, avg 43µs/call
# 2 times (53µs+18µs) by Foswiki::Render::_handleSquareBracketedLink at line 846, avg 36µs/call | ||||
771 | 170 | 1.49ms | my $text = shift; | ||
772 | |||||
773 | if ($text) { | ||||
774 | |||||
775 | # WikiWords, TLAs, and email addresses | ||||
776 | 68 | 463µs | $text =~ s/(?<=[\s\(]) # spent 292µs making 34 calls to Foswiki::Render::CORE:subst, avg 9µs/call
# spent 171µs making 34 calls to Foswiki::Render::CORE:regcomp, avg 5µs/call | ||
777 | ( | ||||
778 | (?: | ||||
779 | (?:($Foswiki::regex{webNameRegex})\.)? | ||||
780 | (?: $Foswiki::regex{wikiWordRegex} | ||||
781 | | $Foswiki::regex{abbrevRegex} ) | ||||
782 | ) | ||||
783 | | $Foswiki::regex{emailAddrRegex} | ||||
784 | )/<nop>$1/gox; | ||||
785 | |||||
786 | # Explicit links | ||||
787 | 68 | 141µs | $text =~ s/($Foswiki::regex{linkProtocolPattern}):(?=\S)/$1<nop>:/go; # spent 86µs making 34 calls to Foswiki::Render::CORE:regcomp, avg 3µs/call
# spent 55µs making 34 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
788 | } | ||||
789 | return $text; | ||||
790 | } | ||||
791 | |||||
792 | # Handle SquareBracketed links mentioned on page $web.$topic | ||||
793 | # format: [[$link]] | ||||
794 | # format: [[$link][$text]] | ||||
795 | # spent 34.5ms (5.05+29.4) within Foswiki::Render::_handleSquareBracketedLink which was called 34 times, avg 1.01ms/call:
# 34 times (5.05ms+29.4ms) by Foswiki::Render::getRenderedVersion at line 1396, avg 1.01ms/call | ||||
796 | 976 | 6.34ms | my ( $this, $topicObject, $link, $text ) = @_; | ||
797 | |||||
798 | # Strip leading/trailing spaces | ||||
799 | 34 | 88µs | $link =~ s/^\s+//; # spent 88µs making 34 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
800 | 34 | 68µs | $link =~ s/\s+$//; # spent 68µs making 34 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
801 | |||||
802 | my $hasExplicitLinkLabel = 0; | ||||
803 | |||||
804 | if ( defined($text) ) { | ||||
805 | |||||
806 | # [[$link][$text]] | ||||
807 | $hasExplicitLinkLabel = 1; | ||||
808 | 32 | 980µs | if ( my $img = $this->_isImageLink($text) ) { # spent 980µs making 32 calls to Foswiki::Render::_isImageLink, avg 31µs/call | ||
809 | $text = $img; | ||||
810 | } | ||||
811 | else { | ||||
812 | 32 | 1.38ms | $text = _escapeAutoLinks($text); # spent 1.38ms making 32 calls to Foswiki::Render::_escapeAutoLinks, avg 43µs/call | ||
813 | } | ||||
814 | } | ||||
815 | |||||
816 | 68 | 192µs | if ( $link =~ m#^($Foswiki::regex{linkProtocolPattern}:|/)# ) { # spent 107µs making 34 calls to Foswiki::Render::CORE:regcomp, avg 3µs/call
# spent 85µs making 34 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
817 | |||||
818 | # Explicit external [[http://$link]] or [[http://$link][$text]] | ||||
819 | # or explicit absolute [[/$link]] or [[/$link][$text]] | ||||
820 | if ( !defined($text) && $link =~ /^(\S+)\s+(.*)$/ ) { | ||||
821 | |||||
822 | my $candidateLink = $1; | ||||
823 | my $candidateText = $2; | ||||
824 | |||||
825 | # If the URL portion contains a ? indicating query parameters then | ||||
826 | # the spaces are possibly embedded in the query string, so don't | ||||
827 | # use the legacy format. | ||||
828 | if ( $candidateLink !~ m/\?/ ) { | ||||
829 | |||||
830 | # Legacy case of '[[URL anchor display text]]' link | ||||
831 | # implicit untaint is OK as we are just recycling topic content | ||||
832 | $link = $candidateLink; | ||||
833 | $text = _escapeAutoLinks($candidateText); | ||||
834 | } | ||||
835 | } | ||||
836 | 2 | 77µs | return $this->_externalLink( $link, $text ); # spent 77µs making 2 calls to Foswiki::Render::_externalLink, avg 38µs/call | ||
837 | } | ||||
838 | |||||
839 | # Extract '?params' | ||||
840 | # $link =~ s/(\?.*?)(?>#|$)//; | ||||
841 | my $params = ''; | ||||
842 | 32 | 54µs | if ( $link =~ s/(\?.*$)// ) { # spent 54µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
843 | $params = $1; | ||||
844 | } | ||||
845 | |||||
846 | 2 | 71µs | $text = _escapeAutoLinks($link) unless defined $text; # spent 71µs making 2 calls to Foswiki::Render::_escapeAutoLinks, avg 36µs/call | ||
847 | 64 | 142µs | $text =~ s/${STARTWW}==(\S+?|\S[^\n]*?\S)==$ENDWW/_fixedFontText($1,1)/gem; # spent 95µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 3µs/call
# spent 47µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
848 | 64 | 124µs | $text =~ s/${STARTWW}__(\S+?|\S[^\n]*?\S) # spent 78µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 46µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
849 | __$ENDWW/<strong><em>$1<\/em><\/strong>/gmx; | ||||
850 | 64 | 121µs | $text =~ s/${STARTWW}\*(\S+?|\S[^\n]*?\S)\*$ENDWW/<strong>$1<\/strong>/gm; # spent 75µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 46µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
851 | 64 | 114µs | $text =~ s/${STARTWW}\_(\S+?|\S[^\n]*?\S)\_$ENDWW/<em>$1<\/em>/gm; # spent 72µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 43µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
852 | 64 | 114µs | $text =~ s/${STARTWW}\=(\S+?|\S[^\n]*?\S)\=$ENDWW/_fixedFontText($1,0)/gem; # spent 73µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 41µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
853 | |||||
854 | # Extract '#anchor' | ||||
855 | # $link =~ s/(\#[a-zA-Z_0-9\-]*$)//; | ||||
856 | my $anchor = ''; | ||||
857 | 64 | 115µs | if ( $link =~ s/($Foswiki::regex{anchorRegex}$)// ) { # spent 70µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 46µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
858 | $anchor = $1; | ||||
859 | |||||
860 | #$text =~ s/#$anchor//; | ||||
861 | } | ||||
862 | |||||
863 | # filter out &any; entities (legacy) | ||||
864 | 32 | 56µs | $link =~ s/\&[a-z]+\;//gi; # spent 56µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
865 | |||||
866 | # filter out { entities (legacy) | ||||
867 | 32 | 50µs | $link =~ s/\&\#[0-9]+\;//g; # spent 50µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
868 | |||||
869 | # Filter junk | ||||
870 | 64 | 119µs | $link =~ s/$Foswiki::cfg{NameFilter}+/ /g; # spent 67µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call
# spent 52µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
871 | |||||
872 | 32 | 139µs | ASSERT( UNTAINTED($link) ) if DEBUG; # spent 139µs making 32 calls to Assert::ASSERTS_OFF, avg 4µs/call | ||
873 | |||||
874 | # Capitalise first word | ||||
875 | $link = ucfirst($link); | ||||
876 | |||||
877 | # Collapse spaces and capitalise following letter | ||||
878 | 64 | 104µs | $link =~ s/\s([$Foswiki::regex{mixedAlphaNum}])/\U$1/go; # spent 54µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call
# spent 50µs making 32 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
879 | |||||
880 | # Get rid of remaining spaces, i.e. spaces in front of -'s and ('s | ||||
881 | 32 | 46µs | $link =~ s/\s//go; # spent 46µs making 32 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
882 | |||||
883 | # The link is used in the topic name, and if locales are in effect, | ||||
884 | # the above conversions will taint the name (Foswiki:Tasks:Item2091) | ||||
885 | 32 | 513µs | $link = Foswiki::Sandbox::untaintUnchecked($link); # spent 513µs making 32 calls to Foswiki::Sandbox::untaintUnchecked, avg 16µs/call | ||
886 | |||||
887 | $link ||= $topicObject->topic; | ||||
888 | |||||
889 | # Topic defaults to the current topic | ||||
890 | 64 | 1.74ms | my ( $web, $topic ) = # spent 1.50ms making 32 calls to Foswiki::normalizeWebTopicName, avg 47µs/call
# spent 240µs making 32 calls to Foswiki::Meta::web, avg 8µs/call | ||
891 | $this->{session}->normalizeWebTopicName( $topicObject->web, $link ); | ||||
892 | |||||
893 | 32 | 23.0ms | return $this->internalLink( $web, $topic, $text, $anchor, 1, undef, # spent 23.0ms making 32 calls to Foswiki::Render::internalLink, avg 720µs/call | ||
894 | $hasExplicitLinkLabel, $params ); | ||||
895 | } | ||||
896 | |||||
897 | # Check if text is an image # (as indicated by the file type) | ||||
898 | # return an img tag, otherwise nothing | ||||
899 | # spent 980µs (712+269) within Foswiki::Render::_isImageLink which was called 32 times, avg 31µs/call:
# 32 times (712µs+269µs) by Foswiki::Render::_handleSquareBracketedLink at line 808, avg 31µs/call | ||||
900 | 192 | 1.01ms | my ( $this, $url ) = @_; | ||
901 | |||||
902 | 32 | 62µs | return if $url =~ /<nop>/; # spent 62µs making 32 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
903 | 32 | 72µs | $url =~ s/^\s+//; # spent 72µs making 32 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
904 | 32 | 84µs | $url =~ s/\s+$//; # spent 84µs making 32 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
905 | 32 | 51µs | if ( $url =~ m#^https?://[^?]*\.(?:gif|jpg|jpeg|png)$#i ) { # spent 51µs making 32 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
906 | my $filename = $url; | ||||
907 | $filename =~ s@.*/@@; | ||||
908 | return CGI::img( { src => $url, alt => $filename } ); | ||||
909 | } | ||||
910 | return; | ||||
911 | } | ||||
912 | |||||
913 | # Handle an external link typed directly into text. If it's an image | ||||
914 | # and no text is specified, then use an img tag, otherwise generate a link. | ||||
915 | # spent 77µs (63+14) within Foswiki::Render::_externalLink which was called 2 times, avg 38µs/call:
# 2 times (63µs+14µs) by Foswiki::Render::_handleSquareBracketedLink at line 836, avg 38µs/call | ||||
916 | 16 | 83µs | my ( $this, $url, $text ) = @_; | ||
917 | |||||
918 | if ( !$text && ( my $img = $this->_isImageLink($url) ) ) { | ||||
919 | return $img; | ||||
920 | } | ||||
921 | my $opt = ''; | ||||
922 | 2 | 10µs | if ( $url =~ /^mailto:/i ) { # spent 10µs making 2 calls to Foswiki::Render::CORE:match, avg 5µs/call | ||
923 | if ( $Foswiki::cfg{AntiSpam}{EmailPadding} ) { | ||||
924 | $url =~ s/(\@[\w\_\-\+]+)(\.) | ||||
925 | /$1$Foswiki::cfg{AntiSpam}{EmailPadding}$2/x; | ||||
926 | if ($text) { | ||||
927 | $text =~ s/(\@[\w\_\-\+]+)(\.) | ||||
928 | /$1$Foswiki::cfg{AntiSpam}{EmailPadding}$2/x; | ||||
929 | } | ||||
930 | } | ||||
931 | if ( $Foswiki::cfg{AntiSpam}{EntityEncode} ) { | ||||
932 | |||||
933 | # Much harder obfuscation scheme. For link text we only encode '@' | ||||
934 | # See also http://develop.twiki.org/~twiki4/cgi-bin/view/Bugs/Item2928 | ||||
935 | # and http://develop.twiki.org/~twiki4/cgi-bin/view/Bugs/Item3430 | ||||
936 | # before touching this | ||||
937 | # Note: & is already encoded, so don't encode any entities | ||||
938 | # See http://foswiki.org/Tasks/Item10905 | ||||
939 | $url =~ s/&(\w+);/$REMARKER$1$REEND/g; # "&abc;" | ||||
940 | $url =~ s/&(#x?[0-9a-f]+);/$REMARKER$1$REEND/gi; # "{" | ||||
941 | $url =~ s/([^\w$REMARKER$REEND])/'&#'.ord($1).';'/ge; | ||||
942 | $url =~ s/$REMARKER(#x?[0-9a-f]+)$REEND/&$1;/goi; | ||||
943 | $url =~ s/$REMARKER(\w+)$REEND/&$1;/go; | ||||
944 | if ($text) { | ||||
945 | $text =~ s/\@/'&#'.ord('@').';'/ge; | ||||
946 | } | ||||
947 | } | ||||
948 | } | ||||
949 | else { | ||||
950 | $opt = ' target="_top"'; | ||||
951 | } | ||||
952 | $text ||= $url; | ||||
953 | |||||
954 | # Item5787: if a URL has spaces, escape them so the URL has less | ||||
955 | # chance of being broken by later rendering. | ||||
956 | 2 | 4µs | $url =~ s/ /%20/g; # spent 4µs making 2 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
957 | |||||
958 | # SMELL: Can't use CGI::a here, because it encodes ampersands in | ||||
959 | # the link, and those have already been encoded once in the | ||||
960 | # rendering loop (they are identified as "stand-alone"). One | ||||
961 | # encoding works; two is too many. None would be better for everyone! | ||||
962 | return '<a href="' . $url . '"' . $opt . '>' . $text . '</a>'; | ||||
963 | } | ||||
964 | |||||
965 | # Generate a "mailTo" link | ||||
966 | sub _mailLink { | ||||
967 | my ( $this, $text ) = @_; | ||||
968 | |||||
969 | my $url = $text; | ||||
970 | return $text if $url =~ /^(?:!|\<nop\>)/; | ||||
971 | |||||
972 | #use Email::Valid (); | ||||
973 | #my $tmpEmail = $url; | ||||
974 | #$tmpEmail =~ s/^mailto://; | ||||
975 | #my $errtxt = ''; | ||||
976 | #$errtxt = "<b>INVALID</b> $tmpEmail " unless (Email::Valid->address($tmpEmail)); | ||||
977 | |||||
978 | # Any special characters in the user portion must be %hex escaped. | ||||
979 | $url =~ s/^((?:mailto\:)?)?(.*?)(@.*?)$/'mailto:'._escape( $2 ).$3/msiex; | ||||
980 | my $lenLeft = length($2); | ||||
981 | my $lenRight = length($3); | ||||
982 | |||||
983 | # Per RFC 3696 Errata, length restricted to 254 overall per RFC 2821 RCPT limits | ||||
984 | return $text | ||||
985 | if ( $lenLeft > 64 || $lenRight > 254 || $lenLeft + $lenRight > 254 ); | ||||
986 | |||||
987 | $url = 'mailto:' . $url unless $url =~ /^mailto:/i; | ||||
988 | return _externalLink( $this, $url, $text ); | ||||
989 | } | ||||
990 | |||||
991 | sub _escape { | ||||
992 | my $txt = shift; | ||||
993 | |||||
994 | my $chars = join( '', keys(%ESCAPED) ); | ||||
995 | $txt =~ s/([$chars])/$ESCAPED{$1}/g; | ||||
996 | $txt =~ s/[\s]/%20/g; # Any folding white space | ||||
997 | return $txt; | ||||
998 | } | ||||
999 | |||||
1000 | =begin TML | ||||
1001 | |||||
1002 | ---++ ObjectMethod renderFORMFIELD ( %params, $topic, $web ) -> $html | ||||
1003 | |||||
1004 | Returns the fully rendered expansion of a %FORMFIELD{}% tag. | ||||
1005 | |||||
1006 | =cut | ||||
1007 | |||||
1008 | # spent 9.48ms (899µs+8.58) within Foswiki::Render::renderFORMFIELD which was called 7 times, avg 1.35ms/call:
# 7 times (899µs+8.58ms) by Foswiki::FORMFIELD at line 22 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/FORMFIELD.pm, avg 1.35ms/call | ||||
1009 | 323 | 947µs | my ( $this, $params, $topicObject ) = @_; | ||
1010 | |||||
1011 | my $formField = $params->{_DEFAULT}; | ||||
1012 | return '' unless defined $formField; | ||||
1013 | my $altText = $params->{alttext}; | ||||
1014 | my $default = $params->{default}; | ||||
1015 | my $rev = $params->{rev} || ''; | ||||
1016 | my $format = $params->{format}; | ||||
1017 | |||||
1018 | $altText = '' unless defined $altText; | ||||
1019 | $default = '' unless defined $default; | ||||
1020 | |||||
1021 | unless ( defined $format ) { | ||||
1022 | $format = '$value'; | ||||
1023 | } | ||||
1024 | |||||
1025 | # SMELL: this local creation of a cache looks very suspicious. Suspect | ||||
1026 | # this may have been a one-off optimisation. | ||||
1027 | 7 | 85µs | my $formTopicObject = $this->{ffCache}{ $topicObject->getPath() . $rev }; # spent 85µs making 7 calls to Foswiki::Meta::getPath, avg 12µs/call | ||
1028 | unless ($formTopicObject) { | ||||
1029 | 3 | 5.99ms | $formTopicObject = # spent 5.97ms making 1 call to Foswiki::Meta::load
# spent 9µs making 1 call to Foswiki::Meta::web
# spent 8µs making 1 call to Foswiki::Meta::topic | ||
1030 | Foswiki::Meta->load( $this->{session}, $topicObject->web, | ||||
1031 | $topicObject->topic, $rev ); | ||||
1032 | 1 | 1.72ms | unless ( $formTopicObject->haveAccess('VIEW') ) { # spent 1.72ms making 1 call to Foswiki::Meta::haveAccess | ||
1033 | |||||
1034 | # Access violation, create dummy meta with empty text, so | ||||
1035 | # it looks like it was already loaded. | ||||
1036 | $formTopicObject = | ||||
1037 | Foswiki::Meta->new( $this->{session}, $topicObject->web, | ||||
1038 | $topicObject->topic, '' ); | ||||
1039 | } | ||||
1040 | 1 | 11µs | $this->{ffCache}{ $formTopicObject->getPath() . $rev } = # spent 11µs making 1 call to Foswiki::Meta::getPath | ||
1041 | $formTopicObject; | ||||
1042 | } | ||||
1043 | |||||
1044 | my $text = $format; | ||||
1045 | my $found = 0; | ||||
1046 | my $title = ''; | ||||
1047 | 7 | 184µs | my @fields = $formTopicObject->find('FIELD'); # spent 184µs making 7 calls to Foswiki::Meta::find, avg 26µs/call | ||
1048 | foreach my $field (@fields) { | ||||
1049 | my $name = $field->{name}; | ||||
1050 | $title = $field->{title} || $name; | ||||
1051 | if ( $title eq $formField || $name eq $formField ) { | ||||
1052 | $found = 1; | ||||
1053 | my $value = $field->{value}; | ||||
1054 | $text = $default if !length($value); | ||||
1055 | 7 | 17µs | $text =~ s/\$title/$title/go; # spent 17µs making 7 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
1056 | 7 | 37µs | $text =~ s/\$value/$value/go; # spent 37µs making 7 calls to Foswiki::Render::CORE:subst, avg 5µs/call | ||
1057 | 7 | 10µs | $text =~ s/\$name/$name/g; # spent 10µs making 7 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
1058 | 7 | 11µs | if ( $text =~ m/\$form/ ) { # spent 11µs making 7 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1059 | my @defform = $formTopicObject->find('FORM'); | ||||
1060 | my $form = $defform[0]; # only one form per topic | ||||
1061 | my $fname = $form->{name}; | ||||
1062 | $text =~ s/\$form/$fname/g; | ||||
1063 | } | ||||
1064 | |||||
1065 | last; # one hit suffices | ||||
1066 | } | ||||
1067 | } | ||||
1068 | |||||
1069 | unless ($found) { | ||||
1070 | $text = $altText || ''; | ||||
1071 | } | ||||
1072 | |||||
1073 | 7 | 500µs | $text = Foswiki::expandStandardEscapes($text); # spent 500µs making 7 calls to Foswiki::expandStandardEscapes, avg 71µs/call | ||
1074 | |||||
1075 | # render nop exclamation marks before words as <nop> | ||||
1076 | 7 | 11µs | $text =~ s/!(\w+)/<nop>$1/gs; # spent 11µs making 7 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
1077 | |||||
1078 | return $text; | ||||
1079 | } | ||||
1080 | |||||
1081 | =begin TML | ||||
1082 | |||||
1083 | ---++ ObjectMethod getRenderedVersion ( $text, $topicObject ) -> $html | ||||
1084 | |||||
1085 | The main rendering function. | ||||
1086 | |||||
1087 | =cut | ||||
1088 | |||||
1089 | # spent 191ms (16.5+174) within Foswiki::Render::getRenderedVersion which was called 5 times, avg 38.1ms/call:
# 5 times (16.5ms+174ms) by Foswiki::Meta::renderTML at line 3144 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 38.1ms/call | ||||
1090 | 2268 | 44.7ms | my ( $this, $text, $topicObject ) = @_; | ||
1091 | 5 | 20µs | ASSERT( $topicObject->isa('Foswiki::Meta') ) if DEBUG; # spent 20µs making 5 calls to Assert::ASSERTS_OFF, avg 4µs/call | ||
1092 | |||||
1093 | return '' unless defined $text; # nothing to do | ||||
1094 | |||||
1095 | my $session = $this->{session}; | ||||
1096 | my $plugins = $session->{plugins}; | ||||
1097 | my $prefs = $session->{prefs}; | ||||
1098 | |||||
1099 | @{ $this->{LIST} } = (); | ||||
1100 | |||||
1101 | # Initial cleanup | ||||
1102 | 5 | 60µs | $text =~ s/\r//g; # spent 60µs making 5 calls to Foswiki::Render::CORE:subst, avg 12µs/call | ||
1103 | |||||
1104 | # whitespace before <! tag (if it is the first thing) is illegal | ||||
1105 | 5 | 26µs | $text =~ s/^\s+(<![a-z])/$1/i; # spent 26µs making 5 calls to Foswiki::Render::CORE:subst, avg 5µs/call | ||
1106 | |||||
1107 | # clutch to enforce correct rendering at end of doc | ||||
1108 | 5 | 92µs | $text =~ s/\n?$/\n<nop>\n/s; # spent 92µs making 5 calls to Foswiki::Render::CORE:subst, avg 18µs/call | ||
1109 | |||||
1110 | # Maps of placeholders to tag parameters and text | ||||
1111 | my $removed = {}; | ||||
1112 | |||||
1113 | # verbatim before literal - see Item3431 | ||||
1114 | 5 | 223µs | $text = Foswiki::takeOutBlocks( $text, 'verbatim', $removed ); # spent 223µs making 5 calls to Foswiki::takeOutBlocks, avg 45µs/call | ||
1115 | 5 | 2.22ms | $text = Foswiki::takeOutBlocks( $text, 'literal', $removed ); # spent 2.22ms making 5 calls to Foswiki::takeOutBlocks, avg 443µs/call | ||
1116 | $text = Foswiki::takeOutBlocks( $text, 'dirtyarea', $removed ) | ||||
1117 | if $Foswiki::cfg{Cache}{Enabled}; | ||||
1118 | |||||
1119 | 10 | 389µs | $text = # spent 345µs making 5 calls to Foswiki::Render::_takeOutProtected, avg 69µs/call
# spent 43µs making 5 calls to Foswiki::Render::CORE:qr, avg 9µs/call | ||
1120 | $this->_takeOutProtected( $text, qr/<\?([^?]*)\?>/s, 'comment', | ||||
1121 | $removed ); | ||||
1122 | 10 | 440µs | $text = # spent 422µs making 5 calls to Foswiki::Render::_takeOutProtected, avg 84µs/call
# spent 19µs making 5 calls to Foswiki::Render::CORE:qr, avg 4µs/call | ||
1123 | $this->_takeOutProtected( $text, qr/<!DOCTYPE([^<>]*)>?/mi, 'comment', | ||||
1124 | $removed ); | ||||
1125 | 10 | 369µs | $text = # spent 350µs making 5 calls to Foswiki::Render::_takeOutProtected, avg 70µs/call
# spent 19µs making 5 calls to Foswiki::Render::CORE:qr, avg 4µs/call | ||
1126 | $this->_takeOutProtected( $text, qr/<head.*?<\/head>/si, 'head', | ||||
1127 | $removed ); | ||||
1128 | 10 | 378µs | $text = $this->_takeOutProtected( $text, qr/<textarea\b.*?<\/textarea>/si, # spent 360µs making 5 calls to Foswiki::Render::_takeOutProtected, avg 72µs/call
# spent 19µs making 5 calls to Foswiki::Render::CORE:qr, avg 4µs/call | ||
1129 | 'textarea', $removed ); | ||||
1130 | 10 | 679µs | $text = # spent 651µs making 5 calls to Foswiki::Render::_takeOutProtected, avg 130µs/call
# spent 28µs making 5 calls to Foswiki::Render::CORE:qr, avg 6µs/call | ||
1131 | $this->_takeOutProtected( $text, qr/<script\b.*?<\/script>/si, 'script', | ||||
1132 | $removed ); | ||||
1133 | |||||
1134 | # Remove the sticky tags (used in WysiwygPlugin's TML2HTML conversion) | ||||
1135 | # since they could potentially break a browser. | ||||
1136 | # They are removed here and not in the plugin because the plugin might | ||||
1137 | # not be installed but the sticky tags are standard markup. | ||||
1138 | 5 | 46µs | $text =~ s#</?sticky>##g; # spent 46µs making 5 calls to Foswiki::Render::CORE:subst, avg 9µs/call | ||
1139 | |||||
1140 | # DEPRECATED startRenderingHandler before PRE removed | ||||
1141 | # SMELL: could parse more efficiently if this wasn't | ||||
1142 | # here. | ||||
1143 | 15 | 501µs | $plugins->dispatch( 'startRenderingHandler', $text, $topicObject->web, # spent 413µs making 5 calls to Foswiki::Plugins::dispatch, avg 83µs/call
# spent 47µs making 5 calls to Foswiki::Meta::web, avg 9µs/call
# spent 41µs making 5 calls to Foswiki::Meta::topic, avg 8µs/call | ||
1144 | $topicObject->topic ); | ||||
1145 | |||||
1146 | 5 | 223µs | $text = Foswiki::takeOutBlocks( $text, 'pre', $removed ); # spent 223µs making 5 calls to Foswiki::takeOutBlocks, avg 45µs/call | ||
1147 | |||||
1148 | # Join lines ending in '\' (don't need \r?, it was removed already) | ||||
1149 | 5 | 39µs | $text =~ s/\\\n//gs; # spent 39µs making 5 calls to Foswiki::Render::CORE:subst, avg 8µs/call | ||
1150 | |||||
1151 | 5 | 56.7ms | $plugins->dispatch( 'preRenderingHandler', $text, $removed ); # spent 56.7ms making 5 calls to Foswiki::Plugins::dispatch, avg 11.3ms/call | ||
1152 | |||||
1153 | 5 | 62µs | if ( $plugins->haveHandlerFor('insidePREHandler') ) { # spent 62µs making 5 calls to Foswiki::Plugins::haveHandlerFor, avg 12µs/call | ||
1154 | foreach my $region ( sort keys %$removed ) { | ||||
1155 | next unless ( $region =~ /^pre\d+$/i ); | ||||
1156 | my @lines = split( /\r?\n/, $removed->{$region}{text} ); | ||||
1157 | my $rt = ''; | ||||
1158 | while ( scalar(@lines) ) { | ||||
1159 | my $line = shift(@lines); | ||||
1160 | $plugins->dispatch( 'insidePREHandler', $line ); | ||||
1161 | if ( $line =~ /\n/ ) { | ||||
1162 | unshift( @lines, split( /\r?\n/, $line ) ); | ||||
1163 | next; | ||||
1164 | } | ||||
1165 | $rt .= $line . "\n"; | ||||
1166 | } | ||||
1167 | $removed->{$region}{text} = $rt; | ||||
1168 | } | ||||
1169 | } | ||||
1170 | |||||
1171 | 5 | 42µs | if ( $plugins->haveHandlerFor('outsidePREHandler') ) { # spent 42µs making 5 calls to Foswiki::Plugins::haveHandlerFor, avg 8µs/call | ||
1172 | |||||
1173 | # DEPRECATED - this is the one call preventing | ||||
1174 | # effective optimisation of the TML processing loop, | ||||
1175 | # as it exposes the concept of a 'line loop' to plugins, | ||||
1176 | # but HTML is not a line-oriented language (though TML is). | ||||
1177 | # But without it, a lot of processing could be moved | ||||
1178 | # outside the line loop. | ||||
1179 | my @lines = split( /\r?\n/, $text ); | ||||
1180 | my $rt = ''; | ||||
1181 | while ( scalar(@lines) ) { | ||||
1182 | my $line = shift(@lines); | ||||
1183 | $plugins->dispatch( 'outsidePREHandler', $line ); | ||||
1184 | if ( $line =~ /\n/ ) { | ||||
1185 | unshift( @lines, split( /\r?\n/, $line ) ); | ||||
1186 | next; | ||||
1187 | } | ||||
1188 | $rt .= $line . "\n"; | ||||
1189 | } | ||||
1190 | |||||
1191 | $text = $rt; | ||||
1192 | } | ||||
1193 | |||||
1194 | # Escape rendering: Change ' !AnyWord' to ' <nop>AnyWord', | ||||
1195 | # for final ' AnyWord' output | ||||
1196 | 10 | 146µs | $text =~ s/$STARTWW\!(?=[\w\*\=])/<nop>/gm; # spent 92µs making 5 calls to Foswiki::Render::CORE:subst, avg 18µs/call
# spent 55µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 11µs/call | ||
1197 | |||||
1198 | # Blockquoted email (indented with '> ') | ||||
1199 | # Could be used to provide different colours for different numbers of '>' | ||||
1200 | 5 | 93µs | $text =~ s/^>(.*?)$/'>'.CGI::cite( {}, $1 ).CGI::br()/gem; # spent 93µs making 5 calls to Foswiki::Render::CORE:subst, avg 19µs/call | ||
1201 | |||||
1202 | # locate isolated < and > and translate to entities | ||||
1203 | # Protect isolated <!-- and --> | ||||
1204 | 5 | 208µs | $text =~ s/<!--/{$REMARKER!--/g; # spent 208µs making 5 calls to Foswiki::Render::CORE:subst, avg 42µs/call | ||
1205 | 5 | 161µs | $text =~ s/-->/--}$REMARKER/g; # spent 161µs making 5 calls to Foswiki::Render::CORE:subst, avg 32µs/call | ||
1206 | |||||
1207 | # SMELL: this next fragment does not handle the case where HTML tags | ||||
1208 | # are embedded in the values provided to other tags. The only way to | ||||
1209 | # do this correctly is to parse the HTML (bleagh!). So we just assume | ||||
1210 | # they have been escaped. | ||||
1211 | 308 | 1.98ms | $text =~ s/<(\/?\w+(:\w+)?)>/{$REMARKER$1}$REMARKER/g; # spent 1.90ms making 303 calls to Foswiki::Render::CORE:substcont, avg 6µs/call
# spent 80µs making 5 calls to Foswiki::Render::CORE:subst, avg 16µs/call | ||
1212 | 224 | 2.44ms | $text =~ s/<(\w+(:\w+)?(\s+.*?|\/)?)>/{$REMARKER$1}$REMARKER/g; # spent 2.33ms making 219 calls to Foswiki::Render::CORE:substcont, avg 11µs/call
# spent 107µs making 5 calls to Foswiki::Render::CORE:subst, avg 21µs/call | ||
1213 | |||||
1214 | # XML processing instruction only valid at start of text | ||||
1215 | 5 | 30µs | $text =~ s/^<(\?\w.*?\?)>/{$REMARKER$1}$REMARKER/g; # spent 30µs making 5 calls to Foswiki::Render::CORE:subst, avg 6µs/call | ||
1216 | |||||
1217 | # entitify lone < and >, praying that we haven't screwed up :-( | ||||
1218 | # Item1985: CDATA sections are not lone < and > | ||||
1219 | 5 | 33µs | $text =~ s/<(?!\!\[CDATA\[)/<\;/g; # spent 33µs making 5 calls to Foswiki::Render::CORE:subst, avg 7µs/call | ||
1220 | 5 | 33µs | $text =~ s/(?<!\]\])>/>\;/g; # spent 33µs making 5 calls to Foswiki::Render::CORE:subst, avg 7µs/call | ||
1221 | 10 | 325µs | $text =~ s/{$REMARKER/</go; # spent 312µs making 5 calls to Foswiki::Render::CORE:subst, avg 62µs/call
# spent 13µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 3µs/call | ||
1222 | 10 | 313µs | $text =~ s/}$REMARKER/>/go; # spent 301µs making 5 calls to Foswiki::Render::CORE:subst, avg 60µs/call
# spent 11µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
1223 | |||||
1224 | # other entities | ||||
1225 | 31 | 186µs | $text =~ s/&(\w+);/$REMARKER$1;/g; # "&abc;" # spent 123µs making 26 calls to Foswiki::Render::CORE:substcont, avg 5µs/call
# spent 62µs making 5 calls to Foswiki::Render::CORE:subst, avg 12µs/call | ||
1226 | 5 | 80µs | $text =~ s/&(#x?[0-9a-f]+);/$REMARKER$1;/gi; # "{" # spent 80µs making 5 calls to Foswiki::Render::CORE:subst, avg 16µs/call | ||
1227 | 5 | 62µs | $text =~ s/&/&/g; # escape standalone "&" # spent 62µs making 5 calls to Foswiki::Render::CORE:subst, avg 12µs/call | ||
1228 | 10 | 111µs | $text =~ s/$REMARKER(#x?[0-9a-f]+;)/&$1/goi; # spent 93µs making 5 calls to Foswiki::Render::CORE:subst, avg 19µs/call
# spent 18µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 4µs/call | ||
1229 | 36 | 195µs | $text =~ s/$REMARKER(\w+;)/&$1/go; # spent 109µs making 26 calls to Foswiki::Render::CORE:substcont, avg 4µs/call
# spent 72µs making 5 calls to Foswiki::Render::CORE:subst, avg 14µs/call
# spent 15µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 3µs/call | ||
1230 | |||||
1231 | # clear the set of unique anchornames in order to inhibit | ||||
1232 | # the 'relabeling' of anchor names if the same topic is processed | ||||
1233 | # more than once, cf. explanation in expandMacros() | ||||
1234 | 5 | 240µs | my $anchors = $this->getAnchorNames($topicObject); # spent 240µs making 5 calls to Foswiki::Render::getAnchorNames, avg 48µs/call | ||
1235 | 5 | 39µs | $anchors->clear(); # spent 39µs making 5 calls to Foswiki::Render::Anchors::clear, avg 8µs/call | ||
1236 | |||||
1237 | # '#WikiName' anchors. Don't attempt to make these unique; renaming | ||||
1238 | # user-defined anchors is not sensible. | ||||
1239 | 12 | 83µs | $text =~ s/^(\#$Foswiki::regex{wikiWordRegex})/ # spent 33µs making 5 calls to Foswiki::Render::CORE:subst, avg 7µs/call
# spent 33µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 7µs/call
# spent 16µs making 2 calls to Foswiki::Render::CORE:substcont, avg 8µs/call | ||
1240 | 2 | 292µs | CGI::a({ # spent 149µs making 1 call to Foswiki::Render::Anchors::add
# spent 143µs making 1 call to CGI::a | ||
1241 | name => $anchors->add( $1 ) | ||||
1242 | }, '')/geom; | ||||
1243 | |||||
1244 | # Headings | ||||
1245 | # '<h6>...</h6>' HTML rule | ||||
1246 | 10 | 84µs | $text =~ s/$Foswiki::regex{headerPatternHt}/ # spent 76µs making 5 calls to Foswiki::Render::CORE:subst, avg 15µs/call
# spent 8µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
1247 | _makeAnchorHeading($this, $2, $1, $anchors)/geo; | ||||
1248 | |||||
1249 | # '----+++++++' rule | ||||
1250 | 18 | 138µs | $text =~ s/$Foswiki::regex{headerPatternDa}/ # spent 74µs making 5 calls to Foswiki::Render::CORE:subst, avg 15µs/call
# spent 55µs making 8 calls to Foswiki::Render::CORE:substcont, avg 7µs/call
# spent 10µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 2µs/call | ||
1251 | 6 | 2.41ms | _makeAnchorHeading($this, $2, length($1), $anchors)/geo; # spent 2.41ms making 6 calls to Foswiki::Render::_makeAnchorHeading, avg 402µs/call | ||
1252 | |||||
1253 | # Horizontal rule | ||||
1254 | 5 | 555µs | my $hr = CGI::hr(); # spent 401µs making 1 call to CGI::AUTOLOAD
# spent 154µs making 4 calls to CGI::hr, avg 39µs/call | ||
1255 | 5 | 49µs | $text =~ s/^---+/$hr/gm; # spent 49µs making 5 calls to Foswiki::Render::CORE:subst, avg 10µs/call | ||
1256 | |||||
1257 | # Now we really _do_ need a line loop, to process TML | ||||
1258 | # line-oriented stuff. | ||||
1259 | my $isList = 0; # True when within a list | ||||
1260 | my $tableRow = 0; | ||||
1261 | my @result; | ||||
1262 | my $isFirst = 1; | ||||
1263 | |||||
1264 | foreach my $line ( split( /\r?\n/, $text ) ) { | ||||
1265 | |||||
1266 | # Table: | cell | cell | | ||||
1267 | # allow trailing white space after the last | | ||||
1268 | 235 | 455µs | if ( $line =~ m/^(\s*)\|.*\|\s*$/ ) { # spent 455µs making 235 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1269 | |||||
1270 | if ($isList) { | ||||
1271 | |||||
1272 | # Table start should terminate previous list | ||||
1273 | _addListItem( $this, \@result, '', '', '', '' ); | ||||
1274 | $isList = 0; | ||||
1275 | } | ||||
1276 | |||||
1277 | unless ($tableRow) { | ||||
1278 | |||||
1279 | # mark the head of the table | ||||
1280 | push( @result, $TABLEMARKER ); | ||||
1281 | } | ||||
1282 | $line =~ s/^(\s*)\|(.*)/$1._emitTR( $this, $2 )/e; | ||||
1283 | $tableRow++; | ||||
1284 | } | ||||
1285 | elsif ($tableRow) { | ||||
1286 | _addTHEADandTFOOT( \@result ); | ||||
1287 | push( @result, '</table>' ); | ||||
1288 | $tableRow = 0; | ||||
1289 | } | ||||
1290 | |||||
1291 | # Lists and paragraphs | ||||
1292 | 561 | 1.37ms | if ( $line =~ m/^\s*$/ ) { # spent 1.37ms making 561 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1293 | unless ( $tableRow || $isFirst ) { | ||||
1294 | $line = '<p></p>'; | ||||
1295 | } | ||||
1296 | $isList = 0; | ||||
1297 | } | ||||
1298 | elsif ( $line =~ m/^\S/ ) { | ||||
1299 | $isList = 0; | ||||
1300 | } | ||||
1301 | elsif ( $line =~ m/^(\t| )+\S/ ) { | ||||
1302 | 433 | 1.05ms | if ( $line =~ # spent 821µs making 366 calls to Foswiki::Render::CORE:subst, avg 2µs/call
# spent 229µs making 67 calls to Foswiki::Render::CORE:match, avg 3µs/call | ||
1303 | s/^((\t| )+)\$\s(([^:]+|:[^\s]+)+?):\s/<dt> $3 <\/dt><dd> / ) | ||||
1304 | { | ||||
1305 | |||||
1306 | # Definition list | ||||
1307 | _addListItem( $this, \@result, 'dl', 'dd', '', $1 ); | ||||
1308 | $isList = 1; | ||||
1309 | } | ||||
1310 | elsif ( $line =~ s/^((\t| )+)(\S+?):\s/<dt> $3<\/dt><dd> /o ) { | ||||
1311 | |||||
1312 | # Definition list | ||||
1313 | _addListItem( $this, \@result, 'dl', 'dd', '', $1 ); | ||||
1314 | $isList = 1; | ||||
1315 | } | ||||
1316 | elsif ( $line =~ s/^((\t| )+)\* /<li> /o ) { | ||||
1317 | |||||
1318 | # Unnumbered list | ||||
1319 | 34 | 1.37ms | _addListItem( $this, \@result, 'ul', 'li', '', $1 ); # spent 1.37ms making 34 calls to Foswiki::Render::_addListItem, avg 40µs/call | ||
1320 | $isList = 1; | ||||
1321 | } | ||||
1322 | elsif ( $line =~ s/^((\t| )+): /<div class='foswikiIndent'> /o ) { | ||||
1323 | |||||
1324 | # Indent pseudo-list | ||||
1325 | _addListItem( $this, \@result, '', 'div', 'foswikiIndent', $1 ); | ||||
1326 | $isList = 1; | ||||
1327 | } | ||||
1328 | elsif ( $line =~ m/^((\t| )+)([1AaIi]\.|\d+\.?) ?/ ) { | ||||
1329 | |||||
1330 | # Numbered list | ||||
1331 | my $ot = $3; | ||||
1332 | $ot =~ s/^(.).*/$1/; | ||||
1333 | if ( $ot !~ /^\d$/ ) { | ||||
1334 | $ot = ' type="' . $ot . '"'; | ||||
1335 | } | ||||
1336 | else { | ||||
1337 | $ot = ''; | ||||
1338 | } | ||||
1339 | $line =~ s/^((\t| )+)([1AaIi]\.|\d+\.?) ?/<li$ot> /; | ||||
1340 | _addListItem( $this, \@result, 'ol', 'li', '', $1 ); | ||||
1341 | $isList = 1; | ||||
1342 | } | ||||
1343 | elsif ( $isList && $line =~ /^(\t| )+\s*\S/ ) { | ||||
1344 | |||||
1345 | # indented line extending prior list item | ||||
1346 | push( @result, $line ); | ||||
1347 | next; | ||||
1348 | } | ||||
1349 | else { | ||||
1350 | $isList = 0; | ||||
1351 | } | ||||
1352 | } | ||||
1353 | elsif ( $isList && $line =~ /^(\t| )+\s*\S/ ) { | ||||
1354 | |||||
1355 | # indented line extending prior list item; case where indent | ||||
1356 | # starts with is at least 3 spaces or a tab, but may not be a | ||||
1357 | # multiple of 3. | ||||
1358 | push( @result, $line ); | ||||
1359 | next; | ||||
1360 | } | ||||
1361 | |||||
1362 | # Finish the list | ||||
1363 | unless ( $isList || $isFirst ) { | ||||
1364 | 195 | 5.54ms | _addListItem( $this, \@result, '', '', '', '' ); # spent 5.54ms making 195 calls to Foswiki::Render::_addListItem, avg 28µs/call | ||
1365 | } | ||||
1366 | |||||
1367 | push( @result, $line ); | ||||
1368 | $isFirst = 0; | ||||
1369 | } | ||||
1370 | |||||
1371 | if ($tableRow) { | ||||
1372 | _addTHEADandTFOOT( \@result ); | ||||
1373 | push( @result, '</table>' ); | ||||
1374 | } | ||||
1375 | 5 | 147µs | _addListItem( $this, \@result, '', '', '', '' ); # spent 147µs making 5 calls to Foswiki::Render::_addListItem, avg 29µs/call | ||
1376 | |||||
1377 | $text = join( '', @result ); | ||||
1378 | |||||
1379 | # SMELL: use of $STARTWW and $ENDWW really limit the number of places | ||||
1380 | # emphasis can happen. But it's a tradeoff between that and excessive | ||||
1381 | # greed. | ||||
1382 | |||||
1383 | 10 | 72µs | $text =~ s/${STARTWW}==(\S+?|\S[^\n]*?\S)==$ENDWW/_fixedFontText($1,1)/gem; # spent 45µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 9µs/call
# spent 26µs making 5 calls to Foswiki::Render::CORE:subst, avg 5µs/call | ||
1384 | 10 | 57µs | $text =~ s/${STARTWW}__(\S+?|\S[^\n]*?\S) # spent 36µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 7µs/call
# spent 22µs making 5 calls to Foswiki::Render::CORE:subst, avg 4µs/call | ||
1385 | __$ENDWW/<strong><em>$1<\/em><\/strong>/gmx; | ||||
1386 | 12 | 86µs | $text =~ s/${STARTWW}\*(\S+?|\S[^\n]*?\S)\*$ENDWW/<strong>$1<\/strong>/gm; # spent 40µs making 5 calls to Foswiki::Render::CORE:subst, avg 8µs/call
# spent 30µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 6µs/call
# spent 16µs making 2 calls to Foswiki::Render::CORE:substcont, avg 8µs/call | ||
1387 | 10 | 91µs | $text =~ s/${STARTWW}\_(\S+?|\S[^\n]*?\S)\_$ENDWW/<em>$1<\/em>/gm; # spent 58µs making 5 calls to Foswiki::Render::CORE:subst, avg 12µs/call
# spent 33µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 7µs/call | ||
1388 | 13 | 789µs | $text =~ s/${STARTWW}\=(\S+?|\S[^\n]*?\S)\=$ENDWW/_fixedFontText($1,0)/gem; # spent 593µs making 1 call to Foswiki::Render::_fixedFontText
# spent 145µs making 5 calls to Foswiki::Render::CORE:subst, avg 29µs/call
# spent 30µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 6µs/call
# spent 20µs making 2 calls to Foswiki::Render::CORE:substcont, avg 10µs/call | ||
1389 | |||||
1390 | # Handle [[][] and [[]] links | ||||
1391 | # Change ' ![[...' to ' [<nop>[...' to protect from further rendering | ||||
1392 | 5 | 47µs | $text =~ s/(^|\s)\!\[\[/$1\[<nop>\[/gm; # spent 47µs making 5 calls to Foswiki::Render::CORE:subst, avg 9µs/call | ||
1393 | |||||
1394 | # Spaced-out Wiki words with alternative link text | ||||
1395 | # i.e. [[$1][$3]] | ||||
1396 | 75 | 34.8ms | $text =~ s(\[\[([^\]\[\n]+)\](\[([^\]\n]+)\])?\]) # spent 34.5ms making 34 calls to Foswiki::Render::_handleSquareBracketedLink, avg 1.01ms/call
# spent 265µs making 36 calls to Foswiki::Render::CORE:substcont, avg 7µs/call
# spent 35µs making 5 calls to Foswiki::Render::CORE:subst, avg 7µs/call | ||
1397 | (_handleSquareBracketedLink( $this,$topicObject,$1,$3))ge; | ||||
1398 | |||||
1399 | # URI - don't apply if the URI is surrounded by url() to avoid naffing | ||||
1400 | # CSS | ||||
1401 | 10 | 4.83ms | $text =~ s/(^|(?<!url)[-*\s(|]) # spent 4.77ms making 5 calls to Foswiki::Render::CORE:subst, avg 953µs/call
# spent 60µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 12µs/call | ||
1402 | ($Foswiki::regex{linkProtocolPattern}: | ||||
1403 | ([^\s<>"]+[^\s*.,!?;:)<|]))/ | ||||
1404 | $1._externalLink( $this,$2)/geox; | ||||
1405 | |||||
1406 | # Normal mailto:foo@example.com ('mailto:' part optional) | ||||
1407 | 10 | 6.60ms | $text =~ s/$STARTWW((mailto\:)? # spent 6.48ms making 5 calls to Foswiki::Render::CORE:subst, avg 1.30ms/call
# spent 121µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 24µs/call | ||
1408 | $Foswiki::regex{emailAddrRegex})$ENDWW/ | ||||
1409 | _mailLink( $this, $1 )/gemx; | ||||
1410 | |||||
1411 | 10 | 918µs | unless ( Foswiki::isTrue( $prefs->getPreference('NOAUTOLINK') ) ) { # spent 659µs making 5 calls to Foswiki::Prefs::getPreference, avg 132µs/call
# spent 259µs making 5 calls to Foswiki::isTrue, avg 52µs/call | ||
1412 | |||||
1413 | # Handle WikiWords | ||||
1414 | 5 | 982µs | $text = Foswiki::takeOutBlocks( $text, 'noautolink', $removed ); # spent 982µs making 5 calls to Foswiki::takeOutBlocks, avg 196µs/call | ||
1415 | 94 | 36.3ms | $text =~ s($STARTWW # spent 30.0ms making 40 calls to Foswiki::Render::_handleWikiWord, avg 749µs/call
# spent 4.26ms making 44 calls to Foswiki::Render::CORE:substcont, avg 97µs/call
# spent 2.00ms making 5 calls to Foswiki::Render::CORE:subst, avg 399µs/call
# spent 70µs making 5 calls to Foswiki::Render::CORE:regcomp, avg 14µs/call | ||
1416 | (?:($Foswiki::regex{webNameRegex})\.)? | ||||
1417 | ($Foswiki::regex{wikiWordRegex}| | ||||
1418 | $Foswiki::regex{abbrevRegex}) | ||||
1419 | ($Foswiki::regex{anchorRegex})?) | ||||
1420 | (_handleWikiWord( $this, $topicObject, $1, $2, $3))gexom; | ||||
1421 | 5 | 696µs | Foswiki::putBackBlocks( \$text, $removed, 'noautolink' ); # spent 696µs making 5 calls to Foswiki::putBackBlocks, avg 139µs/call | ||
1422 | } | ||||
1423 | |||||
1424 | 5 | 426µs | Foswiki::putBackBlocks( \$text, $removed, 'pre' ); # spent 426µs making 5 calls to Foswiki::putBackBlocks, avg 85µs/call | ||
1425 | |||||
1426 | # DEPRECATED plugins hook after PRE re-inserted | ||||
1427 | 5 | 72µs | $plugins->dispatch( 'endRenderingHandler', $text ); # spent 72µs making 5 calls to Foswiki::Plugins::dispatch, avg 14µs/call | ||
1428 | |||||
1429 | # replace verbatim with pre in the final output | ||||
1430 | 5 | 411µs | Foswiki::putBackBlocks( \$text, $removed, 'verbatim', 'pre', # spent 411µs making 5 calls to Foswiki::putBackBlocks, avg 82µs/call | ||
1431 | \&verbatimCallBack ); | ||||
1432 | 5 | 34µs | $text =~ s|\n?<nop>\n$||o; # clean up clutch # spent 34µs making 5 calls to Foswiki::Render::CORE:subst, avg 7µs/call | ||
1433 | |||||
1434 | 5 | 1.07ms | $this->_putBackProtected( \$text, 'script', $removed, \&_filterScript ); # spent 1.07ms making 5 calls to Foswiki::Render::_putBackProtected, avg 215µs/call | ||
1435 | 5 | 1.13ms | Foswiki::putBackBlocks( \$text, $removed, 'literal', '', \&_filterLiteral ); # spent 1.13ms making 5 calls to Foswiki::putBackBlocks, avg 225µs/call | ||
1436 | 5 | 142µs | $this->_putBackProtected( \$text, 'literal', $removed ); # spent 142µs making 5 calls to Foswiki::Render::_putBackProtected, avg 28µs/call | ||
1437 | Foswiki::putBackBlocks( \$text, $removed, 'dirtyarea' ) | ||||
1438 | if $Foswiki::cfg{Cache}{Enabled}; | ||||
1439 | 5 | 181µs | $this->_putBackProtected( \$text, 'comment', $removed ); # spent 181µs making 5 calls to Foswiki::Render::_putBackProtected, avg 36µs/call | ||
1440 | 5 | 164µs | $this->_putBackProtected( \$text, 'head', $removed ); # spent 164µs making 5 calls to Foswiki::Render::_putBackProtected, avg 33µs/call | ||
1441 | 5 | 147µs | $this->_putBackProtected( \$text, 'textarea', $removed ); # spent 147µs making 5 calls to Foswiki::Render::_putBackProtected, avg 29µs/call | ||
1442 | |||||
1443 | 10 | 440µs | $this->{session}->getLoginManager()->endRenderingHandler($text); # spent 291µs making 5 calls to Foswiki::LoginManager::endRenderingHandler, avg 58µs/call
# spent 150µs making 5 calls to Foswiki::getLoginManager, avg 30µs/call | ||
1444 | |||||
1445 | 5 | 828µs | $plugins->dispatch( 'postRenderingHandler', $text ); # spent 828µs making 5 calls to Foswiki::Plugins::dispatch, avg 166µs/call | ||
1446 | return $text; | ||||
1447 | } | ||||
1448 | |||||
1449 | =begin TML | ||||
1450 | |||||
1451 | ---++ StaticMethod verbatimCallBack | ||||
1452 | |||||
1453 | Callback for use with putBackBlocks that replaces < and > | ||||
1454 | by their HTML entities &lt; and &gt; | ||||
1455 | |||||
1456 | =cut | ||||
1457 | |||||
1458 | sub verbatimCallBack { | ||||
1459 | my $val = shift; | ||||
1460 | |||||
1461 | # SMELL: A shame to do this, but been in Foswiki.org have converted | ||||
1462 | # 3 spaces to tabs since day 1 | ||||
1463 | $val =~ s/\t/ /g; | ||||
1464 | |||||
1465 | return Foswiki::entityEncode($val); | ||||
1466 | } | ||||
1467 | |||||
1468 | # Only put script and literal sections back if they are allowed by options | ||||
1469 | # spent 103µs within Foswiki::Render::_filterLiteral which was called 17 times, avg 6µs/call:
# 17 times (103µs+0s) by Foswiki::putBackBlocks at line 2854 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 6µs/call | ||||
1470 | 34 | 121µs | my $val = shift; | ||
1471 | return $val if ( $Foswiki::cfg{AllowInlineScript} ); | ||||
1472 | return CGI::comment( | ||||
1473 | '<literal> is not allowed on this site - denied by deprecated {AllowInlineScript} setting' | ||||
1474 | ); | ||||
1475 | } | ||||
1476 | |||||
1477 | # spent 83µs within Foswiki::Render::_filterScript which was called 12 times, avg 7µs/call:
# 12 times (83µs+0s) by Foswiki::Render::_putBackProtected at line 1684, avg 7µs/call | ||||
1478 | 24 | 101µs | my $val = shift; | ||
1479 | return $val if ( $Foswiki::cfg{AllowInlineScript} ); | ||||
1480 | return CGI::comment( | ||||
1481 | '<script> is not allowed on this site - denied by deprecated {AllowInlineScript} setting' | ||||
1482 | ); | ||||
1483 | } | ||||
1484 | |||||
1485 | =begin TML | ||||
1486 | |||||
1487 | ---++ ObjectMethod TML2PlainText( $text, $topicObject, $opts ) -> $plainText | ||||
1488 | |||||
1489 | Strip TML markup from text for display as plain text without | ||||
1490 | pushing it through the full rendering pipeline. Intended for | ||||
1491 | generation of topic and change summaries. Adds nop tags to | ||||
1492 | prevent subsequent rendering; nops get removed at the very end. | ||||
1493 | |||||
1494 | $opts: | ||||
1495 | * showvar - shows !%VAR% names if not expanded | ||||
1496 | * expandvar - expands !%VARS% | ||||
1497 | * nohead - strips ---+ headings at the top of the text | ||||
1498 | * showmeta - does not filter meta-data | ||||
1499 | |||||
1500 | =cut | ||||
1501 | |||||
1502 | sub TML2PlainText { | ||||
1503 | my ( $this, $text, $topicObject, $opts ) = @_; | ||||
1504 | $opts ||= ''; | ||||
1505 | |||||
1506 | return '' unless defined $text; | ||||
1507 | |||||
1508 | $text =~ s/\r//g; # SMELL, what about OS10? | ||||
1509 | |||||
1510 | if ( $opts =~ /showmeta/ ) { | ||||
1511 | $text =~ s/%META:/%<nop>META:/g; | ||||
1512 | } | ||||
1513 | else { | ||||
1514 | $text =~ s/%META:[A-Z].*?}%//g; | ||||
1515 | } | ||||
1516 | |||||
1517 | if ( $opts =~ /expandvar/ ) { | ||||
1518 | $text =~ s/(\%)(SEARCH){/$1<nop>$2/g; # prevent recursion | ||||
1519 | $topicObject = Foswiki::Meta->new( $this->{session} ) | ||||
1520 | unless $topicObject; | ||||
1521 | $text = $topicObject->expandMacros($text); | ||||
1522 | } | ||||
1523 | else { | ||||
1524 | $text =~ s/%WEB%/$topicObject->web() || ''/ge; | ||||
1525 | $text =~ s/%TOPIC%/$topicObject->topic() || ''/ge; | ||||
1526 | my $wtn = $this->{session}->{prefs}->getPreference('WIKITOOLNAME') | ||||
1527 | || ''; | ||||
1528 | $text =~ s/%WIKITOOLNAME%/$wtn/g; | ||||
1529 | if ( $opts =~ /showvar/ ) { | ||||
1530 | $text =~ s/%(\w+({.*?}))%/$1/g; # defuse | ||||
1531 | } | ||||
1532 | else { | ||||
1533 | $text =~ s/%$Foswiki::regex{tagNameRegex}({.*?})?%//g; # remove | ||||
1534 | } | ||||
1535 | } | ||||
1536 | |||||
1537 | # Format e-mail to add spam padding (HTML tags removed later) | ||||
1538 | $text =~ s/$STARTWW( | ||||
1539 | (mailto\:)? | ||||
1540 | [a-zA-Z0-9-_.+]+@[a-zA-Z0-9-_.]+\.[a-zA-Z0-9-_]+ | ||||
1541 | )$ENDWW | ||||
1542 | /_mailLink( $this, $1 )/gemx; | ||||
1543 | $text =~ s/<!--.*?-->//gs; # remove all HTML comments | ||||
1544 | $text =~ s/<(?!nop)[^>]*>//g; # remove all HTML tags except <nop> | ||||
1545 | $text =~ s/\&[a-z]+;/ /g; # remove entities | ||||
1546 | if ( $opts =~ /nohead/ ) { | ||||
1547 | |||||
1548 | # skip headings on top | ||||
1549 | while ( $text =~ s/^\s*\-\-\-+\+[^\n\r]*// ) { }; # remove heading | ||||
1550 | } | ||||
1551 | |||||
1552 | # keep only link text of legacy [[prot://uri.tld/ link text]] | ||||
1553 | $text =~ s/ | ||||
1554 | \[ | ||||
1555 | \[$Foswiki::regex{linkProtocolPattern}\: | ||||
1556 | ([^\s<>"\]]+[^\s*.,!?;:)<|\]]) | ||||
1557 | \s+([^\[\]]*?) | ||||
1558 | \] | ||||
1559 | \]/$3/gx; | ||||
1560 | |||||
1561 | #keep only test portion of [[][]] links | ||||
1562 | $text =~ s/\[\[([^\]]*\]\[)(.*?)\]\]/$2/g; | ||||
1563 | |||||
1564 | # SMELL: can't do this, it removes these characters even when they're | ||||
1565 | # not for formatting | ||||
1566 | #$text =~ s/[\[\]\*\|=_\&\<\>]/ /g; | ||||
1567 | |||||
1568 | $text =~ s/${STARTWW}==(\S+?|\S[^\n]*?\S)==$ENDWW/$1/gem; | ||||
1569 | $text =~ s/${STARTWW}__(\S+?|\S[^\n]*?\S)__$ENDWW/$1/gm; | ||||
1570 | $text =~ s/${STARTWW}\*(\S+?|\S[^\n]*?\S)\*$ENDWW/$1/gm; | ||||
1571 | $text =~ s/${STARTWW}\_(\S+?|\S[^\n]*?\S)\_$ENDWW/$1/gm; | ||||
1572 | $text =~ s/${STARTWW}\=(\S+?|\S[^\n]*?\S)\=$ENDWW/$1/gem; | ||||
1573 | |||||
1574 | #SMELL: need to correct these too | ||||
1575 | $text =~ s/[\[\]\|\&]/ /g; # remove remaining Wiki formatting chars | ||||
1576 | |||||
1577 | $text =~ s/^\-\-\-+\+*\s*\!*/ /gm; # remove heading formatting and hbar | ||||
1578 | $text =~ s/[\+\-]+/ /g; # remove special chars | ||||
1579 | $text =~ s/^\s+//; # remove leading whitespace | ||||
1580 | $text =~ s/\s+$//; # remove trailing whitespace | ||||
1581 | $text =~ s/!(\w+)/$1/gs; # remove all nop exclamation marks before words | ||||
1582 | $text =~ s/[\r\n]+/\n/s; | ||||
1583 | $text =~ s/[ \t]+/ /s; | ||||
1584 | |||||
1585 | # defuse "Web." prefix in "Web.TopicName" link | ||||
1586 | $text =~ s{$STARTWW | ||||
1587 | (($Foswiki::regex{webNameRegex})\. | ||||
1588 | ($Foswiki::regex{wikiWordRegex} | ||||
1589 | | $Foswiki::regex{abbrevRegex}))} | ||||
1590 | {$2.<nop>$3}gx; | ||||
1591 | $text =~ s/\<nop\>//g; # remove any remaining nops | ||||
1592 | $text =~ s/[\<\>]/ /g; # remove any remaining formatting | ||||
1593 | |||||
1594 | return $text; | ||||
1595 | } | ||||
1596 | |||||
1597 | =begin TML | ||||
1598 | |||||
1599 | ---++ ObjectMethod protectPlainText($text) -> $tml | ||||
1600 | |||||
1601 | Protect plain text from expansions that would normally be done | ||||
1602 | duing rendering, such as wikiwords. Topic summaries, for example, | ||||
1603 | have to be protected this way. | ||||
1604 | |||||
1605 | =cut | ||||
1606 | |||||
1607 | sub protectPlainText { | ||||
1608 | my ( $this, $text ) = @_; | ||||
1609 | |||||
1610 | # prevent text from getting rendered in inline search and link tool | ||||
1611 | # tip text by escaping links (external, internal, Interwiki) | ||||
1612 | $text =~ s/((($Foswiki::regex{webNameRegex})\.)? | ||||
1613 | ($Foswiki::regex{wikiWordRegex} | ||||
1614 | |$Foswiki::regex{abbrevRegex}))/<nop>$1/gx; | ||||
1615 | |||||
1616 | $text =~ s/([@%])/<nop>$1<nop>/g; # email address, macro | ||||
1617 | |||||
1618 | # Encode special chars into XML &#nnn; entities for use in RSS feeds | ||||
1619 | # - no encoding for HTML pages, to avoid breaking international | ||||
1620 | # characters. Only works for ISO-8859-1 sites, since the Unicode | ||||
1621 | # encoding (&#nnn;) is identical for first 256 characters. | ||||
1622 | # I18N TODO: Convert to Unicode from any site character set. | ||||
1623 | if ( $this->{session}->inContext('rss') | ||||
1624 | && $Foswiki::cfg{Site}{CharSet} =~ /^iso-?8859-?1$/i ) | ||||
1625 | { | ||||
1626 | $text =~ s/([\x7f-\xff])/"\&\#" . unpack( 'C', $1 ) .';'/ge; | ||||
1627 | } | ||||
1628 | |||||
1629 | return $text; | ||||
1630 | } | ||||
1631 | |||||
1632 | # DEPRECATED: retained for compatibility with various hack-job extensions | ||||
1633 | sub makeTopicSummary { | ||||
1634 | my ( $this, $text, $topic, $web, $flags ) = @_; | ||||
1635 | my $topicObject = Foswiki::Meta->new( $this->{session}, $web, $topic ); | ||||
1636 | return $topicObject->summariseText( '', $text ); | ||||
1637 | } | ||||
1638 | |||||
1639 | # _takeOutProtected( \$text, $re, $id, \%map ) -> $text | ||||
1640 | # | ||||
1641 | # * =$text= - Text to process | ||||
1642 | # * =$re= - Regular expression that matches tag expressions to remove | ||||
1643 | # * =\%map= - Reference to a hash to contain the removed blocks | ||||
1644 | # | ||||
1645 | # Return value: $text with blocks removed. Unlike takeOuBlocks, this | ||||
1646 | # *preserves* the tags. | ||||
1647 | # | ||||
1648 | # used to extract from $text comment type tags like <!DOCTYPE blah> | ||||
1649 | # | ||||
1650 | # WARNING: if you want to take out <!-- comments --> you _will_ need | ||||
1651 | # to re-write all the takeOuts to use a different placeholder | ||||
1652 | # spent 2.13ms (888µs+1.24) within Foswiki::Render::_takeOutProtected which was called 25 times, avg 85µs/call:
# 5 times (261µs+390µs) by Foswiki::Render::getRenderedVersion at line 1130, avg 130µs/call
# 5 times (211µs+211µs) by Foswiki::Render::getRenderedVersion at line 1122, avg 84µs/call
# 5 times (123µs+237µs) by Foswiki::Render::getRenderedVersion at line 1128, avg 72µs/call
# 5 times (118µs+232µs) by Foswiki::Render::getRenderedVersion at line 1125, avg 70µs/call
# 5 times (176µs+170µs) by Foswiki::Render::getRenderedVersion at line 1119, avg 69µs/call | ||||
1653 | 90 | 1.89ms | my ( $this, $intext, $re, $id, $map ) = @_; | ||
1654 | |||||
1655 | 85 | 1.24ms | $intext =~ s/($re)/_replaceBlock($1, $id, $map)/ge; # spent 443µs making 25 calls to Foswiki::Render::CORE:regcomp, avg 18µs/call
# spent 413µs making 25 calls to Foswiki::Render::CORE:subst, avg 17µs/call
# spent 258µs making 15 calls to Foswiki::Render::_replaceBlock, avg 17µs/call
# spent 125µs making 20 calls to Foswiki::Render::CORE:substcont, avg 6µs/call | ||
1656 | |||||
1657 | return $intext; | ||||
1658 | } | ||||
1659 | |||||
1660 | # spent 258µs within Foswiki::Render::_replaceBlock which was called 15 times, avg 17µs/call:
# 15 times (258µs+0s) by Foswiki::Render::_takeOutProtected at line 1655, avg 17µs/call | ||||
1661 | 75 | 289µs | my ( $scoop, $id, $map ) = @_; | ||
1662 | my $placeholder = $placeholderMarker; | ||||
1663 | $placeholderMarker++; | ||||
1664 | $map->{ $id . $placeholder }{text} = $scoop; | ||||
1665 | |||||
1666 | return '<!--' . $REMARKER . $id . $placeholder . $REMARKER . '-->'; | ||||
1667 | } | ||||
1668 | |||||
1669 | # _putBackProtected( \$text, $id, \%map, $callback ) -> $text | ||||
1670 | # Return value: $text with blocks added back | ||||
1671 | # * =\$text= - reference to text to process | ||||
1672 | # * =$id= - type of taken-out block e.g. 'verbatim' | ||||
1673 | # * =\%map= - map placeholders to blocks removed by takeOutBlocks | ||||
1674 | # * =$callback= - Reference to function to call on each block being inserted (optional) | ||||
1675 | # | ||||
1676 | #Reverses the actions of takeOutProtected. | ||||
1677 | # spent 1.71ms (1.07+634µs) within Foswiki::Render::_putBackProtected which was called 25 times, avg 68µs/call:
# 5 times (642µs+431µs) by Foswiki::Render::getRenderedVersion at line 1434, avg 215µs/call
# 5 times (122µs+59µs) by Foswiki::Render::getRenderedVersion at line 1439, avg 36µs/call
# 5 times (108µs+56µs) by Foswiki::Render::getRenderedVersion at line 1440, avg 33µs/call
# 5 times (98µs+49µs) by Foswiki::Render::getRenderedVersion at line 1441, avg 29µs/call
# 5 times (102µs+39µs) by Foswiki::Render::getRenderedVersion at line 1436, avg 28µs/call | ||||
1678 | 176 | 1.52ms | my ( $this, $text, $id, $map, $callback ) = @_; | ||
1679 | 25 | 83µs | ASSERT( ref($map) eq 'HASH' ) if DEBUG; # spent 83µs making 25 calls to Assert::ASSERTS_OFF, avg 3µs/call | ||
1680 | |||||
1681 | foreach my $placeholder ( keys %$map ) { | ||||
1682 | 82 | 227µs | next unless $placeholder =~ /^$id\d+$/; # spent 147µs making 41 calls to Foswiki::Render::CORE:regcomp, avg 4µs/call
# spent 80µs making 41 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1683 | my $val = $map->{$placeholder}{text}; | ||||
1684 | 12 | 83µs | $val = &$callback($val) if ( defined($callback) ); # spent 83µs making 12 calls to Foswiki::Render::_filterScript, avg 7µs/call | ||
1685 | 30 | 242µs | $$text =~ s/<!--$REMARKER$placeholder$REMARKER-->/$val/; # spent 132µs making 15 calls to Foswiki::Render::CORE:regcomp, avg 9µs/call
# spent 111µs making 15 calls to Foswiki::Render::CORE:subst, avg 7µs/call | ||
1686 | delete( $map->{$placeholder} ); | ||||
1687 | } | ||||
1688 | } | ||||
1689 | |||||
1690 | =begin TML | ||||
1691 | |||||
1692 | ---++ ObjectMethod renderRevisionInfo($topicObject, $rev, $format) -> $string | ||||
1693 | |||||
1694 | Obtain and render revision info for a topic. | ||||
1695 | * =$topicObject= - the topic | ||||
1696 | * =$rev= - the rev number, defaults to latest rev | ||||
1697 | * =$format= - the render format, defaults to | ||||
1698 | =$rev - $time - $wikiusername=. =$format= can contain | ||||
1699 | the following keys for expansion: | ||||
1700 | | =$web= | the web name | | ||||
1701 | | =$topic= | the topic name | | ||||
1702 | | =$rev= | the rev number | | ||||
1703 | | =$username= | the login of the saving user | | ||||
1704 | | =$wikiname= | the wikiname of the saving user | | ||||
1705 | | =$wikiusername= | the web.wikiname of the saving user | | ||||
1706 | | =$date= | the date of the rev (no time) | | ||||
1707 | | =$time= | the time of the rev | | ||||
1708 | | =$min=, =$sec=, etc. | Same date format qualifiers as GMTIME | | ||||
1709 | |||||
1710 | =cut | ||||
1711 | |||||
1712 | # spent 4.66ms (1.08+3.58) within Foswiki::Render::renderRevisionInfo which was called 6 times, avg 776µs/call:
# 6 times (1.08ms+3.58ms) by Foswiki::REVINFO at line 38 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/REVINFO.pm, avg 776µs/call | ||||
1713 | 196 | 1.33ms | my ( $this, $topicObject, $rrev, $format ) = @_; | ||
1714 | my $value = $format || 'r$rev - $date - $time - $wikiusername'; | ||||
1715 | |||||
1716 | # nop if there are no format tokens | ||||
1717 | 6 | 40µs | return $value # spent 40µs making 6 calls to Foswiki::Render::CORE:match, avg 7µs/call | ||
1718 | unless $value =~ | ||||
1719 | /\$(year|ye|wikiusername|wikiname|week|web|wday|username|tz|topic|time|seconds|sec|rev|rcs|month|mo|minutes|min|longdate|isotz|iso|http|hours|hou|epoch|email|dow|day|date)/x; | ||||
1720 | |||||
1721 | my $users = $this->{session}->{users}; | ||||
1722 | if ($rrev) { | ||||
1723 | my $loadedRev = $topicObject->getLoadedRev() || 0; | ||||
1724 | unless ( $rrev == $loadedRev ) { | ||||
1725 | $topicObject = Foswiki::Meta->new($topicObject); | ||||
1726 | $topicObject = $topicObject->load($rrev); | ||||
1727 | } | ||||
1728 | } | ||||
1729 | 6 | 350µs | my $info = $topicObject->getRevisionInfo(); # spent 350µs making 6 calls to Foswiki::Meta::getRevisionInfo, avg 58µs/call | ||
1730 | |||||
1731 | my $wun = ''; | ||||
1732 | my $wn = ''; | ||||
1733 | my $un = ''; | ||||
1734 | if ( $info->{author} ) { | ||||
1735 | 6 | 159µs | my $cUID = $users->getCanonicalUserID( $info->{author} ); # spent 159µs making 6 calls to Foswiki::Users::getCanonicalUserID, avg 26µs/call | ||
1736 | |||||
1737 | #pre-set cuid if author is the unknown user from the basemapper (ie, default value) to avoid further guesswork | ||||
1738 | $cUID = $info->{author} | ||||
1739 | if ( $info->{author} eq | ||||
1740 | $Foswiki::Users::BaseUserMapping::UNKNOWN_USER_CUID ); | ||||
1741 | if ( !$cUID ) { | ||||
1742 | my $ln = $users->getLoginName( $info->{author} ); | ||||
1743 | $cUID = $info->{author} | ||||
1744 | if ( defined($ln) and ( $ln ne 'unknown' ) ); | ||||
1745 | } | ||||
1746 | if ($cUID) { | ||||
1747 | 6 | 170µs | $wun = $users->webDotWikiName($cUID); # spent 170µs making 6 calls to Foswiki::Users::webDotWikiName, avg 28µs/call | ||
1748 | 6 | 46µs | $wn = $users->getWikiName($cUID); # spent 46µs making 6 calls to Foswiki::Users::getWikiName, avg 8µs/call | ||
1749 | 6 | 51µs | $un = $users->getLoginName($cUID); # spent 51µs making 6 calls to Foswiki::Users::getLoginName, avg 9µs/call | ||
1750 | } | ||||
1751 | |||||
1752 | #only do the legwork if we really have to | ||||
1753 | if ( not( defined($wun) and defined($wn) and defined($un) ) | ||||
1754 | or ( ( $wun eq '' ) or ( $wn eq '' ) or ( $un eq '' ) ) ) | ||||
1755 | { | ||||
1756 | my $user = $info->{author}; | ||||
1757 | |||||
1758 | # If we are still unsure, then use whatever is saved in the meta. | ||||
1759 | # But obscure it if the RenderLoggedInButUnknownUsers is enabled. | ||||
1760 | if ( $Foswiki::cfg{RenderLoggedInButUnknownUsers} ) { | ||||
1761 | $user = $info->{author} = 'unknown'; | ||||
1762 | } | ||||
1763 | else { | ||||
1764 | |||||
1765 | #cUID's are forced to ascii by escaping other chars.. | ||||
1766 | #$cUID =~ s/([^a-zA-Z0-9])/'_'.sprintf('%02x', ord($1))/ge; | ||||
1767 | |||||
1768 | #remove any SomeMapping_ prefix from the cuid - as that initial '_' is not escaped. | ||||
1769 | $user =~ s/^[A-Z][A-Za-z]+Mapping_//; | ||||
1770 | |||||
1771 | #and then xform any escaped chars. | ||||
1772 | 2 | 102µs | 2 | 54µs | # spent 45µs (35+10) within Foswiki::Render::BEGIN@1772 which was called:
# once (35µs+10µs) by Foswiki::renderer at line 1772 # spent 45µs making 1 call to Foswiki::Render::BEGIN@1772
# spent 10µs making 1 call to bytes::import |
1773 | $user =~ s/_([0-9a-f][0-9a-f])/chr(hex($1))/ge; | ||||
1774 | 2 | 3.12ms | 2 | 36µs | # spent 27µs (19+9) within Foswiki::Render::BEGIN@1774 which was called:
# once (19µs+9µs) by Foswiki::renderer at line 1774 # spent 27µs making 1 call to Foswiki::Render::BEGIN@1774
# spent 9µs making 1 call to bytes::unimport |
1775 | } | ||||
1776 | $wun ||= $user; | ||||
1777 | $wn ||= $user; | ||||
1778 | $un ||= $user; | ||||
1779 | } | ||||
1780 | } | ||||
1781 | |||||
1782 | 6 | 14µs | $value =~ s/\$web/$topicObject->web() || ''/ge; # spent 14µs making 6 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
1783 | 6 | 9µs | $value =~ s/\$topic\(([^\)]*)\)/ # spent 9µs making 6 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
1784 | Foswiki::Render::breakName( $topicObject->topic(), $1 )/ge; | ||||
1785 | 6 | 9µs | $value =~ s/\$topic/$topicObject->topic() || ''/ge; # spent 9µs making 6 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
1786 | 16 | 52µs | $value =~ s/\$rev/$info->{version}/g; # spent 28µs making 6 calls to Foswiki::Render::CORE:subst, avg 5µs/call
# spent 24µs making 10 calls to Foswiki::Render::CORE:substcont, avg 2µs/call | ||
1787 | 10 | 22µs | $value =~ s/\$time/ # spent 13µs making 6 calls to Foswiki::Render::CORE:subst, avg 2µs/call
# spent 9µs making 4 calls to Foswiki::Render::CORE:substcont, avg 2µs/call | ||
1788 | 2 | 518µs | Foswiki::Time::formatTime($info->{date}, '$hour:$min:$sec')/ge; # spent 518µs making 2 calls to Foswiki::Time::formatTime, avg 259µs/call | ||
1789 | 12 | 30µs | $value =~ s/\$date/ # spent 15µs making 6 calls to Foswiki::Render::CORE:subst, avg 3µs/call
# spent 15µs making 6 calls to Foswiki::Render::CORE:substcont, avg 2µs/call | ||
1790 | 3 | 550µs | Foswiki::Time::formatTime( # spent 550µs making 3 calls to Foswiki::Time::formatTime, avg 183µs/call | ||
1791 | $info->{date}, $Foswiki::cfg{DefaultDateFormat} )/ge; | ||||
1792 | 19 | 63µs | $value =~ s/(\$(rcs|longdate|isotz|iso|http|email|))/ # spent 44µs making 13 calls to Foswiki::Render::CORE:substcont, avg 3µs/call
# spent 19µs making 6 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
1793 | 11 | 1.43ms | Foswiki::Time::formatTime($info->{date}, $1 )/ge; # spent 1.43ms making 11 calls to Foswiki::Time::formatTime, avg 130µs/call | ||
1794 | |||||
1795 | 6 | 17µs | if ( $value =~ # spent 17µs making 6 calls to Foswiki::Render::CORE:match, avg 3µs/call | ||
1796 | /\$(year|ye|week|web|wday|username|tz|seconds|sec|rcs|month|mo|minutes|min|longdate|hours|hou|epoch|dow|day)/ | ||||
1797 | ) | ||||
1798 | { | ||||
1799 | $value = Foswiki::Time::formatTime( $info->{date}, $value ); | ||||
1800 | } | ||||
1801 | 6 | 9µs | $value =~ s/\$username/$un/g; # spent 9µs making 6 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
1802 | 6 | 17µs | $value =~ s/\$wikiname/$wn/g; # spent 17µs making 6 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
1803 | 6 | 17µs | $value =~ s/\$wikiusername/$wun/g; # spent 17µs making 6 calls to Foswiki::Render::CORE:subst, avg 3µs/call | ||
1804 | |||||
1805 | return $value; | ||||
1806 | } | ||||
1807 | |||||
1808 | =begin TML | ||||
1809 | |||||
1810 | ---++ ObjectMethod forEachLine( $text, \&fn, \%options ) -> $newText | ||||
1811 | |||||
1812 | Iterate over each line, calling =\&fn= on each. | ||||
1813 | \%options may contain: | ||||
1814 | * =pre= => true, will call fn for each line in pre blocks | ||||
1815 | * =verbatim= => true, will call fn for each line in verbatim blocks | ||||
1816 | * =literal= => true, will call fn for each line in literal blocks | ||||
1817 | * =noautolink= => true, will call fn for each line in =noautolink= blocks | ||||
1818 | The spec of \&fn is =sub fn( $line, \%options ) -> $newLine=. The %options | ||||
1819 | hash passed into this function is passed down to the sub, and the keys | ||||
1820 | =in_literal=, =in_pre=, =in_verbatim= and =in_noautolink= are set boolean | ||||
1821 | TRUE if the line is from one (or more) of those block types. | ||||
1822 | |||||
1823 | The return result replaces $line in $newText. | ||||
1824 | |||||
1825 | =cut | ||||
1826 | |||||
1827 | # spent 3.16ms (1.42+1.74) within Foswiki::Render::forEachLine which was called 4 times, avg 790µs/call:
# 4 times (1.42ms+1.74ms) by Foswiki::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm:326] at line 312 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm, avg 790µs/call | ||||
1828 | 332 | 1.87ms | my ( $this, $text, $fn, $options ) = @_; | ||
1829 | |||||
1830 | return '' unless defined $text; | ||||
1831 | |||||
1832 | $options->{in_pre} = 0; | ||||
1833 | $options->{in_pre} = 0; | ||||
1834 | $options->{in_verbatim} = 0; | ||||
1835 | $options->{in_literal} = 0; | ||||
1836 | $options->{in_noautolink} = 0; | ||||
1837 | my $newText = ''; | ||||
1838 | foreach my $line ( split( /([\r\n]+)/, $text ) ) { | ||||
1839 | 34 | 88µs | if ( $line =~ /[\r\n]/ ) { # spent 88µs making 34 calls to Foswiki::Render::CORE:match, avg 3µs/call | ||
1840 | $newText .= $line; | ||||
1841 | next; | ||||
1842 | } | ||||
1843 | 19 | 67µs | $options->{in_verbatim}++ if ( $line =~ m|^\s*<verbatim\b[^>]*>\s*$|i ); # spent 67µs making 19 calls to Foswiki::Render::CORE:match, avg 4µs/call | ||
1844 | 19 | 47µs | $options->{in_verbatim}-- if ( $line =~ m|^\s*</verbatim>\s*$|i ); # spent 47µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1845 | 19 | 45µs | $options->{in_literal}++ if ( $line =~ m|^\s*<literal\b[^>]*>\s*$|i ); # spent 45µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1846 | 19 | 44µs | $options->{in_literal}-- if ( $line =~ m|^\s*</literal>\s*$|i ); # spent 44µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1847 | unless ( ( $options->{in_verbatim} > 0 ) | ||||
1848 | || ( ( $options->{in_literal} > 0 ) ) ) | ||||
1849 | { | ||||
1850 | 19 | 42µs | $options->{in_pre}++ if ( $line =~ m|<pre\b|i ); # spent 42µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1851 | 19 | 36µs | $options->{in_pre}-- if ( $line =~ m|</pre>|i ); # spent 36µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1852 | 19 | 48µs | $options->{in_noautolink}++ # spent 48µs making 19 calls to Foswiki::Render::CORE:match, avg 3µs/call | ||
1853 | if ( $line =~ m|^\s*<noautolink\b[^>]*>\s*$|i ); | ||||
1854 | 19 | 44µs | $options->{in_noautolink}-- # spent 44µs making 19 calls to Foswiki::Render::CORE:match, avg 2µs/call | ||
1855 | if ( $line =~ m|^\s*</noautolink>\s*|i ); | ||||
1856 | } | ||||
1857 | unless ( $options->{in_pre} > 0 && !$options->{pre} | ||||
1858 | || $options->{in_verbatim} > 0 && !$options->{verbatim} | ||||
1859 | || $options->{in_literal} > 0 && !$options->{literal} | ||||
1860 | || $options->{in_noautolink} > 0 && !$options->{noautolink} ) | ||||
1861 | { | ||||
1862 | 19 | 1.28ms | $line = &$fn( $line, $options ); # spent 1.28ms making 19 calls to Foswiki::_fixupIncludedTopic, avg 68µs/call | ||
1863 | } | ||||
1864 | $newText .= $line; | ||||
1865 | } | ||||
1866 | return $newText; | ||||
1867 | } | ||||
1868 | |||||
1869 | =begin TML | ||||
1870 | |||||
1871 | ---++ StaticMethod getReferenceRE($web, $topic, %options) -> $re | ||||
1872 | |||||
1873 | * $web, $topic - specify the topic being referred to, or web if $topic is | ||||
1874 | undef. | ||||
1875 | * %options - the following options are available | ||||
1876 | * =interweb= - if true, then fully web-qualified references are required. | ||||
1877 | * =grep= - if true, generate a GNU-grep compatible RE instead of the | ||||
1878 | default Perl RE. | ||||
1879 | * =nosot= - If true, do not generate "Spaced out text" match | ||||
1880 | * =template= - If true, match for template setting in Set/Local statement | ||||
1881 | * =in_noautolink= - Only match explicit (squabbed) WikiWords. Used in <noautolink> blocks | ||||
1882 | * =inMeta= - Re should match exact string. No delimiters needed. | ||||
1883 | * =url= - if set, generates an expression that will match a Foswiki | ||||
1884 | URL that points to the web/topic, instead of the default which | ||||
1885 | matches topic links in plain text. | ||||
1886 | Generate a regular expression that can be used to match references to the | ||||
1887 | specified web/topic. Note that the resultant RE will only match fully | ||||
1888 | qualified (i.e. with web specifier) topic names and topic names that | ||||
1889 | are wikiwords in text. Works for spaced-out wikiwords for topic names. | ||||
1890 | |||||
1891 | The RE returned is designed to be used with =s///= | ||||
1892 | |||||
1893 | =cut | ||||
1894 | |||||
1895 | sub getReferenceRE { | ||||
1896 | my ( $web, $topic, %options ) = @_; | ||||
1897 | |||||
1898 | my $matchWeb = $web; | ||||
1899 | |||||
1900 | # Convert . and / to [./] (subweb separators) and quote | ||||
1901 | # special characters | ||||
1902 | $matchWeb =~ s#[./]#$REMARKER#g; | ||||
1903 | $matchWeb = quotemeta($matchWeb); | ||||
1904 | |||||
1905 | # SMELL: Item10176 - Adding doublequote as a WikiWord delimiter. This causes non-linking quoted | ||||
1906 | # WikiWords in tml to be incorrectly renamed. But does handle quoted topic names inside macro parameters. | ||||
1907 | # But this doesn't really fully fix the issue - $quotWikiWord for example. | ||||
1908 | my $reSTARTWW = qr/^|(?<=[\s"\*=_\(])/m; | ||||
1909 | my $reENDWW = qr/$|(?=[\s"\*#=_,.;:!?)])/m; | ||||
1910 | |||||
1911 | # $REMARKER is escaped by quotemeta so we need to match the escape | ||||
1912 | $matchWeb =~ s#\\$REMARKER#[./]#go; | ||||
1913 | |||||
1914 | # Item1468/5791 - Quote special characters | ||||
1915 | $topic = quotemeta($topic) if defined $topic; | ||||
1916 | |||||
1917 | # Note use of \b to match the empty string at the | ||||
1918 | # edges of a word. | ||||
1919 | my ( $bow, $eow, $forward, $back ) = ( '\b_?', '_?\b', '?=', '?<=' ); | ||||
1920 | if ( $options{grep} ) { | ||||
1921 | $bow = '\b_?'; | ||||
1922 | $eow = '_?\b'; | ||||
1923 | $forward = ''; | ||||
1924 | $back = ''; | ||||
1925 | } | ||||
1926 | my $squabo = "($back\\[\\[)"; | ||||
1927 | my $squabc = "($forward(?:#.*?)?\\][][])"; | ||||
1928 | |||||
1929 | my $re = ''; | ||||
1930 | |||||
1931 | if ( $options{url} ) { | ||||
1932 | |||||
1933 | # URL fragment. Assume / separator (while . is legal, it's | ||||
1934 | # undocumented and is not common usage) | ||||
1935 | $re = "/$web/"; | ||||
1936 | $re .= $topic . $eow if $topic; | ||||
1937 | } | ||||
1938 | else { | ||||
1939 | if ( defined($topic) ) { | ||||
1940 | |||||
1941 | my $sot; | ||||
1942 | unless ( $options{nosot} ) { | ||||
1943 | |||||
1944 | # Work out spaced-out version (allows lc first chars on words) | ||||
1945 | $sot = Foswiki::spaceOutWikiWord( $topic, ' *' ); | ||||
1946 | if ( $sot ne $topic ) { | ||||
1947 | $sot =~ s/\b([a-zA-Z])/'['.uc($1).lc($1).']'/ge; | ||||
1948 | } | ||||
1949 | else { | ||||
1950 | $sot = undef; | ||||
1951 | } | ||||
1952 | } | ||||
1953 | |||||
1954 | if ( $options{interweb} ) { | ||||
1955 | |||||
1956 | # Require web specifier | ||||
1957 | if ( $options{grep} ) { | ||||
1958 | $re = "$bow$matchWeb\\.$topic$eow"; | ||||
1959 | } | ||||
1960 | elsif ( $options{template} ) { | ||||
1961 | |||||
1962 | # $1 is used in replace. Can't use lookbehind because of variable length restriction | ||||
1963 | $re = '(' | ||||
1964 | . $Foswiki::regex{setRegex} | ||||
1965 | . '(?:VIEW|EDIT)_TEMPLATE\s*=\s*)(' | ||||
1966 | . $matchWeb . '\\.' | ||||
1967 | . $topic . ')\s*$'; | ||||
1968 | } | ||||
1969 | elsif ( $options{in_noautolink} ) { | ||||
1970 | $re = "$squabo$matchWeb\\.$topic$squabc"; | ||||
1971 | } | ||||
1972 | else { | ||||
1973 | $re = "$reSTARTWW$matchWeb\\.$topic$reENDWW"; | ||||
1974 | } | ||||
1975 | |||||
1976 | # Matching of spaced out topic names. | ||||
1977 | if ($sot) { | ||||
1978 | |||||
1979 | # match spaced out in squabs only | ||||
1980 | $re .= "|$squabo$matchWeb\\.$sot$squabc"; | ||||
1981 | } | ||||
1982 | } | ||||
1983 | else { | ||||
1984 | |||||
1985 | # Optional web specifier - but *only* if the topic name | ||||
1986 | # is a wikiword | ||||
1987 | if ( $topic =~ /$Foswiki::regex{wikiWordRegex}/ ) { | ||||
1988 | |||||
1989 | # Bit of jigger-pokery at the front to avoid matching | ||||
1990 | # subweb specifiers | ||||
1991 | if ( $options{grep} ) { | ||||
1992 | $re = "(($back\[^./])|^)$bow($matchWeb\\.)?$topic$eow"; | ||||
1993 | } | ||||
1994 | elsif ( $options{template} ) { | ||||
1995 | |||||
1996 | # $1 is used in replace. Can't use lookbehind because of variable length restriction | ||||
1997 | $re = '(' | ||||
1998 | . $Foswiki::regex{setRegex} | ||||
1999 | . '(?:VIEW|EDIT)_TEMPLATE\s*=\s*)' | ||||
2000 | . "($matchWeb\\.)?$topic" . '\s*$'; | ||||
2001 | } | ||||
2002 | elsif ( $options{in_noautolink} ) { | ||||
2003 | $re = "$squabo($matchWeb\\.)?$topic$squabc"; | ||||
2004 | } | ||||
2005 | else { | ||||
2006 | $re = "$reSTARTWW($matchWeb\\.)?$topic$reENDWW"; | ||||
2007 | } | ||||
2008 | |||||
2009 | if ($sot) { | ||||
2010 | |||||
2011 | # match spaced out in squabs only | ||||
2012 | $re .= "|$squabo($matchWeb\\.)?$sot$squabc"; | ||||
2013 | } | ||||
2014 | } | ||||
2015 | else { | ||||
2016 | if ( $options{inMeta} ) { | ||||
2017 | $re = "^($matchWeb\\.)?$topic\$" | ||||
2018 | ; # Updating a META item, Exact match, no delimiters | ||||
2019 | } | ||||
2020 | else { | ||||
2021 | |||||
2022 | # Non-wikiword; require web specifier or squabs | ||||
2023 | $re = "$squabo$topic$squabc"; # Squabbed topic | ||||
2024 | $re .= "|\"($matchWeb\\.)?$topic\"" | ||||
2025 | ; # Quoted string in Meta and Macros | ||||
2026 | $re .= "|(($back\[^./])|^)$bow$matchWeb\\.$topic$eow" | ||||
2027 | unless ( $options{in_noautolink} ) | ||||
2028 | ; # Web qualified topic outside of autolink blocks. | ||||
2029 | } | ||||
2030 | } | ||||
2031 | } | ||||
2032 | } | ||||
2033 | else { | ||||
2034 | |||||
2035 | # Searching for a web | ||||
2036 | # SMELL: Does this web search also need to allow for quoted | ||||
2037 | # "Web.Topic" strings found in macros and META usage? | ||||
2038 | |||||
2039 | if ( $options{interweb} ) { | ||||
2040 | |||||
2041 | if ( $options{in_noautolink} ) { | ||||
2042 | |||||
2043 | # web name used to refer to a topic | ||||
2044 | $re = | ||||
2045 | $squabo | ||||
2046 | . $matchWeb | ||||
2047 | . "(\.[$Foswiki::regex{mixedAlphaNum}]+)" | ||||
2048 | . $squabc; | ||||
2049 | } | ||||
2050 | else { | ||||
2051 | $re = | ||||
2052 | $bow | ||||
2053 | . $matchWeb | ||||
2054 | . "(\.[$Foswiki::regex{mixedAlphaNum}]+)" | ||||
2055 | . $eow; | ||||
2056 | } | ||||
2057 | } | ||||
2058 | else { | ||||
2059 | |||||
2060 | # most general search for a reference to a topic or subweb | ||||
2061 | # note that Foswiki::UI::Rename::_replaceWebReferences() | ||||
2062 | # uses $1 from this regex | ||||
2063 | if ( $options{in_noautolink} ) { | ||||
2064 | $re = | ||||
2065 | $squabo | ||||
2066 | . $matchWeb | ||||
2067 | . "(([\/\.][$Foswiki::regex{upperAlpha}]" | ||||
2068 | . "[$Foswiki::regex{mixedAlphaNum}_]*)+" | ||||
2069 | . "\.[$Foswiki::regex{mixedAlphaNum}]*)" | ||||
2070 | . $squabc; | ||||
2071 | } | ||||
2072 | else { | ||||
2073 | $re = | ||||
2074 | $bow | ||||
2075 | . $matchWeb | ||||
2076 | . "(([\/\.][$Foswiki::regex{upperAlpha}]" | ||||
2077 | . "[$Foswiki::regex{mixedAlphaNum}_]*)+" | ||||
2078 | . "\.[$Foswiki::regex{mixedAlphaNum}]*)" | ||||
2079 | . $eow; | ||||
2080 | } | ||||
2081 | } | ||||
2082 | } | ||||
2083 | } | ||||
2084 | |||||
2085 | #my $optsx = ''; | ||||
2086 | #$optsx .= "NOSOT=$options{nosot} " if ($options{nosot}); | ||||
2087 | #$optsx .= "GREP=$options{grep} " if ($options{grep}); | ||||
2088 | #$optsx .= "URL=$options{url} " if ($options{url}); | ||||
2089 | #$optsx .= "INNOAUTOLINK=$options{in_noautolink} " if ($options{in_noautolink}); | ||||
2090 | #$optsx .= "INTERWEB=$options{interweb} " if ($options{interweb}); | ||||
2091 | #print STDERR "ReferenceRE returns $re $optsx \n"; | ||||
2092 | return $re; | ||||
2093 | } | ||||
2094 | |||||
2095 | =begin TML | ||||
2096 | |||||
2097 | ---++ StaticMethod breakName( $text, $args) -> $text | ||||
2098 | |||||
2099 | * =$text= - text to "break" | ||||
2100 | * =$args= - string of format (\d+)([,\s*]\.\.\.)?) | ||||
2101 | Hyphenates $text every $1 characters, or if $2 is "..." then shortens to | ||||
2102 | $1 characters and appends "..." (making the final string $1+3 characters | ||||
2103 | long) | ||||
2104 | |||||
2105 | _Moved from Search.pm because it was obviously unhappy there, | ||||
2106 | as it is a rendering function_ | ||||
2107 | |||||
2108 | =cut | ||||
2109 | |||||
2110 | sub breakName { | ||||
2111 | my ( $text, $args ) = @_; | ||||
2112 | |||||
2113 | my @params = split( /[\,\s]+/, $args, 2 ); | ||||
2114 | if (@params) { | ||||
2115 | my $len = $params[0] || 1; | ||||
2116 | $len = 1 if ( $len < 1 ); | ||||
2117 | my $sep = '- '; | ||||
2118 | $sep = $params[1] if ( @params > 1 ); | ||||
2119 | if ( $sep =~ /^\.\.\./i ) { | ||||
2120 | |||||
2121 | # make name shorter like 'ThisIsALongTop...' | ||||
2122 | $text =~ s/(.{$len})(.+)/$1.../s; | ||||
2123 | |||||
2124 | } | ||||
2125 | else { | ||||
2126 | |||||
2127 | # split and hyphenate the topic like 'ThisIsALo- ngTopic' | ||||
2128 | $text =~ s/(.{$len})/$1$sep/gs; | ||||
2129 | $text =~ s/$sep$//; | ||||
2130 | } | ||||
2131 | } | ||||
2132 | return $text; | ||||
2133 | } | ||||
2134 | |||||
2135 | =begin TML | ||||
2136 | |||||
2137 | ---++ StaticMethod protectFormFieldValue($value, $attrs) -> $html | ||||
2138 | |||||
2139 | Given the value of a form field, and a set of attributes that control how | ||||
2140 | to display that value, protect the value from further processing. | ||||
2141 | |||||
2142 | The protected value is determined from the value of the field after: | ||||
2143 | * newlines are replaced with <br> or the value of $attrs->{newline} | ||||
2144 | * processing through breakName if $attrs->{break} is defined | ||||
2145 | * escaping of $vars if $attrs->{protectdollar} is defined | ||||
2146 | * | is replaced with &#124; or the value of $attrs->{bar} if defined | ||||
2147 | |||||
2148 | =cut | ||||
2149 | |||||
2150 | # spent 420µs (377+43) within Foswiki::Render::protectFormFieldValue which was called 14 times, avg 30µs/call:
# 14 times (377µs+43µs) by Foswiki::Form::FieldDefinition::renderForDisplay at line 347 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Form/FieldDefinition.pm, avg 30µs/call | ||||
2151 | 154 | 435µs | my ( $value, $attrs ) = @_; | ||
2152 | |||||
2153 | $value = '' unless defined($value); | ||||
2154 | |||||
2155 | if ( $attrs && $attrs->{break} ) { | ||||
2156 | $value =~ s/^\s*(.*?)\s*$/$1/g; | ||||
2157 | $value = breakName( $value, $attrs->{break} ); | ||||
2158 | } | ||||
2159 | |||||
2160 | # Item3489, Item2837. Prevent $vars in formfields from | ||||
2161 | # being expanded in formatted searches. | ||||
2162 | if ( $attrs && $attrs->{protectdollar} ) { | ||||
2163 | $value =~ s/\$(n|nop|quot|percnt|dollar)/\$<nop>$1/g; | ||||
2164 | } | ||||
2165 | |||||
2166 | # change newlines | ||||
2167 | my $newline = '<br />'; | ||||
2168 | if ( $attrs && defined $attrs->{newline} ) { | ||||
2169 | $newline = $attrs->{newline}; | ||||
2170 | $newline =~ s/\$n/\n/gs; | ||||
2171 | } | ||||
2172 | 14 | 24µs | $value =~ s/\r?\n/$newline/gs; # spent 24µs making 14 calls to Foswiki::Render::CORE:subst, avg 2µs/call | ||
2173 | |||||
2174 | # change vbars | ||||
2175 | my $bar = '|'; | ||||
2176 | if ( $attrs && $attrs->{bar} ) { | ||||
2177 | $bar = $attrs->{bar}; | ||||
2178 | } | ||||
2179 | 14 | 19µs | $value =~ s/\|/$bar/g; # spent 19µs making 14 calls to Foswiki::Render::CORE:subst, avg 1µs/call | ||
2180 | |||||
2181 | return $value; | ||||
2182 | } | ||||
2183 | |||||
2184 | =begin TML | ||||
2185 | |||||
2186 | ---++ ObjectMethod getAnchors( $topicObject ) -> $set | ||||
2187 | |||||
2188 | Get the anchor name set generated for the given topic. This is so that the | ||||
2189 | same anchor names can be generated for each time the same topic is | ||||
2190 | %INCLUDEd (the same anchor target will be generated for each time the | ||||
2191 | topic is included. | ||||
2192 | |||||
2193 | Note that anchor names generated this way are unique since the last time the | ||||
2194 | anchor set is cleared, which happens (1) whenever a new session is started | ||||
2195 | and (2) whenever a new %TOC macro is rendered (see Foswiki/Macros/TOC). | ||||
2196 | |||||
2197 | Returns an object of type Foswiki::Render::Anchors. | ||||
2198 | |||||
2199 | =cut | ||||
2200 | |||||
2201 | # spent 240µs (149+91) within Foswiki::Render::getAnchorNames which was called 5 times, avg 48µs/call:
# 5 times (149µs+91µs) by Foswiki::Render::getRenderedVersion at line 1234, avg 48µs/call | ||||
2202 | 27 | 126µs | my ( $this, $topicObject ) = @_; | ||
2203 | 5 | 68µs | my $id = $topicObject->getPath(); # spent 68µs making 5 calls to Foswiki::Meta::getPath, avg 14µs/call | ||
2204 | my $a = $this->{_anchorNames}{$id}; | ||||
2205 | unless ($a) { | ||||
2206 | 1 | 23µs | $a = new Foswiki::Render::Anchors(); # spent 23µs making 1 call to Foswiki::Render::Anchors::new | ||
2207 | $this->{_anchorNames}{$id} = $a; | ||||
2208 | } | ||||
2209 | return $a; | ||||
2210 | } | ||||
2211 | |||||
2212 | =begin TML | ||||
2213 | |||||
2214 | ---++ ObjectMethod renderIconImage($url [, $alt]) -> $html | ||||
2215 | Generate the output for representing an 16x16 icon image. The source of | ||||
2216 | the image is taken from =$url=. The optional =$alt= specifies an alt string. | ||||
2217 | |||||
2218 | re-written using TMPL:DEF{icon:image} in Foswiki.tmpl | ||||
2219 | %TMPL:DEF{"icon:image"}%<span class='foswikiIcon'><img src="%URL%" width="%WIDTH%" height="%HEIGHT%" alt="%ALT%" /></span>%TMPL:END% | ||||
2220 | see System.SkinTemplates:base.css for the default of .foswikiIcon img | ||||
2221 | |||||
2222 | TODO: Sven's not sure this code belongs here - its only use appears to be the ICON macro | ||||
2223 | |||||
2224 | =cut | ||||
2225 | |||||
2226 | sub renderIconImage { | ||||
2227 | my ( $this, $url, $alt ) = @_; | ||||
2228 | |||||
2229 | if ( !defined($alt) ) { | ||||
2230 | |||||
2231 | #yes, you really should have a useful alt text. | ||||
2232 | $alt = $url; | ||||
2233 | } | ||||
2234 | |||||
2235 | my $html = $this->{session}->templates->expandTemplate("icon:image"); | ||||
2236 | $html =~ s/%URL%/$url/ge; | ||||
2237 | $html =~ s/%WIDTH%/16/g; | ||||
2238 | $html =~ s/%HEIGHT%/16/g; | ||||
2239 | $html =~ s/%ALT%/$alt/ge; | ||||
2240 | |||||
2241 | return $html; | ||||
2242 | } | ||||
2243 | |||||
2244 | 1 | 16µs | 1; | ||
2245 | __END__ | ||||
# spent 3.25ms within Foswiki::Render::CORE:match which was called 1339 times, avg 2µs/call:
# 561 times (1.37ms+0s) by Foswiki::Render::getRenderedVersion at line 1292, avg 2µs/call
# 235 times (455µs+0s) by Foswiki::Render::getRenderedVersion at line 1268, avg 2µs/call
# 67 times (229µs+0s) by Foswiki::Render::getRenderedVersion at line 1302, avg 3µs/call
# 50 times (142µs+0s) by Foswiki::Render::_linkToolTipInfo at line 474, avg 3µs/call
# 41 times (80µs+0s) by Foswiki::Render::_putBackProtected at line 1682, avg 2µs/call
# 40 times (140µs+0s) by Foswiki::Render::_handleWikiWord at line 758, avg 3µs/call
# 40 times (95µs+0s) by Foswiki::Render::_handleWikiWord at line 763, avg 2µs/call
# 34 times (88µs+0s) by Foswiki::Render::forEachLine at line 1839, avg 3µs/call
# 34 times (85µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 816, avg 2µs/call
# 32 times (62µs+0s) by Foswiki::Render::_isImageLink at line 902, avg 2µs/call
# 32 times (51µs+0s) by Foswiki::Render::_isImageLink at line 905, avg 2µs/call
# 19 times (67µs+0s) by Foswiki::Render::forEachLine at line 1843, avg 4µs/call
# 19 times (48µs+0s) by Foswiki::Render::forEachLine at line 1852, avg 3µs/call
# 19 times (47µs+0s) by Foswiki::Render::forEachLine at line 1844, avg 2µs/call
# 19 times (45µs+0s) by Foswiki::Render::forEachLine at line 1845, avg 2µs/call
# 19 times (44µs+0s) by Foswiki::Render::forEachLine at line 1854, avg 2µs/call
# 19 times (44µs+0s) by Foswiki::Render::forEachLine at line 1846, avg 2µs/call
# 19 times (42µs+0s) by Foswiki::Render::forEachLine at line 1850, avg 2µs/call
# 19 times (36µs+0s) by Foswiki::Render::forEachLine at line 1851, avg 2µs/call
# 7 times (11µs+0s) by Foswiki::Render::renderFORMFIELD at line 1058, avg 2µs/call
# 6 times (40µs+0s) by Foswiki::Render::renderRevisionInfo at line 1717, avg 7µs/call
# 6 times (17µs+0s) by Foswiki::Render::renderRevisionInfo at line 1795, avg 3µs/call
# 2 times (10µs+0s) by Foswiki::Render::_externalLink at line 922, avg 5µs/call | |||||
# spent 137µs within Foswiki::Render::CORE:qr which was called 27 times, avg 5µs/call:
# 5 times (43µs+0s) by Foswiki::Render::getRenderedVersion at line 1119, avg 9µs/call
# 5 times (28µs+0s) by Foswiki::Render::getRenderedVersion at line 1130, avg 6µs/call
# 5 times (19µs+0s) by Foswiki::Render::getRenderedVersion at line 1122, avg 4µs/call
# 5 times (19µs+0s) by Foswiki::Render::getRenderedVersion at line 1128, avg 4µs/call
# 5 times (19µs+0s) by Foswiki::Render::getRenderedVersion at line 1125, avg 4µs/call
# once (6µs+0s) by Foswiki::renderer at line 27
# once (3µs+0s) by Foswiki::renderer at line 28 | |||||
# spent 2.62ms within Foswiki::Render::CORE:regcomp which was called 749 times, avg 4µs/call:
# 72 times (105µs+0s) by Foswiki::Render::internalLink at line 592, avg 1µs/call
# 72 times (104µs+0s) by Foswiki::Render::internalLink at line 585, avg 1µs/call
# 41 times (147µs+0s) by Foswiki::Render::_putBackProtected at line 1682, avg 4µs/call
# 40 times (71µs+0s) by Foswiki::Render::_handleWikiWord at line 758, avg 2µs/call
# 40 times (63µs+0s) by Foswiki::Render::_handleWikiWord at line 763, avg 2µs/call
# 34 times (171µs+0s) by Foswiki::Render::_escapeAutoLinks at line 776, avg 5µs/call
# 34 times (107µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 816, avg 3µs/call
# 34 times (86µs+0s) by Foswiki::Render::_escapeAutoLinks at line 787, avg 3µs/call
# 32 times (95µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 847, avg 3µs/call
# 32 times (78µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 848, avg 2µs/call
# 32 times (75µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 850, avg 2µs/call
# 32 times (73µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 852, avg 2µs/call
# 32 times (72µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 851, avg 2µs/call
# 32 times (70µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 857, avg 2µs/call
# 32 times (67µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 870, avg 2µs/call
# 32 times (50µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 878, avg 2µs/call
# 25 times (443µs+0s) by Foswiki::Render::_takeOutProtected at line 1655, avg 18µs/call
# 15 times (132µs+0s) by Foswiki::Render::_putBackProtected at line 1685, avg 9µs/call
# 6 times (27µs+0s) by Foswiki::Render::_makeAnchorHeading at line 450, avg 5µs/call
# 5 times (121µs+0s) by Foswiki::Render::getRenderedVersion at line 1407, avg 24µs/call
# 5 times (70µs+0s) by Foswiki::Render::getRenderedVersion at line 1415, avg 14µs/call
# 5 times (60µs+0s) by Foswiki::Render::getRenderedVersion at line 1401, avg 12µs/call
# 5 times (55µs+0s) by Foswiki::Render::getRenderedVersion at line 1196, avg 11µs/call
# 5 times (45µs+0s) by Foswiki::Render::getRenderedVersion at line 1383, avg 9µs/call
# 5 times (36µs+0s) by Foswiki::Render::getRenderedVersion at line 1384, avg 7µs/call
# 5 times (33µs+0s) by Foswiki::Render::getRenderedVersion at line 1239, avg 7µs/call
# 5 times (33µs+0s) by Foswiki::Render::getRenderedVersion at line 1387, avg 7µs/call
# 5 times (30µs+0s) by Foswiki::Render::getRenderedVersion at line 1386, avg 6µs/call
# 5 times (30µs+0s) by Foswiki::Render::getRenderedVersion at line 1388, avg 6µs/call
# 5 times (18µs+0s) by Foswiki::Render::getRenderedVersion at line 1228, avg 4µs/call
# 5 times (15µs+0s) by Foswiki::Render::getRenderedVersion at line 1229, avg 3µs/call
# 5 times (13µs+0s) by Foswiki::Render::getRenderedVersion at line 1221, avg 3µs/call
# 5 times (11µs+0s) by Foswiki::Render::getRenderedVersion at line 1222, avg 2µs/call
# 5 times (10µs+0s) by Foswiki::Render::getRenderedVersion at line 1250, avg 2µs/call
# 5 times (8µs+0s) by Foswiki::Render::getRenderedVersion at line 1246, avg 2µs/call | |||||
# spent 20.5ms within Foswiki::Render::CORE:subst which was called 1954 times, avg 11µs/call:
# 366 times (821µs+0s) by Foswiki::Render::getRenderedVersion at line 1302, avg 2µs/call
# 234 times (400µs+0s) by Foswiki::Render::_addListItem at line 264, avg 2µs/call
# 72 times (325µs+0s) by Foswiki::Render::internalLink at line 592, avg 5µs/call
# 72 times (324µs+0s) by Foswiki::Render::internalLink at line 569, avg 5µs/call
# 72 times (203µs+0s) by Foswiki::Render::internalLink at line 568, avg 3µs/call
# 72 times (131µs+0s) by Foswiki::Render::internalLink at line 585, avg 2µs/call
# 72 times (121µs+0s) by Foswiki::Render::internalLink at line 554, avg 2µs/call
# 50 times (89µs+0s) by Foswiki::Render::_renderExistingWikiWord at line 691, avg 2µs/call
# 34 times (292µs+0s) by Foswiki::Render::_escapeAutoLinks at line 776, avg 9µs/call
# 34 times (88µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 799, avg 3µs/call
# 34 times (68µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 800, avg 2µs/call
# 34 times (55µs+0s) by Foswiki::Render::_escapeAutoLinks at line 787, avg 2µs/call
# 32 times (84µs+0s) by Foswiki::Render::_isImageLink at line 904, avg 3µs/call
# 32 times (72µs+0s) by Foswiki::Render::_isImageLink at line 903, avg 2µs/call
# 32 times (56µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 864, avg 2µs/call
# 32 times (54µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 842, avg 2µs/call
# 32 times (54µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 878, avg 2µs/call
# 32 times (52µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 870, avg 2µs/call
# 32 times (50µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 867, avg 2µs/call
# 32 times (47µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 847, avg 1µs/call
# 32 times (46µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 850, avg 1µs/call
# 32 times (46µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 881, avg 1µs/call
# 32 times (46µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 848, avg 1µs/call
# 32 times (46µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 857, avg 1µs/call
# 32 times (43µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 851, avg 1µs/call
# 32 times (41µs+0s) by Foswiki::Render::_handleSquareBracketedLink at line 852, avg 1µs/call
# 25 times (413µs+0s) by Foswiki::Render::_takeOutProtected at line 1655, avg 17µs/call
# 15 times (111µs+0s) by Foswiki::Render::_putBackProtected at line 1685, avg 7µs/call
# 14 times (24µs+0s) by Foswiki::Render::protectFormFieldValue at line 2172, avg 2µs/call
# 14 times (19µs+0s) by Foswiki::Render::protectFormFieldValue at line 2179, avg 1µs/call
# 7 times (37µs+0s) by Foswiki::Render::renderFORMFIELD at line 1056, avg 5µs/call
# 7 times (17µs+0s) by Foswiki::Render::renderFORMFIELD at line 1055, avg 2µs/call
# 7 times (11µs+0s) by Foswiki::Render::renderFORMFIELD at line 1076, avg 2µs/call
# 7 times (10µs+0s) by Foswiki::Render::renderFORMFIELD at line 1057, avg 1µs/call
# 6 times (28µs+0s) by Foswiki::Render::renderRevisionInfo at line 1786, avg 5µs/call
# 6 times (21µs+0s) by Foswiki::Render::_makeAnchorHeading at line 450, avg 4µs/call
# 6 times (19µs+0s) by Foswiki::Render::renderRevisionInfo at line 1792, avg 3µs/call
# 6 times (17µs+0s) by Foswiki::Render::renderRevisionInfo at line 1803, avg 3µs/call
# 6 times (17µs+0s) by Foswiki::Render::renderRevisionInfo at line 1802, avg 3µs/call
# 6 times (15µs+0s) by Foswiki::Render::renderRevisionInfo at line 1789, avg 3µs/call
# 6 times (14µs+0s) by Foswiki::Render::renderRevisionInfo at line 1782, avg 2µs/call
# 6 times (13µs+0s) by Foswiki::Render::renderRevisionInfo at line 1787, avg 2µs/call
# 6 times (9µs+0s) by Foswiki::Render::renderRevisionInfo at line 1783, avg 2µs/call
# 6 times (9µs+0s) by Foswiki::Render::renderRevisionInfo at line 1801, avg 2µs/call
# 6 times (9µs+0s) by Foswiki::Render::renderRevisionInfo at line 1785, avg 1µs/call
# 5 times (6.48ms+0s) by Foswiki::Render::getRenderedVersion at line 1407, avg 1.30ms/call
# 5 times (4.77ms+0s) by Foswiki::Render::getRenderedVersion at line 1401, avg 953µs/call
# 5 times (2.00ms+0s) by Foswiki::Render::getRenderedVersion at line 1415, avg 399µs/call
# 5 times (312µs+0s) by Foswiki::Render::getRenderedVersion at line 1221, avg 62µs/call
# 5 times (301µs+0s) by Foswiki::Render::getRenderedVersion at line 1222, avg 60µs/call
# 5 times (208µs+0s) by Foswiki::Render::getRenderedVersion at line 1204, avg 42µs/call
# 5 times (161µs+0s) by Foswiki::Render::getRenderedVersion at line 1205, avg 32µs/call
# 5 times (145µs+0s) by Foswiki::Render::getRenderedVersion at line 1388, avg 29µs/call
# 5 times (107µs+0s) by Foswiki::Render::getRenderedVersion at line 1212, avg 21µs/call
# 5 times (93µs+0s) by Foswiki::Render::getRenderedVersion at line 1200, avg 19µs/call
# 5 times (93µs+0s) by Foswiki::Render::getRenderedVersion at line 1228, avg 19µs/call
# 5 times (92µs+0s) by Foswiki::Render::getRenderedVersion at line 1108, avg 18µs/call
# 5 times (92µs+0s) by Foswiki::Render::getRenderedVersion at line 1196, avg 18µs/call
# 5 times (80µs+0s) by Foswiki::Render::getRenderedVersion at line 1226, avg 16µs/call
# 5 times (80µs+0s) by Foswiki::Render::getRenderedVersion at line 1211, avg 16µs/call
# 5 times (76µs+0s) by Foswiki::Render::getRenderedVersion at line 1246, avg 15µs/call
# 5 times (74µs+0s) by Foswiki::Render::getRenderedVersion at line 1250, avg 15µs/call
# 5 times (72µs+0s) by Foswiki::Render::getRenderedVersion at line 1229, avg 14µs/call
# 5 times (62µs+0s) by Foswiki::Render::getRenderedVersion at line 1225, avg 12µs/call
# 5 times (62µs+0s) by Foswiki::Render::getRenderedVersion at line 1227, avg 12µs/call
# 5 times (60µs+0s) by Foswiki::Render::getRenderedVersion at line 1102, avg 12µs/call
# 5 times (58µs+0s) by Foswiki::Render::getRenderedVersion at line 1387, avg 12µs/call
# 5 times (49µs+0s) by Foswiki::Render::getRenderedVersion at line 1255, avg 10µs/call
# 5 times (47µs+0s) by Foswiki::Render::getRenderedVersion at line 1392, avg 9µs/call
# 5 times (46µs+0s) by Foswiki::Render::getRenderedVersion at line 1138, avg 9µs/call
# 5 times (40µs+0s) by Foswiki::Render::getRenderedVersion at line 1386, avg 8µs/call
# 5 times (39µs+0s) by Foswiki::Render::getRenderedVersion at line 1149, avg 8µs/call
# 5 times (35µs+0s) by Foswiki::Render::getRenderedVersion at line 1396, avg 7µs/call
# 5 times (34µs+0s) by Foswiki::Render::getRenderedVersion at line 1432, avg 7µs/call
# 5 times (33µs+0s) by Foswiki::Render::getRenderedVersion at line 1239, avg 7µs/call
# 5 times (33µs+0s) by Foswiki::Render::getRenderedVersion at line 1219, avg 7µs/call
# 5 times (33µs+0s) by Foswiki::Render::getRenderedVersion at line 1220, avg 7µs/call
# 5 times (30µs+0s) by Foswiki::Render::getRenderedVersion at line 1215, avg 6µs/call
# 5 times (26µs+0s) by Foswiki::Render::getRenderedVersion at line 1383, avg 5µs/call
# 5 times (26µs+0s) by Foswiki::Render::getRenderedVersion at line 1105, avg 5µs/call
# 5 times (22µs+0s) by Foswiki::Render::getRenderedVersion at line 1384, avg 4µs/call
# 4 times (32µs+0s) by Foswiki::Render::_renderNonExistingWikiWord at line 699, avg 8µs/call
# 4 times (21µs+0s) by Foswiki::Render::_renderNonExistingWikiWord at line 700, avg 5µs/call
# 4 times (18µs+0s) by Foswiki::Render::_renderNonExistingWikiWord at line 701, avg 4µs/call
# 2 times (4µs+0s) by Foswiki::Render::_externalLink at line 956, avg 2µs/call
# 2 times (3µs+0s) by Foswiki::Render::internalLink at line 557, avg 1µs/call
# once (6µs+0s) by Foswiki::Render::_fixedFontText at line 437
# once (4µs+0s) by Foswiki::Render::_fixedFontText at line 436 | |||||
# spent 9.43ms within Foswiki::Render::CORE:substcont which was called 759 times, avg 12µs/call:
# 303 times (1.90ms+0s) by Foswiki::Render::getRenderedVersion at line 1211, avg 6µs/call
# 219 times (2.33ms+0s) by Foswiki::Render::getRenderedVersion at line 1212, avg 11µs/call
# 44 times (4.26ms+0s) by Foswiki::Render::getRenderedVersion at line 1415, avg 97µs/call
# 38 times (121µs+0s) by Foswiki::Render::internalLink at line 592, avg 3µs/call
# 36 times (265µs+0s) by Foswiki::Render::getRenderedVersion at line 1396, avg 7µs/call
# 26 times (123µs+0s) by Foswiki::Render::getRenderedVersion at line 1225, avg 5µs/call
# 26 times (109µs+0s) by Foswiki::Render::getRenderedVersion at line 1229, avg 4µs/call
# 20 times (125µs+0s) by Foswiki::Render::_takeOutProtected at line 1655, avg 6µs/call
# 13 times (44µs+0s) by Foswiki::Render::renderRevisionInfo at line 1792, avg 3µs/call
# 10 times (24µs+0s) by Foswiki::Render::renderRevisionInfo at line 1786, avg 2µs/call
# 8 times (55µs+0s) by Foswiki::Render::getRenderedVersion at line 1250, avg 7µs/call
# 6 times (15µs+0s) by Foswiki::Render::renderRevisionInfo at line 1789, avg 2µs/call
# 4 times (9µs+0s) by Foswiki::Render::renderRevisionInfo at line 1787, avg 2µs/call
# 2 times (20µs+0s) by Foswiki::Render::getRenderedVersion at line 1388, avg 10µs/call
# 2 times (16µs+0s) by Foswiki::Render::getRenderedVersion at line 1239, avg 8µs/call
# 2 times (16µs+0s) by Foswiki::Render::getRenderedVersion at line 1386, avg 8µs/call |