minimal sdl.cgi script plus deps
[sdlgit/SDL-Site.git] / code / HTML / Zoom / ActionBuilder.pm
CommitLineData
9d159224 1package HTML::Zoom::ActionBuilder;
2
3use strict;
4use warnings FATAL => 'all';
5
6use HTML::Zoom::Parser::BuiltIn;
7use HTML::Zoom::EventFilter;
8use Storable ();
9use Carp qw(confess);
10
11sub build {
12 my ($tb, $name, @args) = @_;
13 confess "Don't know how to build ${name} in ${tb}"
14 unless $tb->can("build_${name}");
15
16 return $tb->${\"build_${name}"}(@args);
17}
18
19sub build_add_attribute {
20 my ($tb, $name, $value) = @_;
21 sub {
22 my ($self, $evt) = @_;
23 delete @{$evt}{qw(raw raw_attrs)};
24 if (defined $evt->{attrs}{$name}) {
25 $evt->{attrs}{$name} .= ' '.$value;
26 } else {
27 $evt->{attrs}{$name} = $value;
28 }
29 };
30}
31
32sub build_set_attribute {
33 my ($tb, $name, $value) = @_;
34 sub {
35 my ($self, $evt) = @_;
36 delete @{$evt}{qw(raw raw_attrs)};
37 $evt->{attrs}{$name} = $value;
38 };
39}
40
41sub build_add_class { shift->build_add_attribute('class' => @_) }
42sub build_set_class { shift->build_set_attribute('class' => @_) }
43
44sub build_replace_content {
45 my ($tb, $text) = @_;
46 my $raw = HTML::Zoom::Parser::BuiltIn::_simple_escape($text);
47 $tb->build_replace_content_raw($raw);
48}
49
50sub build_replace_content_raw {
51 my ($tb, $raw) = @_;
52 sub {
53 my ($self, $evt) = @_;
54 my $in_place_close = $evt->{is_in_place_close};
55 if ($in_place_close) {
56 delete $evt->{raw};
57 $evt->{is_in_place_close} = 0;
58 }
59 $self->until_close_do_last(
60 undef,
61 sub {
62 delete $_[1]->{raw} if $in_place_close;
63 $_[0]->next({ type => 'TEXT', raw => $raw })
64 }
65 )
66 };
67}
68
69sub build_repeat {
70 my ($tb, $args) = @_;
71 my $data = $args->{data};
72 my $do_repeat = sub {
73 my ($self, $to_repeat) = @_;
74 my $stole_last;
75 if ($to_repeat->[-1]->{type} eq 'TEXT') {
76 if ($to_repeat->[-1]->{raw} =~ s/(\s+)$//) {
77 $stole_last = $1;
78 }
79 }
80 foreach my $d (@$data) {
81 my @pairs = map {
82 HTML::Zoom::EventFilter->build_selector_pair($_, $d->{$_})
83 } sort keys %$d;
84 my $sel = HTML::Zoom::EventFilter->selector_handler(\@pairs);
85 $sel->set_next($self->get_next);
86 $sel->call($_) for @$to_repeat;
87 }
88 if (defined $stole_last) {
89 $self->next({ type => 'TEXT', raw => $stole_last });
90 }
91 };
92 sub {
93 my ($self, $evt) = @_;
94 return if $evt->{is_in_place_close}; # no content to repeat
95 my @repeat;
96 $self->until_close_do_last(
97 sub { push(@repeat, $_[1]) },
98 sub { $_[0]->$do_repeat(\@repeat) },
99 );
100 };
101}
102
1031;