/[pub]/suikawiki/script/misc/plugins/SuikaWiki09.wp2
Suika

Contents of /suikawiki/script/misc/plugins/SuikaWiki09.wp2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (hide annotations) (download)
Fri Aug 6 03:38:11 2004 UTC (20 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.14: +4 -1 lines
InterWiki custom source-anchor label implemented

1 wakaba 1.1 #?SuikaWikiConfig/2.0
2    
3     Plugin:
4     @Name: SuikaWiki09
5     @Description:
6     @@@: SuikaWiki/0.9 document format
7     @@lang:en
8 wakaba 1.8 @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.7 @Date.RCS:
16 wakaba 1.15 $Date: 2004/04/26 00:53:00 $
17 wakaba 1.1 @RequiredPlugin[list]:
18 wakaba 1.4 Edit
19     WikiFormCore
20 wakaba 1.2 WikiLinking
21 wakaba 1.4 WikiStruct
22 wakaba 1.1 @Use:
23     use Message::Markup::XML::QName qw/NS_xml_URI/;
24     my $Reg_Form_Content_M = qr{
25     \ \#form
26     \ (?:
27     \ \( (\w+) \) ## id
28     \ )?
29     \ : ' ((?>[^\\']*)(?>(?>[^\\']+|\\.)*)) ' ## input
30 wakaba 1.9 \ (?> : ' ((?>[^\\']*)(?>(?>[^\\']+|\\.)*)) ' ## template
31     \ (?> : ' ((?>[^\\']*)(?>(?>[^\\']+|\\.)*)) ' )? )? ## option
32 wakaba 1.1 }x;
33     my $Reg_Embed_Content_M = qr{
34     \ \#([a-z-]+)
35     \ (?>
36     \ \( (\w+) \) ## id
37     \ )?
38     \ (?>
39     \ : ( \w+ (?> : \w+ )* ) ## parameter
40     \ )?
41     }x;
42     my $Reg_URI_Opaque = qr{
43     \ (?>[^<>"]*)
44     \ (?>
45     \ (?>
46     \ [^<>"]+
47     \ | "(?>[^"\\]*)(?>(?>[^"\\]+|\\.)*)"
48     \ )*
49     \ )
50     }x;
51 wakaba 1.9
52     my ($WIKIRESOURCE, $WIKISTRUCT, $WIKIFORMCORE, $WIKILINKING);
53 wakaba 1.1
54 wakaba 1.2 PluginConst:
55     @NS_SW09:
56     urn:x-suika-fam-cx:markup:suikawiki:0:9:
57     @NS_HTML3:
58     urn:x-suika-fam-cx:markup:ietf:html:3:draft:00:
59     @NS_XHTML1:
60     http://www.w3.org/1999/xhtml
61     @NS_XHTML2:
62     http://www.w3.org/2002/06/xhtml2
63 wakaba 1.9 @WIKIFORMCORE:
64     {($WIKIFORMCORE ||= SuikaWiki::Plugin->module_package ('WikiFormCore'))}
65     @WIKILINKING:
66     {($WIKILINKING ||= SuikaWiki::Plugin->module_package ('WikiLinking'))}
67 wakaba 1.5 @WIKIRESOURCE:
68     {($WIKIRESOURCE ||= SuikaWiki::Plugin->module_package ('WikiResource'))}
69 wakaba 1.9 @WIKISTRUCT:
70     {($WIKISTRUCT ||= SuikaWiki::Plugin->module_package ('WikiStruct'))}
71    
72    
73 wakaba 1.2
74 wakaba 1.1 Format:
75     @ModuleName:
76     SuikaWiki::V0
77     @Description:
78     @@@: Dummy base format for SuikaWiki/0.*
79     @@lang:en
80     @Inherit[list]:
81     Text::Plain
82    
83     Format:
84     @Name: SuikaWiki
85     @Version: 0.9
86     @Type:
87     @@@: text/x-suikawiki
88     @@version: 0.9
89     @ModuleName:
90     SuikaWiki::V0_9
91     @Inherit[list]:
92     SuikaWiki::V0
93     @Description:
94     @@@: SuikaWiki/0.9 document format (Standard document format for SuikaWiki 2)
95     @@lang:en
96 wakaba 1.2
97     @Use:
98     use Message::Markup::XML::QName qw/NS_xml_URI/;
99 wakaba 1.4 use Message::Util::Error;
100 wakaba 1.1
101     @Converter:
102     @@Type: text/html
103     @@IsFragment: 1
104     @@Description:
105     @@@@: Converting SuikaWiki/0.9 to Hypertext Markup Language fragment
106     @@@lang:en
107     @@Main:
108 wakaba 1.4 $opt->{o}->{wiki} ||= $self->{wiki};
109    
110 wakaba 1.2 ## Text format -> XML format
111 wakaba 1.4 my $xml = __FUNCPACK__->get_xml_tree (text => $source, opt => $opt,
112     wiki => $self->{wiki});
113    
114     ## SuikaWiki/0.9 -> XHTML 1
115 wakaba 1.6 __FUNCPACK__->sw09_to_xhtml1 (source => $xml, parent => $opt->{-parent},
116     o => $opt->{o}, page => $opt->{page});
117    
118     if ($opt->{-with_annotation_input}) {
119     SuikaWiki::Plugin->module_package ('WikiFormCore')
120     ->make_content_form_in_html
121     ($opt->{-parent},
122     $WIKIRESOURCE->get
123     (name => 'SuikaWiki/0.9:form:footannotate:input',
124     o => $opt->{o}, wiki => $opt->{o}->{wiki}),
125     option => $WIKIRESOURCE->get
126     (name => 'SuikaWiki/0.9:form:footannotate:option',
127     o => $opt->{o}, wiki => $opt->{o}->{wiki}),
128     o => $opt->{o},
129     wiki => $opt->{o}->{wiki},
130     output => {
131     page => $opt->{page},
132     });
133     }
134    
135    
136     @Converter:
137     @@Type:
138     @@@@: application/x-suikawiki+xml
139     @@@version: 0.9
140     @@Description:
141     @@@@: Converting SuikaWiki/0.9 text format to XML format
142     @@@lang: en
143     @@Main:
144     my $xml = __FUNCPACK__->get_xml_tree (text => $source, opt => $opt,
145     wiki => $self->{wiki});
146     ## TODO: Make a clone
147     $opt->{-parent}->append_node ($xml);
148    
149     @NextIndex:
150     @@Name: anchor
151     @@Main:
152     my $xml = __FUNCPACK__->get_xml_tree (text => $source, opt => \%opt,
153     wiki => $self->{wiki});
154     (__FUNCPACK__->get_last_anchor_index ($xml)) + 1;
155    
156     @WikiForm:
157     @@Main:
158     ## Text format -> XML format
159     my $xml = __FUNCPACK__->get_xml_tree (text => $source, opt => \%opt,
160     wiki => $self->{wiki});
161     local $opt{o}->{var}->{sw09__anchor_index};
162     local $opt{o}->{var}->{sw09__document_tree} = $xml;
163    
164     my $form;
165     if ($opt{o}->{form}->{output}->{id}) {
166     $form = __FUNCPACK__->get_element_by_id
167     ($xml, $opt{o}->{form}->{output}->{id});
168     undef $form unless ref $form and
169     $form->namespace_uri eq $NS_SW09 and
170     $form->local_name eq 'form';
171     } else {
172     $form = __FUNCPACK__->get_nth_element
173     ($xml, $NS_SW09 => 'form',
174     $opt{o}->{form}->{output}->{index});
175     }
176    
177     my $ref;
178     if (ref $form) {
179     $ref = $form->get_attribute_value ('ref', default => 'form');
180     } else {
181     $ref = '#footannotate';
182     }
183    
184    
185     ## WikiForm Option
186     if ($ref eq 'form') {
187     $opt{option} ||= $form->get_attribute_value ('option');
188     } elsif ($ref eq 'comment') {
189     $opt{option} ||= $WIKIRESOURCE->get
190     (name => 'SuikaWiki/0.9:form:comment:option',
191     o => $opt{o}, wiki => $opt{o}->{wiki});
192     } elsif ($ref eq '#footannotate') {
193     $opt{option} ||= $WIKIRESOURCE->get
194     (name => 'SuikaWiki/0.9:form:footannotate:option',
195     o => $opt{o}, wiki => $opt{o}->{wiki});
196     } else {
197     ## TODO:
198     }
199 wakaba 1.11 $WIKIFORMCORE->set_option ($opt{option} => $opt{o}) if $opt{option};
200    
201     my @missing;
202     for (keys %{$opt{o}->{form}->{require}->{id}}) {
203     unless (length $opt{o}->{wiki}->{input}->parameter
204     ($WIKIFORMCORE->control_id ($opt{o}, local_id => $_,
205     local_id_prefix => 'wikiform__')
206     ->{local_id})) {
207     push @missing, $_;
208     }
209     }
210     if (@missing) {
211     return [{
212     type => 'required_param_missing',
213     missing_id => \@missing,
214     }];
215     }
216 wakaba 1.6
217     ## Replace Output Template
218     my $result;
219     if ($ref eq 'form') {
220     $opt{template} ||= $form->get_attribute_value
221     ('template', default => '');
222     } elsif ($ref eq 'comment') {
223     $opt{template} ||= $WIKIRESOURCE->get
224     (name => 'SuikaWiki/0.9:form:comment:template',
225     o => $opt{o}, wiki => $opt{o}->{wiki});
226     } elsif ($ref eq '#footannotate') {
227     $opt{template} ||= $WIKIRESOURCE->get
228     (name => 'SuikaWiki/0.9:form:footannotate:template',
229     o => $opt{o}, wiki => $opt{o}->{wiki});
230     }
231     try {
232     $result = SuikaWiki::Plugin->text_formatter ('form_template')
233     ->replace ($opt{template}, param => $opt{o});
234     } catch Message::Util::Formatter::error with {
235     my $err = shift;
236     SuikaWiki::Plugin->module_package ('Error')
237     ->reporting_formatting_template_error
238     ($err, $err->{option}->{param}->{wiki});
239     ##TODO:
240     throw SuikaWiki::View::Implementation::error -type => 'ERROR_REPORTED';
241     };
242    
243     ## Insert
244     if (length $result) {
245     if ($ref eq '#footannotate') {
246     my $parent;
247     for (@{$xml->child_nodes}) {
248     if ($_->node_type eq '#element' and
249     $_->local_name eq 'document') {
250     for (@{$_->child_nodes}) {
251     if ($_->node_type eq '#element' and
252     $_->local_name eq 'body') {
253     $parent = $_;
254     last;
255     }
256     }
257     }
258     }
259 wakaba 1.9 CORE::die "Buggy implementation: no body element".$xml
260     unless ref $parent;
261 wakaba 1.6
262     $parent->append_new_node (type => '#element',
263     namespace_uri => $NS_SW09,
264     local_name => 'text')
265     ->append_text ($result);
266     } else {
267     my $parent = $form->parent_node;
268     CORE::die "Byggy implementation: No parent of form" unless ref $parent;
269     my $children = $parent->child_nodes;
270    
271     $result .= "\x0A" unless substr ($result, -1) eq "\x0A";
272     $parent->append_new_node (type => '#element',
273     namespace_uri => $NS_SW09,
274     local_name => 'text')
275     ->append_text ($result);
276     my $node = pop @{$children};
277     my $form_str = overload::StrVal ($form);
278     my $i = 0;
279     for (@{$children}) {
280     last if overload::StrVal ($_) eq $form_str;
281     $i++;
282     }
283     if ($opt{o}->{form}->{output}->{reverse}) {
284     splice @{$children}, $i + 1, 0, $node;
285     } else {
286     splice @{$children}, $i, 0, $node;
287     }
288     }
289     } else {
290     ## TODO:
291     }
292    
293     ## XML format -> Text format
294     my $text = __FUNCPACK__->xml_to_text ($xml, {%opt});
295    
296     my %fragment = (fragment => $opt{o}->{form}->{output}->{id}
297     || 'wikiform-'.$opt{o}->{form}->{output}->{index});
298     if (not $opt{o}->{form}->{output}->{reverse} and
299     $opt{o}->{var}->{sw09__anchor_index}) {
300     %fragment = (anchor_no => $opt{o}->{var}->{sw09__anchor_index});
301     }
302    
303     my $action = [
304     {
305     type => 'write',
306     content => $text,
307     update_lastmodified => time,
308     },
309     {
310 wakaba 1.11 type => 'ok',
311 wakaba 1.6 %fragment,
312     },
313     ];
314    
315     @HeadSummary:
316     @@Main:
317     my $xml = __FUNCPACK__->get_xml_tree (text => $source, opt => \%opt,
318     wiki => $self->{wiki});
319     return $xml->inner_text;
320    
321     FormattingRule:
322     @Category[list]:form-template
323     @Name: index
324     @Description:
325     @@@: Next anchor index number
326     @@lang:en
327     @After:
328     if ($o->{var}->{sw09__anchor_index}) {
329     ++$o->{var}->{sw09__anchor_index};
330     } else {
331     $o->{var}->{sw09__anchor_index}
332     = 1 + __FUNCPACK__->get_last_anchor_index
333     ($o->{var}->{sw09__document_tree});
334     }
335     $p->{-result} .= $o->{var}->{sw09__anchor_index};
336    
337     Function:
338     @Name: get_last_anchor_index
339     @Main:
340     my (undef, $xml) = @_;
341     my $anchor = 0;
342     my $get_anchor_no;
343     $get_anchor_no = sub {
344     my $node = shift;
345     for my $child (@{$node->child_nodes}) {
346 wakaba 1.9 my $nt = $child->node_type;
347     if ($nt eq '#element') {
348 wakaba 1.6 if ($child->namespace_uri => $NS_SW09 and
349     $child->local_name eq 'anchor-end') {
350     my $a = $child->get_attribute_value ('anchor', default => 0,
351     namespace_uri => $NS_SW09);
352     $anchor = 0+$a if $anchor < 0+$a;
353     } else {
354     $get_anchor_no->($child);
355     }
356 wakaba 1.9 } elsif ($nt eq '#document' or $nt eq '#fragment') {
357 wakaba 1.6 $get_anchor_no->($child);
358     }
359     }
360     };
361     $get_anchor_no->($xml);
362     $anchor;
363    
364    
365     Function:
366     @Name: get_xml_tree
367     @Main:
368     my (undef, %opt) = @_;
369     if ($opt{opt}->{page}) {
370 wakaba 1.8 ## TODO:
371 wakaba 1.6 unless ($__FUNCPACK__::DBLoaded) {
372     $opt{wiki}->{db}->_set_prop_db (sw09__xml_tree => {-db_open => sub {
373     require SuikaWiki::DB::Hash;
374     new SuikaWiki::DB::Hash;
375     }});
376     $__FUNCPACK__::DBLoaded++;
377     }
378    
379     my $xml = new Message::Markup::XML::Node type => '#fragment';
380     __FUNCPACK__->text_to_xml (${$opt{text}}, {%{$opt{opt}}, -parent => $xml});
381    
382     $opt{wiki}->{db}->set (sw09__xml_tree => $opt{opt}->{page} => $xml);
383     $xml;
384     } else {
385     my $xml = new Message::Markup::XML::Node type => '#fragment';
386     __FUNCPACK__->text_to_xml (${$opt{text}}, {%{$opt{opt}}, -parent => $xml});
387     $xml;
388     }
389    
390     Function:
391     @Name: sw09_to_xhtml1
392     @Main:
393     my (undef, %opt) = @_;
394    
395 wakaba 1.2 my ($apply_template, $apply_template_children);
396     $apply_template_children = sub {
397 wakaba 1.9 for (@{$_[0]->child_nodes}) {
398     $apply_template->($_ => $_[1]) unless $_->node_type eq '#attribute';
399 wakaba 1.2 }
400     };
401     $apply_template = sub {
402     my ($source, $result) = @_;
403     my $ln = $source->local_name;
404     if ($source->node_type eq '#text') {
405     $result->append_text ($source->inner_text);
406     } elsif ({qw/code 1 samp 1 var 1 dfn 1 kbd 1 sub 1 sup 1/}->{$ln}) {
407     my $node = $result->append_new_node
408     (type => '#element',
409     namespace_uri => $NS_XHTML1,
410     local_name => $ln);
411     my $class = $source->get_attribute_value ('class', default => '');
412     $node->set_attribute (class => $class) if $class;
413     $apply_template_children->($source => $node);
414 wakaba 1.4 } elsif ({qw/ins 1 del 1 insert 1 delete 1/}->{$ln}) {
415 wakaba 1.2 my $node = $result->append_new_node
416     (type => '#element',
417     namespace_uri => $NS_XHTML1,
418 wakaba 1.4 local_name => {qw/ins ins insert ins
419     delete del del del/}->{$ln});
420 wakaba 1.2 my $class = $source->get_attribute_value ('class', default => '');
421     $node->set_attribute (class => $class) if $class;
422     ## TODO: cite
423     $apply_template_children->($source => $node);
424     } elsif ({qw/table 1 tbody 1 tr 1 td 1 blockquote 1 ul 1 ol 1
425     li 1 pre 1 dl 1 dt 1 dd 1 em 1 strong 1/}->{$ln}) {
426     my $node = $result->append_new_node
427     (type => '#element',
428     namespace_uri => $NS_XHTML1,
429     local_name => $ln);
430     if ($ln eq 'td') {
431     my $colspan = $source->get_attribute_value ('colspan', default => 0);
432     $node->set_attribute (colspan => $colspan) if $colspan;
433     } elsif ($ln eq 'pre') {
434     $node->set_attribute (space => 'preserve',
435     namespace_uri => NS_xml_URI);
436 wakaba 1.10 my $class = $source->get_attribute_value ('class', default => '');
437     $node->set_attribute (class => $class) if length $class;
438 wakaba 1.2 }
439 wakaba 1.6 $apply_template_children->($source => $node);
440     } elsif ($ln eq 'anchor') {
441     local $opt{o}->{var}->{sw09__anchor_content} = sub {
442     $apply_template_children->($source => shift);
443     };
444     SuikaWiki::Plugin->module_package ('WikiLinking')
445     ->to_wikipage_in_html ({
446 wakaba 1.9 label => $WIKIRESOURCE->get_text
447 wakaba 1.6 (name =>
448     'Link:SuikaWiki/0.9:toWikiPage:SourceLabel',
449     param => $opt{o},
450     wiki => $opt{o}->{wiki}),
451     } => {
452     base => $opt{o}->{wiki}->{var}->{page},
453 wakaba 1.14 page_name => $opt{o}->{wiki}->name ($source->inner_text)
454     ->absolute (wiki => $opt{o}->{wiki},
455     nearest => 'content',
456     base => $opt{o}->{wiki}
457     ->{var}->{page}),
458 wakaba 1.6 page_anchor_no => $source->get_attribute_value
459     ('anchor',
460     namespace_uri => $NS_SW09),
461     }, {
462     o => $opt{o},
463     parent => $result,
464     });
465     } elsif ($ln eq 'p') {
466     $apply_template_children->($source => $result->append_new_node
467 wakaba 1.2 (type => '#element',
468     namespace_uri => $NS_XHTML1,
469 wakaba 1.6 local_name => 'p'));
470     } elsif ($ln eq 'h') {
471     my $node;
472     if ($opt{o}->{var}->{ws__section_depth} > 6) {
473     $node = $result->append_new_node
474 wakaba 1.2 (type => '#element',
475     namespace_uri => $NS_XHTML1,
476 wakaba 1.6 local_name => 'div');
477     $node->set_attribute (class => 'heading h'.$opt{o}->{var}
478     ->{ws__section_depth});
479     } else {
480     $node = $result->append_new_node
481 wakaba 1.2 (type => '#element',
482     namespace_uri => $NS_XHTML1,
483 wakaba 1.6 local_name => 'h'.$opt{o}->{var}
484     ->{ws__section_depth});
485 wakaba 1.2 }
486     $apply_template_children->($source => $node);
487 wakaba 1.9 $WIKISTRUCT->set_section_id ($result, undef, $opt{o}->{wiki},
488 wakaba 1.6 title => $source->inner_text);
489     } elsif ($ln eq 'ruby' or $ln eq 'rubyb') {
490     my @child;
491     for (@{$source->child_nodes}) {
492     if ({qw/rb 1 rt 1/}->{$_->local_name}) {
493     push @child, $_;
494     }
495     }
496     for ($result->append_new_node (type => '#element',
497     namespace_uri => $NS_XHTML1,
498     local_name => 'ruby')) {
499     if ($ln eq 'rubyb') {
500     my $class = join ' ',
501     'descriptive',
502     split /\s+/, $source->get_attribute_value
503     ('class', default => '');
504     $_->set_attribute (class => $class) if $class;
505     } else {
506     my $class = $source->get_attribute_value ('class', default => '');
507     $_->set_attribute (class => $class) if $class;
508     }
509     $apply_template_children->($child[0]
510     => $_->append_new_node (type => '#element',
511     namespace_uri => $NS_XHTML1,
512     local_name => 'rb'));
513     $_->append_new_node (type => '#element',
514     namespace_uri => $NS_XHTML1,
515     local_name => 'rp')
516     ->append_text ('(');
517     if ($child[1]) {
518     $apply_template_children->($child[1]
519     => $_->append_new_node (type => '#element',
520     namespace_uri => $NS_XHTML1,
521     local_name => 'rt'));
522     } else {
523     $_->append_new_node (type => '#element',
524     namespace_uri => $NS_XHTML1,
525     local_name => 'rt');
526     }
527     if ($child[2]) {
528     $_->append_new_node (type => '#element',
529     namespace_uri => $NS_XHTML1,
530     local_name => 'rp')
531     ->append_text ('/');
532     $apply_template_children->($child[2]
533     => $_->append_new_node (type => '#element',
534     namespace_uri => $NS_XHTML1,
535     local_name => 'rt'));
536 wakaba 1.5 }
537 wakaba 1.6 $_->append_new_node (type => '#element',
538     namespace_uri => $NS_XHTML1,
539     local_name => 'rp')
540     ->append_text (')');
541 wakaba 1.5 }
542 wakaba 1.6 } elsif ($ln eq 'abbr') {
543     my (@b);
544     for (@{$source->child_nodes}) {
545     push @b, $_ if {qw/rb 1 rt 1/}->{$_->local_name};
546 wakaba 1.5 }
547 wakaba 1.6 my $node = $result->append_new_node
548     (type => '#element',
549     namespace_uri => $NS_XHTML1,
550     local_name => 'abbr');
551     $node->set_attribute (title => $b[1]->inner_text) if $b[1];
552     $apply_template_children->($b[0] => $node);
553     } elsif ($ln eq 'q') {
554     my $node = $result->append_new_node
555     (type => '#element',
556     namespace_uri => $NS_XHTML1,
557     local_name => 'q');
558     ## TODO: cite
559     $apply_template_children->($source => $node);
560     } elsif ($ln eq 'weak') {
561     my $node = $result->append_new_node
562     (type => '#element',
563     namespace_uri => $NS_XHTML1,
564     local_name => 'span');
565     $node->set_attribute (class => 'weak');
566     $apply_template_children->($source => $node);
567     } elsif ({qw/section 1 bodytext 1/}->{$ln}) {
568     my $node = $result->append_new_node
569     (type => '#element',
570     namespace_uri => $NS_XHTML1,
571     local_name => 'div');
572     $node->set_attribute (class => $ln);
573     local $opt{o}->{var}->{ws__section_depth}
574     = $opt{o}->{var}->{ws__section_depth} + 1;
575     $apply_template_children->($source => $node);
576     } elsif ($ln eq 'anchor-end') {
577     my $node = $result->append_new_node
578     (type => '#element',
579     namespace_uri => $NS_XHTML1,
580     local_name => 'a');
581     $node->set_attribute (id => 'anchor-'.$source->get_attribute_value
582     ('anchor', default => '0',
583     namespace_uri => $NS_SW09));
584 wakaba 1.8 $node->set_attribute (name => 'anchor-'.$source->get_attribute_value
585     ('anchor', default => '0',
586     namespace_uri => $NS_SW09))
587     if $opt{o}->{wiki}->{var}->{client}->{downgrade}->{html_no_id};
588 wakaba 1.12 $node->set_attribute (class => 'anchor');
589 wakaba 1.6 $node->append_text ($source->inner_text);
590     } elsif ($ln eq 'anchor-internal') {
591     my $node = $result->append_new_node
592     (type => '#element',
593     namespace_uri => $NS_XHTML1,
594     local_name => 'a');
595     $node->set_attribute (href => '#anchor-'.$source->get_attribute_value
596     ('anchor',
597     namespace_uri => $NS_SW09, default => '0'));
598     $node->set_attribute (class => 'wiki-anchor');
599     $node->append_text ($source->inner_text);
600     } elsif ($ln eq 'anchor-external') {
601     local $opt{o}->{var}->{sw09__anchor_content} = sub {
602     $apply_template_children->($source => shift);
603     };
604 wakaba 1.9 $WIKILINKING
605 wakaba 1.6 ->to_resource_in_html (
606     {
607 wakaba 1.9 label => $WIKIRESOURCE
608 wakaba 1.6 ->get_text (name =>
609     'Link:SuikaWiki/0.9:toResource:SourceLabel',
610     param => $opt{o},
611     wiki => $opt{o}->{wiki}),
612     }, {
613     resource_scheme =>
614     $source->get_attribute_value ('resScheme',
615     namespace_uri => $NS_SW09,
616     default => 'URI'),
617     resource_parameter =>
618     $source->get_attribute_value ('resParameter',
619     namespace_uri => $NS_SW09,
620     default => ''),
621     }, {
622     o => $opt{o},
623     parent => $result,
624     });
625     } elsif ($ln eq 'form') {
626     my $ref = $source->get_attribute_value ('ref', default => 'form');
627     if ($ref eq 'form') {
628 wakaba 1.9 $WIKIFORMCORE->make_content_form_in_html
629 wakaba 1.6 ($result,
630     $source->get_attribute_value
631     ('input', default => ''),
632     option => $source->get_attribute_value
633     ('option'),
634     name => $source->get_attribute_value ('id'),
635     o => $opt{o},
636     wiki => $opt{o}->{wiki},
637     output => {
638     page => $opt{page},
639     });
640     } elsif ($ref eq 'comment') {
641 wakaba 1.9 $WIKIFORMCORE->make_content_form_in_html
642 wakaba 1.6 ($result,
643     $WIKIRESOURCE->get
644     (name => 'SuikaWiki/0.9:form:comment:input',
645     o => $opt{o}, wiki => $opt{o}->{wiki}),
646     option => $WIKIRESOURCE->get
647     (name => 'SuikaWiki/0.9:form:comment:option',
648     o => $opt{o}, wiki => $opt{o}->{wiki}),
649     name => $source->get_attribute_value ('id'),
650     o => $opt{o},
651     wiki => $opt{o}->{wiki},
652     output => {
653     page => $opt{page},
654     });
655 wakaba 1.5 } else {
656 wakaba 1.14 ## TODO: Warning
657     $WIKIFORMCORE->make_content_form_in_html
658     ($result,
659     '',
660     option => '',
661     o => $opt{o},
662     wiki => $opt{o}->{wiki},
663     output => {
664     page => $opt{page},
665     });
666 wakaba 1.6 }
667     } elsif ($ln eq 'dr') {
668     $apply_template_children->($source => $result);
669     } elsif ($ln eq 'document') {
670     my $body;
671     for (@{$source->child_nodes}) {
672     $body = $_ and last if $_->local_name eq 'body';
673 wakaba 1.5 }
674 wakaba 1.6 my $body_block = $result->append_new_node
675     (type => '#element',
676     namespace_uri => $NS_XHTML1,
677     local_name => 'div');
678     $body_block->set_attribute (class => 'block SuikaWiki-0-9');
679     $apply_template_children->($body => $body_block);
680     } else {
681     my $node = $result->append_new_node
682     (type => '#element',
683     namespace_uri => $NS_XHTML1,
684     local_name => 'span');
685     $node->set_attribute (class => 'warn');
686     for ($node->append_new_node
687     (type => '#element',
688     namespace_uri => $NS_XHTML1,
689     local_name => 'ins')
690     ->append_new_node
691     (type => '#element',
692     namespace_uri => $NS_XHTML1,
693     local_name => 'code')) {
694     $_->set_attribute (class => 'XML element');
695     $_->append_text ("<".$source->namespace_uri.">:$ln");
696 wakaba 1.4 }
697 wakaba 1.6 $apply_template_children->($source => $node);
698 wakaba 1.4 }
699     };
700 wakaba 1.6
701     $apply_template_children->($opt{source} => $opt{parent});
702 wakaba 1.4
703    
704     Function:
705     @Name: xml_to_text
706     @Main:
707     my (undef, $src, $opt) = @_;
708    
709    
710     my %is_block = (
711     qw/p 1 blockquote 1 pre 1 ul 1 ol 1 dl 1 section 1 h 1
712     bodytext 1 document 1 head 1 body 1 table 1 text 1 form 1
713     insert 1 delete 1/
714     );
715    
716     my %x2t;
717     %x2t = (
718     anchor => sub {
719     my $source = shift;
720     my $result = '[['
721     . $x2t{'#inline'}->($source, no_newline => 1)
722     . ']';
723     my $anchor = $source->get_attribute_value
724     ('anchor',
725     namespace_uri => $NS_SW09,
726     default => '');
727     if (length $anchor) {
728     $result .= '>>'.(0+$anchor);
729     } else {
730     $anchor = $source->get_attribute_value
731     ('resScheme',
732     namespace_uri => $NS_SW09);
733     if ($anchor) {
734     my $param = $source->get_attribute_value
735     ('resParameter',
736     namespace_uri => $NS_SW09);
737     if ($anchor eq 'URI' and $param =~ /^[0-9A-Za-z_+.%-]+:/) {
738     $result .= '<' . $param . '>';
739     } else {
740     $result .= '<' . $anchor . ':' . $param . '>';
741     }
742     }
743     }
744     $result . ']';
745     },
746     li => sub {
747     my $source = shift;
748     my $result = ({qw/ul - ol =/}->{$opt->{o}->{var}->{sw09__list_type}}
749     x $opt->{o}->{var}->{sw09__list_depth})
750     . ' ' . $x2t{'#flow'}->($source);
751     $result;
752     },
753     dt => sub {
754     ':' . $x2t{'#inline'}->(return, no_newline => 1) . ':';
755     },
756     h => sub {
757     ("*" x ($opt->{o}->{var}->{ws__section_depth} - 1))
758     . " "
759     . $x2t{'#inline'}->(shift, no_newline => 1);
760     },
761     'anchor-end' => sub {
762     return shift->inner_text;
763     },
764     'anchor-internal' => sub {
765     return shift->inner_text;
766     },
767     'anchor-external' => sub {
768     return '<'.shift->inner_text.'>';
769     },
770     form => sub {
771     my $source = shift;
772     my $ref = $source->get_attribute_value ('ref', default => 'form');
773     my $result = '[[#'.$ref;
774     my $name = $source->get_attribute_value ('id');
775     $name =~ s/([()\\])/\\$1/g;
776     $result .= '(' . $name . ')' if $name;
777     ## General WikiForm
778     if ($ref eq 'form') {
779     $result .= ":'";
780     my $input = $source->get_attribute_value ('input', default => '');
781     $input =~ s/(['\\])/\\$1/g;
782     $result .= $input . "':'";
783     my $template = $source->get_attribute_value ('template', default => '');
784     $template =~ s/(['\\])/\\$1/g;
785     $result .= $template . "'";
786     my $option = $source->get_attribute_value ('option');
787     if ($option) {
788     $option =~ s/(['\\])/\\$1/g;
789     $result .= ":'" . $option . "'";
790     }
791     ## Specific WikiForm
792     } else {
793     my $param = $source->get_attribute_value ('parameter');
794     if ($param) {
795     $result .= ':' . $param;
796     }
797     }
798     $result .= ']]';
799     },
800     pre => sub {
801     my $source = shift;
802     my $result = '[PRE';
803     my $class = $source->get_attribute_value ('class');
804     if ($class) {
805     $class =~ s/([\\()])/\\$1/g;
806     $result .= '(' . $class . ')';
807     }
808     $result .= "[\x0A"
809     . $x2t{'#inline'}->($source);
810     $result .= "\x0A" unless substr ($result, -1) eq "\x0A";
811     $result .= "]PRE]\x0A";
812     },
813     insert => sub {
814     my $source = shift;
815     my $result = '[INS';
816     my $class = $source->get_attribute_value ('class');
817     if ($class) {
818     $class =~ s/([\\()])/\\$1/g;
819     $result .= '(' . $class . ')';
820     }
821     local $opt->{o}->{var}->{sw09__list_depth} = 0;
822     $result .= "[\x0A"
823     . $x2t{'#block'}->($source);
824     $result .= "\x0A" unless substr ($result, -1) eq "\x0A";
825     $result .= "]INS]\x0A";
826     },
827     delete => sub {
828     my $source = shift;
829     my $result = '[DEL';
830     my $class = $source->get_attribute_value ('class');
831     if ($class) {
832     $class =~ s/([\\()])/\\$1/g;
833     $result .= '(' . $class . ')';
834     }
835     local $opt->{o}->{var}->{sw09__list_depth} = 0;
836     $result .= "[\x0A"
837     . $x2t{'#block'}->($source);
838     $result .= "\x0A" unless substr ($result, -1) eq "\x0A";
839     $result .= "]DEL]\x0A";
840     },
841     document => sub {
842     my $source = shift;
843 wakaba 1.6 my $result = '#?'
844     . $source->get_attribute_value
845     ('Name', namespace_uri => $NS_SW09,
846     default => 'SuikaWiki')
847     . '/'
848     . $source->get_attribute_value
849     ('Version', namespace_uri => $NS_SW09,
850     default => '0.9');
851 wakaba 1.4 for (@{$source->child_nodes}) {
852     $result .= ($x2t{$_->local_name} or $x2t{'#undef'})->($_)
853     if $_->node_type eq '#element';
854     }
855     $result;
856     },
857     head => sub {
858     my $source = shift;
859 wakaba 1.6 my $result = '';
860 wakaba 1.4 for (@{$source->child_nodes}) {
861     if ($_->node_type eq '#element' and
862     $_->local_name eq 'parameter') {
863     $result .= ' '.$x2t{parameter}->($_);
864     }
865     }
866     $result . "\x0A";
867     },
868     parameter => sub {
869     my $source = shift;
870     my $result = $source->get_attribute_value ('name', default => '')
871     . '="';
872     my @v;
873     for (@{$source->child_nodes}) {
874     push @v, $x2t{value}->($_) if $_->node_type eq '#element' and
875     $_->local_name eq 'value';
876     }
877     $result .= join ',', @v;
878     $result . '"';
879     },
880     value => sub {
881     my $value = $x2t{'#inline'}->(shift, no_newline => 1);
882     $value =~ s/(["\\])/\\$1/g;
883     $value =~ tr/\x0A\x0D/ /;
884     $value;
885     },
886     section => sub {
887     local $opt->{o}->{var}->{ws__section_depth}
888     = $opt->{o}->{var}->{ws__section_depth} + 1;
889     $x2t{'#block'}->(shift);
890     },
891     body => sub {
892     local $opt->{o}->{var}->{ws__section_depth} = 1;
893     $x2t{'#block'}->(shift);
894     },
895     text => sub {
896     my ($source, %opt) = @_;
897     my $result .= '';
898     for (@{$source->child_nodes}) {
899     if ($_->node_type eq '#text') {
900     $result .= $_->inner_text;
901     } elsif ($_->node_type eq '#element') {
902     $result .= ($x2t{$_->local_name} or $x2t{'#undef'})->($_);
903     }
904     }
905     $result;
906     },
907     dr => sub {
908     my $result = $x2t{'#list'}->(shift);
909     if ($result) {
910     $result . "\x0A";
911     } else {
912     "::\x0A";
913     }
914     },
915     dt => sub {
916     ':' . $x2t{'#inline'}->(shift, no_newline => 1) . ':';
917     },
918     dd => sub {
919     $x2t{'#inline'}->(shift);
920     },
921     tr => sub {
922     my $result = $x2t{'#list'}->(shift);
923     if ($result) {
924     substr ($result, 1) . "\x0A";
925     } else {
926     "',\x0A";
927     }
928     },
929     td => sub {
930     my $source = shift;
931     my $result = $x2t{'#inline'}->($source, no_newline => 1);
932     if ($result =~ /[,"\\]/ or $result =~ /==/) {
933     $result =~ s/(["\\])/\\$1/g;
934     $result = '"' . $result . '"';
935     }
936     my $colspan = $source->get_attribute_value ('colspan', default => 1);
937     $result .= ("\t,==" x ($colspan - 1)) if $colspan > 1;
938     "\t," . $result;
939     },
940     em => sub {
941     "''" . $x2t{'#inline'}->($_, no_newline => 1) . "''";
942     },
943     strong => => sub {
944     "'''" . $x2t{'#inline'}->($_, no_newline => 1) . "'''";
945     },
946     rb => sub {
947     $x2t{'#inline'}->(shift, no_newline => 1);
948     },
949     rt => sub {
950     '] [' . $x2t{'#inline'}->(shift, no_newline => 1);
951     },
952     replace => sub {
953     '__&&' . shift->get_attribute_value ('by', default => '') . '&&__';
954     },
955     bodytext => sub {
956     my ($source, %opt) = @_;
957     local $opt->{o}->{var}->{sw09__bq_depth}
958     = $opt->{o}->{var}->{sw09__bq_depth} + 1;
959     my @result;
960     for (@{$source->child_nodes}) {
961     if ($_->node_type eq '#element') {
962     my $ln = $_->local_name;
963     push @result, [($x2t{$ln} or $x2t{'#undef'})->($_),
964     $ln];
965     }
966     }
967     my $result = '';
968     my $prev = '';
969     for (@result) {
970     my $s = $_->[0];
971     if ($_->[1] eq 'p') {
972     $result .= "\x0A" if length $result and
973     substr ($result, -1) ne "\x0A";
974     $result .= ('>' x $opt->{o}->{var}->{sw09__bq_depth}) . ' ';
975     } elsif ($_->[1] eq 'form' or $_->[1] eq 'replace') {
976     $result .= "\x0A" if length $result and
977     substr ($result, -1) ne "\x0A";
978     $result .= ('>' x $opt->{o}->{var}->{sw09__bq_depth})."\x0A";
979     } elsif ($_->[1] eq 'blockquote' or $_->[1] eq 'text') {
980     $result .= "\x0A" if length $result and
981     substr ($result, -1) ne "\x0A";
982     } else {
983     unless ($prev eq 'text') {
984     $result .= "\x0A" if length $result and
985     substr ($result, -1) ne "\x0A";
986     }
987     $result .= ('>' x $opt->{o}->{var}->{sw09__bq_depth})."\x0A";
988     }
989     $result .= $s;
990     $prev = $_->[1];
991     }
992     $result;
993     },
994 wakaba 1.6 ## Note: This element will be interpreted as a paragraph
995     ## unless format is SuikaWikiImage/0.9.
996     image => sub {
997     my ($source, %opt) = @_;
998     return "\x0A__IMAGE__\x0A" . $source->inner_text . "\x0A";
999     },
1000 wakaba 1.4 '#block' => sub {
1001     my ($source, %opt) = @_;
1002     my @result;
1003     for (@{$source->child_nodes}) {
1004     if ($_->node_type eq '#element') {
1005     my $ln = $_->local_name;
1006     push @result, [($x2t{$ln} or $x2t{'#undef'})->($_),
1007     $ln];
1008     }
1009     }
1010     my $result = '';
1011     my $prev = '';
1012     for (@result) {
1013     my $s = $_->[0];
1014     if ($_->[1] eq 'form') {
1015     $result .= "\x0A" if length $result and
1016     substr ($result, -1) ne "\x0A";
1017     $result .= "\x0A";
1018     } elsif ($_->[1] eq 'replace') {
1019     $result .= "\x0A" if length $result and
1020     substr ($result, -1) ne "\x0A";
1021     } elsif ($_->[1] eq 'text') {
1022     $result .= "\x0A" if length $result and
1023     substr ($result, -1) ne "\x0A";
1024     $result .= "\x0A" if $prev eq 'p';
1025     } else {
1026     if ($prev ne 'text' and $prev ne 'replace') {
1027     $result .= "\x0A" if length $result and
1028     substr ($result, -1) ne "\x0A";
1029     $result .= "\x0A";
1030     }
1031     }
1032     $result .= $s;
1033     $prev = $_->[1];
1034     }
1035     $result;
1036     },
1037     '#flow' => sub {
1038     my ($source, %opt) = @_;
1039     my @result;
1040     for (@{$source->child_nodes}) {
1041     if ($_->node_type eq '#element') {
1042     my $ln = $_->local_name;
1043     if ($is_block{$ln}) {
1044     push @result, [($x2t{$ln} or $x2t{'#undef'})->($_),
1045     $ln];
1046     } else {
1047     if (@result and ($result[$#result]->[1] eq '#inline')) {
1048     $result[$#result]->[0]
1049     .= ($x2t{$ln} or $x2t{'#undef'})->($_);
1050     } else {
1051     push @result, [($x2t{$ln} or $x2t{'#undef'})->($_),
1052     '#inline'];
1053     }
1054     }
1055     } elsif ($_->node_type eq '#text') {
1056     if (@result and ($result[$#result]->[1] eq '#inline')) {
1057     $result[$#result]->[0] .= $_->inner_text;
1058     } else {
1059     push @result, [$_->inner_text, '#inline'];
1060     }
1061     }
1062     }
1063     my $result = '';
1064     my $prev = '';
1065     for (@result) {
1066     my $s = $_->[0];
1067     if ($_->[1] eq '#inline') {
1068     if ($prev ne 'text' and $prev ne 'form' and $prev ne 'replace') {
1069     $result .= "\x0A" if length $result and
1070     substr ($result, -1) ne "\x0A";
1071     }
1072     $s =~ s/\x0D\x0A/\x0A/g;
1073     $s =~ s/\x0D/\x0A/g;
1074     $s =~ s/\x0A\x0A+/\x0A/g;
1075     $s =~ s/\x0A/\x20/g if $opt{no_newline};
1076     } elsif ($_->[1] eq 'form' or $_->[1] eq 'replace') {
1077     if ($prev ne '#inline') {
1078     $result .= "\x0A" if length $result and
1079     substr ($result, -1) ne "\x0A";
1080     }
1081     } elsif ($_->[1] eq 'text') {
1082     $result .= "\x0A" if length $result and
1083     substr ($result, -1) ne "\x0A";
1084     } else {
1085     unless ($prev eq 'text') {
1086     $result .= "\x0A" if length $result and
1087     substr ($result, -1) ne "\x0A";
1088     }
1089     }
1090     $result .= $s;
1091     $prev = $_->[1];
1092     }
1093     $result;
1094     },
1095     '#inline' => sub {
1096     my ($source, %opt) = @_;
1097     my $result .= '';
1098     for (@{$source->child_nodes}) {
1099     if ($_->node_type eq '#text') {
1100     $result .= $_->inner_text;
1101     } elsif ($_->node_type eq '#element') {
1102     $result .= ($x2t{$_->local_name} or $x2t{'#undef'})->($_);
1103     }
1104     }
1105     $result =~ s/\x0D\x0A/\x0A/g;
1106     $result =~ s/\x0D/\x0A/g;
1107     $result =~ s/\x0A\x0A+/\x0A/g;
1108     $result =~ s/\x0A/\x20/g if $opt{no_newline};
1109     $result;
1110     },
1111     '#list' => sub {
1112     my ($source, %opt) = @_;
1113     my $result .= '';
1114     for (@{$source->child_nodes}) {
1115     if ($_->node_type eq '#element') {
1116     $result .= ($x2t{$_->local_name} or $x2t{'#undef'})->($_);
1117     }
1118     }
1119     $result;
1120     },
1121     '#undef' => sub {
1122     my $source = shift;
1123     ## TODO:
1124     "<".$source->namespace_uri.">:".$source->local_name
1125     . $x2t{'#inline'}->($source);
1126     },
1127     );
1128     for (qw/blockquote dl tbody table/) {
1129     $x2t{$_} = sub { $x2t{'#list'}->(shift) };
1130     }
1131     for (qw/p dd/) {
1132     $x2t{$_} = sub { $x2t{'#flow'}->(shift) };
1133     }
1134     for my $type (qw/ul ol/) {
1135     $x2t{$type} = sub {
1136     my $source = shift;
1137     local $opt->{o}->{var}->{sw09__list_type} = $type;
1138     local $opt->{o}->{var}->{sw09__list_depth}
1139     = $opt->{o}->{var}->{sw09__list_depth} + 1;
1140     my @result;
1141     for (@{$source->child_nodes}) {
1142     push @result, $x2t{$_->local_name}->($_)
1143     if $_->node_type eq '#element';
1144     }
1145     my $result = '';
1146     for (@result) {
1147     $result .= "\x0A" unless substr ($result, -1) eq "\x0A";
1148     $result .= $_;
1149     }
1150     substr ($result, 1);
1151     };
1152     }
1153     for my $type (qw/code samp var dfn kbd sub sup weak q ruby rubyb
1154     abbr ins del/) {
1155     $x2t{$type} = sub {
1156     my $source = shift;
1157     my $result = '['.uc $type;
1158     my $class = $source->get_attribute_value ('class', default => '');
1159     if ($class) {
1160     $class =~ s/([()\\])/\\$1/g;
1161     $result .= '(' . $class . ')';
1162     }
1163     $result .= '['
1164     . $x2t{'#inline'}->($source, no_newline => 1)
1165     . ']';
1166     my $anchor = $source->get_attribute_value
1167     ('anchor',
1168     namespace_uri => $NS_SW09,
1169     default => '');
1170     if (length $anchor) {
1171     $result .= '>>'.(0+$anchor);
1172     } else {
1173     $anchor = $source->get_attribute_value
1174     ('resScheme',
1175     namespace_uri => $NS_SW09);
1176     if ($anchor) {
1177     my $param = $source->get_attribute_value
1178     ('resParameter',
1179     namespace_uri => $NS_SW09);
1180     if ($anchor eq 'URI' and $param =~ /^[0-9A-Za-z_+.%-]+:/) {
1181     $result .= '<' . $param . '>';
1182     } else {
1183     $result .= '<' . $anchor . ':' . $param . '>';
1184     }
1185     }
1186     }
1187     $result .= ']';
1188     $result;
1189     };
1190     }
1191    
1192     $x2t{'#list'}->($src);
1193    
1194     Function:
1195     @Name: get_nth_element
1196     @Main:
1197     my (undef, $node, $ns => $ln, $n) = @_;
1198     return $n if $n < 1;
1199     if ($node->node_type eq '#element' and
1200     $node->namespace_uri eq $ns and
1201     $node->local_name eq $ln) {
1202     return $node unless --$n;
1203     }
1204     for (@{$node->child_nodes}) {
1205     if ($_->node_type eq '#element') {
1206     if ($_->namespace_uri eq $ns and
1207     $_->local_name eq $ln) {
1208     return $_ unless --$n;
1209     } else {
1210     $n = __FUNCPACK__->get_nth_element ($_, $ns => $ln, $n);
1211     return $n if ref $n;
1212     }
1213     } elsif ($_->node_type eq '#fragment' or $_->node_type eq '#document') {
1214     $n = __FUNCPACK__->get_nth_element ($_, $ns => $ln, $n);
1215     return $n if ref $n;
1216     }
1217     }
1218     return $n;
1219    
1220     Function:
1221     @Name: get_element_by_id
1222     @Main:
1223     my (undef, $node, $id) = @_;
1224     return $node if $node->node_type eq '#element'
1225     and $node->get_attribute_value ('id', default_value => '')
1226     eq $id;
1227     for (@{$node->child_nodes}) {
1228     if ({'#element'=>1, '#fragment'=>1, '#document'=>1}->{$_->node_type}) {
1229     my $r = __FUNCPACK__->get_element_by_id ($_, $id);
1230     return $r if $r;
1231     }
1232     }
1233 wakaba 1.1
1234     Function:
1235     @Name: text_to_xml
1236     @Description:
1237     @@@:
1238     Converting SuikaWiki/0.9 text format to XML representation
1239     @@lang: en
1240     @Main:
1241     my (undef, $source, $opt) = @_;
1242     $source =~ s/\x0D\x0A/\x0A/g;
1243     $source =~ tr/\x0D/\x0A/;
1244     $source .= "\x0A";
1245     my $root = $opt->{-parent}
1246     ->append_new_node (type => '#element',
1247     namespace_uri => $NS_SW09,
1248     local_name => 'document');
1249     my $head = $root->append_new_node (type => '#element',
1250     namespace_uri => $NS_XHTML2,
1251     local_name => 'head');
1252 wakaba 1.6 $root->append_text ("\x0A");
1253     my $body = $root->append_new_node (type => '#element',
1254     namespace_uri => $NS_XHTML2,
1255     local_name => 'body');
1256     $root->append_text ("\x0A");
1257    
1258     if ($source =~ s#^\#\?(SuikaWiki(?:Image)?)/0\.9\b((?>.*))\s*##) {
1259     my $type = $1;
1260     my $param = $2;
1261     $root->set_attribute (Name => $type, namespace_uri => $NS_SW09);
1262     $root->set_attribute (Version => '0.9', namespace_uri => $NS_SW09);
1263 wakaba 1.1 while ($param =~ /\G\s+([a-z-]+)="((?>[^"\\]*)(?>(?>[^"\\]+|\\.)*))"/g) {
1264     my ($name, $value) = ($1, $2);
1265     $value =~ s/\\(.)/$1/g;
1266     for ($head->append_new_node (type => '#element',
1267     namespace_uri => $NS_SW09,
1268 wakaba 1.4 local_name => 'parameter')) {
1269 wakaba 1.1 $_->set_attribute (name => $name);
1270     for my $value (split /,/, $value) {
1271     $_->append_new_node (type => '#element',
1272     namespace_uri => $NS_SW09,
1273     local_name => 'value')
1274     ->append_text ($value);
1275     }
1276     }
1277     $head->append_text ("\x0A");
1278     }
1279 wakaba 1.6
1280     if ($type eq 'SuikaWikiImage') {
1281     $source =~ s/\x0A__IMAGE__\x0A(.*)$//s;
1282     if (my $image = $1) {
1283     $image =~ s/^\s+//;
1284     $image =~ s/\s+$//;
1285     $root->append_new_node
1286     (type => '#element',
1287     namespace_uri => $NS_SW09,
1288     local_name => 'image')
1289     ->append_text ($image);
1290     $root->append_text ("\x0A");
1291     }
1292     }
1293 wakaba 1.1 } else {
1294 wakaba 1.6 $root->set_attribute (Name => 'SuikaWiki', namespace_uri => $NS_SW09);
1295     $root->set_attribute (Version => '0.9', namespace_uri => $NS_SW09);
1296 wakaba 1.1 ## TODO: warn
1297     }
1298    
1299 wakaba 1.4 __FUNCPACK__->block_text_to_xml (\$source => $body, opt => $opt);
1300 wakaba 1.1
1301     Function:
1302     @Name:block_text_to_xml
1303     @Description:
1304     @@@:
1305     SuikaWiki/0.9 text format to XML representation convertion - block
1306     level elements
1307     @@lang:en
1308     @Main:
1309     my (undef, $source, $current, %opt) = @_;
1310 wakaba 1.4 my %depth = %{$opt{depth} || {}};
1311 wakaba 1.1 my $back_to_section = sub {
1312     my $cur_type = $current->local_name;
1313     while (not (
1314     $cur_type eq 'section'
1315     or $cur_type eq 'body'
1316     or $cur_type eq 'bodytext'
1317 wakaba 1.4 or $cur_type eq 'insert'
1318     or $cur_type eq 'delete'
1319 wakaba 1.1 )
1320     ) {
1321     $current = $current->parent_node;
1322     $cur_type = $current->local_name;
1323     }
1324     delete $depth{list};
1325     };
1326     my $back_to_real_section = sub {
1327     my $cur_type = $current->local_name;
1328     while (not (
1329     $cur_type eq 'section'
1330     or $cur_type eq 'body'
1331 wakaba 1.4 or $cur_type eq 'insert'
1332     or $cur_type eq 'delete'
1333 wakaba 1.1 )
1334     ) {
1335     $current = $current->parent_node;
1336     $cur_type = $current->local_name;
1337     }
1338     delete $depth{bq};
1339     delete $depth{list};
1340     };
1341     while ($$source =~ /\G([^\x0A]*)\x0A/gc) {
1342     my $line = $1;
1343     if ($line eq '') {
1344     $back_to_real_section->();
1345     } elsif ($line =~ s/^([-=]+)\s*//) {
1346     my $list_type = substr ($1, -1) eq '-' ? 'ul' : 'ol';
1347     my $depth = length $1;
1348     my $parent_type = $current->parent_node->local_name;
1349     ## Parent node is list element
1350     if ($parent_type eq 'ul' or $parent_type eq 'ol') {
1351     if ($depth{list} == $depth) {
1352     if ($parent_type eq $list_type) {
1353     $current = $current->parent_node;
1354     } else {
1355     $current = $current->parent_node
1356     ->parent_node
1357     ->append_new_node
1358     (type => '#element',
1359     namespace_uri => $NS_XHTML2,
1360     local_name => $list_type);
1361     }
1362     } elsif ($depth < $depth{list}) {
1363     for ($depth+1..$depth{list}) {
1364     $current = $current->parent_node->parent_node;
1365     }
1366     $current = $current->parent_node;
1367     if ($current->local_name ne $list_type) {
1368     $current = $current->parent_node
1369     ->append_new_node
1370     (type => '#element',
1371     namespace_uri => $NS_XHTML2,
1372     local_name => $list_type);
1373     }
1374     $depth{list} = $depth;
1375     } else { # $depth{list} < $depth
1376     $current = $current->append_new_node
1377     (type => '#element',
1378     namespace_uri => $NS_XHTML2,
1379     local_name => $list_type);
1380     $depth{list}++;
1381     }
1382     ## Parent node is non-list element
1383     } else {
1384     $current = $current->append_new_node (type => '#element',
1385     namespace_uri => $NS_XHTML2,
1386     local_name => $list_type);
1387     $depth{list} = 1;
1388     }
1389     $current->append_text ("\x0A".(" " x $depth{list}));
1390     $current = $current->append_new_node (type => '#element',
1391     namespace_uri => $NS_XHTML2,
1392     local_name => 'li');
1393 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $current, %opt);
1394 wakaba 1.1 } elsif ($line =~ s/^(\*+)\s*//) {
1395     my $depth = length $1;
1396     $back_to_real_section->();
1397     if ($depth <= $depth{section}) {
1398     for ($depth..$depth{section}) {
1399     $back_to_real_section->();
1400     $current = $current->parent_node;
1401     }
1402     $depth{section} = $depth;
1403     } else { # $depth{section} < $depth
1404     for ($depth{section}+2..$depth) {
1405     $current = $current->append_new_node
1406     (type => '#element',
1407     namespace_uri => $NS_XHTML2,
1408     local_name => 'section');
1409     }
1410     $depth{section} = $depth;
1411     }
1412     $current = $current->append_new_node
1413     (type => '#element',
1414     namespace_uri => $NS_XHTML2,
1415     local_name => 'section');
1416     __FUNCPACK__->inline_text_to_xml (\$line =>
1417     $current->append_new_node (type => '#element',
1418     namespace_uri => $NS_XHTML2,
1419 wakaba 1.4 local_name => 'h'), %opt,
1420 wakaba 1.1 );
1421     } elsif ($line =~ s/^(?!>>[0-9])(>+)\s*//) {
1422     my $depth = length $1;
1423     if ($depth <= $depth{bq}) {
1424     for ($depth+1..$depth{bq}) {
1425     $back_to_section->();
1426     $current = $current->parent_node->parent_node;
1427     }
1428     $back_to_section->();
1429     $current->append_text ("\x0A");
1430     $depth{bq} = $depth;
1431     } else { # $depth{bq} < $depth
1432     $back_to_section->();
1433     for ($depth{bq}+1..$depth) {
1434     $current = $current->append_new_node
1435     (type => '#element',
1436     namespace_uri => $NS_XHTML2,
1437     local_name => 'blockquote')
1438     ->append_new_node
1439     (type => '#element',
1440     namespace_uri => $NS_HTML3,
1441     local_name => 'bodytext');
1442     $current->append_text ("\x0A");
1443     }
1444     $depth{bq} = $depth;
1445     }
1446     if (length $line) {
1447     $current = $current->append_new_node
1448     (type => '#element',
1449     namespace_uri => $NS_XHTML2,
1450     local_name => 'p');
1451 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $current, %opt);
1452 wakaba 1.1 }
1453     } elsif ($line =~ s/^(?>:\s*)([^:]+?)\s*:\s*//) {
1454     my $parent_type = $current->local_name;
1455     if ($parent_type eq 'dd') {
1456     $current = $current->parent_node->parent_node;
1457     $current->append_text ("\x0A");
1458     } else { #if ($parent_type ne 'dl') {
1459     $current = $current->append_new_node (type => '#element',
1460     namespace_uri => $NS_XHTML2,
1461     local_name => 'dl');
1462     }
1463     $current = $current->append_new_node
1464     (type => '#element',
1465     namespace_uri => $NS_SW09,
1466     local_name => 'dr');
1467     __FUNCPACK__->inline_text_to_xml (\"$1" =>
1468     $current->append_new_node (type => '#element',
1469     namespace_uri => $NS_XHTML2,
1470 wakaba 1.4 local_name => 'dt'), %opt,
1471 wakaba 1.1 );
1472     $current->append_text ("\x0A");
1473     $current = $current->append_new_node (type => '#element',
1474     namespace_uri => $NS_XHTML2,
1475     local_name => 'dd');
1476 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $current, %opt);
1477 wakaba 1.9 } elsif ($line =~ /^\[(INS|DEL)(?>(\([^()\\]*\))?)\[\s*$/) {
1478 wakaba 1.1 $current->append_text ("\x0A");
1479 wakaba 1.4 my $mod = $current->append_new_node
1480     (type => '#element',
1481     namespace_uri => $NS_SW09,
1482     local_name => {qw/INS insert DEL delete/}->{$1});
1483 wakaba 1.1 $mod->set_attribute (class => $2) if $2;
1484 wakaba 1.4 __FUNCPACK__->block_text_to_xml ($source => $mod, %opt,
1485     'return_by_'.$1 => 1,
1486     depth => \%depth);
1487 wakaba 1.1 } elsif ($line =~ /^\](INS|DEL)\]\s*$/) {
1488     if ($opt{'return_by_'.$1}) {
1489     return;
1490     } else {
1491     ## TODO: warn
1492     }
1493 wakaba 1.10 } elsif ($line =~ /^\[PRE(?>(?>\(((?>[^()\\]*)(?>(?>[^()\\]+|\\.)*))\))?)\[\s*$/) {
1494 wakaba 1.1 $current->append_text ("\x0A");
1495     my $pre = $current->append_new_node (type => '#element',
1496     namespace_uri => $NS_XHTML1,
1497     local_name => 'pre');
1498     $pre->set_attribute (class => $1) if $1;
1499     $pre->set_attribute (space => 'preserve', namespace_uri => NS_xml_URI);
1500     my $f = 1;
1501     while ($$source =~ /\G([^\x0A]*)\x0A/gc) {
1502     my $line = $1;
1503     if ($line =~ /^\]PRE\]\s*$/) {
1504     undef $pre;
1505     last;
1506     } else {
1507     $f ? undef $f : $pre->append_text ("\x0A");
1508 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $pre, %opt);
1509 wakaba 1.1 }
1510     }
1511     if (ref $pre) {
1512     # warn unmatched start-tag
1513     }
1514     } elsif ($line =~ /^\s/) {
1515     $current->append_text ("\x0A");
1516     my $pre = $current->append_new_node (type => '#element',
1517     namespace_uri => $NS_XHTML1,
1518     local_name => 'pre');
1519     $pre->set_attribute (space => 'preserve', namespace_uri => NS_xml_URI);
1520 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $pre, %opt);
1521 wakaba 1.1 while ($$source =~ /\G([^\x0A]*)\x0A/gc) {
1522     my $line = $1;
1523     if (length $line == 0) {
1524     pos ($$source) -= 1;
1525     last;
1526 wakaba 1.4 } elsif ($opt{return_by_INS} and $line =~ /^\]INS\]\s*$/) {
1527     return;
1528     } elsif ($opt{return_by_DEL} and $line =~ /^\]DEL\]\s*$/) {
1529     return;
1530 wakaba 1.1 } else {
1531     $pre->append_text ("\x0A");
1532 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$line => $pre, %opt);
1533 wakaba 1.1 }
1534     }
1535     } elsif ($line =~ /^,/) {
1536     $current->append_text ("\x0A");
1537     my $tbody = $current->append_new_node (type => '#element',
1538     namespace_uri => $NS_XHTML2,
1539     local_name => 'table')
1540     ->append_new_node (type => '#element',
1541     namespace_uri => $NS_XHTML2,
1542     local_name => 'tbody');
1543 wakaba 1.4 __FUNCPACK__->tablerow_text_to_xml (\$line => $tbody, %opt);
1544 wakaba 1.1 while ($$source =~ /\G(,[^\x0A]*)\x0A/gc) {
1545 wakaba 1.4 __FUNCPACK__->tablerow_text_to_xml (\"$1" => $tbody, %opt);
1546 wakaba 1.1 }
1547     } else {
1548     my $current_type = $current->local_name;
1549     if ($current_type eq 'section'
1550     or $current_type eq 'body'
1551     or $current_type eq 'bodytext'
1552 wakaba 1.4 or $current_type eq 'insert'
1553     or $current_type eq 'delete') {
1554 wakaba 1.1 $current->append_text ("\x0A");
1555     if ($line =~ s/^__&&([^&]+)&&__//) {
1556     $current->append_new_node (type => '#element',
1557     namespace_uri => $NS_SW09,
1558     local_name => 'replace')
1559     ->set_attribute (by => $1);
1560     } elsif ($line =~ s/^\[\[$Reg_Form_Content_M\]\]//o) {
1561     for ($current->append_new_node (type => '#element',
1562     namespace_uri => $NS_SW09,
1563     local_name => 'form')) {
1564     $_->set_attribute (id => $1) if $1;
1565     my ($i, $t, $o) = ($2, $3 || '', $4 || '');
1566 wakaba 1.4 s/\\(.)/$1/g for ($i, $t, $o);
1567 wakaba 1.1 $_->set_attribute (input => $i);
1568     $_->set_attribute (template => $t);
1569     $_->set_attribute (option => $o);
1570     }
1571     } elsif ($line =~ s/^\[\[$Reg_Embed_Content_M\]\]//o) {
1572     for ($current->append_new_node (type => '#element',
1573     namespace_uri => $NS_SW09,
1574     local_name => 'form')) {
1575     $_->set_attribute (ref => $1);
1576     $_->set_attribute (id => $2) if $2;
1577     $_->set_attribute (parameter => $3) if defined $3;
1578     }
1579     }
1580 wakaba 1.4 if (length $line) {
1581     $current = $current->append_new_node
1582     (type => '#element',
1583     namespace_uri => $NS_XHTML2,
1584     local_name => 'p');
1585     __FUNCPACK__->inline_text_to_xml (\$line => $current, %opt);
1586     }
1587 wakaba 1.1 } else {
1588 wakaba 1.4 $current->append_text ("\x0A"); # replacement of prev.line's \n
1589     __FUNCPACK__->inline_text_to_xml (\$line => $current, %opt);
1590 wakaba 1.1 }
1591     }
1592     }
1593    
1594     if ($opt{return_by_INS} or $opt{return_by_DEL}) {
1595     # warn
1596     }
1597    
1598     Function:
1599     @Name: tablerow_text_to_xml
1600     @Description:
1601     @@@:
1602     SuikaWiki/0.9 text format to XML representation - table row
1603     @@lang:en
1604     @Main:
1605     my (undef, $source => $current, %opt) = @_;
1606     $current->append_text ("\x0A");
1607     $current = $current->append_new_node (type => '#element',
1608     namespace_uri => $NS_XHTML2,
1609     local_name => 'tr');
1610     my $prev_cell;
1611     while ($$source =~ /\G,\s*/gc) {
1612 wakaba 1.4 $$source =~ /\G([^,"][^,]*|"(?>[^"\\]*)(?>(?>[^"\\]+|\\.)*)"\s*)/gc;
1613 wakaba 1.1 my $cell = $1;
1614     if ($cell =~ s/^"//) {
1615     $cell =~ s/"\s*$//g;
1616     $cell =~ s/\\(.)/$1/g;
1617     } else {
1618     $cell =~ s/\s+$//g;
1619     if ($cell eq '==') {
1620     if (ref $prev_cell) {
1621     $prev_cell->set_attribute (colspan =>
1622     $prev_cell->get_attribute_value ('colspan', default => 1)
1623     + 1);
1624     next;
1625     } else {
1626     # TODO: warn
1627     }
1628     }
1629     }
1630     $prev_cell = $current->append_new_node
1631     (type => '#element',
1632     namespace_uri => $NS_XHTML2,
1633     local_name => 'td');
1634 wakaba 1.4 __FUNCPACK__->inline_text_to_xml (\$cell => $prev_cell, %opt);
1635 wakaba 1.1 }
1636     # TODO: warn
1637    
1638     Function:
1639     @Name: inline_text_to_xml
1640     @Description:
1641     @@@:
1642     SuikaWiki/0.9 text format to XML representation - inline level elements
1643     @@lang:en
1644     @Main:
1645 wakaba 1.9 my (undef, $source => $current, %opt) = @_;
1646    
1647 wakaba 1.1 my $ElementDef = {
1648 wakaba 1.5 ABBR => {ln => 'abbr', ns_uri => $NS_XHTML2},
1649 wakaba 1.1 CODE => {ln => 'code', ns_uri => $NS_XHTML2},
1650     DEL => {ln => 'del', ns_uri => $NS_XHTML1},
1651     DFN => {ln => 'dfn', ns_uri => $NS_XHTML2},
1652     INS => {ln => 'ins', ns_uri => $NS_XHTML1},
1653     KBD => {ln => 'kbd', ns_uri => $NS_XHTML2},
1654     Q => {ln => 'q', ns_uri => $NS_XHTML1},
1655     RUBY => {ln => 'ruby', ns_uri => $NS_XHTML2},
1656     RUBYB => {ln => 'rubyb', ns_uri => $NS_SW09},
1657     SAMP => {ln => 'samp', ns_uri => $NS_XHTML2},
1658     SUB => {ln => 'sub', ns_uri => $NS_XHTML2},
1659     SUP => {ln => 'sup', ns_uri => $NS_XHTML2},
1660     VAR => {ln => 'var', ns_uri => $NS_XHTML2},
1661     WEAK => {ln => 'weak', ns_uri => $NS_SW09},
1662     anchor => {ln => 'anchor', ns_uri => $NS_SW09, has_fragment_no => 1},
1663     del => {has_cite => 1},
1664     ins => {has_cite => 1},
1665     q => {has_cite => 1},
1666     rb => {ln => 'rb', ns_uri => $NS_XHTML2, is_nested => 1},
1667     rt => {ln => 'rt', ns_uri => $NS_XHTML2, is_nested => 1},
1668     };
1669    
1670     if ($$source =~ /\G\[([0-9]+)\]/gc) {
1671     for ($current->append_new_node (type => '#element',
1672     namespace_uri => $NS_SW09,
1673     local_name => 'anchor-end')) {
1674 wakaba 1.4 $_->set_attribute (anchor => 0+$1,
1675     namespace_uri => $NS_SW09);
1676 wakaba 1.1 $_->append_text ('['.$1.']');
1677     }
1678     }
1679     my $depth = 0;
1680     while (pos $$source < length $$source) {
1681     if ($$source =~ /\G\[\[(?=\#)/gc) {
1682     my $form = $current->append_new_node (type => '#element',
1683     namespace_uri => $NS_SW09,
1684     local_name => 'form');
1685     if ($$source =~ /\G$Reg_Form_Content_M\]\]/ogc) {
1686     $form->set_attribute (id => $1) if $1;
1687 wakaba 1.4 my ($i, $t, $o) = ($2, $3, $4);
1688     s/\\(.)/$1/g for ($i, $t, $o);
1689     $form->set_attribute (input => $i);
1690     $form->set_attribute (template => $t);
1691     $form->set_attribute (option => $o);
1692 wakaba 1.1 } elsif ($$source =~ /\G$Reg_Embed_Content_M\]\]/ogc) {
1693     $form->set_attribute (ref => $1);
1694     $form->set_attribute (id => $2) if $2;
1695     $form->set_attribute (parameter => $3) if defined $3;
1696     } else {
1697     ## TODO: error
1698 wakaba 1.4 SuikaWiki::Plugin->module_package('Error')->report_error_simple ($opt{opt}->{o}->{wiki}, InvalidForm => substr ($$source, pos ($$source)));
1699 wakaba 1.1 }
1700 wakaba 1.10 } elsif ($$source =~ /\G\[(?>([A-Z]+)(?>\(((?>[^()\\]*)(?>(?>[^()\\]+|\\.)*))\))?)?\[/gc) {
1701 wakaba 1.1 my $type = $1 || 'anchor';
1702     my $param = $2;
1703     my $def = $ElementDef->{ $type };
1704     unless ($def) {
1705     ## TODO: error
1706 wakaba 1.4 $def = $ElementDef->{CODE};
1707 wakaba 1.1 }
1708     $current = $current->append_new_node (type => '#element',
1709     namespace_uri => $def->{ns_uri},
1710     local_name => $def->{ln});
1711     $current->set_attribute (class => $param) if $param;
1712     if ($type eq 'RUBY' or $type eq 'RUBYB'
1713     or $type eq 'ABBR') {
1714     $current = $current->append_new_node
1715     (type => '#element',
1716     namespace_uri => $ElementDef->{rb}->{ns_uri},
1717     local_name => $ElementDef->{rb}->{ln});
1718     }
1719     $depth++;
1720     } elsif ($$source =~ /\G\](?> <([0-9A-Za-z_+.%-]+):($Reg_URI_Opaque)>
1721     \ | >>([0-9]+) )?
1722     \ \]/gcox) {
1723     my ($scheme, $opaque, $anchor) = ($1, $2, $3);
1724     unless ($depth) {
1725     $current->append_text (substr ($$source, $-[0], $+[0]-$-[0]));
1726     next;
1727     }
1728     my $def = $ElementDef->{$current->local_name} || {};
1729     if (defined $anchor) {
1730 wakaba 1.4 $current->set_attribute (anchor => $anchor + 0,
1731     namespace_uri => $NS_SW09);
1732     } elsif (defined $scheme) {
1733     if ($scheme =~ /[A-Z]/) {
1734     $current->set_attribute (resScheme => $scheme,
1735     namespace_uri => $NS_SW09);
1736     $current->set_attribute (resParameter => $opaque,
1737     namespace_uri => $NS_SW09);
1738 wakaba 1.1 } else {
1739 wakaba 1.4 $current->set_attribute (resScheme => 'URI',
1740 wakaba 1.1 namespace_uri => $NS_SW09);
1741 wakaba 1.4 $current->set_attribute (resParameter => "$scheme:$opaque",
1742 wakaba 1.1 namespace_uri => $NS_SW09);
1743     }
1744     }
1745     $current = $current->parent_node;
1746     $current = $current->parent_node if $def->{is_nested};
1747     $depth--;
1748 wakaba 1.4 } elsif ($$source =~ /\G\]\s*\[/gc) {
1749 wakaba 1.1 if ($current->local_name eq 'rb' or $current->local_name eq 'rt') {
1750     $current = $current->parent_node
1751     ->append_new_node
1752     (type => '#element',
1753     namespace_uri => $ElementDef->{rt}->{ns_uri},
1754     local_name => $ElementDef->{rt}->{ln});
1755     } else {
1756 wakaba 1.10 $current->append_text (substr ($$source, $-[0], $+[0]-$-[0]-1));
1757     pos ($$source)--;
1758 wakaba 1.1 }
1759     } elsif ($$source =~ /\G'''?/gc) {
1760     my $type = $+[0] - $-[0] == 3 ? 'strong' : 'em';
1761     if ($current->local_name eq $type) {
1762     $current = $current->parent_node;
1763     } else {
1764     $current = $current->append_new_node
1765     (type => '#element',
1766     namespace_uri => $NS_XHTML2,
1767     local_name => $type);
1768     }
1769 wakaba 1.9 } elsif ($$source =~ /\G<([0-9A-Za-z_+.%-]+):($Reg_URI_Opaque)>/gco) {
1770 wakaba 1.1 my ($scheme, $data) = ($1, $2);
1771     my $link = $current->append_new_node
1772     (type => '#element',
1773     namespace_uri => $NS_SW09,
1774 wakaba 1.2 local_name => 'anchor-external');
1775 wakaba 1.1 if (substr ($scheme, 0, 1) =~ /[A-Z]/) {
1776 wakaba 1.4 $link->set_attribute (resScheme => $scheme,
1777     namespace_uri => $NS_SW09);
1778     $link->set_attribute (resParameter => $data,
1779     namespace_uri => $NS_SW09);
1780 wakaba 1.1 } else { # URI Reference
1781 wakaba 1.4 $link->set_attribute (resScheme => 'URI',
1782     namespace_uri => $NS_SW09);
1783     $link->set_attribute (resParameter => $scheme.':'.$data,
1784     namespace_uri => $NS_SW09);
1785 wakaba 1.1 }
1786 wakaba 1.3 $link->append_text ($scheme.':'.$data);
1787 wakaba 1.1 } elsif ($$source =~ /\G__&&/gc) {
1788     if ($$source =~ /\G([^&]+)&&__/gc) {
1789     $current->append_new_node
1790     (type => '#element',
1791     namespace_uri => $NS_SW09,
1792 wakaba 1.2 local_name => 'replace')
1793 wakaba 1.1 ->set_attribute (by => $1);
1794     } else {
1795 wakaba 1.2 $current->append_text ('__&&');
1796 wakaba 1.1 }
1797     } elsif ($$source =~ /\G((?>
1798 wakaba 1.4 [^'\[\]<>_]+
1799 wakaba 1.1 | ' (?!')
1800 wakaba 1.4 | \[ (?!\[|[A-Z]+(?>\([^()\\]*
1801     (?>[^()\\]+|\\.)*\))?\[)
1802 wakaba 1.1 | \] (?! \]
1803     | >>[0-9]+\]
1804     | <[0-9A-Za-z_+.%-]+:$Reg_URI_Opaque>\]
1805     | \s*\[ )
1806     | < (?![0-9A-Za-z_+.%-]+:$Reg_URI_Opaque>)
1807     | > (?!>[0-9])
1808     | _ (?!_&&)
1809     )+)/oxgc) {
1810     $current->append_text ($1);
1811     } elsif ($$source =~ /\G>>([0-9]+)/gc) {
1812     for ($current->append_new_node (type => '#element',
1813     namespace_uri => $NS_SW09,
1814 wakaba 1.2 local_name => 'anchor-internal')) {
1815 wakaba 1.4 $_->set_attribute (anchor => 0+$1,
1816     namespace_uri => $NS_SW09);
1817 wakaba 1.1 $_->append_text ('>>'.$1);
1818     }
1819     } else {
1820 wakaba 1.4 CORE::die "Implementation buggy: ", substr ($$source, pos $$source);
1821 wakaba 1.1 }
1822     }
1823    
1824 wakaba 1.2 FormattingRule:
1825 wakaba 1.3 @Category[list]:
1826     page-link
1827     link-to-resource
1828 wakaba 1.2 @Name: sw09--link-anchor-content
1829     @Description:
1830     @@@:
1831     Output content of the anchor element
1832     @@lang:en
1833     @Formatting:
1834     if ($o->{var}->{sw09__anchor_content}) {
1835     $o->{var}->{sw09__anchor_content}->($p->{-parent});
1836     } else {
1837 wakaba 1.9 $WIKIRESOURCE->append_tree
1838 wakaba 1.4 (name => 'Link:SuikaWiki/0.9:link-anchor-content:InvalidContext',
1839     param => $o,
1840     -parent => $p->{-parent},
1841     wiki => $o->{wiki});
1842 wakaba 1.2 }
1843    
1844     Resource:
1845     @Link:SuikaWiki/0.9:link-anchor-content:InvalidContext:
1846 wakaba 1.4 @@@: %percent;sw09--link-anchor-content; cannot be used in this context.
1847 wakaba 1.2 @@lang:en
1848 wakaba 1.3 @Link:SuikaWiki/0.9:toResource:SourceLabel:
1849     @@@:
1850     %select_link_resource_scheme (
1851     URI => {<%link-to-it(
1852     label=>{%link-resource-parameters;}p,
1853     );>},
1854 wakaba 1.15 IW => {%iw--source-label (default => {<%link-to-it (
1855     label => {%link-resource-scheme;:%link-resource-parameters;}p,
1856     );});},
1857 wakaba 1.3 MAIL => {<%link-to-it(
1858     label => {%link-resource-parameters;}p,
1859     description
1860     => {%res (name=>{Link:MailAddress=});<%link-resource-parameters;>}p,
1861     );>},
1862     otherwise => {<%link-to-it(
1863     label => {%sw09--link-anchor-content;}p,
1864     description => {%res (name=>{Link:URIReference=});<%uri-reference;>}p,
1865     );>},
1866     );
1867     @@lang:en
1868 wakaba 1.2 @Link:SuikaWiki/0.9:toWikiPage:SourceLabel:
1869     @@@:
1870     %link-to-it(
1871     label=>{%sw09--link-anchor-content;%if-linked-wikipage-exist(
1872     true=>{%if-link-has-dest-anchor-no(true=>{>>%link-dest-anchor-no;});},
1873     false=>{%res(name=>{Link:toWikiPage:NotExist:Mark});}
1874     );}p,
1875     description=>{%page-name(absolute);; %if-linked-wikipage-exist(
1876     true=>{%page-headline;},
1877     false=>{(%res(name=>{Link:toWikiPage:NotExist:Description});)},
1878     );}p,
1879     class=>{%if-linked-wikipage-exist(false=>{not-exist});}p,
1880     );
1881 wakaba 1.5 @SuikaWiki/0.9:form:comment:input:
1882     %line (content => {%textarea (id=>msg,size=>20,lines=>3);}p);
1883     %line (content => {
1884     (%text (description => {%res (name => {Form:Description:HumanName});}p,
1885     id => name, size => 6);
1886     [%text (description =>
1887     {%res (name => {Form:Description:MailAddress});}p,
1888     id => mail, size => 5);]
1889     %check (default, id => record-date,
1890     label => {%res (name => {Form:Label:LogDate});}p,
1891     description => {%res (name => {Form:Description:LogDate});}p);)
1892     %submit (label => {%res (name => {Form:Label:Add});}p,
1893     description => {%res (name => {Form:Description:Add});}p);
1894     %we--update-lastmodified-datetime;
1895     }p);
1896     @SuikaWiki/0.9:form:comment:template:
1897     %n
1898     ;[%index;]%n
1899     ;%text(source=>msg);%n;(%name;%text(source=>mail,prefix=>" [",suffix=>"]");%iif(source=>record-date,true=>" [WEAK[%date;]]");)%n;
1900     @SuikaWiki/0.9:form:comment:option:
1901     %require (msg);
1902     @SuikaWiki/0.9:form:footannotate:input:
1903     %line (content => {%textarea (id=>msg,size=>20,lines=>3);}p);
1904     %line (content => {
1905     (%text (description => {%res (name => {Form:Description:HumanName});}p,
1906     id => name, size => 6);
1907     [%text (description =>
1908     {%res (name => {Form:Description:MailAddress});}p,
1909     id => mail, size => 5);]
1910     %check (default, id => record-date,
1911     label => {%res (name => {Form:Label:LogDate});}p,
1912     description => {%res (name => {Form:Description:LogDate});}p);)
1913     %submit (label => {%res (name => {Form:Label:Add});}p,
1914     description => {%res (name => {Form:Description:Add});}p);
1915     %we--update-lastmodified-datetime;
1916     }p);
1917     @SuikaWiki/0.9:form:footannotate:template:
1918     %n
1919     ;[%index;]%n
1920     ;%text(source=>msg);%n
1921     ;(%name;%text(source=>mail,prefix=>" [",suffix=>"]");%iif(source=>record-date,true=>" [WEAK[%date;]]");)%n;
1922     @SuikaWiki/0.9:form:footannotate:option:
1923     %require (msg);
1924 wakaba 1.13 @WikiFormat:MediaType:Description:IMT:text/x-suikawiki;version="0.9"##:
1925     @@@: SuikaWiki/0.9 (text format), as used in SuikaWiki 2
1926     @@lang: en
1927     @WikiFormat:MediaType:Label:IMT:text/x-suikawiki;version="0.9"##:
1928     @@@: SuikaWiki/0.9 (text format)
1929     @@lang: en
1930     @WikiFormat:MediaType:Description:MAGIC:SuikaWiki/0.9##:
1931     @@@: SuikaWiki/0.9 (text format), as used in SuikaWiki 2
1932     @@lang: en
1933     @WikiFormat:MediaType:Label:MAGIC:SuikaWiki/0.9##:
1934     @@@: SuikaWiki/0.9 (text format)
1935     @@lang: en
1936    
1937 wakaba 1.3
1938 wakaba 1.4 Error:
1939     @Name: text_parse
1940     @Definition:
1941     @@INLINE_NO_CLOSE_TAG:
1942     @@@description:
1943     Close tag of element "%t (name => element_type);" not found.
1944     @@@level: non-fatal
1945     @@BLOCK_NO_CLOSE_TAG:
1946     @@@description:
1947     Close tag of element "%t (name => element_type);" not found.
1948     @@@level: non-fatal
1949     @@INVALID_FORM:
1950     @@@description:
1951     Invalid syntax of WikiForm
1952     @@@level: non-fatal
1953    
1954     Error:
1955     @Name: xml_to_text
1956     @IsA[list]:
1957     ::SuikaWiki::Format::
1958     @Definition:
1959     @@

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24