Skip to content

Commit 1e61058

Browse files
committed
add helpers 'asUrlPath' and 'asUrlQuery'
1 parent fbfb1c1 commit 1e61058

6 files changed

Lines changed: 181 additions & 22 deletions

File tree

build.gradle

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ plugins {
55
id 'idea'
66
id 'maven-publish'
77
id "com.github.ethankhall.semantic-versioning" version "1.1.0"
8-
id "com.github.ben-manes.versions" version "0.13.0"
9-
id "com.jfrog.bintray" version "1.7.1"
10-
id "org.asciidoctor.convert" version "1.5.3"
11-
id 'org.ajoberstar.github-pages' version '1.6.0-rc.1'
12-
id "com.github.hierynomus.license" version "0.13.1"
13-
id "net.saliman.properties" version "1.4.5"
14-
id 'com.github.jk1.dependency-license-report' version '0.3.5'
8+
id "com.github.ben-manes.versions" version "0.17.0"
9+
id "com.jfrog.bintray" version "1.8.0"
10+
id "org.asciidoctor.convert" version "1.5.7"
11+
id 'org.ajoberstar.github-pages' version '1.7.2'
12+
id "com.github.hierynomus.license" version "0.14.0"
13+
id "net.saliman.properties" version "1.4.6"
14+
id 'com.github.jk1.dependency-license-report' version '0.4.1'
1515
}
1616

1717
project.version.with {
@@ -45,7 +45,7 @@ def pomConfig = {
4545
}
4646
}
4747

48-
ext.groovyVersion = '2.4.7'
48+
ext.groovyVersion = '2.4.13'
4949

5050

