Placeholder Forms

:discourse2: Summary Placeholder Forms will let you build dynamic documentation, by creating a form that replaces any occurrence of a =PATTERN= in your post with the value from a text or selectable input field.
:eyeglasses: Preview Preview on Discourse Theme Creator
:hammer_and_wrench: Repository Link https://github.com/discourse/discourse-placeholder-theme-component
:open_book: New to Discourse Themes? Beginner’s guide to using Discourse Themes

Install this theme component

Features

Add placeholders to posts in this format:

[wrap=placeholder key=NAME description="Your name"][/wrap]
[wrap=placeholder key=COUNTRY default=US defaults=FR,DE,US,CN,AU,CA][/wrap]

Your email: =NAME=-=COUNTRY=@example.com

And this will result in:

This is used in mailing list

Your email: =ZNAME=-=ZCOUNTRY=@example.com

As seen above, text inside the wrapper will be used as a long description.

[wrap=placeholder key=NAME description="Your name"]
This is used in mailing list
[/wrap]

Available keys

  • key: The key that should be replaced in your post
  • default/defaults: default value(s)
  • description: a placeholder text for the input

Examples

# create a new plugin
rails g plugin =PLUGIN_NAME=
cd plugins/=PLUGIN_NAME=

We use it to create runbooks, howtos and reusable templates (it will work in code blocks). Please share your use cases!

Settings

Translation Default
toolbar.builder Add Placeholder
builder.errors.no_key A key is required.
builder.title Add Placeholder
builder.insert Insert
builder.key.label Key
builder.key.description The =Key= to be replaced in the post.
builder.description.label Description
builder.description.description Description displayed on input with no value set.
builder.values.label Default value(s)
builder.values.description Optional value(s) for your placeholder, if multiple values are defined, a select will be used.

:discourse2: Hosted by us? Theme components are available to use on our Standard, Business, and Enterprise plans.

Last edited by @JammyDodger 2024-06-13T22:28:45Z

Check documentPerform check on document:
62 Likes

The big issue with math handling like this, is that you need to eval() and eval is unsafe, so you need to use some lib which provide a safe eval with a limited subset of the real eval. I’m unsure we want all this complexity for such a rare case.

6 Likes

I tried ! and that would be a neat composer-preview-redux-in-OP kind of thing but… :pensive: I must be missing something, if I understand correctly the Reply Template component takes the raw and looks for ā€œreplacersā€, but the Placeholder Forms component decorates the cooked?

What I’m trying to do is ease my users into adding some quizz Q&As in a topic, with minimal technical friction, clicks or even key strokes, :heavy-sigh: :roll_eyes:

[wrap=placeholder key="question" description="question"][/wrap]
[wrap=placeholder key="rƩponse" description="rƩponse"][/wrap]

[wrap=template key="template-spoiler" action="reply" tagsList="#qui, #quand, #où, #comment"]

## Question
=question=
### RƩponse
[spoiler]
=rƩponse=
[/spoiler]
---
*Ɖtiquette(s) ?*
[/wrap]

which gives

so far so good, but unfortunately, the placeholders =question= and =rƩponse= are kept in the composer when hitting the template button

Yes I’m not sure what I was thinking when I wrote this… I probably had a different use case in mind, but can’t remember.

It can’t work this way for sure. I will think a little bit about this… Both theme components were experiments at the time and might deserve better treatment as people have been using it quite frequently.

7 Likes

Thank you !

happy lets go GIF by Shalita Grant

3 Likes

:grin: I don’t know what’s cookin’ in the chef kitchen, but as I usually stuff myself with pistachios or whatnot while waiting, I managed to make it work (for my specific use of course as I’ve almost no idea of what I’m doing, but hey… :sweat_smile: )

4 Likes

Ideally I would like to be able to let admin define their own replacers, but eval is risky (and not even possible with a secure csp) so I’m not sure how I could achieve this…

2 Likes

First of all - great and really helpful theme component.

