Skip to content

Commit

Permalink
Implemented XML text escaping, and 'structure' keyword.
Browse files Browse the repository at this point in the history
  • Loading branch information
supernovus committed Oct 7, 2010
1 parent 76ae95b commit ed24b24
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 27 deletions.
8 changes: 5 additions & 3 deletions README
Expand Up @@ -33,9 +33,11 @@ Note: Flower is not yet complete, and is still missing a lot of functionality.
There is no equivelant to the Petal::Parser::HTB, and no plans for one. There is no equivelant to the Petal::Parser::HTB, and no plans for one.
Use well-formed XML, it's just better. Use well-formed XML, it's just better.
* Flower supports petal:block elements, as per the PHPTAL project. * Flower supports petal:block elements, as per the PHPTAL project.
* There is no 'structure' keyword. Strings are turned into Exemel::Text * While you can use the 'structure' keyword, it's not really needed.
objects. If you really want to use XML structures in a replace or content If you want an unescaped XML structure for a replacement, send an
statement, return an Exemel::Element. Exemel object (any class other than Document) and it will be added to
the XML tree. Send an array of Exemel objects, and they will additionally
be parsed for TAL statements.
* Nested repeats cannot use the same attribute name, it will get clobbered. * Nested repeats cannot use the same attribute name, it will get clobbered.
* The built-in repeat object is implemented as per the Zope/PHPTAL, not * The built-in repeat object is implemented as per the Zope/PHPTAL, not
the Petal version. Note: it does not support the 'letter' or 'Letter' the Petal version. Note: it does not support the 'letter' or 'Letter'
Expand Down
7 changes: 3 additions & 4 deletions docs/TODO.txt
@@ -1,13 +1,12 @@
Short Term (October 2010) Short Term (October 2010, Version 1.0 stable)
- Implement XML escaping on text nodes.
- Finish implementing Flower::Utils, as per the README. - Finish implementing Flower::Utils, as per the README.


Medium Term (December 2010) Medium Term (December 2010, Version 1.1 stable)
- Implement METAL support. - Implement METAL support.
- Implement query caching. - Implement query caching.
- Implement multiple paths (/test/path1 | /test/path2) support. - Implement multiple paths (/test/path1 | /test/path2) support.


Long Term (2011) Long Term (2011, Undetermined versions)
- Implement I18N support. - Implement I18N support.
- Implement on-error. - Implement on-error.


32 changes: 20 additions & 12 deletions lib/Flower.pm
Expand Up @@ -253,8 +253,8 @@ method !parse-omit-tag ($xml is rw, $tag) {
} }
} }


## Query data, this ## Query data.
method query ($query, :$noxml, :$forcexml, :$bool) { method query ($query is copy, :$noxml, :$forcexml, :$bool, :$noescape is copy) {
if $query eq '' { if $query eq '' {
if ($bool) { return True; } if ($bool) { return True; }
else { return ''; } else { return ''; }
Expand All @@ -263,26 +263,34 @@ method query ($query, :$noxml, :$forcexml, :$bool) {
if ($bool) { return False; } if ($bool) { return False; }
else { return ''; } else { return ''; }
} }
if $query ~~ /^\'(.*?)\'$/ { if $query ~~ /^ structure \s+ / {
if ($forcexml) { $query.=subst(/^ structure \s+ /, '');
return Exemel::Text.new(:text(~$0)); $noescape = True;
} }
return ~$0; if $query ~~ /^\'(.*?)\'$/ {
return self.process-query(~$0, :$forcexml, :$noxml, :$noescape);
} # quoted string, no interpolation. } # quoted string, no interpolation.
if $query ~~ /^<.ident>+\:/ { if $query ~~ /^<.ident>+\:/ {
my ($handler, $subquery) = $query.split(/\:\s*/, 2); my ($handler, $subquery) = $query.split(/\:\s*/, 2);
if %!modifiers.exists($handler) { if %!modifiers.exists($handler) {
my $data = %!modifiers{$handler}(self, $subquery, :$noxml, :$forcexml, :$bool); ## Modifiers are responsible for subqueries, and calls to process-query.
return self!query-xml($data, :$forcexml, :$noxml); return %!modifiers{$handler}(self, $subquery, :$noxml, :$forcexml, :$bool, :$noescape);
} }
} }
my @paths = $query.split('/'); my @paths = $query.split('/');
my $data = self!lookup(@paths, %.data); my $data = self!lookup(@paths, %.data);
return self!query-xml($data, :$forcexml, :$noxml); return self.process-query($data, :$forcexml, :$noxml, :$noescape);
} }


