Also see #4010
This change is motivated by the Bootstrap docs, but this should be generally very useful. Given the example Markdown below:
https://raw.githubusercontent.com/twbs/bootstrap/v4-dev-xmr-hugo/docs/content/docs/4.0/about/team.md
All of this is currently possible with Hugo, but to get that loop you would probably end up with creating a shortcode, which is probably not what you want since this is used one time only.
So, I suggest we create some magic internal "inline shortcode wrapper" that allows shortcodes to be defined inside content files (i.e. scoped for that content file only).
So, combined with #4010 and the inline shortcode wrapper, the above example could look something like this:
---
layout: docs
title: Team
description: An overview of the founding team and core contributors to Bootstrap.
group: about
---
Bootstrap is maintained by the founding team and a small group of invaluable core contributors, with the massive support and involvement of our community.
{{< team.inline >}}
<div class="list-group bd-team">
{{ range .Site.Data.core-team }}
<div class="list-group-item">
<iframe class="github-btn" src="https://ghbtns.com/github-btn.html?user={{ .user }}&type=follow"></iframe>
<a class="team-member" href="https://github.com/{{ .user }}">
<img src="https://secure.gravatar.com/avatar/{{ .gravatar }}" alt="@{{ .user }}" width="32" height="32">
<strong>{{ .name }}</strong> <small>@{{ .user }}</small>
</a>
</div>
{{ end }}
</div>
{{< / team.inline >}}
Get involved with Bootstrap development by [opening an issue]({{< param "repo" >}}/issues/new) or submitting a pull request. Read our [contributing guidelines]({{< param "repo" >}}/blob/v{{< param "current_version" >}}/.github/CONTRIBUTING.md) for information on how we develop.
Some notes to the above:
Comments etc. are welcomed.
/cc @XhmikosR @moorereason @spf13 @digitalcraftsman and gang
So an "inline shortcode" has a name. As such, it should be possible to define it once and then reuse it later, possibly with different params.
So:
The **number one thing** to know about Hugo is:
{{< hugo_rules.inline "100" >}}
{{ range (seq (.Get 0)) }}Hugo Rules! {{ end }}
{{< / hugo_rules.inline >}}
If the above wasn't clear enough:
{{< hugo_rules.inline "300" />}}
So the valid names for inline shortcodes are any name that ends with "inline". You are responsible to keep them separated. Any repeated inline name will have its shortcode reused, which of course can be very useful (see above).
Note the use of the self-closing shortcode syntax in the last example (probably, let's see). We reuse the shortcode definition earlier in the same markdown file.
The order is important here, and this does not work across different files.
A general remark to the above: The main performance cost of shortcode is the template parsing, so the main use of shortcode will still be to put them in layouts/shortcodes. But this would be useful for those special use cases.
I named it
__inlineto mark it as something internal, but I would appreciate a better name for this special shortcode
What about __lambda? Also could it be defined first and (re)used _at whim_ within the document? I'm dreaming of a one-time/special-purpose shortcode that could be invoked as needed throughout the same content file…
+1 for __lambda .. resonates well with lisps and even Python.
What if one needs multiple one-time shortcodes in a content page?
What if one needs multiple one-time shortcodes in a content page?
@kaushalmodi I think this use case is already covered as nothing prevents you from redefining (and executing) the anonymous shortcode elsewhere in the content file — an immediate analogy that comes to mind is the IIFE ("iffy") JavaScript idiom. But in order to invoke _distinct_ inline shortcodes over and over, we should be given the ability to name things (e.g. labels ⁉️)…
we should be given the ability to name things
That's what I meant. May be this new construct acts like a macro that generates shortcodes with the specified name?
Example: {{< __inline foo >}} ..
Or may be something like: {{< define_scode foo >}} .. ?
The benefit of having a unique name is also searchability. If you have different versions of __inline in the same project, it can get kind of difficult to get to the __inline definition you really wanted.
I think it's a great feature, and Bep is really at it with significant improvements (fast render mode, related content, Chroma incorporation and improvements, plus upcoming bags and 'inlines'). Very impressive! 😄
What I don't like is the name __lambda. I think that, as Hugo grows, it pays to have terminology that's more accessible, and also more inclusive for people with all educational and work backgrounds. While I suspect that practically every backend developer understands how this new feature works when we say that 'Hugo also supports lambda functions in the content file'.
But for people that come from WordPress, Ghost, or another CMS might have no clue what lambdas are. And that technical term might make it harder for them to understand what's going on. Even front developers that know JavaScript might be unclear what it means.
(Interestingly, I see here a whole page from a JavaScript book writer to try explain Lambda functions in the context of JavaScript. I don't think that we should assume that other people also have a clear grasp of lambda functions.)
So I'm in favour of the name __inline because I think it's more descriptive for Hugo beginners.
I have adjusted my proposal a little + added one more example.
lambda; what is the definition of that in the world of Lisp? (I still think I like inline better -- it was the first thing that popped into my head, which is usually a good sign).To the people suggesting lambda; what is the definition of that in the world of Lisp?
The lambda suggestion was before the development to named shortcodes. Here's a pretty good explanation of lambda from (E)lisp manual: http://www.gnu.org/software/emacs/manual/html_node/elisp/Lambda-Expressions.html
Instead of first defining the function and then calling it, you just throw in the anonymous function definition where a function call is expected.
Now with named inline shortcodes, the anonymous part doesn't hold true. So the update in the proposal looks good! :+1:
@bep So to be clear, in the updated example:
{{< team.inline >}}
..
{{< / team.inline >}}
Get involved with Bootstrap ...
The place where you have the team.inline "definition" is where it gets applied, right? Then it doesn't need to be "called" separately? In that sense, it does feel like a lambda, and lambda definitely has a cooler ring to it then inline IMO.
As to point that @Jos512 raised about having terms accessible to general public.. just as the general public have to learn about the differences between template and short code, layouts and scopes of params, etc, lambda can be just one more thing. And folks who are already familiar with lambda can easily relate with this. WDYT?
The place where you have the team.inline "definition" is where it gets applied, right? Then it doesn't need to be "called" separately?
That is correct, and its main use case (my guess) is to use it once and forget about it. I just added the "name" as a requirement because there are several good reasons to have one (searching, reuse) -- and it makes the implementation slightly simpler.
So, a lambda is an anonymous function, which may on some level apply here. But it is a foreign word to many, even to me -- and I have been in the game to remember the talk about the year 2000 issue) ... So maybe the cool thing isn't really enough.
But, I also do agree that people learn fast -- and the important thing is that it is distinct.
So maybe the cool thing isn't really enough.
I didn't say that was the only reason.
Along with lisps, Python (which I believe has one of the largest mind-share in the developer/coder world) uses lambda too, apparently inspired from lisps): Python lambda expressions or this (one of the many Google results on searching Python lambda).
The example has:
def make_incrementor(n):
return lambda x: x + n
That basically generates an anonymous function that adds n to the input arg x and returns that sum. So instead of having a separate function that does that and calling it, lambda x: x + n does the same in a much concise fashion.
Your team.inline example does very much the same thing, except that we are just giving it a name (just in case it needs to be referred again, and for searching).
I have added a shortcode name to the syntax to enable reuse. My first thought was to just add an internal counter to all the "internal shortcodes" in a document, but the above is cleaner I think.
@bep It is indeed. Thank you! 👍
What about the .macro suffix? Would it make more sense for the less tech-savvy users?
The **number one thing** to know about Hugo is:
{{< hugo_rules.macro "100" >}}
{{ range (seq (.Get 0)) }}Hugo Rules! {{ end }}
{{< / hugo_rules.macro >}}
If the above wasn't clear enough:
{{< hugo_rules.macro "300" />}}
Sorry, one last thing on lambda and Go. So I googled (as I don't know Go :)) and apparently Go has something called function literals that are like lambdas:
BTW, do you have to repeat the .inline, .lambda, .macro or whatever suffix for any subsequent invocation?
The **number one thing** to know about Hugo is:
{{< hugo_rules.macro "100" >}}
{{ range (seq (.Get 0)) }}Hugo Rules! {{ end }}
{{< / hugo_rules.macro >}}
If the above wasn't clear enough:
{{< hugo_rules "300" />}}
BTW, do you have to repeat the
I don't have to do anything. But it makes it unambiguous (i.e. what would I do in the above example if there was a shortcode in layouts/shortcodes/hugo_rules.html?).
I could add some complex logic, or I could keep it simple.
An added note to the above, that my current spec does not solve, is this:
For shortcodes in layouts/shortcodes you can have multiple versions of the same shortcode for different outputformats, i.e.:
note.html
note.amp.html
I have no idea how to support that in the inline variant, so I'm inclined to drop it for now. If no one has a brilliant idea ...
IMHO inline shortcodes could be given precedence over standard shortcodes. That's the whole point of being able to define shortcodes in the scope of a content file. Is it possible in your current spec to nest standard shortcodes within inline shortcodes?
@galopin Nesting is possible, as mentioned above (for Bootstrap it would be great to wrap the highlight shortcode around an inline shortcode). Re. precedence: I'm not sure I follow the "that's the whole point" argument. The main point (i.e. the bulk of the "whole point") of the main example above is to create a "one time inline shortcode" (i.e. not overriding anything), which then is reused later in the same document? There is no talk about presedence in that usage ... So what is your take on this: To override the built-in figure shortcode with an inline definition?
Note that I'm not saying you don't have a point, just that I obviously have not thought about everything.
I'm not sold on the concept of inline shortcodes. I'm not against them, but it's not very hard to define a shortcode. We are adding a reasonable amount of complexity for a small gain. I do see the advantage of not having to create another file, but only a small one.
If we do inline shortcodes there should be some clear rules around them.
There shouldn't be any precedence or conflict with existing shortcodes as these are anonymous. They shouldn't be used to "override" another shortcode.. they are simply different things.
@spf13 is correct. His "scope limiting" will not make every person happy, but it does make this a fairly simple task -- and it jumps over possibly impossible problems such as how to handle multiple output formats etc.
also I feel quite strongly that "inline" is the right term to use. Adding a prefix such as "__inline" may solve the problem of "inline" not conflicting with a shortcode named "inline.html", though I'm also ok with that just being a prohibited name. Lambda is not a well understood term across most languages (both computer and speaking) and definitely not among most web creators. It also has different meanings in different programming languages, so using it here would add another definition to an already overloaded term.
For the name, think about answering questions in the forums: "How do I put template code directly in my content files?".
The difference between templates and shortcodes is already a little fuzzy for new users, so I think it's important to pick the least-confusing term for a feature that lets you use template code in a content file.
One suggestion I'd make is to have a config parameter to enable the feature; not everyone wants their content creators writing code.
I have slept on this and have updated the spec in line with how it's going to be.
So what is your take on this: To override the built-in figure shortcode with an inline definition?
@bep Exactly. When I define something in the local scope, I expect it to override anything defined in the global scope. I'm glad you did not remove the naming ability for inline shortcodes — using the .inline suffix systematically solves any shortcode name-collision issue 👍
Lambda is not a well understood term across most languages (both computer and speaking) […]
@spf13 Touché! I guess we could say the same about "partial", a term which has distinct meanings outside the context of a templating language 😉
[…] not everyone wants their content creators writing code.
@jgreely Lambda was merely a suggestion and not a recommendation. Strictly speaking, inserting an inline shortcode into a content file has nothing to do with programming but I understand your concern. Hugo seems to be stricter than Jekyll in the way it handles Markdown content files. Hence #4011 and #4013 are welcome features that will help people transition from other SSGs such as Jekyll. What I miss, for example, is the ability to capture the output of a whole block into a variable.
This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open.
If this is a feature request, and you feel that it is still relevant and valuable, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.
Most helpful comment
The benefit of having a unique name is also searchability. If you have different versions of
__inlinein the same project, it can get kind of difficult to get to the__inlinedefinition you really wanted.