But I think I found a bug. If I use a placeholder in a code snippet, that contains backticks (`), it is not working. An example is a SQL code snippet:

DELETE FROM `=TABLENAME=`
WHERE id NOT IN(
        SELECT
            id FROM (
                SELECT
                    id FROM `=TABLENAME=`
                ORDER BY
                    id DESC
                LIMIT 20
) subquery);

TABLENAME gets never replaced (if there is a TABLENAME placeholder).

Would be cool if this also included some Jinja2 like conditions. So that e.g. someone could create a key red and map that to the icon :red_circle:, orange would map to :orange_circle:. But I can do without of course, but would’ve been cool to have these test conditions.

I really love this component. :star_struck:


ā€œAnd you really live by the =NOUN_1=? What a =ADJECTIVE_1= life!ā€

ā€œBy it and with it and on it and in it,ā€ said =PERSON_1=. ā€œIt’s brother and sister to me, and aunts, and =NOUN_2=, and food and drink, and (=ADJECTIVE_2=) =VERBING_1=. It’s my =NOUN_3=, and I don’t want any other. What it hasn’t got is not worth =VERBING_2=, and what it doesn’t know is not worth =VERBING_3=. Lord! the =NOUNS_1= we’ve had together! Whether in winter or summer, spring or autumn, it’s always got its =NOUN_4= and its =NOUNS_2=. When the =NOUNS_3= are on in February, and my =NOUNS_4= and basement are brimming with =NOUN_5= that’s no good to me, and the =COLOR_1= =NOUN_6= runs by my best =NOUN_7= window; or again when it all drops =ADVERB_1= and shows patches of =NOUN_8= that smells like =FOOD_1=, and the =NOUNS_5= and =NOUNS_6= clog the channels, and I can =VERB_1= about =MOISTURE= =NOUN_9= over most of the =NOUN_10= of it and find fresh =FOOD_2= to eat, and things =ADJECTIVE_3= people have dropped out of =NOUNS_7=!ā€


Original taken from Standard Ebooks version of The Wind in the Willows, available to read online (search for By it and with it).

10 Likes

Hello :wave:

Thanks for this component :heart: It fits perfectly what I try to achieve now. Actually my first thought was it would be super cool if it can be combine with Reply Template component. But unfortunately it’s not possible as the posts above explained it. :confused:


I’ve found a workaround for this to use it as a template, it works with link to new topics and link to new personal messages.

Here is how made it:

1. Create a Placeholder form (to keep it simple I use the example in OP)

Your email: =NAME=-=COUNTRY=@example.com


2. Create a link to new topic:
I set up in the link:

  1. category
  2. title
  3. body

If you want to add empty lines, use \ so it won’t break the link or to make it invisible you can use   which will add a space in the new line. It will be a part of the template and makes empty line,

<a href="https://meta.discourse.org/new-topic?category==CATEGORY=&title=This is a topic created by =NAME=&body=Hello :wave:
&nbsp;
This is a test topic... Let's see the placeholder form.
\
Your email: =NAME=-=COUNTRY=@example.com
">Use template as new topic</a>

3. Create a topic preview

Selected category

=CATEGORY=

Topic title

This is a topic created by =NAME=

Topic body

Hello :wave:

This is a test topic… Let’s see the placeholder form.

Your email: =NAME=-=COUNTRY=@example.com


4. Create ā€œUse template as new topicā€ button (in the example above this is a link you can make button from this)

Make a [wrap] element from this text. This makes it available to target it with CSS and style it. I add this to below.

<a href="https://meta.discourse.org/new-topic?category==CATEGORY=&title=This is a topic created by =NAME=&body=Hello :wave:
&nbsp;
This is a test topic... Let's see the placeholder form.
\
Your email: =NAME=-=COUNTRY=@example.com
">[wrap=template-button]Use template as new topic[/wrap]</a>

Styling [wrap=template-button]
something like :arrow_down_small:

Common / CSS

[data-wrap="template-button"] {
  background: var(--tertiary);
  color: var(--secondary);
  border-radius: var(--d-button-border-radius);
  padding: 0.5em 0.65em;
  transition: background 0.25s;
  &:focus,
  &:hover {
    background: var(--tertiary-hover);
    color: var(--secondary); 
  }
}

The template button will looks like this :arrow_down_small:

template-button


Demo

Use template as new topic


I hope this little tutorial will help someone who needs something similar :slightly_smiling_face:

Edit: I’ve seted up a category chooser which add the ability to create topic in different categories.


Check the raw version of this post…

7 Likes

That’s amazing Don, thank you. This actually suits one of my needs very well :slight_smile:

2 Likes

Something to note is that code blocks sometimes cause problems:

usermod -aG sudo =USERNAME=

In this case, highlight.js assumes this is Java and converts the codeblock to:

<code class="hljs language-java" data-highlighted="yes">
  usermod -
  <span class="hljs-type">aG</span> 
  <span class="hljs-variable">sudo</span> 
  <span class="hljs-operator">=</span>
  USERNAME=
</code>

I’m able to fix it by signaling this is actually a shell command:

    ```shell
    usermod -aG sudo =USERNAME=
    ```

That results in:

usermod -aG sudo =USERNAME=

If all else fails, text prevents highlight.js from messing with the placeholders.

A more general solution (that Meta Discourse must be using) is to change the default code lang setting from auto to plaintext or somesuch. :wink:


Not that it matters much, but using java is a way to avoid having the placeholder expand when you want to write about placeholders.

1 Like

Can you check the preview link? It seems to be broken for me.

CleanShot 2024-06-05 at 16.34.16

1 Like

This is an amazing feature, and I can see many uses for it.
However, in our reply, is it possible to hide the =(name)= until the user starts typing in the text box? I feel that users (especially new ones) may not understand its purpose, or, it looks like incorrect formatting.

I think I’ve got one working again (:crossed_fingers: :slight_smile:)

https://discourse.theme-creator.io/theme/Discourse/placeholder-forms

I’ve also added it to try.discourse.org so you can have more of a hands-on play with it. :+1:

1 Like

Perhaps you could enter a default value that will display instead.

1 Like

That worked! Thank you!

2 Likes

This workaround doesn’t seem to work anymore.

Are there other options to combine reply-template and placeholder-forms?

Is it possible to use a placeholder in a link ? I can’t achieve it:

[https://=D0MAIN=]()

https://=DOMAIN=

The link is not clickable, whether I use markdown or HTML in the composer.

It outputs:

<a>https://discourse.org</a>