Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/WysiwygPlugin.pm |
Statements | Executed 2309 statements in 13.6ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1131 | 1 | 1 | 13.8ms | 30.1ms | beforeCommonTagsHandler | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 139µs | 583µs | initPlugin | Foswiki::Plugins::WysiwygPlugin::
5 | 1 | 1 | 40µs | 40µs | postRenderingHandler | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 32µs | 94µs | modifyHeaderHandler | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 29µs | 36µs | BEGIN@25 | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 20µs | 60µs | BEGIN@85 | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 18µs | 60µs | BEGIN@28 | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 17µs | 34µs | BEGIN@26 | Foswiki::Plugins::WysiwygPlugin::
1 | 1 | 1 | 16µs | 45µs | BEGIN@87 | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | WHY | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:57] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:59] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:61] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:63] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:65] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:68] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:70] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:72] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | __ANON__[:74] | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | _execute | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | addXMLTag | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | afterEditHandler | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | beforeEditHandler | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | beforeMergeHandler | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | beforeSaveHandler | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | notWysiwygEditable | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | postConvertURL | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | startRenderingHandler | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | wysiwygEditingDisabledForThisContent | Foswiki::Plugins::WysiwygPlugin::
0 | 0 | 0 | 0s | 0s | wysiwygEditingNotPossibleForThisContent | Foswiki::Plugins::WysiwygPlugin::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+ package WysiwygPlugin | ||||
6 | |||||
7 | This plugin is responsible for translating TML to HTML before an edit starts | ||||
8 | and translating the resultant HTML back into TML. | ||||
9 | |||||
10 | Note: In the case of a new topic, you might expect to see the "create topic" | ||||
11 | screen in the editor when it goes back to Foswiki for the topic content. This | ||||
12 | doesn't happen because the earliest possible handler is called on the topic | ||||
13 | content and not the template. The template is effectively ignored and a blank | ||||
14 | document is sent to the editor. | ||||
15 | |||||
16 | Attachment uploads can be handled by URL requests from the editor to the rest | ||||
17 | handler in this plugin. This avoids the need to add any scripts to the bin dir. | ||||
18 | You will have to use a form, though, as XmlHttpRequest does not support file | ||||
19 | uploads. | ||||
20 | |||||
21 | =cut | ||||
22 | |||||
23 | package Foswiki::Plugins::WysiwygPlugin; | ||||
24 | |||||
25 | 2 | 46µs | 2 | 44µs | # spent 36µs (29+7) within Foswiki::Plugins::WysiwygPlugin::BEGIN@25 which was called:
# once (29µs+7µs) by Foswiki::Plugin::BEGIN@2.21 at line 25 # spent 36µs making 1 call to Foswiki::Plugins::WysiwygPlugin::BEGIN@25
# spent 7µs making 1 call to strict::import |
26 | 2 | 45µs | 2 | 52µs | # spent 34µs (17+18) within Foswiki::Plugins::WysiwygPlugin::BEGIN@26 which was called:
# once (17µs+18µs) by Foswiki::Plugin::BEGIN@2.21 at line 26 # spent 34µs making 1 call to Foswiki::Plugins::WysiwygPlugin::BEGIN@26
# spent 18µs making 1 call to warnings::import |
27 | |||||
28 | 2 | 702µs | 2 | 102µs | # spent 60µs (18+42) within Foswiki::Plugins::WysiwygPlugin::BEGIN@28 which was called:
# once (18µs+42µs) by Foswiki::Plugin::BEGIN@2.21 at line 28 # spent 60µs making 1 call to Foswiki::Plugins::WysiwygPlugin::BEGIN@28
# spent 42µs making 1 call to Assert::import |
29 | |||||
30 | 1 | 2µs | our $SHORTDESCRIPTION = 'Translator framework for WYSIWYG editors'; | ||
31 | 1 | 2µs | our $NO_PREFS_IN_TOPIC = 1; | ||
32 | 1 | 1µs | our $VERSION = '$Rev$'; | ||
33 | |||||
34 | 1 | 2µs | our $RELEASE = '1.1.3'; | ||
35 | |||||
36 | 1 | 1µs | our %xmltag; | ||
37 | |||||
38 | # The following are all used in Handlers, but declared here so we can | ||||
39 | # check them without loading the handlers module | ||||
40 | 1 | 900ns | our $tml2html; | ||
41 | 1 | 700ns | our $recursionBlock; | ||
42 | 1 | 1µs | our %FoswikiCompatibility; | ||
43 | |||||
44 | # Set to 1 for reasons for rejection | ||||
45 | sub WHY { 0 } | ||||
46 | |||||
47 | # spent 583µs (139+444) within Foswiki::Plugins::WysiwygPlugin::initPlugin which was called:
# once (139µs+444µs) by Foswiki::Plugin::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm:235] at line 228 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm | ||||
48 | 11 | 101µs | my ( $topic, $web, $user, $installWeb ) = @_; | ||
49 | |||||
50 | # %OWEB%.%OTOPIC% is the topic where the initial content should be | ||||
51 | # grabbed from, as defined in templates/edit.skin.tmpl | ||||
52 | # Note; rather than declaring the handlers in this module, we use | ||||
53 | # the _execute function to hand off execution to | ||||
54 | # Foswiki::Plugins::WysiwygPlugin::Handlers. The goal is to keep this | ||||
55 | # module small and light so it loads fast. | ||||
56 | Foswiki::Func::registerTagHandler( 'OWEB', | ||||
57 | 1 | 48µs | sub { _execute( '_OWEBTAG', @_ ) } ); # spent 48µs making 1 call to Foswiki::Func::registerTagHandler | ||
58 | Foswiki::Func::registerTagHandler( 'OTOPIC', | ||||
59 | 1 | 46µs | sub { _execute( '_OTOPICTAG', @_ ) } ); # spent 46µs making 1 call to Foswiki::Func::registerTagHandler | ||
60 | Foswiki::Func::registerTagHandler( 'WYSIWYG_TEXT', | ||||
61 | 1 | 45µs | sub { _execute( '_WYSIWYG_TEXT', @_ ) } ); # spent 45µs making 1 call to Foswiki::Func::registerTagHandler | ||
62 | Foswiki::Func::registerTagHandler( 'JAVASCRIPT_TEXT', | ||||
63 | 1 | 45µs | sub { _execute( '_JAVASCRIPT_TEXT', @_ ) } ); # spent 45µs making 1 call to Foswiki::Func::registerTagHandler | ||
64 | Foswiki::Func::registerTagHandler( 'WYSIWYG_SECRET_ID', | ||||
65 | 1 | 44µs | sub { _execute( '_SECRET_ID', @_ ) } ); # spent 44µs making 1 call to Foswiki::Func::registerTagHandler | ||
66 | |||||
67 | Foswiki::Func::registerRESTHandler( 'tml2html', | ||||
68 | 1 | 71µs | sub { _execute( '_restTML2HTML', @_ ) } ); # spent 71µs making 1 call to Foswiki::Func::registerRESTHandler | ||
69 | Foswiki::Func::registerRESTHandler( 'html2tml', | ||||
70 | 1 | 49µs | sub { _execute( '_restHTML2TML', @_ ) } ); # spent 49µs making 1 call to Foswiki::Func::registerRESTHandler | ||
71 | Foswiki::Func::registerRESTHandler( 'upload', | ||||
72 | 1 | 51µs | sub { _execute( '_restUpload', @_ ) } ); # spent 51µs making 1 call to Foswiki::Func::registerRESTHandler | ||
73 | Foswiki::Func::registerRESTHandler( 'attachments', | ||||
74 | 1 | 45µs | sub { _execute( '_restAttachments', @_ ) } ); # spent 45µs making 1 call to Foswiki::Func::registerRESTHandler | ||
75 | |||||
76 | # Plugin correctly initialized | ||||
77 | return 1; | ||||
78 | } | ||||
79 | |||||
80 | sub _execute { | ||||
81 | my $fn = shift; | ||||
82 | |||||
83 | require Foswiki::Plugins::WysiwygPlugin::Handlers; | ||||
84 | $fn = 'Foswiki::Plugins::WysiwygPlugin::Handlers::' . $fn; | ||||
85 | 2 | 68µs | 2 | 100µs | # spent 60µs (20+40) within Foswiki::Plugins::WysiwygPlugin::BEGIN@85 which was called:
# once (20µs+40µs) by Foswiki::Plugin::BEGIN@2.21 at line 85 # spent 60µs making 1 call to Foswiki::Plugins::WysiwygPlugin::BEGIN@85
# spent 40µs making 1 call to strict::unimport |
86 | return &$fn(@_); | ||||
87 | 2 | 1.76ms | 2 | 75µs | # spent 45µs (16+29) within Foswiki::Plugins::WysiwygPlugin::BEGIN@87 which was called:
# once (16µs+29µs) by Foswiki::Plugin::BEGIN@2.21 at line 87 # spent 45µs making 1 call to Foswiki::Plugins::WysiwygPlugin::BEGIN@87
# spent 29µs making 1 call to strict::import |
88 | } | ||||
89 | |||||
90 | =begin TML | ||||
91 | |||||
92 | ---++ StaticMethod notWysiwygEditable($text) -> $boolean | ||||
93 | Determine if the given =$text= is WYSIWYG editable, based on the topic content | ||||
94 | and the value of the Foswiki preferences WYSIWYG_EXCLUDE and | ||||
95 | WYSIWYG_EDITABLE_CALLS. Returns a descriptive string if the text is not | ||||
96 | editable, 0 otherwise. | ||||
97 | |||||
98 | =cut | ||||
99 | |||||
100 | sub notWysiwygEditable { | ||||
101 | |||||
102 | #my ($text, $exclusions) = @_; | ||||
103 | my $disabled = wysiwygEditingDisabledForThisContent( $_[0], $_[1] ); | ||||
104 | return $disabled if $disabled; | ||||
105 | |||||
106 | # Check that the topic text can be converted to HTML. This is an | ||||
107 | # *expensive* process, to be avoided if possible (hence all the | ||||
108 | # earlier checks) | ||||
109 | my $impossible = wysiwygEditingNotPossibleForThisContent( $_[0] ); | ||||
110 | return $impossible if $impossible; | ||||
111 | |||||
112 | return 0; | ||||
113 | } | ||||
114 | |||||
115 | sub wysiwygEditingDisabledForThisContent { | ||||
116 | |||||
117 | #my ($text, $exclusions) = @_; | ||||
118 | |||||
119 | my $exclusions = $_[1]; | ||||
120 | unless ( defined($exclusions) ) { | ||||
121 | $exclusions = Foswiki::Func::getPreferencesValue('WYSIWYG_EXCLUDE') | ||||
122 | || ''; | ||||
123 | } | ||||
124 | |||||
125 | # Check for explicit exclusions before generic, non-configurable | ||||
126 | # purely content-related reasons for exclusion | ||||
127 | if ($exclusions) { | ||||
128 | my $calls_ok = | ||||
129 | Foswiki::Func::getPreferencesValue('WYSIWYG_EDITABLE_CALLS') | ||||
130 | || '---'; | ||||
131 | $calls_ok =~ s/\s//g; | ||||
132 | |||||
133 | my $ok = 1; | ||||
134 | if ( $exclusions =~ /calls/ | ||||
135 | && $_[0] =~ /%((?!($calls_ok){)[A-Z_]+{.*?})%/s ) | ||||
136 | { | ||||
137 | print STDERR "WYSIWYG_DEBUG: has calls $1 (not in $calls_ok)\n" | ||||
138 | if (WHY); | ||||
139 | return "Text contains calls"; | ||||
140 | } | ||||
141 | if ( $exclusions =~ /(macros|variables)/ && $_[0] =~ /%([A-Z_]+)%/s ) { | ||||
142 | print STDERR "$exclusions WYSIWYG_DEBUG: has macros $1\n" | ||||
143 | if (WHY); | ||||
144 | return "Text contains macros"; | ||||
145 | } | ||||
146 | if ( $exclusions =~ /html/ | ||||
147 | && $_[0] =~ /<\/?((?!literal|verbatim|noautolink|nop|br)\w+)/ ) | ||||
148 | { | ||||
149 | print STDERR "WYSIWYG_DEBUG: has html: $1\n" | ||||
150 | if (WHY); | ||||
151 | return "Text contains HTML"; | ||||
152 | } | ||||
153 | if ( $exclusions =~ /comments/ && $_[0] =~ /<[!]--/ ) { | ||||
154 | print STDERR "WYSIWYG_DEBUG: has comments\n" | ||||
155 | if (WHY); | ||||
156 | return "Text contains comments"; | ||||
157 | } | ||||
158 | if ( $exclusions =~ /pre/ && $_[0] =~ /<pre\w/ ) { | ||||
159 | print STDERR "WYSIWYG_DEBUG: has pre\n" | ||||
160 | if (WHY); | ||||
161 | return "Text contains PRE"; | ||||
162 | } | ||||
163 | } | ||||
164 | |||||
165 | # Copy the content. | ||||
166 | # Then crunch verbatim blocks, because verbatim blocks may | ||||
167 | # contain *anything*. | ||||
168 | my $text = $_[0]; | ||||
169 | |||||
170 | # Look for combinations of sticky and other markup that cause | ||||
171 | # problems together | ||||
172 | for my $tag ('literal') { | ||||
173 | while ( $text =~ /<$tag\b[^>]*>(.*?)<\/$tag>/gsi ) { | ||||
174 | my $inner = $1; | ||||
175 | if ( $inner =~ /<sticky\b[^>]*>/i ) { | ||||
176 | print STDERR "WYSIWYG_DEBUG: <sticky> inside <$tag>\n" | ||||
177 | if (WHY); | ||||
178 | return "<sticky> inside <$tag>"; | ||||
179 | } | ||||
180 | } | ||||
181 | } | ||||
182 | |||||
183 | my $wasAVerbatimTag = "\000verbatim\001"; | ||||
184 | while ( $text =~ s/<verbatim\b[^>]*>(.*?)<\/verbatim>/$wasAVerbatimTag/i ) { | ||||
185 | |||||
186 | #my $content = $1; | ||||
187 | # If there is any content that breaks conversion if it is inside | ||||
188 | # a verbatim block, check for it here: | ||||
189 | } | ||||
190 | |||||
191 | # Look for combinations of verbatim and other markup that cause | ||||
192 | # problems together | ||||
193 | for my $tag ('literal') { | ||||
194 | while ( $text =~ /<$tag\b[^>]*>(.*?)<\/$tag>/gsi ) { | ||||
195 | my $inner = $1; | ||||
196 | if ( $inner =~ /$wasAVerbatimTag/i ) { | ||||
197 | print STDERR "WYSIWYG_DEBUG: <verbatim> inside <$tag>\n" | ||||
198 | if (WHY); | ||||
199 | return "<verbatim> inside <$tag>"; | ||||
200 | } | ||||
201 | } | ||||
202 | } | ||||
203 | |||||
204 | return 0; | ||||
205 | } | ||||
206 | |||||
207 | sub wysiwygEditingNotPossibleForThisContent { | ||||
208 | eval { | ||||
209 | require Foswiki::Plugins::WysiwygPlugin::Handlers; | ||||
210 | Foswiki::Plugins::WysiwygPlugin::Handlers::TranslateTML2HTML( $_[0], | ||||
211 | 'Fakewebname', 'FakeTopicName', dieOnError => 1 ); | ||||
212 | }; | ||||
213 | if ($@) { | ||||
214 | print STDERR | ||||
215 | "WYSIWYG_DEBUG: TML2HTML conversion threw an exception: $@\n" | ||||
216 | if (WHY); | ||||
217 | return "TML2HTML conversion fails"; | ||||
218 | } | ||||
219 | |||||
220 | return 0; | ||||
221 | } | ||||
222 | |||||
223 | sub addXMLTag { | ||||
224 | require Foswiki::Plugins::WysiwygPlugin::Handlers; | ||||
225 | Foswiki::Plugins::WysiwygPlugin::Handlers::addXMLTag(@_); | ||||
226 | } | ||||
227 | |||||
228 | sub postConvertURL { | ||||
229 | require Foswiki::Plugins::WysiwygPlugin::Handlers; | ||||
230 | Foswiki::Plugins::WysiwygPlugin::Handlers::postConvertURL(@_); | ||||
231 | } | ||||
232 | |||||
233 | sub beforeEditHandler { | ||||
234 | _execute( 'beforeEditHandler', @_ ); | ||||
235 | } | ||||
236 | |||||
237 | sub beforeSaveHandler { | ||||
238 | _execute( 'beforeSaveHandler', @_ ); | ||||
239 | } | ||||
240 | |||||
241 | sub beforeMergeHandler { | ||||
242 | _execute( 'beforeMergeHandler', @_ ); | ||||
243 | } | ||||
244 | |||||
245 | sub afterEditHandler { | ||||
246 | _execute( 'afterEditHandler', @_ ); | ||||
247 | } | ||||
248 | |||||
249 | # The next few handlers have to be executed on topic views, so have to | ||||
250 | # avoid lazy-loading the handlers unless absolutely necessary. | ||||
251 | |||||
252 | 1 | 2µs | $FoswikiCompatibility{startRenderingHandler} = 2.1; | ||
253 | |||||
254 | sub startRenderingHandler { | ||||
255 | $_[0] =~ s#</?sticky>##g; | ||||
256 | } | ||||
257 | |||||
258 | # spent 30.1ms (13.8+16.4) within Foswiki::Plugins::WysiwygPlugin::beforeCommonTagsHandler which was called 1131 times, avg 27µs/call:
# 1131 times (13.8ms+16.4ms) by Foswiki::Plugin::invoke at line 287 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm, avg 27µs/call | ||||
259 | 2271 | 10.8ms | return if $recursionBlock; | ||
260 | 1131 | 16.1ms | return unless Foswiki::Func::getContext()->{body_text}; # spent 16.1ms making 1131 calls to Foswiki::Func::getContext, avg 14µs/call | ||
261 | |||||
262 | 3 | 78µs | my $query = Foswiki::Func::getCgiQuery(); # spent 78µs making 3 calls to Foswiki::Func::getCgiQuery, avg 26µs/call | ||
263 | |||||
264 | return unless $query; | ||||
265 | |||||
266 | 3 | 182µs | return unless defined( $query->param('wysiwyg_edit') ); # spent 182µs making 3 calls to Foswiki::Request::param, avg 61µs/call | ||
267 | _execute( 'beforeCommonTagsHandler', @_ ); | ||||
268 | } | ||||
269 | |||||
270 | # spent 40µs within Foswiki::Plugins::WysiwygPlugin::postRenderingHandler which was called 5 times, avg 8µs/call:
# 5 times (40µs+0s) by Foswiki::Plugin::invoke at line 287 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm, avg 8µs/call | ||||
271 | 5 | 33µs | return if ( $recursionBlock || !$tml2html ); | ||
272 | _execute( 'postRenderingHandler', @_ ); | ||||
273 | } | ||||
274 | |||||
275 | # spent 94µs (32+62) within Foswiki::Plugins::WysiwygPlugin::modifyHeaderHandler which was called:
# once (32µs+62µs) by Foswiki::Plugin::invoke at line 287 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm | ||||
276 | 2 | 18µs | my ( $headers, $query ) = @_; | ||
277 | |||||
278 | 1 | 62µs | if ( $query->param('wysiwyg_edit') ) { # spent 62µs making 1 call to Foswiki::Request::param | ||
279 | _execute( 'modifyHeaderHandler', @_ ); | ||||
280 | } | ||||
281 | } | ||||
282 | |||||
283 | 1 | 8µs | 1; | ||
284 | __END__ |