mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
Support typed bool, int and float in shortcode params
This means that you now can do: {{< vidur 9KvBeKu false true 32 3.14 >}} And the boolean and numeric values will be converted to `bool`, `int` and `float64`. If you want these to be strings, they must be quoted: {{< vidur 9KvBeKu "false" "true" "32" "3.14" >}} Fixes #6371
This commit is contained in:
parent
e073f4efb1
commit
329e88db1f
12 changed files with 202 additions and 53 deletions
|
@ -151,14 +151,7 @@ func (scp *ShortcodeWithPage) Get(key interface{}) interface{} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch x.Kind() {
|
return x.Interface()
|
||||||
case reflect.String:
|
|
||||||
return x.String()
|
|
||||||
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
|
|
||||||
return x.Int()
|
|
||||||
default:
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,17 +212,17 @@ func (sc shortcode) String() string {
|
||||||
// for testing (mostly), so any change here will break tests!
|
// for testing (mostly), so any change here will break tests!
|
||||||
var params interface{}
|
var params interface{}
|
||||||
switch v := sc.params.(type) {
|
switch v := sc.params.(type) {
|
||||||
case map[string]string:
|
case map[string]interface{}:
|
||||||
// sort the keys so test assertions won't fail
|
// sort the keys so test assertions won't fail
|
||||||
var keys []string
|
var keys []string
|
||||||
for k := range v {
|
for k := range v {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
var tmp = make([]string, len(keys))
|
var tmp = make(map[string]interface{})
|
||||||
|
|
||||||
for i, k := range keys {
|
for _, k := range keys {
|
||||||
tmp[i] = k + ":" + v[k]
|
tmp[k] = v[k]
|
||||||
}
|
}
|
||||||
params = tmp
|
params = tmp
|
||||||
|
|
||||||
|
@ -539,12 +532,12 @@ Loop:
|
||||||
} else if pt.Peek().IsShortcodeParamVal() {
|
} else if pt.Peek().IsShortcodeParamVal() {
|
||||||
// named params
|
// named params
|
||||||
if sc.params == nil {
|
if sc.params == nil {
|
||||||
params := make(map[string]string)
|
params := make(map[string]interface{})
|
||||||
params[currItem.ValStr()] = pt.Next().ValStr()
|
params[currItem.ValStr()] = pt.Next().ValTyped()
|
||||||
sc.params = params
|
sc.params = params
|
||||||
} else {
|
} else {
|
||||||
if params, ok := sc.params.(map[string]string); ok {
|
if params, ok := sc.params.(map[string]interface{}); ok {
|
||||||
params[currItem.ValStr()] = pt.Next().ValStr()
|
params[currItem.ValStr()] = pt.Next().ValTyped()
|
||||||
} else {
|
} else {
|
||||||
return sc, errShortCodeIllegalState
|
return sc, errShortCodeIllegalState
|
||||||
}
|
}
|
||||||
|
@ -553,12 +546,12 @@ Loop:
|
||||||
} else {
|
} else {
|
||||||
// positional params
|
// positional params
|
||||||
if sc.params == nil {
|
if sc.params == nil {
|
||||||
var params []string
|
var params []interface{}
|
||||||
params = append(params, currItem.ValStr())
|
params = append(params, currItem.ValTyped())
|
||||||
sc.params = params
|
sc.params = params
|
||||||
} else {
|
} else {
|
||||||
if params, ok := sc.params.([]string); ok {
|
if params, ok := sc.params.([]interface{}); ok {
|
||||||
params = append(params, currItem.ValStr())
|
params = append(params, currItem.ValTyped())
|
||||||
sc.params = params
|
sc.params = params
|
||||||
} else {
|
} else {
|
||||||
return sc, errShortCodeIllegalState
|
return sc, errShortCodeIllegalState
|
||||||
|
|
|
@ -34,11 +34,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckShortCodeMatch(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error) {
|
func CheckShortCodeMatch(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error) {
|
||||||
|
t.Helper()
|
||||||
CheckShortCodeMatchAndError(t, input, expected, withTemplate, false)
|
CheckShortCodeMatchAndError(t, input, expected, withTemplate, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckShortCodeMatchAndError(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error, expectError bool) {
|
func CheckShortCodeMatchAndError(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error, expectError bool) {
|
||||||
|
t.Helper()
|
||||||
cfg, fs := newTestCfg()
|
cfg, fs := newTestCfg()
|
||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
|
|
||||||
|
@ -1158,3 +1159,39 @@ title: "Hugo Rocks!"
|
||||||
"test/hello: test/hello",
|
"test/hello: test/hello",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShortcodeTypedParams(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c := qt.New(t)
|
||||||
|
|
||||||
|
builder := newTestSitesBuilder(t).WithSimpleConfigFile()
|
||||||
|
|
||||||
|
builder.WithContent("page.md", `---
|
||||||
|
title: "Hugo Rocks!"
|
||||||
|
---
|
||||||
|
|
||||||
|
# doc
|
||||||
|
|
||||||
|
types positional: {{< hello true false 33 3.14 >}}
|
||||||
|
types named: {{< hello b1=true b2=false i1=33 f1=3.14 >}}
|
||||||
|
types string: {{< hello "true" trues "33" "3.14" >}}
|
||||||
|
|
||||||
|
|
||||||
|
`).WithTemplatesAdded(
|
||||||
|
"layouts/shortcodes/hello.html",
|
||||||
|
`{{ range $i, $v := .Params }}
|
||||||
|
- {{ printf "%v: %v (%T)" $i $v $v }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $b1 := .Get "b1" }}
|
||||||
|
Get: {{ printf "%v (%T)" $b1 $b1 | safeHTML }}
|
||||||
|
`).Build(BuildCfg{})
|
||||||
|
|
||||||
|
s := builder.H.Sites[0]
|
||||||
|
c.Assert(len(s.RegularPages()), qt.Equals, 1)
|
||||||
|
|
||||||
|
builder.AssertFileContent("public/page/index.html",
|
||||||
|
"types positional: - 0: true (bool) - 1: false (bool) - 2: 33 (int) - 3: 3.14 (float64)",
|
||||||
|
"types named: - b1: true (bool) - b2: false (bool) - f1: 3.14 (float64) - i1: 33 (int) Get: true (bool) ",
|
||||||
|
"types string: - 0: true (string) - 1: trues (string) - 2: 33 (string) - 3: 3.14 (string) ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -16,12 +16,15 @@ package pageparser
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Type ItemType
|
Type ItemType
|
||||||
Pos int
|
Pos int
|
||||||
Val []byte
|
Val []byte
|
||||||
|
isString bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Items []Item
|
type Items []Item
|
||||||
|
@ -30,6 +33,36 @@ func (i Item) ValStr() string {
|
||||||
return string(i.Val)
|
return string(i.Val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i Item) ValTyped() interface{} {
|
||||||
|
str := i.ValStr()
|
||||||
|
if i.isString {
|
||||||
|
// A quoted value that is a string even if it looks like a number etc.
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
if boolRe.MatchString(str) {
|
||||||
|
return str == "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
if intRe.MatchString(str) {
|
||||||
|
num, err := strconv.Atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
if floatRe.MatchString(str) {
|
||||||
|
num, err := strconv.ParseFloat(str, 64)
|
||||||
|
if err != nil {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
func (i Item) IsText() bool {
|
func (i Item) IsText() bool {
|
||||||
return i.Type == tText
|
return i.Type == tText
|
||||||
}
|
}
|
||||||
|
@ -132,3 +165,9 @@ const (
|
||||||
// preserved for later - keywords come after this
|
// preserved for later - keywords come after this
|
||||||
tKeywordMarker
|
tKeywordMarker
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
boolRe = regexp.MustCompile(`^(true$)|(false$)`)
|
||||||
|
intRe = regexp.MustCompile(`^[-+]?\d+$`)
|
||||||
|
floatRe = regexp.MustCompile(`^[-+]?\d*\.\d+$`)
|
||||||
|
)
|
||||||
|
|
35
parser/pageparser/item_test.go
Normal file
35
parser/pageparser/item_test.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2019 The Hugo Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package pageparser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
qt "github.com/frankban/quicktest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestItemValTyped(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
|
||||||
|
c.Assert(Item{Val: []byte("3.14")}.ValTyped(), qt.Equals, float64(3.14))
|
||||||
|
c.Assert(Item{Val: []byte(".14")}.ValTyped(), qt.Equals, float64(.14))
|
||||||
|
c.Assert(Item{Val: []byte("314")}.ValTyped(), qt.Equals, 314)
|
||||||
|
c.Assert(Item{Val: []byte("314x")}.ValTyped(), qt.Equals, "314x")
|
||||||
|
c.Assert(Item{Val: []byte("314 ")}.ValTyped(), qt.Equals, "314 ")
|
||||||
|
c.Assert(Item{Val: []byte("314"), isString: true}.ValTyped(), qt.Equals, "314")
|
||||||
|
c.Assert(Item{Val: []byte("true")}.ValTyped(), qt.Equals, true)
|
||||||
|
c.Assert(Item{Val: []byte("false")}.ValTyped(), qt.Equals, false)
|
||||||
|
c.Assert(Item{Val: []byte("trues")}.ValTyped(), qt.Equals, "trues")
|
||||||
|
|
||||||
|
}
|
|
@ -142,7 +142,13 @@ func (l *pageLexer) backup() {
|
||||||
|
|
||||||
// sends an item back to the client.
|
// sends an item back to the client.
|
||||||
func (l *pageLexer) emit(t ItemType) {
|
func (l *pageLexer) emit(t ItemType) {
|
||||||
l.items = append(l.items, Item{t, l.start, l.input[l.start:l.pos]})
|
l.items = append(l.items, Item{t, l.start, l.input[l.start:l.pos], false})
|
||||||
|
l.start = l.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends a string item back to the client.
|
||||||
|
func (l *pageLexer) emitString(t ItemType) {
|
||||||
|
l.items = append(l.items, Item{t, l.start, l.input[l.start:l.pos], true})
|
||||||
l.start = l.pos
|
l.start = l.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,14 +157,14 @@ func (l *pageLexer) isEOF() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case, do not send '\\' back to client
|
// special case, do not send '\\' back to client
|
||||||
func (l *pageLexer) ignoreEscapesAndEmit(t ItemType) {
|
func (l *pageLexer) ignoreEscapesAndEmit(t ItemType, isString bool) {
|
||||||
val := bytes.Map(func(r rune) rune {
|
val := bytes.Map(func(r rune) rune {
|
||||||
if r == '\\' {
|
if r == '\\' {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}, l.input[l.start:l.pos])
|
}, l.input[l.start:l.pos])
|
||||||
l.items = append(l.items, Item{t, l.start, val})
|
l.items = append(l.items, Item{t, l.start, val, isString})
|
||||||
l.start = l.pos
|
l.start = l.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +182,7 @@ var lf = []byte("\n")
|
||||||
|
|
||||||
// nil terminates the parser
|
// nil terminates the parser
|
||||||
func (l *pageLexer) errorf(format string, args ...interface{}) stateFunc {
|
func (l *pageLexer) errorf(format string, args ...interface{}) stateFunc {
|
||||||
l.items = append(l.items, Item{tError, l.start, []byte(fmt.Sprintf(format, args...))})
|
l.items = append(l.items, Item{tError, l.start, []byte(fmt.Sprintf(format, args...)), true})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +207,16 @@ func (l *pageLexer) consumeToNextLine() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *pageLexer) consumeToSpace() {
|
||||||
|
for {
|
||||||
|
r := l.next()
|
||||||
|
if r == eof || unicode.IsSpace(r) {
|
||||||
|
l.backup()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *pageLexer) consumeSpace() {
|
func (l *pageLexer) consumeSpace() {
|
||||||
for {
|
for {
|
||||||
r := l.next()
|
r := l.next()
|
||||||
|
|
|
@ -112,7 +112,7 @@ func lexShortcodeParam(l *pageLexer, escapedQuoteStart bool) stateFunc {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAlphaNumericOrHyphen(r) {
|
if !isAlphaNumericOrHyphen(r) && r != '.' { // Floats have period
|
||||||
l.backup()
|
l.backup()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,12 @@ func lexShortcodeParam(l *pageLexer, escapedQuoteStart bool) stateFunc {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lexShortcodeParamVal(l *pageLexer) stateFunc {
|
||||||
|
l.consumeToSpace()
|
||||||
|
l.emit(tScParamVal)
|
||||||
|
return lexInsideShortcode
|
||||||
|
}
|
||||||
|
|
||||||
func lexShortcodeQuotedParamVal(l *pageLexer, escapedQuotedValuesAllowed bool, typ ItemType) stateFunc {
|
func lexShortcodeQuotedParamVal(l *pageLexer, escapedQuotedValuesAllowed bool, typ ItemType) stateFunc {
|
||||||
openQuoteFound := false
|
openQuoteFound := false
|
||||||
escapedInnerQuoteFound := false
|
escapedInnerQuoteFound := false
|
||||||
|
@ -176,9 +182,9 @@ Loop:
|
||||||
}
|
}
|
||||||
|
|
||||||
if escapedInnerQuoteFound {
|
if escapedInnerQuoteFound {
|
||||||
l.ignoreEscapesAndEmit(typ)
|
l.ignoreEscapesAndEmit(typ, true)
|
||||||
} else {
|
} else {
|
||||||
l.emit(typ)
|
l.emitString(typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := l.next()
|
r := l.next()
|
||||||
|
@ -273,8 +279,13 @@ func lexInsideShortcode(l *pageLexer) stateFunc {
|
||||||
case isSpace(r), isEndOfLine(r):
|
case isSpace(r), isEndOfLine(r):
|
||||||
l.ignore()
|
l.ignore()
|
||||||
case r == '=':
|
case r == '=':
|
||||||
|
l.consumeSpace()
|
||||||
l.ignore()
|
l.ignore()
|
||||||
return lexShortcodeQuotedParamVal(l, l.peek() != '\\', tScParamVal)
|
peek := l.peek()
|
||||||
|
if peek == '"' || peek == '\\' {
|
||||||
|
return lexShortcodeQuotedParamVal(l, peek != '\\', tScParamVal)
|
||||||
|
}
|
||||||
|
return lexShortcodeParamVal
|
||||||
case r == '/':
|
case r == '/':
|
||||||
if l.currShortcodeName == "" {
|
if l.currShortcodeName == "" {
|
||||||
return l.errorf("got closing shortcode, but none is open")
|
return l.errorf("got closing shortcode, but none is open")
|
||||||
|
|
|
@ -80,7 +80,7 @@ func (t *Iterator) Input() []byte {
|
||||||
return t.l.Input()
|
return t.l.Input()
|
||||||
}
|
}
|
||||||
|
|
||||||
var errIndexOutOfBounds = Item{tError, 0, []byte("no more tokens")}
|
var errIndexOutOfBounds = Item{tError, 0, []byte("no more tokens"), true}
|
||||||
|
|
||||||
// Current will repeatably return the current item.
|
// Current will repeatably return the current item.
|
||||||
func (t *Iterator) Current() Item {
|
func (t *Iterator) Current() Item {
|
||||||
|
|
|
@ -27,7 +27,7 @@ type lexerTest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func nti(tp ItemType, val string) Item {
|
func nti(tp ItemType, val string) Item {
|
||||||
return Item{tp, 0, []byte(val)}
|
return Item{tp, 0, []byte(val), false}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -119,6 +119,7 @@ func equal(i1, i2 []Item) bool {
|
||||||
if i1[k].Type != i2[k].Type {
|
if i1[k].Type != i2[k].Type {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(i1[k].Val, i2[k].Val) {
|
if !reflect.DeepEqual(i1[k].Val, i2[k].Val) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,22 +16,26 @@ package pageparser
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tstEOF = nti(tEOF, "")
|
tstEOF = nti(tEOF, "")
|
||||||
tstLeftNoMD = nti(tLeftDelimScNoMarkup, "{{<")
|
tstLeftNoMD = nti(tLeftDelimScNoMarkup, "{{<")
|
||||||
tstRightNoMD = nti(tRightDelimScNoMarkup, ">}}")
|
tstRightNoMD = nti(tRightDelimScNoMarkup, ">}}")
|
||||||
tstLeftMD = nti(tLeftDelimScWithMarkup, "{{%")
|
tstLeftMD = nti(tLeftDelimScWithMarkup, "{{%")
|
||||||
tstRightMD = nti(tRightDelimScWithMarkup, "%}}")
|
tstRightMD = nti(tRightDelimScWithMarkup, "%}}")
|
||||||
tstSCClose = nti(tScClose, "/")
|
tstSCClose = nti(tScClose, "/")
|
||||||
tstSC1 = nti(tScName, "sc1")
|
tstSC1 = nti(tScName, "sc1")
|
||||||
tstSC1Inline = nti(tScNameInline, "sc1.inline")
|
tstSC1Inline = nti(tScNameInline, "sc1.inline")
|
||||||
tstSC2Inline = nti(tScNameInline, "sc2.inline")
|
tstSC2Inline = nti(tScNameInline, "sc2.inline")
|
||||||
tstSC2 = nti(tScName, "sc2")
|
tstSC2 = nti(tScName, "sc2")
|
||||||
tstSC3 = nti(tScName, "sc3")
|
tstSC3 = nti(tScName, "sc3")
|
||||||
tstSCSlash = nti(tScName, "sc/sub")
|
tstSCSlash = nti(tScName, "sc/sub")
|
||||||
tstParam1 = nti(tScParam, "param1")
|
tstParam1 = nti(tScParam, "param1")
|
||||||
tstParam2 = nti(tScParam, "param2")
|
tstParam2 = nti(tScParam, "param2")
|
||||||
tstVal = nti(tScParamVal, "Hello World")
|
tstParamBoolTrue = nti(tScParam, "true")
|
||||||
tstText = nti(tText, "Hello World")
|
tstParamBoolFalse = nti(tScParam, "false")
|
||||||
|
tstParamInt = nti(tScParam, "32")
|
||||||
|
tstParamFloat = nti(tScParam, "3.14")
|
||||||
|
tstVal = nti(tScParamVal, "Hello World")
|
||||||
|
tstText = nti(tText, "Hello World")
|
||||||
)
|
)
|
||||||
|
|
||||||
var shortCodeLexerTests = []lexerTest{
|
var shortCodeLexerTests = []lexerTest{
|
||||||
|
@ -69,6 +73,12 @@ var shortCodeLexerTests = []lexerTest{
|
||||||
{"close with extra keyword", `{{< sc1 >}}{{< /sc1 keyword>}}`, []Item{
|
{"close with extra keyword", `{{< sc1 >}}{{< /sc1 keyword>}}`, []Item{
|
||||||
tstLeftNoMD, tstSC1, tstRightNoMD, tstLeftNoMD, tstSCClose, tstSC1,
|
tstLeftNoMD, tstSC1, tstRightNoMD, tstLeftNoMD, tstSCClose, tstSC1,
|
||||||
nti(tError, "unclosed shortcode")}},
|
nti(tError, "unclosed shortcode")}},
|
||||||
|
{"float param, positional", `{{< sc1 3.14 >}}`, []Item{
|
||||||
|
tstLeftNoMD, tstSC1, nti(tScParam, "3.14"), tstRightNoMD, tstEOF}},
|
||||||
|
{"float param, named", `{{< sc1 param1=3.14 >}}`, []Item{
|
||||||
|
tstLeftNoMD, tstSC1, tstParam1, nti(tScParamVal, "3.14"), tstRightNoMD, tstEOF}},
|
||||||
|
{"float param, named, space before", `{{< sc1 param1= 3.14 >}}`, []Item{
|
||||||
|
tstLeftNoMD, tstSC1, tstParam1, nti(tScParamVal, "3.14"), tstRightNoMD, tstEOF}},
|
||||||
{"Youtube id", `{{< sc1 -ziL-Q_456igdO-4 >}}`, []Item{
|
{"Youtube id", `{{< sc1 -ziL-Q_456igdO-4 >}}`, []Item{
|
||||||
tstLeftNoMD, tstSC1, nti(tScParam, "-ziL-Q_456igdO-4"), tstRightNoMD, tstEOF}},
|
tstLeftNoMD, tstSC1, nti(tScParam, "-ziL-Q_456igdO-4"), tstRightNoMD, tstEOF}},
|
||||||
{"non-alphanumerics param quoted", `{{< sc1 "-ziL-.%QigdO-4" >}}`, []Item{
|
{"non-alphanumerics param quoted", `{{< sc1 "-ziL-.%QigdO-4" >}}`, []Item{
|
||||||
|
|
2
tpl/tplimpl/embedded/templates.autogen.go
generated
2
tpl/tplimpl/embedded/templates.autogen.go
generated
|
@ -422,7 +422,7 @@ if (!doNotTrack) {
|
||||||
{{- if $pc.Simple -}}
|
{{- if $pc.Simple -}}
|
||||||
{{ template "_internal/shortcodes/twitter_simple.html" . }}
|
{{ template "_internal/shortcodes/twitter_simple.html" . }}
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
{{- $url := printf "https://api.twitter.com/1/statuses/oembed.json?id=%s&dnt=%t" (index .Params 0) $pc.EnableDNT -}}
|
{{- $url := printf "https://api.twitter.com/1/statuses/oembed.json?id=%v&dnt=%t" (index .Params 0) $pc.EnableDNT -}}
|
||||||
{{- $json := getJSON $url -}}
|
{{- $json := getJSON $url -}}
|
||||||
{{ $json.html | safeHTML }}
|
{{ $json.html | safeHTML }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{{- if $pc.Simple -}}
|
{{- if $pc.Simple -}}
|
||||||
{{ template "_internal/shortcodes/twitter_simple.html" . }}
|
{{ template "_internal/shortcodes/twitter_simple.html" . }}
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
{{- $url := printf "https://api.twitter.com/1/statuses/oembed.json?id=%s&dnt=%t" (index .Params 0) $pc.EnableDNT -}}
|
{{- $url := printf "https://api.twitter.com/1/statuses/oembed.json?id=%v&dnt=%t" (index .Params 0) $pc.EnableDNT -}}
|
||||||
{{- $json := getJSON $url -}}
|
{{- $json := getJSON $url -}}
|
||||||
{{ $json.html | safeHTML }}
|
{{ $json.html | safeHTML }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
|
@ -126,7 +126,13 @@ func (ns *Namespace) refArgsToMap(args interface{}) (map[string]interface{}, err
|
||||||
s string
|
s string
|
||||||
of string
|
of string
|
||||||
)
|
)
|
||||||
switch v := args.(type) {
|
|
||||||
|
v := args
|
||||||
|
if _, ok := v.([]interface{}); ok {
|
||||||
|
v = cast.ToStringSlice(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v := v.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
return v, nil
|
return v, nil
|
||||||
case map[string]string:
|
case map[string]string:
|
||||||
|
@ -152,6 +158,7 @@ func (ns *Namespace) refArgsToMap(args interface{}) (map[string]interface{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"path": s,
|
"path": s,
|
||||||
"outputFormat": of,
|
"outputFormat": of,
|
||||||
|
|
Loading…
Reference in a new issue