Made SyntaxHighlight more generic so /commitdiff now gets highlighting too.
[catagits/Gitalist.git] / lib / Gitalist / View / SyntaxHighlight.pm
CommitLineData
7e54e579 1package Gitalist::View::SyntaxHighlight;
2use Moose;
3use Gitalist; # ->path_to
4use namespace::autoclean;
5
6extends 'Catalyst::View';
7
8use Syntax::Highlight::Engine::Kate ();
9use Syntax::Highlight::Engine::Kate::Perl ();
10
c8870bd3 11use HTML::Entities qw(encode_entities);
12
f5da8e7a 13=begin
14
15B<Notes>
16
17What should be done, but isn't currently:
18
19 broquaint> Another Cat question - if I want to have arbitrary things highlighted is pushing things through a View at all costs terribly wrong?
20 broquaint> e.g modifying this slightly to highlight anything (or arrays of anything) http://github.com/broquaint/Gitalist/blob/a7cc1ede5f9729465bb53da9c3a8b300a3aa8a0a/lib/Gitalist/View/SyntaxHighlight.pm
21 t0m> no, that's totally fine.. I'd tend to push the rendering logic into a model, so you end up doing something like: $c->model('SyntaxDriver')->highlight_all($stuff, $c->view('SyntaxHighlight'));
22 broquaint> I'm thinking it's a bad idea because the Controller needs to munge data such that the View knows what to do
23 broquaint> You just blew my mind ;)
24 t0m> ^^ That works _much_ better if you split up your view methods into process & render..
25 t0m> ala TT..
26 t0m> i.e. I'd have 'highlight this scalar' as the ->render method in the view..
27 t0m> And then the 'default' thing (i.e. process method) will do that and shove the output in the body..
28 t0m> but then you can write foreach my $thing (@things) { push(@highlighted_things, $c->view('SyntaxHighlight')->render($thing)); }
29 t0m> and then I'd move that ^^ loop down into a model which actually knows about / abstracts walking the data structures concerned..
30 t0m> But splitting render and process is the most important bit.. :) Otherwise you need to jump through hoops to render things that don't fit 'nicely' into the bits of stash / body that the view uses by 'default'
31 t0m> I wouldn't kill you for putting the structure walking code in the view given you're walking simple arrays / hashes.. It becomes more important if you have a more complex visitor..
32 t0m> (I use Visitor in the design patterns sense)
33 t0m> As the visitor is responsible for walking the structure, delegating to the ->render call in the view which is responsible for actually mangling the content..
34
35=cut
36
7e54e579 37sub process {
38 my($self, $c) = @_;
c8870bd3 39
f5da8e7a 40 for($c->stash->{blobs} ? @{$c->stash->{blobs}} : $c->stash->{blob}) {
41 $_ = $self->highlight($c->stash->{language} => $_);
42 }
43
44 $c->forward('View::Default');
45}
46
47sub highlight {
48 my($self, $lang, $blob) = @_;
49
47495599 50 # If we're not going to highlight the blob unsure that it's ready to go
51 # into HTML at least.
f5da8e7a 52 if($lang) {
c8870bd3 53 # via
54 # http://github.com/jrockway/angerwhale/blob/master/lib/Angerwhale/Format/Pod.pm#L136
f5da8e7a 55 my $ret = eval {
c8870bd3 56 no warnings 'redefine';
57 local *Syntax::Highlight::Engine::Kate::Template::logwarning
58 = sub { die @_ }; # i really don't care
59 my $hl = Syntax::Highlight::Engine::Kate->new(
f5da8e7a 60 language => $lang,
c8870bd3 61 substitutions => {
62 "<" => "&lt;",
63 ">" => "&gt;",
64 "&" => "&amp;",
65 q{'} => "&apos;",
66 q{"} => "&quot;",
67 },
68 format_table => {
69 # convert Kate's internal representation into
70 # <span class="<internal name>"> value </span>
71 map {
72 $_ => [ qq{<span class="$_">}, '</span>' ]
73 }
74 qw/Alert BaseN BString Char Comment DataType
75 DecVal Error Float Function IString Keyword
76 Normal Operator Others RegionMarker Reserved
77 String Variable Warning/,
78 },
79 );
80
f5da8e7a 81 $hl->highlightText($blob);
c8870bd3 82 };
83 warn $@ if $@;
f5da8e7a 84 return $ret || $blob;
c8870bd3 85 } else {
f5da8e7a 86 return encode_entities($blob);
c8870bd3 87 }
7e54e579 88}
89
1ef8dc7d 90__PACKAGE__->meta->make_immutable;