/[Frey]/trunk/lib/Frey/Web.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/lib/Frey/Web.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 446 - (show annotations)
Wed Nov 19 03:11:11 2008 UTC (15 years, 5 months ago) by dpavlin
File size: 4451 byte(s)
support newlines in head html content
1 package Frey::Web;
2 use Moose::Role;
3
4 use Frey::Types;
5
6 use Continuity::Widget::DomNode;
7 use Data::Dump qw/dump/;
8 use Carp qw/confess/;
9 use File::Slurp;
10
11 use Frey::Bookmarklet;
12 use Frey::ClassBrowser;
13
14 has 'head' => (
15 is => 'rw',
16 isa => 'ArrayRef[Str]',
17 default => sub { [ 'static/frey.css' ] },
18 );
19
20 has 'status' => (
21 is => 'rw',
22 isa => 'ArrayRef[HashRef[Str]]',
23 lazy => 1,
24 default => sub { [
25 { 'Bookmarklets' => Frey::Bookmarklet->new->markup },
26 { 'ClassBrowser' => Frey::ClassBrowser->new( usage_on_top => 0 )->markup },
27 ] },
28 );
29
30 has 'request_url' => (
31 is => 'rw',
32 isa => 'Uri', coerce => 1,
33 default => '/',
34 );
35
36 has 'title' => (
37 is => 'rw',
38 isa => 'Str',
39 lazy => 1,
40 default => sub {
41 my ($self) = @_;
42 ref($self);
43 },
44 );
45
46 =head2 inline_smaller_than
47
48 Inline JavaScript and CSS smaller than this size into page reducing
49 round-trips to server.
50
51 =cut
52
53 has 'inline_smaller_than' => (
54 is => 'rw',
55 isa => 'Int',
56 default => 10240,
57 );
58
59 sub dom2html {
60 # warn "## dom2html ",dump( @_ );
61 return Continuity::Widget::DomNode->create( @_ )->to_string;
62 }
63
64 sub _inline_path {
65 my ( $self, $path ) = @_;
66 -s $path < $self->inline_smaller_than;
67 }
68
69 sub _head_html {
70 my $self = shift;
71 my $out = '';
72 foreach my $path ( @{ $self->head } ) {
73 $path =~ s!^/!!;
74 if ( $path =~ m/\.js$/ ) {
75 $out .= $self->_inline_path( $path ) ?
76 qq|<!-- $path --><script type="text/javascript">\n| . read_file($path) . qq|\n</script>| :
77 qq|<script type="text/javascript" src="/$path"></script>|;
78 } elsif ( $path =~ m/\.css$/ ) {
79 $out .= $self->_inline_path( $path ) ?
80 qq|<!-- $path --><style type="text/css">\n| . read_file( $path ) . qq|\n</style>| :
81 qq|<link type="text/css" rel="stylesheet" href="/$path" media="screen">|;
82 } elsif ( $path =~ m{<.+>}s ) {
83 $out .= $path;
84 } else {
85 confess "don't know how to render $path";
86 }
87 $out .= "\n";
88 }
89 return $out;
90 }
91
92 =head2 add_head
93
94 $o->add_head( 'path/to/external.js' );
95
96 my $size = $o->add_head( 'path/to/external.css' );
97
98 $o->add_head( '<!-- html content -->' );
99
100 =cut
101
102 sub add_head {
103 my ( $self, $path ) = @_;
104 return if ! defined $path || $path eq '';
105 $path =~ s!^/!!;
106
107 if ( $path =~ m{<.*>}s ) {
108 push @{ $self->head }, $path;
109 } elsif ( -e $path ) {
110 if ( $path =~ m/\.(?:js|css)$/ ) {
111 push @{ $self->head }, $path;
112 } else {
113 confess "can't add_head( $path ) it's not js or css";
114 }
115 return -s $path;
116 } else {
117 confess "can't find $path: $!";
118 }
119
120 }
121
122 our $reload_counter = 0;
123
124
125 =head2 page
126
127 $self->page(
128 title => 'page title',
129 head => '<!-- optional head markup -->',
130 body => '<b>Page Body</b>',
131 );
132
133 =cut
134
135 sub page {
136 my $self = shift;
137 my $a = {@_};
138
139 $reload_counter++;
140
141 my $status_line = '';
142 foreach my $part ( @{ $self->status } ) {
143 if ( ref($part) ne 'HASH' ) {
144 warn "part not hash ",dump( $part ) ;
145 #$self->status( $part );
146 next;
147 }
148 foreach my $name ( keys %$part ) {
149 my $content = $part->{$name};
150 if ( ref($content) ) {
151 $content = '<code>' . dump($content) . '</code>';
152 my $l = length($content);
153 $content = qq|<span>$l bytes</span>| if $l > 1024;
154 } else {
155 $content = qq|<span>$content</span>|;
156 }
157 warn "### part [$name] = ", length( $content ), " bytes" if $self->debug;
158 $status_line .= qq|<span class="frey-popup">$name $content</span>\n|;
159 }
160 }
161
162 my $url = $self->request_url;
163 $url =~ s{\?reload=\d+}{};
164
165 my $html = join("\n",
166 qq|<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html><head>|,
167 $self->_head_html,
168 '<title>' . ( $self->title || $a->{title} || ref($self) ) . '</title>',
169 '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">',
170 ( $a->{head} || '' ),
171 '</head><body>',
172 ( $a->{body} || $self->markup || '<!-- no body -->' ),
173 qq|
174 <div class="frey-status-line">
175 <a href="/">Frey</a> $Frey::VERSION
176 <a href="?reload=$reload_counter"><code>$url</code></a>
177 $status_line
178 </div>
179 </body></html>
180 |,
181 );
182
183 warn "## >>> page ",length($html), " bytes\n" if $self->debug;
184
185 return $html;
186 }
187
188 sub error {
189 my $self = shift;
190 my $error = join(" ", @_);
191 my ($package, $filename, $line) = caller;
192 $error .= " at $filename line $line" if $error !~ m{ at };
193 warn "WARN: $error\n";
194 $error =~ s{at\s+(\S+)\s+line\s+(\d+)}{at <a target="editor" href="/editor+$1+$2">$1</a> line $2}gsm;
195 $error =~ s{(via package ")([\w:]+)(")}{$1<a target="editor" href="/editor+$2+1">$2</a>$3}gsm;
196 return qq|<pre class="frey-error">$error</pre>|;
197 }
198
199 1;

  ViewVC Help
Powered by ViewVC 1.1.26