Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Based Themes: Dynamic values in static HTML theme files #20966

johnstonphilip opened this issue Mar 17, 2020 · 10 comments

Block Based Themes: Dynamic values in static HTML theme files #20966

johnstonphilip opened this issue Mar 17, 2020 · 10 comments


Copy link

@johnstonphilip johnstonphilip commented Mar 17, 2020

The problem

There isn't currently a way to define a dynamic URL which uses the current site's domain name as the base in static HTML files for distribution. While this previously could be done in a PHP template file using get_bloginfo( 'url' ), there's no way to define an equivalent variable value in static HTML.

Themes will often include things like images with the theme as part of the design (backgrounds, etc). Blocks facilitate this, in that some blocks have image URL settings. For example, the cover block allows for a background image.

The Theme Experiments repo is currently pulling all included images from an outside source.

But pulling from an outside server is probably not the right approach to delivering a theme.

Possible solutions (all have drawbacks)

1: Parse the HTML files for dynamic values and replace on-the-fly.
Some sort of placeholder could be used in static html files to represent the current site's URL. However, this would require that each HTML file's code be parsed, and the strings be found-and-replaced on-the-fly. This would cause large page slowdowns on every page load.

2: Parse the HTML files for dynamic values and replace once.
Instead of on-the-fly replacing, this would find-and-replace each base TLD in the theme file and re-write the theme's html files upon theme activation, so that the parsing only happens once. But this would result in overwritten theme core files, which would be wiped out upon theme updates. It would also need to be re-done if a theme file was manually edited in any way. This approach would open a whole host of issues like this.

3: Theme files as JSON.
Instead of using static HTML files, theme files could be JSON files, with url values being easy to parse, and the resulting parsed block templates being stored in the database as wp_template. Similar in approach to Alternative 2 (above), the theme files would never be loaded except during theme activation, and then essentially would be forgotten.

JSON is a better format than static HTML when it comes to parsing-and-extracting a value. However, it has similar issues when it comes to editing a theme file after-the-fact, in that the "default" block template in the database would need to be overwritten again. If that default were kept as an immutable post (except via theme json files), it may work.

4: Theme files as PHP
Instead of being used as they have in the past, a PHP file could return a block template with the dynamic portions manually coded. For example:

