1

I have the following page structure in Grav:

# Title
## Subtitle
### Subsubtitle

The page structure is always the same and it has just those three items.

How can I retrieve each item (Title/Subtitle/Subsubtitle) separately in Twig template?

The twig template will then do things like:

<p> You typed {{ page.whatever_retrieves_the_title_# }} as title, then {{ page.whatever_retrieves_the_subtitle_## }} as subtitle and finally {{ page.whatever_retrieves_the_subsubtitle_### }} as subsubtitle</p>

What if instead of the above structure I have:

- Title
- Subtitle
- Subsubtitle

The objective is that the user adds just that structure of three items and the twig template use each item to display a more complex layout.

M.E.
  • 4,955
  • 4
  • 49
  • 128
  • Is there a reason why you don't want to define these as vars in your header? – Paul Massendari Feb 21 '18 at 21:34
  • @PaulMassendari if I properly understood how grav admin user interface works, a user would need to select expert mode to edit those as vars in header. I would like a non-technical user being able to change that text. – M.E. Feb 22 '18 at 18:37
  • not exactly, you can provide your own blueprint. I will provide an answer as an example. – Paul Massendari Feb 23 '18 at 11:23

2 Answers2

4

This is Markdown, right?

# Title
## Subtitle
### Subsubtitle

You can get the HTML version of the page's Markdown in Twig with {{ page.content }}, as described in Grav's documentation. So you should get something like this:

<h1>Title</h1>
<h2>Subtitle</h2>
<h3>Subsubtitle</h3>

You can use the split and raw filters to extract the contents of those tags. I'm also using the default filter so that there won't be an error if the extraction of the tag contents fails:

Title is:
{{ page.content|split('<h1>')[1]|default|raw|split('</h1>')[0] }}

Subtitle is:
{{ page.content|split('<h2>')[1]|default|raw|split('</h2>')[0] }}

Subsubtitle is:
{{ page.content|split('<h3>')[1]|default|raw|split('</h3>')[0] }}

Or because Grav seems to provide a regex_replace filter, you could also use it:

Title is:
{{ page.content|regex_replace('~.*<h1>(.*)</h1>.*~s', '$1') }}

Subtitle is:
{{ page.content|regex_replace('~.*<h2>(.*)</h2>.*~s', '$1') }}

Subsubtitle is:
{{ page.content|regex_replace('~.*<h3>(.*)</h3>.*~s', '$1') }}

If instead you have this:

- Title
- Subtitle
- Subsubtitle

You can again use the split, default and raw filters:

Title is:
{{ page.content|split('<li>')[1]|default|raw|split('</li>')[0] }}

Subtitle is:
{{ page.content|split('<li>')[2]|default|raw|split('</li>')[0] }}

Subsubtitle is:
{{ page.content|split('<li>')[3]|default|raw|split('</li>')[0] }}

Not very beautiful. :-) If the titles can contain HTML (e.g. ## Hello **world**!<h2>Hello <strong>world</strong>!</h2>) or special characters, you probably need to append |raw to the already long magic spells.

Matias Kinnunen
  • 7,828
  • 3
  • 35
  • 46
  • 1
    Thanks this answers the question, however I finally found that a much better approach in Grav is to use a plugin which allows to define sections and then retrieve such sections in Twig. – M.E. Feb 21 '18 at 19:18
  • @M.E. This solution here is very ugly and hacky so great if you found a better approach! – Matias Kinnunen Feb 21 '18 at 19:20
  • 1
    As reference I include this question which is related and have a better approach: https://stackoverflow.com/questions/48912840/grav-using-shortcodes-in-twig/48913273#48913273 – M.E. Feb 21 '18 at 19:28
1

Others provided good solution with markdown manipulation. However, you could use grav features and provide your own blueprints, and have your user fills some fields.

Let's say this is for a page that uses the template blog_article.html.twig, you can therefore create a file named blog_article.yaml inside user/themes/yourtheme/blueprints and fill it with the following blueprint:

title: Blog_Article
'@extends':
    type: default
    context: blueprints://pages

form:
  fields:
    tabs:
      fields:
        content:
          fields:
            header.mytitle:
              type: text
              label: My Label
            header.mysubtitle:
              type: text
              label: Type Subtitle
            header.mysubsubtitle
              type: text
              label: Type subsubtitle

Now, if you try to edit your page from admin, you will see three new fields added to the page, under the page medias.

You can then display these fields in your template with the following twig:

{{ page.header.mytitle }} 
{{ page.header.mysubtitle }}
{{ page.header.mysubsubtitle }}

Hope it helps

Paul Massendari
  • 417
  • 3
  • 6
  • This is extremely interesting and I will give it a try. I have never used blueprints so far – M.E. Feb 26 '18 at 15:34