mediawiki.pm 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. # -*-perl-*-
  2. ######################################################################
  3. # File: mediawiki.pm
  4. #
  5. # Override values for various customizable procedures are set in this file
  6. # in such a way as to create text suitable for pasting into a MediaWiki.
  7. #
  8. # Load the file with command-line option: --init-file mediawiki.pm
  9. #
  10. # This file is in the public domain. Thus it may easily be used as an
  11. # example for further customizations.
  12. #
  13. # Originally written by Derek Price in 2005.
  14. # Modified in 2008 and 2009.
  15. #
  16. # $Id: mediawiki.pm,v 1.1 2011-04-09 00:10:45 pertusus Exp $
  17. use strict;
  18. #html_default_load();
  19. t2h_default_load_format('html');
  20. # remark: in my tests, there was no support for mathtt in texvc
  21. # https://bugzilla.wikimedia.org/show_bug.cgi?id=21475
  22. default_load_tex_math();
  23. # inline css style
  24. set_default('INLINE_CSS_STYLE', 1);
  25. set_default('USE_SECTIONS', 1);
  26. set_default('USE_NODES', undef);
  27. # numbers are added automatically based on mediawiki markup
  28. set_default('NUMBER_SECTIONS', 0);
  29. # if this is set footnotes are on a separated page. Otherwise they are at
  30. # the end of each file (if the document is split).
  31. # At the end is better for the mediawiki output which is more per page
  32. # oriented.
  33. set_default('footnotestyle', 'end');
  34. # extension
  35. set_default('EXTENSION', undef);
  36. # extension for nodes files when NODE_FILES is true
  37. set_default('NODE_FILE_EXTENSION', '');
  38. # no title page at the beginning
  39. set_default('USE_TITLEPAGE_FOR_TITLE', 0);
  40. # if set and SPLIT is set, then split index pages at the next letter
  41. # after they have more than that many entries
  42. set_default('SPLIT_INDEX', undef);
  43. # Use preformatted menus.
  44. set_default('SIMPLE_MENU', 1);
  45. # no NODE_FILES. In fact the whole ref to external manual is broken.
  46. # This may be revisited later.
  47. set_default('NODE_FILES', 0);
  48. $DEFAULT_RULE = "\n----\n";
  49. my %mediawiki_table_commands;
  50. # FIXME b, i could be ''' ''
  51. # FIXME ''' and '' are stopped by end of lines!
  52. my %style_map_mediawiki = (
  53. 'emph', {'inline_begin' => "''"},
  54. 'email', {'function' => \&mediawiki_default_email},
  55. 'math', {'function' => \&mediawiki_default_math},
  56. 'url', {'function' => \&mediawiki_default_uref},
  57. 'uref', {'function' => \&mediawiki_default_uref},
  58. 'strong', {'inline_begin' => "'''"}
  59. );
  60. foreach my $style_command (keys(%style_map_mediawiki))
  61. {
  62. if ($style_map_mediawiki{$style_command}->{'inline_begin'})
  63. {
  64. foreach my $key ('inline_attribute', 'attribute')
  65. {
  66. delete $style_map_pre{$style_command}->{$key};
  67. delete $style_map{$style_command}->{$key};
  68. }
  69. $style_map_pre{$style_command}->{'inline_end'} = $style_map_mediawiki{$style_command}->{'inline_begin'};
  70. $style_map{$style_command}->{'inline_end'} = $style_map_mediawiki{$style_command}->{'inline_begin'};
  71. }
  72. foreach my $key (keys(%{$style_map_mediawiki{$style_command}}))
  73. {
  74. $style_map_pre{$style_command}->{$key} = $style_map_mediawiki{$style_command}->{$key};
  75. $style_map{$style_command}->{$key} = $style_map_mediawiki{$style_command}->{$key};
  76. }
  77. }
  78. # no samp/kbd in allowed html elements in the default case.
  79. foreach my $style_command (keys(%style_map))
  80. {
  81. if ($style_map{$style_command}->{'inline_attribute'})
  82. {
  83. $style_map{$style_command}->{'inline_attribute'} =~ s/^(samp|kbd)/code/;
  84. }
  85. }
  86. foreach my $style_command (keys(%style_map_pre))
  87. {
  88. if ($style_map_pre{$style_command}->{'inline_attribute'})
  89. {
  90. $style_map_pre{$style_command}->{'inline_attribute'} =~ s/^(samp|kbd)/code/;
  91. }
  92. }
  93. $style_map{'indicateurl'} = {'begin' => '&lt;<code><nowiki>', 'end' => '</nowiki></code>&gt;'};
  94. $style_map_pre{'indicateurl'} = {'begin' => '&lt;<code><nowiki>', 'end' => '</nowiki></code>&gt;'};
  95. sub mediawiki_default_email($$)
  96. {
  97. my $command = shift;
  98. my $args = shift;
  99. my $mail = shift @$args;
  100. my $text = shift @$args;
  101. $text = '' if (!defined($text));
  102. $mail = main::normalise_space($mail);
  103. $text = main::normalise_space($text);
  104. return $text if ($mail eq '');
  105. $text = ' ' . $text if ($text ne '');
  106. return "[mailto:$mail$text]";
  107. }
  108. sub mediawiki_default_uref($$)
  109. {
  110. shift;
  111. my $args = shift;
  112. my $url = shift @$args;
  113. my $text = shift @$args;
  114. my $replacement = shift @$args;
  115. $url = main::normalise_space($url);
  116. $replacement = '' if (!defined($replacement));
  117. $replacement = main::normalise_space($replacement);
  118. $text = '' if (!defined($text));
  119. $text = main::normalise_space($text);
  120. $text = $replacement if ($replacement ne '');
  121. return $text if ($url eq '');
  122. return &$anchor('', $url, $text);
  123. }
  124. sub mediawiki_default_math($$)
  125. {
  126. shift;
  127. my $args = shift;
  128. my $text = shift @$args;
  129. return "<math>$text</math>";
  130. }
  131. foreach my $format ('enumerate', 'table', 'vtable', 'ftable')
  132. {
  133. $format_map{$format} = '';
  134. }
  135. my %processed_formats = ();
  136. # there are no pre used in mediawiki, to have links working in
  137. # complex formats, therefore the styles are copied in div that
  138. # are used instead. This doesn't really improve the situation,
  139. # though, since the div outside of a <pre> is not taken into account.
  140. foreach my $complex_format (keys(%complex_format_map))
  141. {
  142. my $class = $complex_format_map{$complex_format}->{'class'};
  143. $class = $complex_format if (!defined($class));
  144. # Avoid doing things twice if the class is associated with more than one
  145. # complex format
  146. next if($processed_formats{$class});
  147. if (defined($css_map{"pre.$class"}))
  148. {
  149. if (defined($css_map{"div.$class"}))
  150. {
  151. $css_map{"div.$class"} .= "; ";
  152. }
  153. else
  154. {
  155. $css_map{"div.$class"} = '';
  156. }
  157. $css_map{"div.$class"} .= $css_map{"pre.$class"};
  158. }
  159. $processed_formats{$class} = 1;
  160. }
  161. foreach my $format ('example', 'display', 'lisp', 'format')
  162. {
  163. $complex_format_map{$format}->{'begin'} = html_default_attribute_class('div', $format).">\n";
  164. $complex_format_map{"small$format"}->{'begin'} = html_default_attribute_class('div', "small$format").">\n";
  165. $complex_format_map{$format}->{'end'} = '</div>'."\n";
  166. $complex_format_map{"small$format"}->{'end'} = '</div>'."\n";
  167. }
  168. foreach my $format ('menu', 'detailmenu', 'menu_comment')
  169. {
  170. my $class = $complex_format_map{$format}->{'class'};
  171. $class = $format if (!defined($class));
  172. $complex_format_map{$format}->{'begin'} = html_default_attribute_class('div', $class).">\n";
  173. $complex_format_map{$format}->{'end'} = '</div>'."\n";
  174. }
  175. $texi_formats_map{'direntry'} = 0;
  176. # no acronym nor abbr allowed in wikitext.
  177. $acronym_like = \&t2h_default_acronym_like;
  178. push @command_handler_setup, \&mediawiki_default_initialize_variables;
  179. my %mediawiki_doc_nr_to_file; # File name cache based on file index.
  180. my %mediawiki_target_to_name;
  181. my %mediawiki_special_file_name;
  182. sub mediawiki_default_initialize_variables()
  183. {
  184. %mediawiki_doc_nr_to_file = (); # File name cache based on file index.
  185. %mediawiki_target_to_name = ();
  186. %mediawiki_special_file_name = ();
  187. }
  188. my @html_files_from_tex;
  189. my $mediawiki_out_dir;
  190. my $tex_extension;
  191. push @command_handler_init, \&mediawiki_default_init_html_to_wiki;
  192. sub mediawiki_default_init_html_to_wiki
  193. {
  194. # This must be done here, because the latex2html handler is added
  195. # after command line scanning, so after the mediawiki.pm parsing
  196. push @command_handler_process, \&mediawiki_default_html_to_wiki;
  197. $command_handler{'math'}->{'init'} = undef;
  198. $command_handler{'math'}->{'expand'} = undef;
  199. $command_handler{'math'} = undef;
  200. $mediawiki_out_dir = "$Texi2HTML::THISDOC{'destination_directory'}";
  201. $mediawiki_out_dir = './' if (!defined($mediawiki_out_dir) or $mediawiki_out_dir =~ /^\s*$/);
  202. @html_files_from_tex = ();
  203. $tex_extension = undef;
  204. if ($Texi2HTML::THISDOC{'extensions'}->{'tex4ht'})
  205. {
  206. push @html_files_from_tex, "$Texi2HTML::THISDOC{'file_base_name'}_tex4ht_tex.html";
  207. $tex_extension = 'tex4ht';
  208. }
  209. elsif (get_conf('L2H'))
  210. {
  211. push @html_files_from_tex, "$Texi2HTML::THISDOC{'file_base_name'}_l2h.html";
  212. $tex_extension = 'l2h';
  213. # avoid use of the cache
  214. set_default('L2H_SKIP', 0);
  215. }
  216. }
  217. # could be in texi2html.pm...
  218. sub mediawiki_default_readd_end_of_lines($$$$;$)
  219. {
  220. my $from_file = shift;
  221. my $to_file = shift;
  222. my $tex_extension = shift;
  223. my $basename = shift;
  224. my $before_wiki = shift;
  225. # html2wiki removes end of lines, they are readded here
  226. unless (open (ORIG, $from_file))
  227. {
  228. print STDERR "open $from_file error: $!\n";
  229. return 0;
  230. }
  231. unless (open (FINAL, ">$to_file"))
  232. {
  233. print STDERR "open $to_file error: $!\n";
  234. return 0;
  235. }
  236. my $line;
  237. while ($line = <ORIG>)
  238. {
  239. if ($before_wiki)
  240. {
  241. $line =~ s/(<!-- ${tex_extension}_end $basename ((\w+ |)(\d+)) -->) *$/$1\n\n<p>intersticiae<\/p>\n/;
  242. $line = Texi2HTML::LaTeX2HTML::change_image_file_names($line) if ($tex_extension eq 'l2h');
  243. }
  244. else
  245. {
  246. $line =~ s/^(<!-- ${tex_extension}_begin $basename ((\w+ |)(\d+)) -->)(.+)/$1\n$5/;
  247. $line =~ s/(.+)(<!-- ${tex_extension}_end $basename ((\w+ |)(\d+)) -->) *$/$1\n$2/;
  248. }
  249. print FINAL "$line";
  250. }
  251. close ORIG;
  252. close FINAL;
  253. return 1;
  254. }
  255. sub mediawiki_default_html_to_wiki
  256. {
  257. foreach my $file (@html_files_from_tex)
  258. {
  259. if (-f $mediawiki_out_dir.$file)
  260. {
  261. my $html_file = $mediawiki_out_dir.$file;
  262. my $tmp_file = $mediawiki_out_dir.$file.".tmp";
  263. my $tmp_file2 = $mediawiki_out_dir.$file.".tmp2";
  264. my $tmp_file3 = $mediawiki_out_dir.$file.".tmp3";
  265. my $basename = $file;
  266. $basename =~ s/\.html$//;
  267. if (!rename ($html_file, $tmp_file))
  268. {
  269. print STDERR "rename $html_file $tmp_file error: $!\n";
  270. return;
  271. }
  272. #system ("cp $tmp_file $tmp_file.save");
  273. # Add a paragraph between the end and begin comments to force
  274. # html2wiki to leave them appart.
  275. return unless (mediawiki_default_readd_end_of_lines($tmp_file, $tmp_file3, $tex_extension, $basename, 1));
  276. if (!rename ($tmp_file3, $tmp_file))
  277. {
  278. print STDERR "rename $tmp_file3 $tmp_file error: $!\n";
  279. return;
  280. }
  281. #system ("cp $tmp_file $tmp_file3.save");
  282. my $cmd = "html2wiki --dialect MediaWiki --strip-tags '' $tmp_file > $tmp_file2";
  283. print STDERR "Launching(". Cwd::cwd() ."): $cmd\n" if (get_conf('VERBOSE'));
  284. if (system ($cmd))
  285. {
  286. main::document_warn ("mediawiki_tex command failed: $cmd");
  287. return;
  288. }
  289. # this ensures that there is one end of line before the
  290. # html comment, and after, even though html2wiki removed them
  291. return unless (mediawiki_default_readd_end_of_lines($tmp_file2, $html_file, $tex_extension, $basename));
  292. #system ("cp $html_file $html_file.save");
  293. }
  294. else
  295. { # FIXME error message?
  296. }
  297. }
  298. }
  299. $heading_text = \&mediawiki_heading_text;
  300. sub mediawiki_heading_text($$$)
  301. {
  302. my $command = shift;
  303. my $text = shift;
  304. my $level = shift;
  305. return '' if ($text !~ /\S/);
  306. $level = 1 if ($level == 0);
  307. return (("=" x $level) . "= $text =" . ("=" x $level) . "\n");
  308. }
  309. ###################################################################
  310. # Layout of standard header and footer
  311. #
  312. $print_page_head = \&mediawiki_default_print_page_head;
  313. $print_page_foot = \&mediawiki_default_print_page_foot;
  314. sub mediawiki_default_print_page_head($)
  315. {
  316. my $fh = shift;
  317. print $fh "$AFTER_BODY_OPEN\n" if $AFTER_BODY_OPEN;
  318. }
  319. sub mediawiki_default_print_page_foot($)
  320. {
  321. my $fh = shift;
  322. my $program_string = &$program_string();
  323. print $fh $program_string, "\n";
  324. print $fh $PRE_BODY_CLOSE, "\n" if $PRE_BODY_CLOSE;
  325. }
  326. # This function produces an anchor
  327. #
  328. # arguments:
  329. # $name : anchor name
  330. # $href : anchor href
  331. # $text : text displayed
  332. # extra_attribs : added to anchor attributes list
  333. $anchor = \&mediawiki_anchor;
  334. sub mediawiki_anchor($;$$$)
  335. {
  336. my $name = shift;
  337. my $href = shift;
  338. my $text = shift;
  339. my $attributes = shift; # ignored
  340. $href = '' if !defined $href or $href !~ /\S/;
  341. $text = '' if !defined $text or $text !~ /\S/;
  342. return $text if $name eq '' and $href eq '';
  343. $name = "<div id=\"$name\"></div>" if $name ne '';
  344. if (defined($href) and $href ne '')
  345. {
  346. my $wiki_href;
  347. my ($file, $target);
  348. if ($href =~ /^([^#]*)\#(.+)$/)
  349. {
  350. $file = $1;
  351. $target = $2;
  352. if (defined($mediawiki_target_to_name{$target}))
  353. {
  354. if ($file eq '')
  355. {
  356. $target = $mediawiki_target_to_name{$target}->[0]->[1]->{'simple_format'}
  357. if ($mediawiki_target_to_name{$target}->[0]->[1]->{'simple_format'} ne '');
  358. $wiki_href = '#' . $target;
  359. }
  360. else
  361. {
  362. foreach my $element (@{$mediawiki_target_to_name{$target}})
  363. {
  364. if ($file eq $element->[0])
  365. {
  366. $target = $element->[1]->{'simple_format'} if ($element->[1]->{'simple_format'} ne '');
  367. $wiki_href = $file . '#' . $target;
  368. }
  369. }
  370. }
  371. }
  372. # Element pages, or misc relative links.
  373. # mediawiki 1.15.1 doesn't like anchor only urls, they work as wiki_ref.
  374. if (!defined($wiki_href) and ($mediawiki_special_file_name{$file} or $file eq ''))
  375. {
  376. $wiki_href = $href;
  377. }
  378. }
  379. # Element page, no target
  380. elsif ($mediawiki_special_file_name{$href})
  381. {
  382. $file = $href;
  383. $wiki_href = $href;
  384. }
  385. if (defined($wiki_href))
  386. {
  387. $text = "|$text" if $text;
  388. # FIXME trouble with http://meta.wikimedia.org/wiki/Help:Namespace#Generic_namespace_names
  389. # and with http://en.wikipedia.org/wiki/Wikipedia:Naming_conventions_(technical_restrictions)#Forbidden_characters
  390. $href = "[[$wiki_href$text]]";
  391. }
  392. else
  393. {
  394. $text = " $text" if $text;
  395. $href = "[$href$text]";
  396. }
  397. }
  398. else
  399. {
  400. $href = $text;
  401. }
  402. #print STDERR "!!!$name!$href!$text!$attributes!\n";
  403. return "$name$href";
  404. }
  405. # it is not possible (at least not easy) to protect only 2 consecutive
  406. # {, although it would be better.
  407. foreach my $brace ('{', '}')
  408. {
  409. $simple_map{$brace} = "<nowiki>$simple_map{$brace}</nowiki>";
  410. $simple_map_pre{$brace} = "<nowiki>$simple_map_pre{$brace}</nowiki>";
  411. }
  412. # remark: this nullifies the change of default_load_tex_math for normal_text.
  413. # We assume that in @math the TeX characters have already been
  414. # rightly protected and so don't protect once more. This is important
  415. # for <, not to lead to &lt;.
  416. # remark: texvc doesn't accept " \&
  417. $normal_text = \&mediawiki_default_normal_text;
  418. sub mediawiki_default_normal_text($$$$$$$;$)
  419. {
  420. my @initial_args = @_;
  421. my $text = shift;
  422. my $in_raw_text = shift; # remove_texi
  423. my $in_preformatted = shift;
  424. my $in_code = shift;
  425. my $in_math = shift;
  426. my $in_simple = shift;
  427. my $style_stack = shift;
  428. my $state = shift;
  429. if ($in_math)
  430. {
  431. $text = uc($text) if (in_cmd($style_stack, 'sc'));
  432. return $text;
  433. }
  434. $text = &html_default_normal_text (@initial_args);
  435. my $colon = '';
  436. foreach my $command (@$style_stack)
  437. {
  438. if ($mediawiki_table_commands{$command} or $def_map{$command})
  439. {
  440. $colon = '|( :)' ;
  441. last;
  442. }
  443. #print STDERR "$command\n";
  444. }
  445. # '' is changed to &ldsquo; so it doesn't needs to be protected in
  446. # normal text...
  447. if (!$in_raw_text and !$in_simple)
  448. {
  449. $text =~ s/(([\[\]]|[']{2,}|(\{\{)|(\}\})$colon)+)/<nowiki>$1<\/nowiki>/g;
  450. }
  451. return $text;
  452. }
  453. #$heading = \&mediawiki_default_heading;
  454. sub mediawiki_default_heading($$$$$;$$)
  455. {
  456. my $element = shift;
  457. my $command = shift;
  458. my $texi_line = shift;
  459. my $line = shift;
  460. my $in_preformatted = shift;
  461. my $one_section = shift;
  462. my $element_heading = shift;
  463. my $result = t2h_default_heading($element, $command, $texi_line, $line,
  464. $in_preformatted, $one_section, $element_heading);
  465. if ($result ne '')
  466. {
  467. if ($element->{'no_texi'} =~ /[\#<>\[\]|{}]/)
  468. {
  469. main::msg_warn("# < > [ ] | { } not allowed in title `$element->{'texi'}'",$element->{'line_nr'});
  470. }
  471. }
  472. return $result;
  473. }
  474. # This function formats a footnote reference and the footnote text associated
  475. # with a given footnote.
  476. # The footnote reference is the text appearing in the main document pointing
  477. # to the footnote text.
  478. #
  479. # arguments:
  480. # absolute number of the footnote (in the document)
  481. # relative number of the footnote (in the page)
  482. # identifier for the footnote
  483. # identifier for the footnote reference in the main document
  484. # main document file
  485. # footnote text file
  486. # array with the footnote text lines
  487. # the state. See menu entry.
  488. #
  489. # returns:
  490. # reference on an array containing the footnote text lines which should
  491. # have been updated
  492. # the text for the reference pointing on the footnote text
  493. # FIXME the <ref>... stuff is only available with the Cite extension.
  494. $foot_line_and_ref = \&mediawiki_default_foot_line_and_ref;
  495. $foot_section = \&mediawiki_default_foot_section;
  496. sub mediawiki_default_foot_line_and_ref($$$$$$$)
  497. {
  498. my $number_in_doc = shift;
  499. my $number_in_page = shift;
  500. my $footnote_id = shift;
  501. my $place_id = shift;
  502. my $document_file = shift;
  503. my $footnote_file = shift;
  504. my $lines = shift;
  505. my $state = shift;
  506. my $result = '<ref>';
  507. foreach my $line (@$lines)
  508. {
  509. $result .= $line;
  510. }
  511. # The result shouldn't be empty, such that the call to print_Footnotes
  512. # and foot_section are not skipped
  513. return ([' '], $result . '</ref>');
  514. }
  515. # formats a group of footnotes.
  516. #
  517. # argument:
  518. # array reference on the footnotes texts lines
  519. #
  520. # returns an array reference on the group of footnotes lines
  521. # FIXME maybe do a header?
  522. sub mediawiki_default_foot_section($)
  523. {
  524. my $lines = shift;
  525. #unshift @$lines, "$DEFAULT_RULE\n" if $DEFAULT_RULE;
  526. #unshift @$lines, "==== " . gdt('Footnotes') . " ====\n";
  527. @$lines = ("<references/>\n\n");
  528. return $lines;
  529. }
  530. # FIXME maybe also a header here?
  531. $print_Footnotes = \&mediawiki_default_print_Footnotes;
  532. sub mediawiki_default_print_Footnotes
  533. {
  534. my $fh = shift;
  535. my $new_file = shift;
  536. my $misc_page = shift;
  537. my $buttons = \@MISC_BUTTONS;
  538. &$print_misc_header($fh, $buttons, $new_file, $misc_page) if ($new_file);
  539. print $fh "<references/>\n\n";
  540. &$print_misc_footer($fh, $buttons, $new_file) if ($new_file);
  541. }
  542. $button_formatting = \&mediawiki_button_formatting;
  543. sub mediawiki_button_formatting
  544. {
  545. my $button = shift;
  546. my $vertical = shift;
  547. my ($active, $passive) = HTML_DEFAULT_button_formatting($button, $vertical);
  548. if (defined($active) and !ref($button))
  549. {
  550. $active =~ s/^\[/\|/;
  551. $active =~ s/\]$/\|/;
  552. }
  553. return ($active, $passive);
  554. }
  555. $element_file_name = \&mediawiki_element_file_name;
  556. sub mediawiki_element_file_name
  557. {
  558. my $element = shift;
  559. my $type = shift;
  560. my $docu_name = shift;
  561. my $file;
  562. #print STDERR "!$element!$type!$docu_name!\n";
  563. if (!$element)
  564. {
  565. if ($type =~ /^toc$/)
  566. {
  567. $file = $docu_name . ": Table of Contents";
  568. }
  569. elsif ($type =~ /^stoc$/)
  570. {
  571. $file = $docu_name . ": Short Table of Contents";
  572. }
  573. elsif ($type =~ /^foot$/)
  574. {
  575. $file = $docu_name . ": Footnotes";
  576. }
  577. elsif ($type =~ /^about$/)
  578. {
  579. $file = $docu_name . ": About this Manual";
  580. }
  581. elsif ($type =~ /^doc$/)
  582. {
  583. $file = $docu_name;
  584. }
  585. }
  586. else
  587. {
  588. my $name = main::substitute_line($element->{'texi'}, 'file name', {'remove_texi' => 1}, $element->{'line_nr'});
  589. if (exists $mediawiki_doc_nr_to_file{$element->{'doc_nr'}})
  590. {
  591. $file = $mediawiki_doc_nr_to_file{$element->{'doc_nr'}};
  592. $mediawiki_doc_nr_to_file{$element->{'doc_nr'}} = $file;
  593. }
  594. else
  595. {
  596. $name =~ s,/,%47,g;
  597. $name =~ s,\\,%92,g;
  598. $file = "$docu_name" . (($type eq 'top') ? "" : ": " . $name);
  599. $mediawiki_doc_nr_to_file{$element->{'doc_nr'}} = $file;
  600. }
  601. push @{$mediawiki_target_to_name{$element->{'target'}}}, [ $file, $element ];
  602. if ($name =~ /[\#<>\[\]|{}]/)
  603. {
  604. main::msg_warn("# < > [ ] | { } not allowed in title `$element->{'texi'}'",$element->{'line_nr'});
  605. }
  606. }
  607. $mediawiki_special_file_name{$file} = 1;
  608. return $file;
  609. }
  610. $node_file_name = \&mediawiki_default_node_file_name;
  611. sub mediawiki_default_node_file_name($$)
  612. {
  613. my $node = shift;
  614. my $type = shift;
  615. my $filename = T2H_DEFAULT_node_file_name($node, $type);
  616. my $command = 'node';
  617. $command = $node->{'tag'};
  618. my $name = main::substitute_line($node->{'texi'}, 'node name', {'remove_texi' => 1}, $node->{'line_nr'});
  619. if ($name =~ /[\#<>\[\]|{}]/)
  620. {
  621. main::msg_warn("# < > [ ] | { } not allowed in references, in \@$command `$node->{'texi'}'",$node->{'line_nr'});
  622. }
  623. return $filename;
  624. }
  625. # a preformatted region
  626. # arguments:
  627. # $text of the preformatted region
  628. # $pre_style css style
  629. # $class identifier for the preformatted region (example, menu-comment)
  630. # The following is usefull if the preformatted is in an itemize.
  631. # $leading_command is the leading formatting command (like @minus)
  632. # $leading_command_formatted is the leading formatting command formatted
  633. # $preformatted_number is a reference on the number of preformatteds appearing
  634. # in the format. The value should be increased if a preformatted is done
  635. $preformatted = \&mediawiki_default_preformatted;
  636. sub mediawiki_default_preformatted($$$$$$$$$$)
  637. {
  638. my $text = shift;
  639. my $pre_style = shift;
  640. my $class = shift;
  641. my $leading_command = shift;
  642. my $leading_command_formatted = shift;
  643. my $preformatted_number = shift;
  644. my $format = shift;
  645. my $item_nr = shift;
  646. my $enumerate_style = shift;
  647. my $number = shift;
  648. my $command_stack_at_end = shift;
  649. my $command_stack_at_begin = shift;
  650. return '' if ($text eq '');
  651. $leading_command_formatted = '' if (!defined($leading_command_formatted) or
  652. exists($special_list_commands{$format}->{$leading_command}));
  653. if (defined($preformatted_number) and defined($$preformatted_number))
  654. {
  655. $$preformatted_number++;
  656. }
  657. my $top_stack = '';
  658. $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
  659. if ($top_stack eq 'multitable')
  660. {
  661. $text =~ s/^\s*//;
  662. $text =~ s/\s*$//;
  663. }
  664. $text =~ s/^/ /mg;
  665. # return html_default_attribute_class('div', $class).">\n$text</div>\n";
  666. return "$text";
  667. #return "<pre class=\"$class\"><nowiki>$text</nowiki></pre>";
  668. }
  669. sub mediawiki_default_remove_eol($)
  670. {
  671. my $text = shift;
  672. chomp($text);
  673. my $res = '';
  674. foreach my $line (split /\n/, $text)
  675. {
  676. $res .= $line . " ";
  677. }
  678. $res =~ s/ $//;
  679. $res .= "\n";
  680. return $res;
  681. }
  682. my %mediawiki_default_indent_symbol = (
  683. 'itemize' => '*',
  684. 'enumerate' => '#'
  685. );
  686. foreach my $table ('table', 'ftable', 'vtable')
  687. {
  688. $mediawiki_default_indent_symbol{$table} = ':';
  689. $mediawiki_table_commands{$table} = 1;
  690. }
  691. foreach my $definition_command (keys(%def_map))
  692. {
  693. $mediawiki_default_indent_symbol{$definition_command} = ':';
  694. }
  695. sub mediawiki_default_indent_string($;$)
  696. {
  697. my $commands = shift;
  698. my $remove_last = shift;
  699. $commands = $Texi2HTML::THISDOC{'command_stack'} if (!defined($commands));
  700. my $indent_string = '';
  701. foreach my $format (@$commands)
  702. {
  703. $indent_string .= $mediawiki_default_indent_symbol{$format}
  704. if defined($mediawiki_default_indent_symbol{$format});
  705. }
  706. $indent_string =~ s/.$// if ($remove_last);
  707. return $indent_string;
  708. }
  709. $paragraph = \&mediawiki_default_paragraph;
  710. sub mediawiki_default_paragraph($$$$$$$$$$$$)
  711. {
  712. my $text = shift;
  713. my $align = shift;
  714. my $indent = shift;
  715. my $paragraph_command = shift;
  716. my $paragraph_command_formatted = shift;
  717. my $paragraph_number = shift;
  718. my $format = shift;
  719. my $item_nr = shift;
  720. my $enumerate_style = shift;
  721. my $number = shift;
  722. my $command_stack_at_end = shift;
  723. my $command_stack_at_begin = shift;
  724. #print STDERR "format: $format\n" if (defined($format));
  725. #print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n";
  726. # $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or
  727. # exists($special_list_commands{$format}->{$paragraph_command}));
  728. return '' if ($text =~ /^\s*$/);
  729. if (defined($paragraph_number) and defined($$paragraph_number))
  730. {
  731. $$paragraph_number++;
  732. }
  733. # remove leading spaces, they trigger a preformatted environment in wikitext
  734. $text =~ s/^\s*//mg;
  735. my $top_stack = '';
  736. $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
  737. if ($top_stack eq 'multitable')
  738. {
  739. $html_default_multitable_stack[-1]->[1]++;
  740. return mediawiki_default_remove_eol($text);
  741. }
  742. if ($align)
  743. {
  744. $text = "<p align=\"$paragraph_style{$align}\">".$text.'</p>';
  745. }
  746. my $indent_string = mediawiki_default_indent_string($command_stack_at_begin);
  747. if ($indent_string)
  748. {
  749. $text = $indent_string . ' ' .mediawiki_default_remove_eol($text);
  750. }
  751. return $text;
  752. }
  753. $list_item = \&mediawiki_default_list_item;
  754. sub mediawiki_default_list_item
  755. {
  756. my $text = shift;
  757. return $text;
  758. }
  759. $def_item = \&mediawiki_default_def_item;
  760. sub mediawiki_default_def_item($$$)
  761. {
  762. my $text = shift;
  763. my $only_inter_item_commands = shift;
  764. my $command = shift;
  765. if ($text =~ /\S/)
  766. {
  767. if (! get_conf('DEF_TABLE'))
  768. {
  769. return $text;# unless $only_inter_item_commands;
  770. #return $text; # invalid without dd in ul
  771. }
  772. else
  773. {
  774. return '<tr><td colspan="2">' . $text . '</td></tr>';
  775. }
  776. }
  777. return '';
  778. }
  779. $table_item = \&mediawiki_default_table_item;
  780. sub mediawiki_default_table_item($$$$$$$)
  781. {
  782. my $text = shift;
  783. my $index_label = shift;
  784. my $format = shift;
  785. my $command = shift;
  786. # my $formatted_command = shift;
  787. my $style_stack = shift;
  788. # my $text_formatted = shift;
  789. # my $text_formatted_leading_spaces = shift;
  790. # my $text_formatted_trailing_spaces = shift;
  791. my $item_cmd = shift;
  792. my $formatted_index_entry = shift;
  793. # if (defined($text_formatted) and !exists $special_list_commands{$format}->{$command})
  794. # {
  795. # $text = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces;
  796. # }
  797. # $formatted_command = '' if (!defined($formatted_command) or
  798. # exists($special_list_commands{$format}->{$command}));
  799. if (html_teletyped_in_stack($style_stack))
  800. {
  801. # $text .= '</tt>';
  802. # $formatted_command = '<tt>' . $formatted_command;
  803. $text = '<tt>' . $text . '</tt>';
  804. }
  805. $text .= "\n" . $index_label if (defined($index_label));
  806. # return '<dt>' . $formatted_command . $text . '</dt>' . "\n";
  807. return mediawiki_default_indent_string(undef,1) .";$text\n";
  808. }
  809. $table_line = \&mediawiki_default_table_line;
  810. sub mediawiki_default_table_line($$$)
  811. {
  812. my $text = shift;
  813. my $only_inter_item_commands = shift;
  814. my $before_items = shift;
  815. $only_inter_item_commands = '' if (!defined($only_inter_item_commands));
  816. if ($text =~ /\S/)
  817. {
  818. #return ";$text\n";# unless ($only_inter_item_commands);
  819. return $text;
  820. #return $text; # invalid without dd in ul
  821. }
  822. return '';
  823. }
  824. $def_line = \&mediawiki_default_def_line;
  825. sub mediawiki_default_def_line($$$$$$$$$$$$$$$$)
  826. {
  827. my $category_prepared = shift;
  828. my $name = shift;
  829. my $type = shift;
  830. my $arguments = shift;
  831. my $index_label = shift;
  832. my $arguments_array = shift;
  833. my $arguments_type_array = shift;
  834. my $unformatted_arguments_array = shift;
  835. my $command = shift;
  836. my $class_name = shift;
  837. my $category = shift;
  838. my $class = shift;
  839. my $style = shift;
  840. my $original_command = shift;
  841. $index_label = '' if (!defined($index_label));
  842. chomp($index_label);
  843. $category_prepared = '' if (!defined($category_prepared) or ($category_prepared =~ /^\s*$/));
  844. $name = '' if (!defined($name) or ($name =~ /^\s*$/));
  845. $type = '' if (!defined($type) or $type =~ /^\s*$/);
  846. if (!defined($arguments) or $arguments =~ /^\s*$/)
  847. {
  848. $arguments = '';
  849. }
  850. else
  851. {
  852. chomp ($arguments);
  853. $arguments = '<em>' . $arguments . '</em>';
  854. }
  855. my $type_name = '';
  856. $type_name = " <em>$type</em>" if ($type ne '');
  857. $type_name .= ' <strong>' . $name . '</strong>' if ($name ne '');
  858. $type_name .= $arguments;
  859. if (! get_conf('DEF_TABLE'))
  860. {
  861. return mediawiki_default_indent_string(undef,1) .';'. $index_label. $category_prepared . '<nowiki>:</nowiki>' . $type_name . "\n";
  862. }
  863. else
  864. {
  865. return "<tr><td align=\"left\">" . $type_name .
  866. "</td><td align=\"right\">" . $category_prepared . $index_label . "</td></tr>\n";
  867. }
  868. }
  869. $def = \&mediawiki_default_def;
  870. sub mediawiki_default_def($$)
  871. {
  872. my $text = shift;
  873. my $command = shift;
  874. if ($text =~ /\S/)
  875. {
  876. if (! get_conf('DEF_TABLE'))
  877. {
  878. return $text;
  879. }
  880. else
  881. {
  882. return "<table width=\"100%\">\n" . $text . "</table>\n";
  883. }
  884. }
  885. return '';
  886. }
  887. $table_list = \&mediawiki_default_table_list;
  888. sub mediawiki_default_table_list($$$$$$$$$)
  889. {
  890. my $format_command = shift;
  891. my $text = shift;
  892. my $command = shift;
  893. my $formatted_command = shift;
  894. # enumerate
  895. my $item_nr = shift;
  896. my $enumerate_style = shift;
  897. # itemize
  898. my $prepended = shift;
  899. my $prepended_formatted = shift;
  900. # multitable
  901. my $columnfractions = shift;
  902. my $prototype_row = shift;
  903. my $prototype_lengths = shift;
  904. my $column_number = shift;
  905. if ($format_command eq 'multitable')
  906. {
  907. pop @html_default_multitable_stack;
  908. return &$format('multitable', 'table', $text);
  909. }
  910. return $text;
  911. }
  912. # format an index summary. This is a list of letters linking to the letter
  913. # entries.
  914. #
  915. # arguments:
  916. # array reference containing the formatted alphabetical letters
  917. # array reference containing the formatted non lphabetical letters
  918. $index_summary = \&mediawiki_index_summary;
  919. sub mediawiki_index_summary($$)
  920. {
  921. my $alpha = shift;
  922. my $nonalpha = shift;
  923. my $join = '';
  924. my $nonalpha_text = '';
  925. my $alpha_text = '';
  926. return "" if !@$nonalpha and !@$alpha;
  927. $nonalpha_text = join ("", map {"<td>$_</td>"} @$nonalpha) . "\n"
  928. if @$nonalpha;
  929. $alpha_text = join ("", @$alpha) . "\n &nbsp; \n"
  930. if @$alpha;
  931. return '<table cellpadding="1" cellspacing="1" border="0">'
  932. . "<tr><th valign=\"top\">" . gdt('Jump to') .":</th>\n"
  933. . join ("", map {"<td>$_</td>\n"} @$nonalpha, @$alpha)
  934. . "</tr></table>\n";
  935. }
  936. $line_command = \&mediawiki_line_command;
  937. sub mediawiki_line_command($$$$)
  938. {
  939. my $command = shift;
  940. my $arg_text = shift;
  941. my $arg_texi = shift;
  942. my $state = shift;
  943. return '' if ($arg_text eq '' or ($command eq 'author' and (!$state->{'region'} or $state->{'region'} ne 'titlepage')));
  944. if ($command eq 'title')
  945. {
  946. $arg_text = '== ' .$arg_text. " ==\n";
  947. }
  948. elsif ($command eq 'subtitle')
  949. {
  950. $arg_text = '=== ' .$arg_text. " ===\n";
  951. }
  952. elsif ($command eq 'author')
  953. {
  954. $arg_text = '<strong> ' .$arg_text. " </strong><br>\n";
  955. }
  956. return $arg_text;
  957. }
  958. $image = \&mediawiki_default_image;
  959. sub mediawiki_default_image($$$$$$$$$$$$$$$$$)
  960. {
  961. my $file = shift;
  962. my $base = shift;
  963. my $preformatted = shift;
  964. my $file_name = shift;
  965. my $alt = shift;
  966. my $width = shift;
  967. my $height = shift;
  968. my $raw_alt = shift;
  969. my $extension = shift;
  970. my $working_dir = shift;
  971. my $file_path = shift;
  972. my $in_paragraph = shift;
  973. my $file_locations = shift;
  974. my $base_simple_format = shift;
  975. my $extension_simple_format = shift;
  976. my $file_name_simple_format = shift;
  977. my $line_nr = shift;
  978. if (!defined($file_path) or $file_path eq '')
  979. {
  980. if (defined($extension) and $extension ne '')
  981. {
  982. $file = "$base.$extension";
  983. }
  984. else
  985. {
  986. $file = "$base.jpg";
  987. }
  988. main::line_warn (sprintf(__("\@image file `%s' not found, using `%s'"), $base, $file), $line_nr);
  989. }
  990. elsif (! get_conf('COMPLETE_IMAGE_PATHS'))
  991. {
  992. $file = $file_name;
  993. }
  994. my $alt_text = '';
  995. $alt_text = "|alt=$alt" if (defined($alt) and $alt ne '');
  996. # it is possible that $file_name is more correct as it allows the user
  997. # to chose the relative path.
  998. $file = &$protect_text($file);
  999. return "[[Image:$file$alt_text]]";
  1000. }
  1001. # FIXME <math> in mediawiki is only valid for one formula, not for
  1002. # random TeX.
  1003. # One possibility could be to use TeX -> html -> html2wiki
  1004. #$raw = \&mediawiki_default_raw;
  1005. sub mediawiki_default_raw($$;$)
  1006. {
  1007. my $style = shift;
  1008. my $text = shift;
  1009. my $line_nr = shift;
  1010. my $expanded = 1 if (grep {$style eq $_} @EXPAND);
  1011. if ($style eq 'verbatim' or $style eq 'verbatiminclude')
  1012. {
  1013. $style = 'verbatim' if ($style eq 'verbatiminclude');
  1014. return html_default_attribute_class('pre', $style).">" . &$protect_text($text) . '</pre>';
  1015. }
  1016. elsif ($style eq 'html' and $expanded)
  1017. {
  1018. chomp ($text);
  1019. return $text;
  1020. }
  1021. elsif ($style eq 'tex' and $expanded)
  1022. {
  1023. chomp ($text);
  1024. return "<math>$text</math>\n";
  1025. }
  1026. elsif ($expanded)
  1027. {
  1028. main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr);
  1029. return &$protect_text($text);
  1030. }
  1031. else
  1032. {
  1033. return '';
  1034. }
  1035. }
  1036. ## a simple menu entry ref in case we aren't in a standard menu context
  1037. #$simple_menu_link = \&mediawiki_simple_menu_link;
  1038. # a menu link. We are always in preformatted because of SIMPLE_MENU.
  1039. # currently not used.
  1040. #$menu_link = \&mediawiki_simple_menu_link;
  1041. sub mediawiki_simple_menu_link($$$$$$$)
  1042. {
  1043. my $entry = shift;
  1044. # my $preformatted = shift; # We assume this is true.
  1045. my $state = shift;
  1046. my $href = shift;
  1047. my $node = shift;
  1048. my $title = shift;
  1049. my $ending = shift;
  1050. my $has_title = shift;
  1051. my $command_stack = shift;
  1052. my $preformatted = shift;
  1053. $title = '' unless ($has_title);
  1054. $ending = '' unless defined $ending;
  1055. $entry = "</nowiki>";
  1056. $entry .= "$MENU_SYMBOL";
  1057. if ($href)
  1058. {
  1059. $entry .= &$anchor ('', $href, $node);
  1060. }
  1061. else
  1062. {
  1063. $title .= ":" if ($title ne '');
  1064. $entry .= "$title$node";
  1065. }
  1066. $entry .= $ending;
  1067. $entry .= "<nowiki>";
  1068. return $entry;
  1069. }