5151
tasks.withType(Javadoc) {
@@ -107,19 +107,19 @@ signArchives {
107107

108108
dependencies {
109109
compile "org.codehaus.groovy:groovy-all:$groovyVersion"
110-
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
110+
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
111111
compile 'com.github.jknack:handlebars:4.0.6'
112112

113113
provided 'com.google.code.findbugs:findbugs-annotations:3.0.1'
114114

115-
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.7'
116-
testCompile 'org.yaml:snakeyaml:1.17'
117-
testCompile('org.spockframework:spock-core:1.1-groovy-2.4-rc-2') {
115+
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
116+
testCompile 'org.yaml:snakeyaml:1.19'
117+
testCompile('org.spockframework:spock-core:1.1-groovy-2.4') {
118118
exclude module: 'groovy-all'
119119
}
120-
testCompile 'cglib:cglib-nodep:3.2.4'
121-
testCompile 'org.objenesis:objenesis:2.4'
122-
testCompile('com.athaydes:spock-reports:1.2.12') { transitive = false}
120+
testCompile 'cglib:cglib-nodep:3.2.5'
121+
testCompile 'org.objenesis:objenesis:2.6'
122+
testCompile('com.athaydes:spock-reports:1.4.0') { transitive = false}
123123

124124
}
125125

doc/helpers.adoc

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Team size: 3 developers
122122
== math
123123
Computes the result of an arithmetic operation.
124124

125-
*Syntax*: {{[purple]##math## _operand1_ _'operator'_ _operand2_ {startsb}[purple]##decimals##: _dec_ {startsb}[purple]##locale##: _loc_{endsb}{endsb}}}
125+
*Syntax*: {{[purple]##math## _operand1_ _'operator'_ _operand2_ {startsb}[purple]##decimals##=_dec_ {startsb}[purple]##locale##=_loc_{endsb}{endsb}}}
126126

127127
Supported operators: `+`, `-`, `\*`, `/`, `%`, `**`.
128128

@@ -170,7 +170,7 @@ interest: 37,50 EUR
170170
== compare
171171
Compares two operands using the specified relational operator.
172172

173-
*Syntax*: {{[purple]##compare## _operand1_ _'operator'_ _operand2_}}
173+
*Syntax*: {{[purple]##compare## _operand1_ _'operator'_ _operand2_ {startsb}[purple]##asString##=_strBool_{endsb}}}
174174

175175
Supported relational operators: `==`, `!=`, `<`, `\<=`, `>`, `>=`.
176176

@@ -199,6 +199,7 @@ Exceeded allowed penalty: false
199199
You won!
200200
----
201201

202+
If the operands are numeric you can enforce comparing them as strings by specifying `asString=true`.
202203

203204
== asBoolean
204205
Returns the boolean value of the operand.
@@ -323,7 +324,7 @@ Click here to download the logs.
323324
== asJavaId
324325
Converts a value to a valid Java identifier.
325326

326-
*Syntax*: {{[purple]##asJavaId## _value_ {startsb}[purple]##camelCase##: _ccBool_{endsb} {startsb}[purple]##underscore##: _usBool_{endsb}}}
327+
*Syntax*: {{[purple]##asJavaId## _value_ {startsb}[purple]##camelCase##=_ccBool_{endsb} {startsb}[purple]##underscore##=_usBool_{endsb}}}
327328

328329
You can control the format of the generated Java identifier by specifying the values of the boolean flags [purple]##camelCase## and [purple]##underscore##.
329330
The default values are: [purple]##camelCase## = true and [purple]##underscore## = false.
@@ -348,6 +349,59 @@ package: byte_as_an_octet
348349
----
349350

350351

352+
== asUrlPath
353+
Encodes a string as the path part of a URL.
354+
355+
*Syntax*: {{[purple]##asUrlPath## _value_ {startsb}[purple]##ascii##=_aBool_{endsb}}}
356+
357+
If the [purple]##ascii## flag is `true`, the string will be encoded so that it only contains characters in the US-ASCII charset.
358+
The default value of the [purple]##ascii## flag is `false`.
359+
360+
*Example:*
361+
362+
.YAML Model
363+
----
364+
name: Mötley Crüe
365+
----
366+
367+
.Template
368+
----
369+
Click <a href="http://videos.example.org/{{asUrlPath name}}.mp4">here</a> to download.
370+
371+
Click <a href="http://videos.example.org/{{asUrlPath name ascii=true}}.mp4">here</a> to download.
372+
----
373+
374+
.Result
375+
----
376+
Click <a href="http://videos.example.org/Mötley%20Crüe.mp4">here</a> to download.
377+
378+
Click <a href="http://videos.example.org/M%C3%B6tley%20Cr%C3%BCe.mp4">here</a> to download.
379+
----
380+
381+
382+
== asUrlQuery
383+
Encodes a string as the query part of a URL.
384+
385+
*Syntax*: {{[purple]##asUrlQuery## _value_}}
386+
387+
*Example:*
388+
389+
.YAML Model
390+
----
391+
url: http://www.example.org/news?id=101
392+
----
393+
394+
.Template
395+
----
396+
Click <a href="http://translate.example.org?url={{asUrlQuery url}}">here</a> to translate the page.
397+
----
398+
399+
.Result
400+
----
401+
Click <a href="http://translate.example.org?url=http%3A%2F%2Fwww.example.org%2Fnews%3Fid%3D101">here</a> to translate the page.
402+
----
403+
404+
351405
== javaComment
352406
Inserts the content of a file as a Java comment.
353407

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-bin.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

src/main/groovy/org/beryx/hbs/Helpers.groovy

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ import groovy.transform.stc.FromAbstractTypeMethods
2424
import groovy.util.logging.Slf4j
2525
import org.apache.commons.lang3.LocaleUtils
2626

27+
import java.nio.charset.StandardCharsets
28+
2729
@Slf4j
2830
enum Helpers implements Helper {
2931
DEF ("def", { varName, options ->
3032
Context ctx = options.context
31-
def val = (options.params.size() > 0) ? options.prm(0) : options.fn()
33+
def val = (options.params.length > 0) ? options.prm(0) : options.fn()
3234
varName = from(varName)
3335
ctx.combine(varName, val)
3436
options.buffer()
@@ -64,7 +66,6 @@ enum Helpers implements Helper {
6466
operand1 = from(operand1)
6567
def op = options.prm(0)
6668
def operand2 = options.prm(1)
67-
6869
boolean asString = options.hash("asString", false)
6970
if(!asString && isNumber(operand1) && isNumber(operand2)) {
7071
operand1 = operand1 as double
@@ -195,7 +196,29 @@ enum Helpers implements Helper {
195196
buffer.append(' */\n')
196197
}
197198
buffer
198-
})
199+
}),
200+
201+
AS_URL_PATH("asUrlPath", { path, options ->
202+
Options.Buffer buffer = options.buffer()
203+
path = from(path)
204+
if(path) {
205+
def uri = new URI(null, null, path, null, null)
206+
boolean ascii = options.hash("ascii", false)
207+
def encoded = ascii ? uri.toASCIIString() : uri.toString()
208+
buffer.append(encoded)
209+
}
210+
buffer
211+
}),
212+
213+
AS_URL_QUERY("asUrlQuery", { query, options ->
214+
Options.Buffer buffer = options.buffer()
215+
query = from(query)
216+
if(query) {
217+
def encoded = URLEncoder.encode(query, StandardCharsets.UTF_8.name())
218+
buffer.append(encoded)
219+
}
220+
buffer
221+
}),
199222

200223

201224
static {

src/test/groovy/org/beryx/hbs/DocExamplesSpec.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,46 @@ class DocExamplesSpec extends Specification implements TestUtil {
304304
}
305305

306306

307+
def "doc example: asUrlPath"() {
308+
given:
309+
def ctx = '''
310+
name: Mötley Crüe
311+
'''
312+
def template = '''
313+
Click <a href="http://videos.example.org/{{asUrlPath name}}.mp4">here</a> to download.
314+
Click <a href="http://videos.example.org/{{asUrlPath name ascii=true}}.mp4">here</a> to download.
315+
'''
316+
317+
when:
318+
def merged = merge(template, ctx)
319+
320+
then:
321+
merged == '''
322+
Click <a href="http://videos.example.org/Mötley%20Crüe.mp4">here</a> to download.
323+
Click <a href="http://videos.example.org/M%C3%B6tley%20Cr%C3%BCe.mp4">here</a> to download.
324+
'''.stripAll()
325+
}
326+
327+
328+
def "doc example: asUrlQuery"() {
329+
given:
330+
def ctx = '''
331+
url: http://www.example.org/news?id=101
332+
'''
333+
def template = '''
334+
Click <a href="http://translate.example.org?url={{asUrlQuery url}}">here</a> to translate the page.
335+
'''
336+
337+
when:
338+
def merged = merge(template, ctx)
339+
340+
then:
341+
merged == '''
342+
Click <a href="http://translate.example.org?url=http%3A%2F%2Fwww.example.org%2Fnews%3Fid%3D101">here</a> to translate the page.
343+
'''.stripAll()
344+
}
345+
346+
307347
def "README example: the fifteenth anniversary of a person born in #year was in a #res year"() {
308348
given:
309349
def ctx = "birthYear: $year"

src/test/groovy/org/beryx/hbs/HelpersSpec.groovy

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,46 @@ class HelpersSpec extends Specification implements TestUtil {
414414
'''.stripAll()
415415

416416
}
417+
418+
def "asUrlPath should convert'#path' to '#encoded'"() {
419+
given:
420+
def template = "{{asUrlPath $path}}"
421+
422+
when:
423+
def merged = merge(template, context)
424+
425+
then:
426+
merged == "$encoded"
427+
428+
where:
429+
path | encoded
430+
"''" | ''
431+
"' '" | '%20'
432+
"'/'" | '/'
433+
"'/abc/def'" | '/abc/def'
434+
"'a and b'" | 'a%20and%20b'
435+
"'göögle'" | 'göögle'
436+
"'göögle' ascii=true" | 'g%C3%B6%C3%B6gle'
437+
}
438+
439+
def "asUrlQuery should convert'#query' to '#encoded'"() {
440+
given:
441+
def template = "{{asUrlQuery $query}}"
442+
443+
when:
444+
def merged = merge(template, context)
445+
446+
then:
447+
merged == "$encoded"
448+
449+
where:
450+
query | encoded
451+
"''" | ''
452+
"' '" | '+'
453+
"'/'" | '%2F'
454+
"'key1=val1&key2=val2'" | 'key1%3Dval1%26key2%3Dval2'
455+
"'url=http://www.example.org/doc?name=guide&page=3#intro'" | 'url%3Dhttp%3A%2F%2Fwww.example.org%2Fdoc%3Fname%3Dguide%26page%3D3%23intro'
456+
"'göögle'" | 'g%C3%B6%C3%B6gle'
457+
}
458+
417459
}

0 commit comments

Comments
 (0)