1 |
wakaba |
1.1 |
#?SuikaWikiConfig/2.0 |
2 |
|
|
|
3 |
|
|
Plugin: |
4 |
|
|
@Name: WikiEdit |
5 |
|
|
@Description: |
6 |
|
|
@@@: WikiPage editing components |
7 |
|
|
@@lang:en |
8 |
wakaba |
1.9 |
@License: %%Perl%% |
9 |
wakaba |
1.1 |
@Author: |
10 |
|
|
@@Name: |
11 |
|
|
@@@@: Wakaba |
12 |
|
|
@@@lang:ja |
13 |
|
|
@@@script:Latn |
14 |
|
|
@@Mail[list]: w@suika.fam.cx |
15 |
wakaba |
1.9 |
@Date.RCS: |
16 |
wakaba |
1.11 |
$Date: 2004/03/29 03:22:30 $ |
17 |
wakaba |
1.1 |
@RequiredModule[list]: |
18 |
|
|
Digest::SHA1 |
19 |
wakaba |
1.2 |
@RequiredPlugin[list]: |
20 |
|
|
WikiView |
21 |
|
|
WikiStruct |
22 |
|
|
WikiLinking |
23 |
|
|
WikiFormCore |
24 |
wakaba |
1.3 |
WikiFormText |
25 |
wakaba |
1.6 |
WikiResource |
26 |
wakaba |
1.2 |
HTML |
27 |
wakaba |
1.7 |
@Use: |
28 |
|
|
use Message::Util::Error; |
29 |
wakaba |
1.1 |
|
30 |
|
|
PluginConst: |
31 |
|
|
@NS_XHTML1: |
32 |
|
|
http://www.w3.org/1999/xhtml |
33 |
|
|
|
34 |
|
|
ViewDefinition: |
35 |
|
|
@Mode: edit |
36 |
|
|
@Condition: |
37 |
|
|
@@http-method[list]: |
38 |
|
|
GET |
39 |
|
|
HEAD |
40 |
|
|
@Description: |
41 |
|
|
@@@: Edit WikiPage content as whole, as a plaintext |
42 |
|
|
@@lang: en |
43 |
|
|
@template: |
44 |
|
|
@@http-status-code: 200 |
45 |
|
|
@@media-type: text/html |
46 |
|
|
@@use-media-type-charset: 1 |
47 |
|
|
@@expires: %%edit%% |
48 |
|
|
@@body: |
49 |
|
|
%html-document ( |
50 |
|
|
title => {%res(name=>{Edit:WebPageTitle});}p, |
51 |
wakaba |
1.2 |
link-meta => {%template (name => links); |
52 |
|
|
%html-meta(name => ROBOTS, content => NOINDEX);}p, |
53 |
wakaba |
1.1 |
content => { |
54 |
|
|
%template ( |
55 |
|
|
name => ws--page, |
56 |
wakaba |
1.2 |
-content => {%template (name => we--edit-body);}, |
57 |
wakaba |
1.1 |
); |
58 |
|
|
}p, |
59 |
|
|
); |
60 |
|
|
|
61 |
|
|
ViewDefinition: |
62 |
|
|
@Mode: write |
63 |
|
|
@Condition: |
64 |
|
|
@@http-method[list]: |
65 |
|
|
POST |
66 |
|
|
@Description: |
67 |
|
|
@@@: Saving modified (new) WikiPage content |
68 |
|
|
@@lang: en |
69 |
wakaba |
1.7 |
@Use: |
70 |
|
|
use Message::Util::Error; |
71 |
wakaba |
1.1 |
@method: |
72 |
|
|
@@@: |
73 |
|
|
my $touch = $self->{view}->{wiki}->{input}->parameter ('we--touch'); |
74 |
|
|
|
75 |
|
|
$self->{view}->{wiki}->{var}->{db}->{read_only}->{'content'} = 0; |
76 |
|
|
$self->{view}->{wiki}->{var}->{db}->{read_only}->{'lastmodified'} = 0 |
77 |
|
|
if $touch; |
78 |
wakaba |
1.11 |
$self->{view}->{wiki}->{var}->{db}->{read_only}->{'referer'} = 0; |
79 |
wakaba |
1.1 |
$self->{view}->init_db; |
80 |
|
|
|
81 |
|
|
my $page = $self->{view}->{wiki}->{var}->{page}; |
82 |
|
|
|
83 |
|
|
## Check confliction |
84 |
wakaba |
1.7 |
my $current_content; |
85 |
|
|
try { |
86 |
|
|
$current_content = $self->{view}->{wiki}->{db}->get (content => $page); |
87 |
|
|
} catch SuikaWiki::DB::Util::Error with { |
88 |
wakaba |
1.9 |
my $err = shift; |
89 |
|
|
if ($err->{-type} eq 'ERROR_REPORTED') { |
90 |
|
|
$err->throw; |
91 |
|
|
} else { |
92 |
|
|
$self->{view}->{wiki}->view_in_mode (mode => '-wdb--fatal-error'); |
93 |
|
|
throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED'; |
94 |
|
|
} |
95 |
wakaba |
1.7 |
}; |
96 |
wakaba |
1.10 |
|
97 |
|
|
my $current_digest = ''; |
98 |
wakaba |
1.1 |
if (length $current_content) { |
99 |
wakaba |
1.10 |
$current_digest = __FUNCPACK__->digest ($current_content, |
100 |
wakaba |
1.2 |
normalize => 1); |
101 |
wakaba |
1.1 |
my $prev_digest |
102 |
|
|
= $self->{view}->{wiki}->{input}->parameter ('we--digest'); |
103 |
|
|
if ($current_digest ne $prev_digest) { |
104 |
wakaba |
1.2 |
return $self->{view}->{wiki}->view_in_mode |
105 |
|
|
(mode => '-conflict'); |
106 |
wakaba |
1.1 |
} |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
my $new_content |
110 |
|
|
= $self->{view}->{wiki}->{input}->parameter ('we--content'); |
111 |
|
|
if (length $new_content) { |
112 |
wakaba |
1.10 |
## Really modified? |
113 |
|
|
my $new_digest = __FUNCPACK__->digest ($new_content, normalize => 1); |
114 |
|
|
if ($current_digest ne $new_digest) { |
115 |
|
|
|
116 |
|
|
## Update content |
117 |
wakaba |
1.7 |
try { |
118 |
wakaba |
1.10 |
$self->{view}->{wiki}->{db}->set (content => $page => $new_content); |
119 |
wakaba |
1.7 |
} catch SuikaWiki::DB::Util::Error with { |
120 |
wakaba |
1.9 |
my $err = shift; |
121 |
wakaba |
1.10 |
if ($err->{-type} eq 'ERROR_REPORTED') { |
122 |
|
|
$err->throw; |
123 |
|
|
} else { |
124 |
|
|
$self->{view}->{wiki}->view_in_mode (mode => '-wdb--fatal-error'); |
125 |
|
|
throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED'; |
126 |
|
|
} |
127 |
wakaba |
1.7 |
}; |
128 |
wakaba |
1.10 |
|
129 |
|
|
## Update lastmodified |
130 |
|
|
if ($touch) { |
131 |
|
|
try { |
132 |
|
|
$self->{view}->{wiki}->{db}->set (lastmodified => $page => time); |
133 |
|
|
} catch SuikaWiki::DB::Util::Error with { |
134 |
|
|
my $err = shift; |
135 |
|
|
$err->throw if $err->{-type} eq 'ERROR_REPORTED'; |
136 |
|
|
}; |
137 |
|
|
} |
138 |
wakaba |
1.1 |
} |
139 |
wakaba |
1.10 |
|
140 |
wakaba |
1.1 |
my $new_mode = $self->{view}->{wiki}->{input}->parameter |
141 |
|
|
('we--mode-modified'); |
142 |
|
|
$new_mode =~ s/[^0-9A-Za-z._-]+//g; |
143 |
wakaba |
1.10 |
my $uri = $self->{view}->{wiki}->uri_reference |
144 |
|
|
(page => $page, |
145 |
|
|
mode => $new_mode, |
146 |
|
|
up_to_date => 1, |
147 |
|
|
param => {we__mode_modified => $new_mode}); |
148 |
wakaba |
1.1 |
|
149 |
|
|
require SuikaWiki::Output::HTTP; |
150 |
|
|
my $output = SuikaWiki::Output::HTTP->new |
151 |
wakaba |
1.10 |
(wiki => $self->{view}->{wiki}); |
152 |
wakaba |
1.1 |
$output->set_redirect (uri => $uri, status_code => 303); |
153 |
|
|
$output->output (output => 'http-cgi'); |
154 |
|
|
} else { |
155 |
wakaba |
1.7 |
try { |
156 |
|
|
$self->{view}->{wiki}->{db}->delete (content => $page); |
157 |
|
|
$self->{view}->{wiki}->{db}->delete (lastmodified => $page) if $touch; |
158 |
|
|
} catch SuikaWiki::DB::Util::Error with { |
159 |
wakaba |
1.9 |
my $err = shift; |
160 |
|
|
if ($err->{-type} eq 'ERROR_REPORTED') { |
161 |
|
|
$err->throw; |
162 |
|
|
} else { |
163 |
|
|
$self->{view}->{wiki}->view_in_mode (mode => '-wdb--fatal-error'); |
164 |
|
|
throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED'; |
165 |
|
|
} |
166 |
wakaba |
1.7 |
}; |
167 |
wakaba |
1.2 |
$self->{view}->{wiki}->view_in_mode (mode => '-deleted'); |
168 |
wakaba |
1.1 |
} |
169 |
|
|
@@Name: main |
170 |
|
|
|
171 |
|
|
ViewDefinition: |
172 |
|
|
@Mode: adminedit |
173 |
|
|
@Condition: |
174 |
|
|
@@http-method[list]: |
175 |
|
|
GET |
176 |
|
|
HEAD |
177 |
|
|
@Description: |
178 |
|
|
@@@: Edit WikiPage content as whole, as a plaintext (administrator mode) |
179 |
|
|
@@lang: en |
180 |
|
|
@template: |
181 |
|
|
@@http-status-code: 200 |
182 |
|
|
@@media-type: application/xhtml+xml |
183 |
|
|
@@use-media-type-charset: 1 |
184 |
|
|
@@expires: %%edit%% |
185 |
|
|
@@body: |
186 |
wakaba |
1.2 |
%html-document ( |
187 |
|
|
title => {%res(name=>{Edit:Admin:WebPageTitle});}p, |
188 |
wakaba |
1.6 |
link-meta => {%template (name => links); |
189 |
wakaba |
1.2 |
%html-meta(name=>ROBOTS,content=>NOINDEX);}p, |
190 |
|
|
content => { |
191 |
|
|
%template ( |
192 |
|
|
name => ws--page, |
193 |
|
|
-content => {%template (name => we--adminedit-body);}, |
194 |
|
|
); |
195 |
|
|
}p, |
196 |
|
|
); |
197 |
wakaba |
1.1 |
|
198 |
wakaba |
1.2 |
ViewDefinition: |
199 |
wakaba |
1.1 |
@Mode: -conflict |
200 |
|
|
@Condition: |
201 |
|
|
@@http-method[list]: |
202 |
|
|
GET |
203 |
|
|
HEAD |
204 |
|
|
@Description: |
205 |
|
|
@@@: Confliction message |
206 |
|
|
@@lang: en |
207 |
|
|
@template: |
208 |
|
|
@@http-status-code: 409 |
209 |
|
|
@@media-type: text/html |
210 |
|
|
@@use-media-type-charset: 1 |
211 |
|
|
@@body: |
212 |
wakaba |
1.2 |
%html-document ( |
213 |
|
|
title => {%res(name=>{Edit:Conflict:WebPageTitle});}p, |
214 |
|
|
link-meta => {%template(name=>links); |
215 |
|
|
%html-meta(name=>ROBOTS,content=>NOINDEX);}p, |
216 |
|
|
content => { |
217 |
|
|
%template ( |
218 |
|
|
name => ws--page, |
219 |
|
|
-content => { |
220 |
wakaba |
1.6 |
%section ( |
221 |
wakaba |
1.2 |
title => {%res(name=>{Edit:Conflict:Title});}p, heading, |
222 |
|
|
content => {%template (name => we--conflict-body);}p, |
223 |
|
|
); |
224 |
|
|
}, |
225 |
|
|
); |
226 |
|
|
}p, |
227 |
|
|
); |
228 |
|
|
|
229 |
|
|
ViewDefinition: |
230 |
|
|
@Mode: -deleted |
231 |
|
|
@Condition: |
232 |
|
|
@@http-method[list]: |
233 |
|
|
GET |
234 |
|
|
HEAD |
235 |
|
|
@Expires:%%view%% |
236 |
|
|
@Description: |
237 |
|
|
@@@: Confliction message |
238 |
|
|
@@lang: en |
239 |
|
|
@template: |
240 |
|
|
@@http-status-code: 200 |
241 |
|
|
@@media-type: text/html |
242 |
|
|
@@use-media-type-charset: 1 |
243 |
|
|
@@body: |
244 |
|
|
%html-document ( |
245 |
|
|
title => {%res (name => {Edit:Deleted:WebPageTitle});}p, |
246 |
|
|
link-meta => {%template (name => links); |
247 |
|
|
%html-meta (name => ROBOTS, content => NOINDEX);}p, |
248 |
|
|
content => { |
249 |
|
|
%template ( |
250 |
|
|
name => ws--page, |
251 |
|
|
-content => { |
252 |
wakaba |
1.6 |
%section ( |
253 |
wakaba |
1.2 |
title => {%res(name=>{Edit:Deleted:Title});}p, heading, |
254 |
|
|
content => { |
255 |
|
|
%paragraph (content => {%res |
256 |
|
|
(name => {Edit:Deleted:Description});}p); |
257 |
|
|
}p, |
258 |
|
|
); |
259 |
|
|
}, |
260 |
|
|
); |
261 |
|
|
}p, |
262 |
|
|
); |
263 |
wakaba |
1.1 |
|
264 |
|
|
ViewFragment: |
265 |
|
|
@Name: links |
266 |
|
|
@Description: |
267 |
|
|
@@@: Link to edit mode of the WikiPage |
268 |
|
|
@@lang:en |
269 |
|
|
@Formatting: |
270 |
wakaba |
1.6 |
%link-wiki(mode => edit, up-to-date, |
271 |
|
|
rel => edit, class => wiki-cmd, |
272 |
|
|
description => {%res(name=>{Link:Edit:Description});}p); |
273 |
|
|
%link-wiki(mode => adminedit, up-to-date, |
274 |
|
|
rel=>edit, class => wiki-cmd, |
275 |
|
|
description => {%res(name=>{Link:AdminEdit:Description});}p); |
276 |
wakaba |
1.1 |
|
277 |
|
|
ViewFragment: |
278 |
|
|
@Name: navbar |
279 |
|
|
@Description: |
280 |
|
|
@@@: Link to edit mode of the WikiPage |
281 |
|
|
@Order: 10 |
282 |
|
|
@Formatting: |
283 |
wakaba |
1.3 |
%link-to-wikipage ( |
284 |
|
|
mode => edit, |
285 |
|
|
rel => edit, |
286 |
|
|
up-to-date, |
287 |
|
|
label => {%link-to-it ( |
288 |
|
|
class => wiki-cmd, |
289 |
|
|
label => {%res (name => EditThisPage);}p, |
290 |
|
|
description => {%res (name => EditThisPageLong);}p, |
291 |
|
|
);}, |
292 |
|
|
page-anchor-name => edit, |
293 |
|
|
); |
294 |
wakaba |
1.2 |
|
295 |
|
|
ViewFragment: |
296 |
|
|
@Template[list]: |
297 |
|
|
we--conflict-body |
298 |
|
|
@Order: 30 |
299 |
|
|
@Description: |
300 |
|
|
@@@: Conflict report |
301 |
|
|
@@lang:en |
302 |
|
|
@Formatting: |
303 |
|
|
%paragraph (content=>{%res(name=>{Edit:Conflict:Description});}p); |
304 |
|
|
%we--conflict-modified-content; |
305 |
wakaba |
1.6 |
%section ( |
306 |
wakaba |
1.2 |
id => edit-conflict-diff, |
307 |
|
|
title => {%res(name=>{Edit:Conflict:Diff:Title});}p, heading, |
308 |
|
|
content => { |
309 |
|
|
%paragraph ( |
310 |
|
|
content => {%res(name=>{Edit:Conflict:Diff:Description});}p); |
311 |
|
|
%conflict-diff; |
312 |
|
|
}p, |
313 |
|
|
); |
314 |
|
|
|
315 |
|
|
ViewFragment: |
316 |
|
|
@Template[list]: we--edit-body |
317 |
|
|
@Order:80 |
318 |
|
|
@Description: |
319 |
|
|
@@@: Editing WikiPage form section |
320 |
|
|
@@lang:en |
321 |
|
|
@Formatting: |
322 |
wakaba |
1.6 |
%section ( |
323 |
wakaba |
1.2 |
id => edit, |
324 |
|
|
title => {%res (name => {Edit:Title});}p, heading, |
325 |
|
|
content => {%edit-form;}p, |
326 |
|
|
); |
327 |
|
|
|
328 |
|
|
ViewFragment: |
329 |
|
|
@Template[list]: we--adminedit-body |
330 |
|
|
@Order:80 |
331 |
|
|
@Description: |
332 |
|
|
@@@: Editing WikiPage form section (Admin edit mode) |
333 |
|
|
@@lang:en |
334 |
|
|
@Formatting: |
335 |
wakaba |
1.6 |
%section ( |
336 |
wakaba |
1.2 |
id => edit, |
337 |
|
|
title => {%res(name=>{Edit:Title});}p, heading, |
338 |
|
|
content => {%edit-form(admin);}p, |
339 |
|
|
); |
340 |
|
|
|
341 |
|
|
ViewFragment: |
342 |
|
|
@Template[list]: we--conflict-body |
343 |
|
|
@Order: 80 |
344 |
|
|
@Description: |
345 |
|
|
@@@: Editing-WikiPage-form section (conflict mode) |
346 |
|
|
@@lang:en |
347 |
|
|
@Formatting: |
348 |
wakaba |
1.6 |
%section ( |
349 |
wakaba |
1.2 |
id => edit, |
350 |
|
|
title => {%res(name=>{Edit:Title});}p, heading, |
351 |
|
|
content => { |
352 |
|
|
%paragraph(name=>{%res(name=>{Edit:Conflict:Edit:Description});}p); |
353 |
|
|
%edit-form; |
354 |
|
|
}p, |
355 |
|
|
); |
356 |
wakaba |
1.1 |
|
357 |
|
|
ViewFragment: |
358 |
|
|
@Name: we--edit |
359 |
|
|
@Description: |
360 |
|
|
@@@: Edit form --- main textarea |
361 |
|
|
@@lang:en |
362 |
|
|
@Order: 0 |
363 |
|
|
@Formatting: |
364 |
wakaba |
1.5 |
%textarea (id => we--content, size => {%res (name=>{Edit:Form:Size});}p, |
365 |
wakaba |
1.6 |
source => content, lines => {%res (name=>{Edit:Form:Lines});}p); |
366 |
wakaba |
1.1 |
ViewFragment: |
367 |
|
|
@Name: we--edit |
368 |
|
|
@Description: |
369 |
|
|
@@@: Submit button |
370 |
|
|
@@lang:en |
371 |
|
|
@Order: 200 |
372 |
|
|
@Formatting: |
373 |
|
|
%submit(label=>{%res(name=>{Edit:Save});}p); |
374 |
|
|
|
375 |
|
|
FormattingRule: |
376 |
|
|
@Category[list]: view |
377 |
|
|
@Name: edit-form |
378 |
|
|
@Description: |
379 |
|
|
@@@: Provides WikiPage editing form |
380 |
|
|
@@lang: en |
381 |
|
|
@Parameter: |
382 |
|
|
@@Name: admin |
383 |
|
|
@@Type: boolean |
384 |
|
|
@@Default: {0} |
385 |
|
|
@@Description: |
386 |
|
|
@@@@: Whether administrator's editing mode or not |
387 |
|
|
@@@lang:en |
388 |
wakaba |
1.5 |
@Parameter: |
389 |
|
|
@@Name: page |
390 |
|
|
@@Type: WikiName |
391 |
|
|
@@Default: (auto) |
392 |
|
|
@@Description: |
393 |
|
|
@@@@: WikiPage that is editing |
394 |
|
|
@@@lang:en |
395 |
wakaba |
1.1 |
@Formatting: |
396 |
wakaba |
1.5 |
__ATTRTEXT:%admin__;__ATTRTEXT:%page__; |
397 |
wakaba |
1.8 |
my $page = $o->{wiki}->name ($p->{page} || $o->{wiki}->{var}->{page}); |
398 |
wakaba |
1.5 |
my $template = $o->{wiki}->{view}->assemble_template ('we__edit'); |
399 |
|
|
local $o->{var} = { |
400 |
wakaba |
1.1 |
#content |
401 |
|
|
is_admin_mode => $p->{admin}, |
402 |
|
|
is_conflict_mode => 0, |
403 |
|
|
#is_new_page_template |
404 |
|
|
}; |
405 |
wakaba |
1.5 |
$o->{var}->{content} = __FUNCPACK__->get_content ($o, $page); |
406 |
|
|
SuikaWiki::Plugin->module_package ('WikiFormCore') |
407 |
|
|
->make_form_in_html |
408 |
|
|
($p->{-parent}, $template, |
409 |
|
|
wiki => $o->{wiki}, |
410 |
|
|
o => $o, |
411 |
|
|
index => -1, |
412 |
|
|
output => { |
413 |
|
|
mode => 'write', |
414 |
|
|
page => $page, |
415 |
|
|
hidden => sub { |
416 |
|
|
my ($hidden, $o) = @_; |
417 |
wakaba |
1.3 |
for ($hidden->append_new_node (type => '#element', |
418 |
wakaba |
1.5 |
namespace_uri => $NS_XHTML1, |
419 |
|
|
local_name => 'input')) { |
420 |
wakaba |
1.1 |
$_->set_attribute (type => 'hidden'); |
421 |
|
|
$_->set_attribute (name => 'we--digest'); |
422 |
wakaba |
1.2 |
$_->set_attribute (value => ($o->{var}->{is_new_page_template}?'': |
423 |
wakaba |
1.5 |
__FUNCPACK__->digest ($o->{var}->{content}, |
424 |
|
|
normalize => 1))); |
425 |
wakaba |
1.1 |
$_->option (use_EmptyElemTag => 1); |
426 |
|
|
} |
427 |
wakaba |
1.5 |
}, |
428 |
|
|
}); |
429 |
|
|
|
430 |
wakaba |
1.1 |
|
431 |
|
|
FormattingRule: |
432 |
|
|
@Category[list]: view |
433 |
wakaba |
1.2 |
@Name: we--conflict-modified-content |
434 |
wakaba |
1.1 |
@Description: |
435 |
|
|
@@@: |
436 |
wakaba |
1.2 |
Modified content that is conflicted with current content |
437 |
wakaba |
1.1 |
@@lang:en |
438 |
|
|
@Formatting: |
439 |
wakaba |
1.3 |
$p->{-parent}->append_new_node (type => '#element', |
440 |
wakaba |
1.2 |
namespace_uri => $NS_XHTML1, |
441 |
wakaba |
1.3 |
local_name => 'pre') |
442 |
|
|
->append_text (scalar $o->{wiki}->{input}->parameter ('we--content')); |
443 |
wakaba |
1.1 |
|
444 |
|
|
FormattingRule: |
445 |
|
|
@Category[list]:view |
446 |
|
|
@Name: conflict-diff |
447 |
|
|
@Description: |
448 |
|
|
@@@: |
449 |
|
|
Provides marked diff between latest WikiPage content and |
450 |
|
|
submitted one |
451 |
|
|
@@lang:en |
452 |
|
|
@Formatting: |
453 |
wakaba |
1.6 |
my $before = scalar $o->{wiki}->{input}->parameter ('we--content'); |
454 |
wakaba |
1.7 |
my $after; |
455 |
|
|
try { |
456 |
|
|
$after = $o->{wiki}->{db}->get (content => $o->{wiki}->{var}->{page}); |
457 |
|
|
} catch SuikaWiki::DB::Util::Error with { |
458 |
wakaba |
1.9 |
my $err = shift; |
459 |
|
|
$err->throw if $err->{-type} eq 'ERROR_REPORTED'; |
460 |
wakaba |
1.7 |
$after = undef; |
461 |
|
|
}; |
462 |
wakaba |
1.6 |
__FUNCPACK__->diff_in_html (\$before => \$after, $p->{-parent}); |
463 |
|
|
|
464 |
|
|
Function: |
465 |
|
|
@Name: diff_in_html |
466 |
|
|
@Main: |
467 |
|
|
my (undef, $before, $after, $parent, %opt) = @_; |
468 |
wakaba |
1.3 |
require Algorithm::Diff; |
469 |
wakaba |
1.6 |
my $diff = $parent->append_new_node (type => '#element', |
470 |
|
|
namespace_uri => $NS_XHTML1, |
471 |
|
|
local_name => 'pre'); |
472 |
wakaba |
1.3 |
$diff->set_attribute (class => 'diff'); |
473 |
wakaba |
1.6 |
for (Algorithm::Diff::diff |
474 |
|
|
([split /\x0D?\x0A/, $$before]=>[split /\x0D?\x0A/, $$after])) { |
475 |
wakaba |
1.1 |
for (@{$_}) { |
476 |
|
|
my ($sign, $lineno, $text) = @{$_}; |
477 |
wakaba |
1.3 |
my $line = $diff->append_new_node (type => '#element', |
478 |
wakaba |
1.2 |
namespace_uri => $NS_XHTML1, |
479 |
|
|
local_name => ({qw/+ ins - del/}->{$sign}||'span')); |
480 |
|
|
|
481 |
|
|
$line->set_attribute (class => 'line'); |
482 |
|
|
for ($line->append_new_node (type => '#element', |
483 |
|
|
namespace_uri => $NS_XHTML1, |
484 |
|
|
local_name => 'span')) { |
485 |
|
|
$_->set_attribute (class => 'lineno'); |
486 |
|
|
$_->append_text ($lineno); |
487 |
|
|
} |
488 |
|
|
$line->append_text (' '); |
489 |
|
|
for ($line->append_new_node (type => '#element', |
490 |
|
|
namespace_uri => $NS_XHTML1, |
491 |
|
|
local_name => 'span')) { |
492 |
|
|
$_->set_attribute (class => 'sign'); |
493 |
|
|
$_->append_text ($sign); |
494 |
|
|
} |
495 |
|
|
$line->append_text (' '); |
496 |
|
|
for ($line->append_new_node (type => '#element', |
497 |
|
|
namespace_uri => $NS_XHTML1, |
498 |
|
|
local_name => 'span')) { |
499 |
|
|
$_->set_attribute (class => 'content'); |
500 |
|
|
$_->append_text ($text); |
501 |
|
|
} |
502 |
|
|
$line->append_text ("\n"); |
503 |
|
|
} # diff lines |
504 |
wakaba |
1.1 |
} |
505 |
|
|
|
506 |
|
|
FormattingRule: |
507 |
|
|
@Name:mode-after-edit-selection |
508 |
wakaba |
1.5 |
@Category[list]:form-input |
509 |
wakaba |
1.8 |
@Parameter: |
510 |
|
|
@@Name: description |
511 |
|
|
@@Type: text |
512 |
|
|
@@Default: (none) |
513 |
|
|
@@Description: |
514 |
|
|
@@@@: Human readable description about this input |
515 |
|
|
@@@lang: en |
516 |
wakaba |
1.1 |
@Formatting: |
517 |
wakaba |
1.8 |
## TODO: media-type prop support |
518 |
wakaba |
1.1 |
my $magic = ''; |
519 |
|
|
$magic = $1 if $o->{var}->{content} =~ m/^([^\x0A\x0D]+)/s; |
520 |
|
|
|
521 |
wakaba |
1.5 |
my $name = 'we--mode-modified'; |
522 |
wakaba |
1.1 |
my $selected_mode = $o->{wiki}->{input}->parameter ($name); |
523 |
|
|
unless ($selected_mode) { |
524 |
|
|
if ($magic =~ /C(?:on(?:fig|st)|SS)/) { |
525 |
|
|
$selected_mode = 'edit'; |
526 |
|
|
} else { |
527 |
|
|
$selected_mode = 'default'; |
528 |
|
|
} |
529 |
|
|
} |
530 |
|
|
|
531 |
wakaba |
1.3 |
my $SELECT = $p->{-parent}->append_new_node (type => '#element', |
532 |
|
|
namespace_uri => $NS_XHTML1, |
533 |
|
|
local_name => 'select'); |
534 |
wakaba |
1.1 |
$SELECT->set_attribute (name => $name); |
535 |
wakaba |
1.8 |
__ATTRTEXT:%description__; |
536 |
|
|
$SELECT->set_attribute (title => $p->{description}) |
537 |
|
|
if length $p->{description}; |
538 |
wakaba |
1.1 |
for (qw/default read edit/) { |
539 |
|
|
for my $OPTION ($SELECT->append_new_node (type => '#element', |
540 |
|
|
namespace_uri => $NS_XHTML1, |
541 |
|
|
local_name => 'option')) { |
542 |
|
|
$OPTION->set_attribute (value => $_); |
543 |
wakaba |
1.6 |
my $label = SuikaWiki::Plugin->module_package ('WikiResource') |
544 |
|
|
->append_node (name => 'Edit:SaveAnd:'.$_.':Label', |
545 |
|
|
param => $o, |
546 |
|
|
wiki => $o->{wiki}); |
547 |
|
|
$OPTION->set_attribute (label => $label->inner_text); |
548 |
|
|
$OPTION->append_node ($label); |
549 |
wakaba |
1.1 |
$OPTION->set_attribute |
550 |
wakaba |
1.6 |
(title => SuikaWiki::Plugin->module_package ('WikiResource') |
551 |
|
|
->append_node (name => 'Edit:SaveAnd:'.$_.':Description', |
552 |
|
|
param => $o, |
553 |
|
|
wiki => $o->{wiki})->inner_text); |
554 |
wakaba |
1.1 |
$OPTION->set_attribute (selected => 'selected') |
555 |
|
|
if $selected_mode eq $_; |
556 |
|
|
} |
557 |
|
|
} |
558 |
|
|
|
559 |
wakaba |
1.5 |
FormattingRule: |
560 |
|
|
@Category[list]:form-input |
561 |
|
|
@Name:we--update-lastmodified-datetime |
562 |
|
|
@Description: |
563 |
|
|
@@@: |
564 |
|
|
This direction force to update last-modified date-time |
565 |
|
|
of the WikiPage modified. |
566 |
|
|
\ |
567 |
|
|
Allowing user to select whether last-modified date-time should be |
568 |
|
|
updated, use another formatting rule provided by WikiFormSelection |
569 |
wakaba |
1.10 |
module, like: |
570 |
|
|
\ |
571 |
|
|
\ %check (id => we--touch, |
572 |
|
|
\ label => {%res (name => {Edit:UpdateTimeStamp});}p, |
573 |
|
|
\ description => {%res |
574 |
|
|
\ (name => {Edit:UpdateTimeStamp:Description});}p, |
575 |
|
|
\ default); |
576 |
wakaba |
1.5 |
\ |
577 |
|
|
WikiForm other that editing form might not be affected by this |
578 |
|
|
parameter. See also "we--touch" parameter. |
579 |
|
|
@@lang:en |
580 |
|
|
@Formatting: |
581 |
|
|
for ($p->{-parent}->append_new_node |
582 |
|
|
(type => '#element', |
583 |
|
|
namespace_uri => $NS_XHTML1, |
584 |
|
|
local_name => 'input')) { |
585 |
|
|
$_->set_attribute (type => 'hidden'); |
586 |
|
|
$_->set_attribute (name => 'we--touch'); |
587 |
|
|
$_->set_attribute (value => 'on'); |
588 |
|
|
$_->option (use_EmptyElemTag => 1); |
589 |
|
|
} |
590 |
|
|
|
591 |
|
|
|
592 |
wakaba |
1.1 |
Resource: |
593 |
wakaba |
1.2 |
@Edit:Conflict:Title: |
594 |
|
|
@@@:Confliction detected! |
595 |
|
|
@@lang:en |
596 |
|
|
@Edit:Conflict:WebPageTitle: |
597 |
|
|
@@@:%page-name; (Edit : 409 CONFLICTION) |
598 |
|
|
@@lang:en |
599 |
|
|
@Edit:Deleted:Description: |
600 |
|
|
@@@:Content of WikiPage %page-name; has been removed. |
601 |
|
|
@@lang:en |
602 |
|
|
@Edit:Deleted:Title: |
603 |
|
|
@@@:WikiPage Deleted |
604 |
|
|
@@lang:en |
605 |
|
|
@Edit:Deleted:WebPageTitle: |
606 |
|
|
@@@:%page-name; (Deleted) |
607 |
|
|
@@lang:en |
608 |
wakaba |
1.1 |
@Edit:Form:Lines:15 |
609 |
|
|
@Edit:Form:Size:18 |
610 |
|
|
@Edit:Save: |
611 |
|
|
@@@:Save |
612 |
|
|
@@lang:en |
613 |
wakaba |
1.8 |
@Edit:SaveAnd:Description: |
614 |
|
|
@@@: Select what to do after saving content |
615 |
|
|
@@lang: en |
616 |
wakaba |
1.1 |
@Edit:SaveAnd:default:Description: |
617 |
|
|
@@@: Save modified content and show content with your default view mode |
618 |
|
|
@@lang:en |
619 |
|
|
@Edit:SaveAnd:default:Label: |
620 |
|
|
@@@: Default view |
621 |
|
|
@@lang:en |
622 |
|
|
@Edit:SaveAnd:edit:Description: |
623 |
|
|
@@@: Save modified content and show content in the edit mode again |
624 |
|
|
@@lang:en |
625 |
|
|
@Edit:SaveAnd:edit:Label: |
626 |
|
|
@@@: Edit again |
627 |
|
|
@@lang:en |
628 |
|
|
@Edit:SaveAnd:read:Description: |
629 |
|
|
@@@: Save modified content and show content in the read mode |
630 |
|
|
@@lang:en |
631 |
|
|
@Edit:SaveAnd:read:Label: |
632 |
|
|
@@@: Show content |
633 |
|
|
@@lang:en |
634 |
|
|
@EditThisPage: |
635 |
|
|
@@@: Edit |
636 |
|
|
@@lang:en |
637 |
|
|
@EditThisPageLong: |
638 |
|
|
@@@: Edit this WikiPage |
639 |
|
|
@@lang:en |
640 |
|
|
@Edit:WebPageTitle: |
641 |
|
|
@@@: %page-name; (Modification) |
642 |
|
|
@@lang:en |
643 |
|
|
@Edit:Title: |
644 |
|
|
@@@: Modification of the WikiPage |
645 |
|
|
@@lang:en |
646 |
|
|
@Link:AdminEdit:Description: |
647 |
|
|
@@@: Edit this WikiPage (administrator's mode) |
648 |
|
|
@@lang:en |
649 |
|
|
@Link:Edit:Description: |
650 |
|
|
@@@: Edit this WikiPage |
651 |
|
|
@@lang:en |
652 |
wakaba |
1.8 |
@Mode:adminedit: |
653 |
|
|
@@@: Editing (for administrator) |
654 |
|
|
@@lang: en |
655 |
|
|
@Mode:edit: |
656 |
|
|
@@@: Editing |
657 |
|
|
@@lang: en |
658 |
wakaba |
1.1 |
|
659 |
|
|
Function: |
660 |
wakaba |
1.2 |
@Name:digest |
661 |
|
|
@Description: |
662 |
|
|
@@@: Compute digest of given string |
663 |
|
|
@@lang:en |
664 |
|
|
@Main: |
665 |
wakaba |
1.5 |
my (undef, $s, %opt) = @_; |
666 |
wakaba |
1.2 |
require Digest::SHA1; |
667 |
|
|
if ($opt{normalize}) { |
668 |
|
|
$s =~ s/\x0D\x0A/\x0A/g; |
669 |
|
|
$s =~ tr/\x0D/\x0A/; |
670 |
|
|
} |
671 |
|
|
Digest::SHA1::sha1_base64 ($s); |
672 |
|
|
|
673 |
|
|
Function: |
674 |
wakaba |
1.1 |
@Name:get_content |
675 |
|
|
@Description: |
676 |
|
|
@@@:Get WikiPage content to be modified. For new (currently not exist) |
677 |
|
|
WikiPage, new page template content is returned. |
678 |
|
|
@@lang:en |
679 |
|
|
@Main: |
680 |
wakaba |
1.5 |
my (undef, $o, $page) = @_; |
681 |
wakaba |
1.1 |
my $content; |
682 |
wakaba |
1.7 |
try { |
683 |
|
|
$content = $o->{wiki}->{db}->get (content => $page); |
684 |
|
|
|
685 |
|
|
unless (length $content) { |
686 |
|
|
## TODO: use namespaced template page |
687 |
|
|
$content = $o->{wiki}->{db}->get |
688 |
|
|
(content => $o->{wiki}->{config}->{page}->{NewPageTemplate}); |
689 |
|
|
$o->{var}->{is_new_page_template} = 1; |
690 |
|
|
} |
691 |
|
|
} catch SuikaWiki::DB::Util::Error with { |
692 |
wakaba |
1.9 |
my $err = shift; |
693 |
|
|
$err->throw if $err->{-type} eq 'ERROR_REPORTED'; |
694 |
wakaba |
1.7 |
$o->{wiki}->view_in_mode (mode => '-wdb--fatal-error'); |
695 |
|
|
throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED'; |
696 |
|
|
}; |
697 |
wakaba |
1.1 |
$content; |
698 |
|
|
|
699 |
|
|
Parameter: |
700 |
wakaba |
1.2 |
@Name: we--content |
701 |
|
|
@Type: text |
702 |
|
|
@Default: "" |
703 |
|
|
@Description: |
704 |
|
|
@@@: |
705 |
|
|
Content of WikiPage (to be) |
706 |
|
|
@@lang:en |
707 |
|
|
|
708 |
|
|
Parameter: |
709 |
wakaba |
1.1 |
@Name: we--digest |
710 |
|
|
@Type: "Base64ed SHA1" |
711 |
|
|
@Default: {undef} |
712 |
|
|
@Description: |
713 |
|
|
@@@: |
714 |
|
|
SHA1 digest value of the WikiPage content before the modification. |
715 |
|
|
This value is used to detect confliction of modifying. |
716 |
|
|
Empty value (undef or length-zero-string) means that |
717 |
|
|
there were no WikiPage content. |
718 |
wakaba |
1.2 |
@@lang:en |
719 |
|
|
|
720 |
|
|
Parameter: |
721 |
|
|
@Name: we--mode-modified |
722 |
|
|
@Type: mode-name |
723 |
|
|
@Default: "default" |
724 |
|
|
@Description: |
725 |
|
|
@@@: |
726 |
|
|
WikiEngine running mode to be specified after modification is completed |
727 |
wakaba |
1.1 |
@@lang:en |
728 |
|
|
|
729 |
|
|
Parameter: |
730 |
|
|
@Name: we--touch |
731 |
wakaba |
1.5 |
@Type: |
732 |
|
|
form:checkbox-value |
733 |
wakaba |
1.1 |
@Default: "off" |
734 |
|
|
@Description: |
735 |
|
|
@@@: |
736 |
|
|
Whether last-modified date-time of the WikiPage should be updated or not |
737 |
|
|
when the WikiPage is modified. |
738 |
|
|
@@lang:en |