summaryrefslogtreecommitdiff
path: root/pandoc-todo
blob: 991f98f360bd40a82f0d4175c96f2e1f787833cb (plain)
  1. #!/usr/bin/perl
  2. # TODO: support multi-match within word
  3. # TODO: support multi-word match
  4. # TODO: always count and allow expressing which (default: all)
  5. # TODO: parse regex+commeent as definition in external markdown TODO file.
  6. # TODO: normal hyphenation within note (keep quote with word in "word")
  7. # TODO: clear font styling in notes
  8. # TODO: track headline levels and note skipping when "diving"
  9. use warnings;
  10. use strict;
  11. use feature qw(switch);
  12. no if $] >= 5.018, warnings => "experimental::smartmatch";
  13. use Pandoc::Filter 0.05;
  14. use Pandoc::Elements;
  15. my $breakable_chars = qr/[\&\;\/\.\?\!\=]/;
  16. my $hyphen_chars = qr/[\x{2010}-\x{2015}\x{2053}\x{2212}]/;
  17. my $doublequote_chars = qr/[\x{00AB}\x{00BB}\x{201C}-\x{201F}\x{300C}-\x{300F}\x{301D}-\x{301F}\x{FE41}-\x{FE44}\x{FF02}\x{FF62}\x{FF63}]/;
  18. my $singlequote_chars = qr/[\x{0060}\x{2018}\x{2019}\x{201A}\x{201B}\x{2039}\x{203A}\x{FF07}]/;
  19. my $odd_singlequote_chars = qr/[\x{2019}]/;
  20. my $inline_count;
  21. pandoc_filter(
  22.     \&todo,
  23. );
  24. sub latex_encode {
  25.     my $s = shift;
  26.     $s =~ s/(?<!\s|$breakable_chars)($breakable_chars])(?!\s)/$1\\-/g;
  27.     $s =~ s/$odd_singlequote_chars/'/g; #'
  28.     return $s;
  29. }
  30. sub mark_inside {
  31.     my ( $before, $it, $after, $note ) = @_;
  32.     return [ RawInline( 'latex', sprintf( '%s\\mytodo{%s}{%s}%s',
  33.         latex_encode($before),
  34.         latex_encode($note),
  35.         latex_encode($it),
  36.         latex_encode($after),
  37.     ))];
  38. };
  39. sub todo {
  40.     my $self = shift;
  41.     $inline_count = 0 if ( $self->is_block );
  42.     return unless ( $self->name eq 'Str' );
  43.     given ($self->content) {
  44.         $inline_count++;
  45.         when (/^(-)$/) {
  46.             return mark_inside( '', $1, '', 'maybe break' ) };
  47.         when (/^(---+)(.+?)$/) {
  48.             return mark_inside( '', $1, $2, 'maybe break' ) };
  49.         when (/^(.+?)(--+)(.+?)$/) {
  50.             return mark_inside( $1, $2, $3, 'maybe range' ) };
  51.         when ( /^(.*?)($hyphen_chars(?:.*$hyphen_chars)?)(.*?)$/ ) {
  52.             return mark_inside( $1, $2, $3, 'fancy hyphen' ) };
  53.         when ( /^(.*?)($doublequote_chars(?:.*$doublequote_chars)?)(.*?)$/ ) {
  54.             return mark_inside( $1, $2, $3, 'fancy quote' ) };
  55.         when ( /^(.*?)($singlequote_chars(?:.*$singlequote_chars)?)(.*?)$/ ) {
  56.             return mark_inside( $1, $2, $3, 'fancy quote' ) };
  57.         when ( $inline_count == 1 and /^(\(?\d+\)|\d+\.)$/ ) {
  58.             return mark_inside( '', $1, '', 'maybe list' ) };
  59.         when ( $inline_count == 1 and /^(\(?[ivxc]+\)|\d+\.[\d.]+)$/ ) {
  60.             return mark_inside( '', $1, '', 'maybe fancy list' ) };
  61.         default { return };
  62.     }
  63. };