--- /dev/null
+use strict;
+use warnings FATAL => 'all';
+use Test::More;
+
+{
+ eval "use HTML::Zoom; 1" ?
+ plan qw(no_plan) :
+ plan skip_all => "HTML::Zoom is not installed";
+}
+
+{
+ package BasicPage;
+ use HTML::Tags;
+
+ sub show_landing_html {
+ as_html(\&landing, (
+ title => "Welcome to the Demo Home",
+ site_version => 10,
+ new_user_link => 'create_user.html',
+ ));
+ }
+
+ sub show_landing_events {
+ as_events(\&landing, (
+ title => "Welcome to the Demo Home",
+ site_version => 10,
+ new_user_link => 'create_user.html',
+ ));
+ }
+
+ sub layout {
+ my (%data) = @_;
+ \'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
+ <html>,
+ <head>,
+ <!-- here is a comment -->,
+ <title>, ($data{title} || 'Hello World'), </title>,
+ </head>,
+ <body>,
+ @{$data{content}},
+ </body>,
+ </html>;
+ }
+
+ sub landing {
+ my (%data) = @_;
+ <p>, "Hi, I'm version: ", $data{site_version}, </p>,
+ <p>, "Here's some interesting things about me", </p>,
+ <img src="smilyface.png" alt="smiles" />,
+ <ul>,
+ <li>, <a href="/user">, "My Users", </li>,
+ <li>, <a href="/user/$data{new_user_link}">, "Create", "New User", </li>,
+ </ul>;
+ }
+
+ sub process_templates {
+ my ($templates, %data) = @_;
+ for my $template(@$templates) {
+ my @processed = $template->(%data);
+ $data{content} = \@processed;
+ }
+ return @{$data{content}};
+ }
+
+ sub as_html {
+ my ($template, %data) = @_;
+ my @content = process_templates([$template, \&layout], %data);
+ return join '', HTML::Tags::to_html_string(@content);
+ }
+
+ sub as_events {
+ my ($template, %data) = @_;
+ my @content = process_templates([$template, \&layout], %data);
+ return [_convert_to_events(@content)];
+ }
+
+ sub _convert_to_events {
+ map {
+ my $raw = ref $_ ? $$_ : $_;
+ my @info = ($raw =~m{
+ (
+ (?:[^<]*) < (?:
+ ( / )? ( [^/!<>\s"'=]+ )
+ ( (?:"[^"]*"|'[^']*'|[^"'<>])+? )?
+ |
+ (!-- .*? -- | ![^\-] .*? )
+ ) (\s*/\s*)? >
+ )
+ ([^<]*)
+ }x);
+
+ my ($whole, $is_close, $tag_name, $attrs, $comment_or_directive,
+ $in_place_close) = @info;
+
+ if($comment_or_directive) {
+ +{ type => 'SPECIAL', raw => $raw };
+ } elsif(!scalar(@info)) {
+ +{ type => 'TEXT', raw => $raw };
+ } else {
+ if($is_close) {
+ $tag_name =~ tr/A-Z/a-z/;
+ +{ type => 'CLOSE', name => $tag_name, raw => $raw};
+ } else {
+ $attrs = '' if !defined($attrs) or $attrs =~ /^ +$/;
+ +{
+ type => 'OPEN',
+ name => $tag_name,
+ is_in_place_close => $in_place_close,
+ HTML::Zoom::Parser::BuiltIn::_hacky_attribute_parser($attrs),
+ raw_attrs => $attrs||'',
+ raw => $whole,
+ }, $in_place_close ?
+ +{
+ type => 'CLOSE',
+ name => $tag_name,
+ raw => '',
+ is_in_place_close => 1,
+ } :
+ +();
+ }
+ }
+ } @_;
+ }
+}
+
+ok my $html = BasicPage->show_landing_html;
+ok my $zoom = HTML::Zoom->from_html($html);
+ok my $events = BasicPage->show_landing_events;
+
+use Data::Dump 'dump';
+warn dump $html;
+warn dump $zoom->to_events;
+warn dump $events;
+