## Enforce forcexml and noxml rules for query(). ## Enforce processing rules for query().
method !query-xml($data, :$forcexml, :$noxml) { method process-query($data is copy, :$forcexml, :$noxml, :$noescape, :$bool) {
## First off, let's escape text, unless noescape is set.
if (!defined $noescape && $data ~~ Str) {
$data.=subst('&', '&amp;', :g);
$data.=subst('<', '&lt;', :g);
$data.=subst('>', '&gt;', :g);
$data.=subst('"', '&quot;', :g);
}
## Default rule for forcexml converts non-XML objects into Exemel::Text. ## Default rule for forcexml converts non-XML objects into Exemel::Text.
if ($forcexml && $data !~~ Exemel) { if ($forcexml && $data !~~ Exemel) {
return Exemel::Text.new(:text(~$data)); return Exemel::Text.new(:text(~$data));
Expand Down
2 changes: 1 addition & 1 deletion lib/Flower/DefaultModifiers.pm
Expand Up @@ -25,6 +25,6 @@ our sub string ($parent, $query, *%opts) {
my $string = $query; my $string = $query;
# $string ~~ s:g/ '${' (.*?) '}' / $parent.query($0) /; # NYI in rakudo. # $string ~~ s:g/ '${' (.*?) '}' / $parent.query($0) /; # NYI in rakudo.
$string.=subst(:g, rx/'${' (.*?) '}'/, -> $/ { $parent.query($0) }); $string.=subst(:g, rx/'${' (.*?) '}'/, -> $/ { $parent.query($0) });
return $string; return $parent.process-query($string, |%opts);
} }


10 changes: 6 additions & 4 deletions lib/Flower/Utils/Debug.pm
Expand Up @@ -14,12 +14,14 @@ our sub all() {
} }


our sub dump_perl($parent, $query, *%opts) { our sub dump_perl($parent, $query, *%opts) {
my $result = $parent.query($query); my $result = $parent.query($query, :noescape);
return $result.perl; %opts.delete('noescape');
return $parent.process-query($result.perl, :noescape, |%opts);
} }


our sub what_perl($parent, $query, *%opts) { our sub what_perl($parent, $query, *%opts) {
my $result = $parent.query($query); my $result = $parent.query($query, :noescape);
return $result.WHAT.perl; %opts.delete('noescape');
return $parent.process-query($result.WHAT.perl, :noescape, |%opts);
} }


2 changes: 1 addition & 1 deletion lib/Flower/Utils/Perl.pm
Expand Up @@ -17,6 +17,6 @@ our sub perl_query ($parent, $query, *%opts) {
my $perl = $query.subst(/^(<&keyname>)/, -> $/ { '$parent.data<'~$0~'>' }); my $perl = $query.subst(/^(<&keyname>)/, -> $/ { '$parent.data<'~$0~'>' });
$perl.=subst('.eval','.chomp', :g); ## Kill any attempts to eval. $perl.=subst('.eval','.chomp', :g); ## Kill any attempts to eval.
my $result = eval($perl); my $result = eval($perl);
return $result; return $parent.process-query($result, |%opts);
} }


4 changes: 2 additions & 2 deletions lib/Flower/Utils/Text.pm
Expand Up @@ -14,11 +14,11 @@ our sub all() {


our sub upper ($parent, $query, *%opts) { our sub upper ($parent, $query, *%opts) {
my $result = $parent.query($query); my $result = $parent.query($query);
return $result.uc; return $parent.process-query($result.uc, |%opts);
} }


our sub lower ($parent, $query, *%opts) { our sub lower ($parent, $query, *%opts) {
my $result = $parent.query($query); my $result = $parent.query($query);
return $result.lc; return $parent.process-query($result.lc, |%opts);
} }


16 changes: 16 additions & 0 deletions t/07-escape.t
@@ -0,0 +1,16 @@
#!/usr/bin/env perl6

BEGIN { @*INC.unshift: './lib' }

use Test;
use Flower;

plan 1;

my $xml = '<?xml version="1.0"?>';

my $template = '<test><escaped tal:content="string"/><unescaped tal:content="structure string"/></test>';
my $flower = Flower.new(:template($template));

is $flower.parse(string=>'hello to you & your friend, "how are you?"'), $xml~'<test><escaped>hello to you &amp; your friend, &quot;how are you?&quot;</escaped><unescaped>hello to you & your friend, "how are you?"</unescaped></test>', 'XML escapes and structure keyword';

0 comments on commit ed24b24

Please sign in to comment.