summaryrefslogtreecommitdiffstats
path: root/hugolib/shortcode.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-04-22 14:07:29 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-04-22 17:40:51 +0200
commit85535084dea4d3e3adf1ebd08ae57b39d76e1904 (patch)
treea30056019dacb9642be603ce44e243c864931e8f /hugolib/shortcode.go
parent19084eaf74246feac61d618c55031369520dfa8e (diff)
hugolib: Process and render shortcodes in their order of appearance
Fixes #3359
Diffstat (limited to 'hugolib/shortcode.go')
-rw-r--r--hugolib/shortcode.go69
1 files changed, 37 insertions, 32 deletions
diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go
index df4acba5f..933bbe44e 100644
--- a/hugolib/shortcode.go
+++ b/hugolib/shortcode.go
@@ -180,11 +180,11 @@ type shortcodeHandler struct {
p *PageWithoutContent
// This is all shortcode rendering funcs for all potential output formats.
- contentShortcodes map[scKey]func() (string, error)
+ contentShortcodes *orderedMap
// This map contains the new or changed set of shortcodes that need
// to be rendered for the current output format.
- contentShortcodesDelta map[scKey]func() (string, error)
+ contentShortcodesDelta *orderedMap
// This maps the shorcode placeholders with the rendered content.
// We will do (potential) partial re-rendering per output format,
@@ -192,7 +192,7 @@ type shortcodeHandler struct {
renderedShortcodes map[string]string
// Maps the shortcodeplaceholder with the actual shortcode.
- shortcodes map[string]shortcode
+ shortcodes *orderedMap
// All the shortcode names in this set.
nameSet map[string]bool
@@ -216,8 +216,8 @@ func (s *shortcodeHandler) createShortcodePlaceholder() string {
func newShortcodeHandler(p *Page) *shortcodeHandler {
return &shortcodeHandler{
p: p.withoutContent(),
- contentShortcodes: make(map[scKey]func() (string, error)),
- shortcodes: make(map[string]shortcode),
+ contentShortcodes: newOrderedMap(),
+ shortcodes: newOrderedMap(),
nameSet: make(map[string]bool),
renderedShortcodes: make(map[string]string),
}
@@ -259,7 +259,7 @@ const innerNewlineRegexp = "\n"
const innerCleanupRegexp = `\A<p>(.*)</p>\n\z`
const innerCleanupExpand = "$1"
-func prepareShortcodeForPage(placeholder string, sc shortcode, parent *ShortcodeWithPage, p *PageWithoutContent) map[scKey]func() (string, error) {
+func prepareShortcodeForPage(placeholder string, sc *shortcode, parent *ShortcodeWithPage, p *PageWithoutContent) map[scKey]func() (string, error) {
m := make(map[scKey]func() (string, error))
lang := p.Lang()
@@ -277,7 +277,7 @@ func prepareShortcodeForPage(placeholder string, sc shortcode, parent *Shortcode
func renderShortcode(
tmplKey scKey,
- sc shortcode,
+ sc *shortcode,
parent *ShortcodeWithPage,
p *PageWithoutContent) string {
@@ -298,8 +298,8 @@ func renderShortcode(
switch innerData.(type) {
case string:
inner += innerData.(string)
- case shortcode:
- inner += renderShortcode(tmplKey, innerData.(shortcode), data, p)
+ case *shortcode:
+ inner += renderShortcode(tmplKey, innerData.(*shortcode), data, p)
default:
p.s.Log.ERROR.Printf("Illegal state on shortcode rendering of %q in page %q. Illegal type in inner data: %s ",
sc.name, p.Path(), reflect.TypeOf(innerData))
@@ -363,48 +363,51 @@ func (s *shortcodeHandler) updateDelta() bool {
contentShortcodes := s.contentShortcodesForOutputFormat(s.p.s.rc.Format)
- if s.contentShortcodesDelta == nil || len(s.contentShortcodesDelta) == 0 {
+ if s.contentShortcodesDelta == nil || s.contentShortcodesDelta.Len() == 0 {
s.contentShortcodesDelta = contentShortcodes
return true
}
- delta := make(map[scKey]func() (string, error))
+ delta := newOrderedMap()
- for k, v := range contentShortcodes {
- if _, found := s.contentShortcodesDelta[k]; !found {
- delta[k] = v
+ for _, k := range contentShortcodes.Keys() {
+ if !s.contentShortcodesDelta.Contains(k) {
+ v, _ := contentShortcodes.Get(k)
+ delta.Add(k, v)
}
}
s.contentShortcodesDelta = delta
- return len(delta) > 0
+ return delta.Len() > 0
}
-func (s *shortcodeHandler) contentShortcodesForOutputFormat(f output.Format) map[scKey]func() (string, error) {
- contentShortcodesForOuputFormat := make(map[scKey]func() (string, error))
+func (s *shortcodeHandler) contentShortcodesForOutputFormat(f output.Format) *orderedMap {
+ contentShortcodesForOuputFormat := newOrderedMap()
lang := s.p.Lang()
- for shortcodePlaceholder := range s.shortcodes {
+ for _, key := range s.shortcodes.Keys() {
+ shortcodePlaceholder := key.(string)
+ // shortcodePlaceholder := s.shortcodes.getShortcode(key)
key := newScKeyFromLangAndOutputFormat(lang, f, shortcodePlaceholder)
- renderFn, found := s.contentShortcodes[key]
+ renderFn, found := s.contentShortcodes.Get(key)
if !found {
key.OutputFormat = ""
- renderFn, found = s.contentShortcodes[key]
+ renderFn, found = s.contentShortcodes.Get(key)
}
// Fall back to HTML
if !found && key.Suffix != "html" {
key.Suffix = "html"
- renderFn, found = s.contentShortcodes[key]
+ renderFn, found = s.contentShortcodes.Get(key)
}
if !found {
panic(fmt.Sprintf("Shortcode %q could not be found", shortcodePlaceholder))
}
- contentShortcodesForOuputFormat[newScKeyFromLangAndOutputFormat(lang, f, shortcodePlaceholder)] = renderFn
+ contentShortcodesForOuputFormat.Add(newScKeyFromLangAndOutputFormat(lang, f, shortcodePlaceholder), renderFn)
}
return contentShortcodesForOuputFormat
@@ -412,27 +415,29 @@ func (s *shortcodeHandler) contentShortcodesForOutputFormat(f output.Format) map
func (s *shortcodeHandler) executeShortcodesForDelta(p *PageWithoutContent) error {
- for k, render := range s.contentShortcodesDelta {
+ for _, k := range s.contentShortcodesDelta.Keys() {
+ render := s.contentShortcodesDelta.getShortcodeRenderer(k)
renderedShortcode, err := render()
if err != nil {
return fmt.Errorf("Failed to execute shortcode in page %q: %s", p.Path(), err)
}
- s.renderedShortcodes[k.ShortcodePlaceholder] = renderedShortcode
+ s.renderedShortcodes[k.(scKey).ShortcodePlaceholder] = renderedShortcode
}
return nil
}
-func createShortcodeRenderers(shortcodes map[string]shortcode, p *PageWithoutContent) map[scKey]func() (string, error) {
+func createShortcodeRenderers(shortcodes *orderedMap, p *PageWithoutContent) *orderedMap {
- shortcodeRenderers := make(map[scKey]func() (string, error))
+ shortcodeRenderers := newOrderedMap()
- for k, v := range shortcodes {
- prepared := prepareShortcodeForPage(k, v, nil, p)
+ for _, k := range shortcodes.Keys() {
+ v := shortcodes.getShortcode(k)
+ prepared := prepareShortcodeForPage(k.(string), v, nil, p)
for kk, vv := range prepared {
- shortcodeRenderers[kk] = vv
+ shortcodeRenderers.Add(kk, vv)
}
}
@@ -444,8 +449,8 @@ var errShortCodeIllegalState = errors.New("Illegal shortcode state")
// pageTokens state:
// - before: positioned just before the shortcode start
// - after: shortcode(s) consumed (plural when they are nested)
-func (s *shortcodeHandler) extractShortcode(pt *pageTokens, p *PageWithoutContent) (shortcode, error) {
- sc := shortcode{}
+func (s *shortcodeHandler) extractShortcode(pt *pageTokens, p *PageWithoutContent) (*shortcode, error) {
+ sc := &shortcode{}
var isInner = false
var currItem item
@@ -616,7 +621,7 @@ Loop:
placeHolder := s.createShortcodePlaceholder()
result.WriteString(placeHolder)
- s.shortcodes[placeHolder] = currShortcode
+ s.shortcodes.Add(placeHolder, currShortcode)
case tEOF:
break Loop
case tError: