Simplify how content gets mangled. last-mangle-in-paris
Dan Brook [Sun, 6 Nov 2011 22:37:44 +0000 (22:37 +0000)]
The many layers of abstraction were unnecessary at this point so I've
pared the code down to the bare minimum based on this POC code:

https://gist.github.com/1343603

Now how we mangle content is based on a wee hash that only takes into
account the current action and the cm (i.e content mangler)
parameter. We decide what to pass into the mangler basde on a wee hash
in ContentMangler which defines the relevant parts of the stash to
pass in. A ContentMangler::Transformer now simply returns a hash that
will be reintegrated into the stash, none of this
action-at-a-distance.

The things that used to work before (diffs & perl code) should
continue to work. I've also added a POC that will PODify blobs
accessible by setting the cm query parameter to doc e.g

http://localhost:3000/Gitalist/master/blob/lib%2FGitalist.pm?cm=doc

12 files changed:
gitalist.conf
lib/Gitalist/ContentMangler/Resolver.pm [deleted file]
lib/Gitalist/ContentMangler/Resolver/Default.pm [deleted file]
lib/Gitalist/ContentMangler/Transformer/EnPodulate.pm [new file with mode: 0644]
lib/Gitalist/ContentMangler/Transformer/SyntaxHighlight.pm [deleted file]
lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightBlob.pm [new file with mode: 0644]
lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightDiff.pm [new file with mode: 0644]
lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightRole.pm [new file with mode: 0644]
lib/Gitalist/Controller/Fragment/Ref.pm
lib/Gitalist/Model/ContentMangler.pm
root/inc/syntax_highlight_css.tt2
root/ref/blob.tt2

index 7de94a7..238ea14 100644 (file)
@@ -9,6 +9,18 @@ name Gitalist
     # repo_dir __path_to(../)__
 </Model::CollectionOfRepos>
 
+# default = standard Gitalist transformer
+# other   = ?cm=$mangler
+<Model::ContentMangler>
+  <blob>
+    default Gitalist::ContentMangler::Transformer::SyntaxHighlightBlob
+    doc     Gitalist::ContentMangler::Transformer::EnPodulate
+  </blob>
+  <diff_fancy>
+    default Gitalist::ContentMangler::Transformer::SyntaxHighlightDiff
+  </diff_fancy>
+</Model::ContentMangler>
+
 sitename "A Gitalist"
 
 <paging>