function my_theme_front_page() {
	return '<!-- wp:cover {"url":"' . get_template_directory_uri() .'/block-background-image.png","id":273,"dimRatio":0,"minHeight":647,"align":"wide"} -->';

There are many drawbacks to this approach as well, though it's likely the least code-complex solution, as it would not require any parsing or finding-and-replacing of values.

Other ideas are definitely welcome, as all of these have problems and drawbacks.


This comment has been minimized.

Copy link

@jffng jffng commented Mar 18, 2020

Just adding that this seems related to #20542.

@youknowriad youknowriad mentioned this issue Mar 18, 2020
6 of 30 tasks complete

This comment has been minimized.

Copy link

@petrozavodsky petrozavodsky commented Mar 20, 2020

php is a great template engine and you need to use it.
Development of blocks for WordPress themes is somehow related to php and this does not introduce additional problems.
Html has no reception, and carries performance degradation😔


This comment has been minimized.

Copy link

@nicpelletier nicpelletier commented Mar 20, 2020

I guest that could translate to option 1 or 2, but could Twig be used? It works well for Symfony and Drupal. Having one less templating language to learn means more time to build cool things.


This comment has been minimized.

Copy link

@mtias mtias commented Mar 23, 2020

@johnstonphilip it'd help to classify the use cases a bit more. The images, for example, depends a bit on whether it's structural or starter content (meant to be replaced by the user). Blocks can be dynamic sources, the fact they can be expressed in an HTML file doesn't affect that. (The site home url, for example, would be handled by the site title block.) That said, the HTML representation is not final as there still needs to be proper handling of translations, which is in the same problem space as mapping urls to the site or theme folder, so gathering more of the examples that would not be handled by a specific block would be useful.


This comment has been minimized.

Copy link

@rilwis rilwis commented Mar 24, 2020

Thanks @mtias for the comment.

I think the dynamic data sources in blocks can be treated similarly as in dynamic blocks, which is already available in Gutenberg (like recent posts, recent comments or widget block).


This comment has been minimized.

Copy link
Contributor Author

@johnstonphilip johnstonphilip commented Mar 24, 2020

@mtias I hope I've understood your question properly here. I believe that the uses cases that are relevant here are any blocks that hardcode dynamic values in the HTML.

Here are a few of the things I see getting hardcoded into the HTML that would need to be replaced:

  • Strings which are hardcoded into the html and require translation.
  • All hardcoded URLs (images, videos, any file) which are hardcoded in the HTML and are intended to be local to the site.
  • Navigation Menu URLs (#20542) which are hardcoded into the HTML.

You're right in that non-hardcoded/dynamic blocks (which do not hardcode any URLs or replaceable things in the HTML) are not part of this issue. For example, the site title block does not hardcode the URL at all in the HTML. It simply adds this: <!-- wp:site-title /-->

Structural vs Starter content

I think that what is structural content and what is starter content will vary based on the situation. For example, a client who says:

Make the whole site for me and send a, I don't want to have to do or edit anything myself

For them, everything is structural as they do not want to edit anything themselves.

"that's what I'm paying you for!!" -- Client

Therefore, I would argue that structural vs starter does not matter, and that every block which hardcodes anything should have these capabilities.

Many blocks affected

To try and narrow it down, I tested all of the Common blocks to see which ones allow for hardcoded URLs. All of them actually do (I tested more than just these but kept to these to keep this brief). For example:

  • Cover Block (hardcoded image URL)
    <!-- wp:cover {"url":"https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png","id":1575} -->

  • Image Block (hardcoded image URL)
    <!-- wp:image {"id":1575,"sizeSlug":"large"} --><figure class="wp-block-image size-large"><img src="https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png" alt="" class="wp-image-1575"/></figure><!-- /wp:image -->

  • Paragraph Block (hardcoded inline image URL)
    <!-- wp:paragraph --><p>Here is some text with an inline image:<img class="wp-image-1575" style="width: 100px;" src="https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png" alt=""></p><!-- /wp:paragraph -->

  • Heading Block (hardcoded inline image URL)
    <!-- wp:heading --><h2>Here's the heading<img class="wp-image-1575" style="width: 100px;" src="https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png" alt=""></h2><!-- /wp:heading -->

  • List Block (hardcoded inline image urls)
    <!-- wp:list --><ul><li>Image 1 <img class="wp-image-1575" style="width: 100px;" src="https://wpengine1.local/wp-content/themes/custom-theme-for-client/image.png" alt=""></li></ul><!-- /wp:list -->

  • Quote Block (hardcoded inline image urls)
    <!-- wp:quote --><blockquote class="wp-block-quote"><p>Hello world <img class="wp-image-1575" style="width: 100px;" src="https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png" alt=""></p><cite>Brian Kernighan</cite></blockquote><!-- /wp:quote -->

  • Audio File Block (hardcoded audio url)
    <!-- wp:audio {"id":234} --><figure class="wp-block-audio"><audio controls src="https://mystagingsite.local/wp-content/themes/custom-theme-for-client/song.mp3"></audio></figure><!-- /wp:audio -->

Another possible solution

@nicpelletier While Twig is an approach that could work, I wonder about frontend-only blocks. They wouldn't be rendered on the server, and would require this type of dynamic templating on the frontend.

@BMO-tech mentioned in the core-editor meeting that we should look at Mustache templates for this as they are language agnostic, and could be used in either PHP or Javascript.

Here's how it might work with Mustache templates:
<!-- wp:cover {"url":"{{template_directory_uri}}/image.png","id":1575} -->


This comment has been minimized.

Copy link

@carolinan carolinan commented Mar 27, 2020

Related to this is the translations.
For block patterns and templates to be able to showcase to a user what they look like, they do not only need image content or links, they may also need text.
We can't translate text in plain html.


This comment has been minimized.

Copy link

@wpscholar wpscholar commented Mar 27, 2020

Related: #21204


This comment has been minimized.

Copy link

@wpscholar wpscholar commented Mar 27, 2020

Unlike PHP theme templates, HTML templates don’t allow us to conditionally apply classes to a parent element based on whether or not, for example, a featured image exists on a post. Are we going to lean on JavaScript for this?


This comment has been minimized.

Copy link

@skorasaurus skorasaurus commented Apr 9, 2020

ACF are another dynamic example. For example, having a page where the content is already included from using get_field

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
10 participants
You can’t perform that action at this time.