From 2ba0daa5e3831f105dc8400e25c792b6001e9826 Mon Sep 17 00:00:00 2001 From: George Clark Date: Sat, 11 Mar 2017 10:33:42 -0500 Subject: [PATCH] Item14339: Implement "fragment" support in SCRIPTURL tags This adds the # as a legal character for macro parameter names. It extends the SCRIPTURL and SCRIPTURLPATH macros to accept # as a valid parameter and adds the fragment to the end of the generated URL --- UnitTestContrib/test/unit/AttrsTests.pm | 46 +++++++++++++++++++++++ UnitTestContrib/test/unit/Fn_SCRIPTURL.pm | 18 +++++++++ core/data/System/Macros.txt | 5 ++- core/lib/Foswiki/Attrs.pm | 12 +++--- 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/UnitTestContrib/test/unit/AttrsTests.pm b/UnitTestContrib/test/unit/AttrsTests.pm index 43ea50ca5c..80682c8e89 100644 --- a/UnitTestContrib/test/unit/AttrsTests.pm +++ b/UnitTestContrib/test/unit/AttrsTests.pm @@ -60,6 +60,36 @@ sub test_default { $this->assert( $attrs->isEmpty() ); } +sub test_anchor_friendly { + my $this = shift; + + my $attrs = + Foswiki::Attrs->new( + "var1=val1 var2= val2, var3 = 3 var4 =val4 #=blah a#a=1#1", 1 ); + $this->assert_str_equals( "val1", $attrs->remove("var1") ); + $this->assert_str_equals( "val2", $attrs->remove("var2") ); + $this->assert_str_equals( "3", $attrs->remove("var3") ); + $this->assert_str_equals( "val4", $attrs->remove("var4") ); + $this->assert_str_equals( "blah", $attrs->remove("#") ); + $this->assert_str_equals( "1#1", $attrs->remove("a#a") ); + $this->assert( $attrs->isEmpty() ); +} + +sub test_anchor_unfriendly { + my $this = shift; + + my $attrs = + Foswiki::Attrs->new( + 'var1="val1" var2=" val2" var3="3" var4="val4" #="blah" a#a="1#1"', 0 ); + $this->assert_str_equals( "val1", $attrs->remove("var1") ); + $this->assert_str_equals( " val2", $attrs->remove("var2") ); + $this->assert_str_equals( "3", $attrs->remove("var3") ); + $this->assert_str_equals( "val4", $attrs->remove("var4") ); + $this->assert_str_equals( "blah", $attrs->remove("#") ); + $this->assert_str_equals( "1#1", $attrs->remove("a#a") ); + $this->assert( $attrs->isEmpty() ); +} + sub test_unquoted { my $this = shift; @@ -123,6 +153,22 @@ sub test_mixedQuotes { $this->assert( $attrs->isEmpty() ); } +sub test_mixedAlpha { + my $this = shift; + + my $attrs = + Foswiki::Attrs->new( "aa = AA AA = aa Aa ='\"', bB=\"'\" \"'\"", 1 ); + $this->assert_str_equals( "\"", $attrs->remove("Aa") ); + $this->assert_str_equals( "'", $attrs->remove("bB") ); + $this->assert_str_equals( "aa", $attrs->remove("AA") ); + $this->assert_str_equals( "AA", $attrs->remove("aa") ); + $this->assert_str_equals( "'", $attrs->remove("_DEFAULT") ); + $this->assert( $attrs->isEmpty() ); + $attrs = Foswiki::Attrs->new( "'\"'", 1 ); + $this->assert_str_equals( "\"", $attrs->remove("_DEFAULT") ); + $this->assert( $attrs->isEmpty() ); +} + sub test_toString { my $this = shift; diff --git a/UnitTestContrib/test/unit/Fn_SCRIPTURL.pm b/UnitTestContrib/test/unit/Fn_SCRIPTURL.pm index 71140c5433..d07c5c6d39 100644 --- a/UnitTestContrib/test/unit/Fn_SCRIPTURL.pm +++ b/UnitTestContrib/test/unit/Fn_SCRIPTURL.pm @@ -71,6 +71,24 @@ sub test_SCRIPTURL { $result = $this->{test_topicObject}->expandMacros("%SCRIPTURLPATH{snarf}%"); $this->assert_str_equals( "sausages", $result ); + + # anchor parameter # is added as a fragment. + $result = + $this->{test_topicObject}->expandMacros( + "%SCRIPTURLPATH{\"view\" topic=\"Main.WebHome\" #=\"frag\"}%"); + $this->assert_str_equals( + $Foswiki::cfg{ScriptUrlPath} . '/view.dot/Main/WebHome#frag', $result ); + + # Use of # anywhere but the anchor tag is encoded. + $result = + $this->{test_topicObject}->expandMacros( +"%SCRIPTURLPATH{\"view\" topic=\"Main.WebHome\" #=\"frag\" A#A=\"another\"}%" + ); + $this->assert_str_equals( + $Foswiki::cfg{ScriptUrlPath} + . '/view.dot/Main/WebHome?A%23A=another#frag', + $result + ); } 1; diff --git a/core/data/System/Macros.txt b/core/data/System/Macros.txt index f041eb2419..45c343c7ff 100644 --- a/core/data/System/Macros.txt +++ b/core/data/System/Macros.txt @@ -1,4 +1,4 @@ -%META:TOPICINFO{author="ProjectContributor" date="1452350387" format="1.1" version="1"}% +%META:TOPICINFO{author="ProjectContributor" date="1489246418" format="1.1" version="1"}% %META:TOPICPARENT{name="UserDocumentationCategory"}% %STARTINCLUDE% ---+ Macros @@ -18,6 +18,9 @@ Macros are text strings in one of three basic forms: }% +Parameter names may be upper or lower case, and may consist of the ascii alphas, numbers, and the symbol #, Other characters and Unicode extended +alpha characters are not valid. + The third form is a new feature in Foswiki 2.1 to significantly improve readability with complex macros, see [[#Readable_Macros][Readable Macros]] for details. These usually expand into content when a topic is rendered for viewing. There are two types of macros: diff --git a/core/lib/Foswiki/Attrs.pm b/core/lib/Foswiki/Attrs.pm index 23219c6df1..67bb7a528a 100644 --- a/core/lib/Foswiki/Attrs.pm +++ b/core/lib/Foswiki/Attrs.pm @@ -148,7 +148,7 @@ sub _unfriendly { my $first = 1; if ( $string =~ -s/^\s*\"(.*?)\"\s*(?=([a-z0-9_]+\s*(?:$nameOp)|[a-z0-9_]*\s*(?:$nonmOp))\s*\"|$)//is +s/^\s*\"(.*?)\"\s*(?=([#a-z0-9_]+\s*(?:$nameOp)|[#a-z0-9_]*\s*(?:$nonmOp))\s*\"|$)//is ) { $this->{_DEFAULT} = $1; @@ -157,7 +157,7 @@ s/^\s*\"(.*?)\"\s*(?=([a-z0-9_]+\s*(?:$nameOp)|[a-z0-9_]*\s*(?:$nonmOp))\s*\"|$) while ( $string =~ m/\S/s ) { # name $op "value" pairs - if ( $string =~ s/^\s*([a-z0-9_]+)\s*($nameOp)\s*\"(.*?)\"//is ) { + if ( $string =~ s/^\s*([#a-z0-9_]+)\s*($nameOp)\s*\"(.*?)\"//is ) { $key = $1; $Ops{$2}[0]( \$this->{$key}, $3 ); $first = 0; @@ -195,7 +195,7 @@ sub _friendly { while ( $string =~ m/\S/s ) { # name $op "value" pairs - if ( $string =~ s/^[\s,]*([a-z0-9_]+)\s*($nameOp)\s*\"(.*?)\"//is ) { + if ( $string =~ s/^[\s,]*([#a-z0-9_]+)\s*($nameOp)\s*\"(.*?)\"//is ) { $key = $1; $Ops{$2}[0]( \$this->{$key}, $3 ); } @@ -209,14 +209,14 @@ sub _friendly { } # name $op 'value' pairs - elsif ( $string =~ s/^[\s,]*([a-z0-9_]+)\s*($nameOp)\s*'(.*?)'//is ) { + elsif ( $string =~ s/^[\s,]*([#a-z0-9_]+)\s*($nameOp)\s*'(.*?)'//is ) { $key = $1; $Ops{$2}[0]( \$this->{$key}, $3 ); } # name $op value pairs - elsif ( - $string =~ s/^[\s,]*([a-z0-9_]+)\s*($nameOp)\s*([^\s,\}\'\"]*)//is ) + elsif ( $string =~ + s/^[\s,]*([#a-z0-9_]+)\s*($nameOp)\s*([^\s,\}\'\"]*)//is ) { $key = $1; $Ops{$2}[0]( \$this->{$key}, $3 );