summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/highlight.pm
blob: f116c41ddc0d14b08c2e017b0e36c6daea9fc890 (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::highlight;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 3.00;
  6. # locations of highlight's files
  7. my $filetypes="/etc/highlight/filetypes.conf";
  8. my $langdefdir="/usr/share/highlight/langDefs";
  9. sub import {
  10. hook(type => "getsetup", id => "highlight", call => \&getsetup);
  11. hook(type => "checkconfig", id => "highlight", call => \&checkconfig);
  12. # this hook is used by the format plugin
  13. hook(type => "htmlizefallback", id => "highlight", call =>
  14. \&htmlizefallback);
  15. }
  16. sub getsetup () {
  17. return
  18. plugin => {
  19. safe => 1,
  20. rebuild => 1, # format plugin
  21. },
  22. tohighlight => {
  23. type => "string",
  24. example => ".c .h .cpp .pl .py Makefile:make",
  25. description => "source files to syntax highlight",
  26. safe => 1,
  27. rebuild => 1,
  28. },
  29. }
  30. sub checkconfig () {
  31. if (exists $config{tohighlight}) {
  32. foreach my $file (split ' ', $config{tohighlight}) {
  33. my @opts = $file=~s/^\.// ?
  34. (keepextension => 1) :
  35. (noextension => 1);
  36. my $ext = $file=~s/:(.*)// ? $1 : $file;
  37. my $langfile=ext2langfile($ext);
  38. if (! defined $langfile) {
  39. error(sprintf(gettext(
  40. "tohighlight contains unknown file type '%s'"),
  41. $ext));
  42. }
  43. hook(
  44. type => "htmlize",
  45. id => $file,
  46. call => sub {
  47. my %params=@_;
  48. highlight($langfile, $params{content});
  49. },
  50. longname => sprintf(gettext("Source code: %s"), $file),
  51. @opts,
  52. );
  53. }
  54. }
  55. }
  56. sub htmlizefallback {
  57. my $format=lc shift;
  58. my $langfile=ext2langfile($format);
  59. if (! defined $langfile) {
  60. return;
  61. }
  62. return highlight($langfile, shift);
  63. }
  64. my %ext2lang;
  65. my $filetypes_read=0;
  66. # Parse highlight's config file to get extension => language mappings.
  67. sub read_filetypes () {
  68. open (IN, $filetypes);
  69. while (<IN>) {
  70. chomp;
  71. if (/^\$ext\((.*)\)=(.*)$/) {
  72. $ext2lang{$_}=$1 foreach $1, split ' ', $2;
  73. }
  74. }
  75. close IN;
  76. $filetypes_read=1;
  77. }
  78. sub langfile ($) {
  79. return "$langdefdir/$_[0].lang";
  80. }
  81. # Given a filename extension, determines the language definition to
  82. # use to highlight it.
  83. sub ext2langfile ($) {
  84. my $ext=shift;
  85. read_filetypes() unless $filetypes_read;
  86. if (exists $ext2lang{$ext}) {
  87. return langfile($ext2lang{$ext});
  88. }
  89. # If a language only has one common extension, it will not
  90. # be listed in filetypes, so check the langfile.
  91. elsif (-e langfile($ext)) {
  92. return langfile($ext);
  93. }
  94. else {
  95. return undef;
  96. }
  97. }
  98. # Interface to the highlight C library.
  99. sub highlight ($$) {
  100. my $langfile=shift;
  101. my $input=shift;
  102. eval q{use highlight};
  103. if ($@) {
  104. print STDERR gettext("warning: highlight perl module not available; falling back to pass through");
  105. return $input;
  106. }
  107. my $gen = highlightc::CodeGenerator_getInstance($highlightc::XHTML);
  108. $gen->setFragmentCode(1); # generate html fragment
  109. $gen->setHTMLEnclosePreTag(1); # include stylish <pre>
  110. $gen->initLanguage($langfile);
  111. $gen->initTheme("/dev/null"); # theme is not needed because CSS is not emitted
  112. $gen->setEncoding("utf-8");
  113. my $output=$gen->generateString($input);
  114. highlightc::CodeGenerator_deleteInstance($gen);
  115. return $output;
  116. }
  117. 1