wrap and replace for templating
Matt S Trout [Tue, 31 Jul 2012 20:49:45 +0000 (20:49 +0000)]
lib/App/SCS/Plugin/Core/PagePlugin/Template.pm

index 6bac9fe..0587b80 100644 (file)
@@ -1,5 +1,6 @@
 package App::SCS::Plugin::Core::PagePlugin::Template;
 
+use List::Util qw(reduce);
 use Moo;
 
 with 'App::SCS::Role::PagePlugin';
@@ -14,14 +15,46 @@ sub filter_html_zoom {
     or die "No such template ${\$self->name}";
   my $template_zoom = HTML::Zoom->from_html($template_page->html);
   my @ev;
-  $template_zoom->select('*[data-replace]')
+  my %wrap;
+  $template_zoom->select('*[data-wrap]')
                 ->collect({ into => \@ev, passthrough => 1 })
                 ->then
-                ->replace(sub {
-                    my $sel = $ev[0]->{attrs}{'data-replace'};
-                    $zoom->collect($sel, { into => \my @replace })->run;
-                    HTML::Zoom::ArrayStream->new({ array => \@replace })
-                  });
+                ->collect({ filter => sub {
+                    my %attrs = %{$ev[0]->{attrs}};
+                    my $select = delete $attrs{'data-wrap'};
+                    $ev[0] = {
+                      %{$ev[0]},
+                      raw => undef, raw_attrs => undef,
+                      attrs => \%attrs,
+                      attr_names => [
+                        grep $_ ne 'data-wrap', @{$ev[0]->{attr_names}}
+                      ]
+                    };
+                    $wrap{$select} = \@ev;
+                    return $_[0];
+                  } })
+                ->run;
+  reduce {
+    my @orig;
+    my $sel = $b;
+    $a->select($sel)
+      ->collect({ into => \@orig, passthrough => 1 })
+      ->then
+      ->replace(sub {
+          my $orig = HTML::Zoom->from_events(\@orig);
+          my $wrap = HTML::Zoom->from_events(\@{$wrap{$sel}});
+          my @to_replace;
+          $wrap->select('*[data-replace]')
+               ->collect({ into => \@to_replace, passthrough => 1 })
+               ->then
+               ->replace(sub {
+                   my $sel = $to_replace[0]->{attrs}{'data-replace'};
+                   $orig->collect($sel, { into => \my @replace_with })->run;
+                   HTML::Zoom::ArrayStream->new({ array => \@replace_with })
+                 })
+               ->to_stream;
+        });
+  } $zoom, keys %wrap;
 }
 
 1;