diff --git a/lib/Gitalist/ContentMangler/Resolver.pm b/lib/Gitalist/ContentMangler/Resolver.pm
deleted file mode 100644 (file)
index f0ba985..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package Gitalist::ContentMangler::Resolver;
-use Moose::Role;
-
-requires 'resolve';
-
-1;
diff --git a/lib/Gitalist/ContentMangler/Resolver/Default.pm b/lib/Gitalist/ContentMangler/Resolver/Default.pm
deleted file mode 100644 (file)
index 29aeda4..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-use MooseX::Declare;
-
-class Gitalist::ContentMangler::Resolver::Default with Gitalist::ContentMangler::Resolver {
-    method resolve ($data) {
-        # This should be pulled out of $self->config
-        my $language;
-        $language = 'Perl' if $data->{filename} =~ /\.p[lm]$/i;
-        $language = 'Diff' if $data->{action} eq 'diff_fancy';
-        return unless $language;
-        return 'Gitalist::ContentMangler::Transformer::SyntaxHighlight' => {language => $language, css => $language};
-    }
-}
diff --git a/lib/Gitalist/ContentMangler/Transformer/EnPodulate.pm b/lib/Gitalist/ContentMangler/Transformer/EnPodulate.pm
new file mode 100644 (file)
index 0000000..d360add
--- /dev/null
@@ -0,0 +1,15 @@
+use MooseX::Declare;
+
+# Currently a POC to demonstrate non SyntaxHighlight based
+# CM::Transformer. The default output is ugly as sin.
+class Gitalist::ContentMangler::Transformer::EnPodulate {
+    use Pod::Simple::HTML;
+    
+    method transform(Str :$blob, Str :$filename) {
+        my $p = Pod::Simple::HTML->new;
+        $p->output_string(\my $html);
+        $p->parse_string_document( $blob );
+        $html =~ m{<body[^>]*>(.*?)</body>}s;
+        return { blob => $1 };
+    }
+}
diff --git a/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlight.pm b/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlight.pm
deleted file mode 100644 (file)
index 8d53aaf..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-use MooseX::Declare;
-
-class Gitalist::ContentMangler::Transformer::SyntaxHighlight {
-  method transform($c, $config) {
-    $c->stash(
-      syntax_css => $c->uri_for("/static/css/syntax/$config->{css}.css"),
-      mangled    => 1,
-    );
-    for (grep $_, $c->stash->{blobs} ? @{$c->stash->{blobs}} : $c->stash->{blob}) {
-      $_ = $c->view('SyntaxHighlight')->render($c, $_, $config);
-    }
-  }
-}
diff --git a/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightBlob.pm b/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightBlob.pm
new file mode 100644 (file)
index 0000000..4d73e73
--- /dev/null
@@ -0,0 +1,9 @@
+use MooseX::Declare;
+
+class Gitalist::ContentMangler::Transformer::SyntaxHighlightBlob
+ with Gitalist::ContentMangler::Transformer::SyntaxHighlightRole {
+     method transform(Str :$blob, Str :$filename) {
+         return unless $filename =~ /\.p[lm]$/;
+         return { blob => $self->highlight($blob, 'Perl'), language => 'Perl' };
+     }
+}
diff --git a/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightDiff.pm b/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightDiff.pm
new file mode 100644 (file)
index 0000000..b84d894
--- /dev/null
@@ -0,0 +1,11 @@
+use MooseX::Declare;
+
+class Gitalist::ContentMangler::Transformer::SyntaxHighlightDiff
+ with Gitalist::ContentMangler::Transformer::SyntaxHighlightRole {
+     method transform(ArrayRef :$diffs) {
+         return {
+             language => 'Diff',
+             blobs    => [map $self->highlight($_, 'Diff'), @$diffs],
+         };
+     }
+}
diff --git a/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightRole.pm b/lib/Gitalist/ContentMangler/Transformer/SyntaxHighlightRole.pm
new file mode 100644 (file)
index 0000000..09a0ca2
--- /dev/null
@@ -0,0 +1,51 @@
+use MooseX::Declare;
+
+role Gitalist::ContentMangler::Transformer::SyntaxHighlightRole {
+    use Syntax::Highlight::Engine::Kate ();
+    use Syntax::Highlight::Engine::Kate::Perl ();
+
+    use HTML::Entities qw(encode_entities);
+
+    method highlight(Str $blob, Str $lang) {
+        # Don't bother with anything over 128kb, it'll be tragically slow.
+        return encode_entities $blob if length $blob > 131_072;
+    
+        my $ret;
+        if ($lang) {
+            # via http://github.com/jrockway/angerwhale/blob/master/lib/Angerwhale/Format/Pod.pm#L136
+            $ret = eval {
+                no warnings 'redefine';
+                local *Syntax::Highlight::Engine::Kate::Template::logwarning
+                     = sub { die @_ }; # i really don't care
+                my $hl = Syntax::Highlight::Engine::Kate->new(
+                    language      => $lang,
+                    substitutions => {
+                        "<"  => "&lt;",
+                        ">"  => "&gt;",
+                        "&"  => "&amp;",
+                        q{'} => "&apos;",
+                        q{"} => "&quot;",
+                    },
+                    format_table => {
+                        # convert Kate's internal representation into
+                        # <span class="<internal name>"> value </span>
+                        map {
+                            $_ => [ qq{<span class="$_">}, '</span>' ]
+                        }
+                             qw/Alert BaseN BString Char Comment DataType
+                                DecVal Error Float Function IString Keyword
+                                Normal Operator Others RegionMarker Reserved
+                                String Variable Warning/,
+                    },
+                );
+
+                my $hltxt = $hl->highlightText($blob);
+                $hltxt =~ s/([^[:ascii:]])/encode_entities($1)/eg;
+                $hltxt;
+            };
+            warn $@ if $@;
+        }
+
+        return $ret || encode_entities($blob);
+    }
+}
index cbfacda..9b0b2a6 100644 (file)
@@ -28,7 +28,7 @@ sub _diff {
       diff_tree => $tree,
       diff      => $patch,
       # XXX Hack hack hack, see View::SyntaxHighlight
-      blobs     => [map $_->{diff}, @$patch],
+      diffs     => [map $_->{diff}, @$patch],
       %diff_args,
     );
 }
index 6182362..93dc06c 100644 (file)
@@ -2,61 +2,37 @@ package Gitalist::Model::ContentMangler;
 use Moose;
 use MooseX::Types::Moose qw/HashRef/;
 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-use Gitalist::ContentMangler::Resolver;
 use namespace::autoclean;
 
 extends 'Catalyst::Model';
 
-has resolver_class => (
-    isa => NonEmptySimpleStr,
+# XXX This could live as metadata somewhere or in the config or whatever..
+has transform_params => (
     is => 'ro',
-    required => 1,
-    default => 'Gitalist::ContentMangler::Resolver::Default',
-);
-
-has resolver_config => (
     isa => HashRef,
-    is => 'ro',
-    default => sub { {} },
+    default => sub { {
+        blob => [qw/blob filename/],
+        diff_fancy => [qw/diffs/],
+    } },
 );
 
-has _resolver => (
-    does => 'Gitalist::ContentMangler::Resolver',
-    handles => ['resolve'],
-    is => 'bare', lazy => 1,
-    default => sub {
-        my $self = shift;
-        my $class = $self->resolver_class;
-        Class::MOP::load_class($class);
-        return $class->new($self->resolver_config);
-    },
-);
-
-# FIXME This method is a gross hack.
-#
-# We need to work out what types of content mangles we have for various things based on hit type
-# file name and mime type, and perform the appropriate bits..
-
-# We need to support multiple languages, and we also want to be able to do HTMLizing (for e.g. Pod)
-
 sub process {
-  my ($self, $c) = @_;
-
-  # Find appropriate mangler based on filename,action,config
-  # Mangler should provide a transform e.g what part of the stash to mangle
-  # Then call the transform with the appropriate mangling
-
-  my($transformer, $config) = $self->resolve({
-    filename => $c->stash->{filename} || '',
-    config   => Gitalist->config->{'Model::ContentMangler'},
-    action   => $c->action->name,
-  });
-
-  return
-       unless $transformer;
-
-  Class::MOP::load_class($transformer);
-  $transformer->new($config)->transform($c, $config);
+    my ($self, $c) = @_;
+
+    my $config  = Gitalist->config->{'Model::ContentMangler'}; # XXX Yeah it's a bit ugly. Feh.
+    my $action  = $c->action->name;
+    my $mangler = $c->req->param('cm') || '';
+    my $transformer = $config->{$action}{$mangler || 'default'};
+
+    return unless $transformer;
+    Class::MOP::load_class($transformer);
+    
+    my $result = $transformer->new()->transform(
+        map { $_ => $c->stash->{$_} } @{ $self->transform_params->{$action} }
+    ) || {};
+
+    $c->stash->{mangled} = 1 if %$result;
+    $c->stash(%$result);
 }
 
 __PACKAGE__->meta->make_immutable;
index e710a44..6049480 100644 (file)
@@ -1 +1 @@
-[% IF syntax_css %]<link rel="stylesheet" type="text/css" href="[% syntax_css %]"/>[% END %]
+[% IF language %]<link rel="stylesheet" type="text/css" href="[% c.uri_for("/static/css/syntax/" _ language _ ".css") %]"/>[% END %]
index 5afc3ae..3702e37 100755 (executable)
@@ -6,7 +6,7 @@
    </div>
   [% END %]
 
-[% subinclude('/fragment/ref/blob', c.req.captures, c.req.args.to_path) %]
+[% subinclude('/fragment/ref/blob', c.req.captures, c.req.args.to_path, c.req.parameters) %]