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

Open
johnstonphilip opened this issue Mar 17, 2020 · 39 comments
Open

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

johnstonphilip opened this issue Mar 17, 2020 · 39 comments

Comments

Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
@johnstonphilip
Copy link
Contributor

@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.

@jffng
Copy link
Contributor

@jffng jffng commented Mar 18, 2020

Just adding that this seems related to #20542.

@petrozavodsky
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😔

@nicpelletier
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.

@mtias
Copy link
Contributor

@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.

@rilwis
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).

@johnstonphilip
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 theme.zip, 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} -->

@carolinan
Copy link
Contributor

@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.

@wpscholar
Copy link
Member

@wpscholar wpscholar commented Mar 27, 2020

Related: #21204

@wpscholar
Copy link
Member

@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?

@skorasaurus
Copy link
Member

@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

@ockham
Copy link
Contributor

@ockham ockham commented Apr 17, 2020

I wonder if block context, as discussed at #19685 (comment) and implemented in #21467 could be part of a solution to this problem. In short, block context would allow passing information from an ancestor to a descendant block. The canonical example for block context is a Post block (that doesn't necessarily render anything visible itself) that communicate the post's ID to its children, and a wrapped Post Title block that uses it to display that block's title.

The problem we're dealing with in this issue is that in a page template, we're using a number of established general-purpose blocks (such as Cover or Image block) that reference assets that are part of the theme -- which means we cannot simply hardcode absolute URLs. See the examples in #20966 (comment), e.g.

<!-- wp:cover {"url":"https://mystagingsite.local/wp-content/themes/custom-theme-for-client/image.png","id":1575} -->

Using block context (in the example case: to the url attribute from block context) for the present problem would however require some changes/additions:

  • The (arguably) easiest part would be some all-encompassing site block, or just some generally available site context that provides infomation akin to get_bloginfo(). (Maybe only in template editing mode.)
  • In the example, we wouldn't want the entire url attribute to be provided from context; rather, we'd concatenate it from the site's URL, plus the theme's path to the image. That means we'd need to allow for some logic that doesn't map context to attributes 1:1, but allows for some processing of context.
  • UI-wise, we might need to get cute there, as we still want to allow users to pick their image from the file browser; meaning that we'd have to basically remove the blog URL from the full image path in order to get a relative URL.
  • Unlike a Post Title (or Post Author, etc) block, the blocks we're using in templates are general-purpose -- they aren't coupled to the presence of a context but can be used without. Two potential solutions I can think of:
    1. We provide two flavors of those blocks: the general-purpose ones, and opinionated ones that expect their attributes from context. (Downside: Confusing, potentially hard to maintain.)
    2. We merge both flavors into one: Blocks are either general-purpose, or opinionated, depending on where they're used. (E.g. template-editing mode could always imply using the opinionated ones. Also see the very first item in this list)
  • The Cover block is the most-straightforward example, since we're talking about an actual attribute there. The Image block is probably also simple enough, since its src (while attached to and img element) is available through the usual block attributes API (IIRC). However, other examples listed in #20966 (comment) might be harder to tackle, as asset URLs are more implicit there. I don't have a clear answer there.

While the above sounds complex, I think it's still within the expected complexity of full-site editing, and it would use a technology (block context) that seems natural enough in this case.

cc/ @aduth

@ockham
Copy link
Contributor

@ockham ockham commented Apr 20, 2020

Some more thoughts on 'contextual' blocks here: #21728

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 21, 2020

I think we should look at this from a higher level.

The core issue being discussed is that serialized block content's only way of being dynamic is through dynamic blocks. This is an issue for two reasons:

  • We can't nest a dynamic block inside things like an image src to render a dynamic base URL. #20966
  • We can't nest a dynamic block for every bit of text we need to translate. #21204

Block Context is not something that can solve this. We would just be creating template versions of Core blocks or introducing different render paths in the current ones. We would also be forcing all of them to have render_callbacks. Block Context is for hierarchical provision and consumption of data.

Inline PHP in the templates also doesn't solve this, because then parsing and validation would be dependent on the environment and any edits would remove the dynamic parts. Inline PHP conflicts with our goals of full direct manipulation.

I think the root cause is that the granularity for defining dynamic parts of content is too coarse. We can only make entire blocks dynamic, but we also clearly need inline dynamic content. I think the best way to move forward would be to enhance the inline tokens/images/etc. API so that block edits can define inline dynamic tokens.

For example:

function ParagraphEdit() {
	return <I18NRichText />;
}

function ImageEdit() {
	return (
		<img
			src={
				<>
					<BaseURL />
					/path
				</>
			}
		/>
	);
}

These inline blocks should only be available programmatically, not through any inserter, and of course, they'll have their own edit and render_callback implementations. This is very powerful because not only does it provide a way of having inline dynamic content, but it also allows us to customize the editor experience. I.e., we can expose inline UI controls for any needed configurations.

What does everyone think? Have I overlooked anything obvious? @mtias I know you had reservations about adding inline tokens like these, but they still seem like the best way to support what we need both in the editor and front-end.

A more straightforward solution that doesn't solve i18n in post content would be to translate all text in templates and replace all asset URLs. Still, I think it doesn't make sense to add more complexity here when we need something like the inline block approach for i18n later down the line anyway.

@johnstonphilip
Copy link
Contributor Author

@johnstonphilip johnstonphilip commented Apr 21, 2020

@epiqueras Very interesting thought! Can you explain a bit more about this?

These inline blocks should only be available programmatically, not through any inserter

Would the ability to choose a "local" URL as a prefix to an image be available in the Gutenberg UI? If not, how would I use a local path in an image block? Would I need to hardcode something in the post_content?

@ockham
Copy link
Contributor

@ockham ockham commented Apr 21, 2020

[...]
Block Context is not something that can solve this. We would just be creating template versions of Core blocks or introducing different render paths in the current ones.

Yeah, that was basically my proposal. @epiqueras Can you elaborate why that's a no-go?

Inline PHP in the templates also doesn't solve this, because then parsing and validation would be dependent on the environment and any edits would remove the dynamic parts. Inline PHP conflicts with our goals of full direct manipulation.

Agree.

[...]
What does everyone think? Have I overlooked anything obvious? @mtias I know you had reservations about adding inline tokens like these, but they still seem like the best way to support what we need both in the editor and front-end.

I'm trying to think through how the second example would work in practice, upon image upload. Currently, there are different directories for uploaded files (wp-content/uploads/ if memory serves) and themes (wp-content/themes/). Both are customizable through filters -- I don't think there's any guarantee about how they relate to each other. For a theme to be distributable, its assets would need to be colocated with its source (templates). Upon file upload into an image block (in content or template editing mode regardless):

  • Would files still unconditionally end up in the usual uploads directory?
  • Would we then have the block infer the image file's location relative to the uploads folder, and express that location via <BaseURL /> + path?
  • If we were to export the theme for distribution, we'd need to include the image asset, and change the URL in the image block accordingly to point to the asset within the themes folder. I'm not sure that's feasible if we hard-wire BaseURL in the image block. 🤔

I'm not sure how to avoid the latter, unless we implement indeed a different behavior for blocks in template editing: all uploads go to the current theme's folder, and the image block refers to <ThemeBaseURL /> + path from the start.


My hypothesis in #21728 was that a lot of the requirements we have for site editing don't translate back to content (i.e. post/page) editing: strings generally don't need to be translated, and asset URLs work fine when left absolute. (This is what lead me to different code paths or different versions of blocks for site vs content editing.) I'd say that in content editing, we wouldn't normally want e.g. translations at individual block level such as

function ParagraphEdit() {
	return <I18NRichText />;
}

and there's a bit of a risk that such a solution might preclude a later solution for multilingual content (as @noahtallen pointed out in #21728) -- assuming that it might e.g. be post-based rather than block-based.

I'd invite you to join #21728, I think there's been some rather insightful discussion.

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 21, 2020

@johnstonphilip

Would the ability to choose a "local" URL as a prefix to an image be available in the Gutenberg UI? If not, how would I use a local path in an image block? Would I need to hardcode something in the post_content?

The image block would know when to insert it or offer a setting to do so.

@ockham

Yeah, that was basically my proposal. @epiqueras Can you elaborate why that's a no-go?

It doesn't scale once you start needing things like translatable gallery captions, and it forces all of these types of blocks to be server-rendered even if they don't have any other reason to be so.

I'm trying to think through how the second example would work in practice, upon image upload.

We can avoid changing anything with the current upload process. <BaseURL /> would know what to render on the front end based on whether the template is a wp_template or an .html file. Things on the editor should just work.

When exporting a theme, we include the referenced images in the templates in the .zip file.

My hypothesis in #21728 was that a lot of the requirements we have for site editing don't translate back to content (i.e. post/page) editing: strings generally don't need to be translated,...
I'd say that in content editing, we wouldn't normally want e.g. translations at individual block level such as

Anything the user enters could need translation, and most blocks are more than one continuous blob of text: E.g. image captions, quotes, galleries, covers. Furthermore, I think it would be pretty cool if we could allow users to highlight only a specific part of a paragraph and mark it for translation.

@johnstonphilip
Copy link
Contributor Author

@johnstonphilip johnstonphilip commented Apr 21, 2020

@epiqueras if the <BaseURL /> only operates if the source is an .html file, what would happen to all of the image links if the user makes an unrelated edit and saves, thus generating a wp_template?

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 21, 2020

The images can be copied to the uploads folder when that happens.

@johnstonphilip
Copy link
Contributor Author

@johnstonphilip johnstonphilip commented Apr 21, 2020

@epiqueras I was wondering that too. But what if the post has a ton of large images? Would it be necessary to do that migration in batches to ensure no server timeouts? It's also possible that it could cause a server disk space max-out and fail. Just a few thoughts about what might happen with that approach.

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 21, 2020

I don't think a single wp_template will have enough images to cause issues.

@mcsf
Copy link
Contributor

@mcsf mcsf commented Apr 23, 2020

I think the root cause is that the granularity for defining dynamic parts of content is too coarse. We can only make entire blocks dynamic, but we also clearly need inline dynamic content. I think the best way to move forward would be to enhance the inline tokens/images/etc. API so that block edits can define inline dynamic tokens.

These inline blocks should only be available programmatically, not through any inserter, and of course, they'll have their own edit and render_callback implementations. This is very powerful because not only does it provide a way of having inline dynamic content, but it also allows us to customize the editor experience. I.e., we can expose inline UI controls for any needed configurations.

It's not clear how these inline tokens would materialise in such a way that they could be dynamically handled by the server. Right now, consumers of the Inline API, such as Inline Images, don't output anything that looks like a block boundary or any other easily spotted demarcation.

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 23, 2020

Could we add a new boundary to the parser's grammar?

@mcsf
Copy link
Contributor

@mcsf mcsf commented Apr 24, 2020

Could we add a new boundary to the parser's grammar?

Technically yes, or you could even shoehorn something on the side like WordPress did for <!-- more -->, but at that point I'm worried about the overall fragility of this and I worry that we're not exploring our options deeply enough.

One thing to consider is that demarcations of the <!-- kind are just HTML comments. This conforms very well to the model — where our post is ultimately an HTML document — in which things like <!-- more --> sit at the root of the document, in between elements, and blocks are also well formed HTML nodes. However, it is ill-suited for inline tokens that are meant to be inserted inside HTML elements (e.g. as attribute values or even keys). It's not that it can't work — WordPress can guarantee that no <!-- inline-token --> is left on the rendered page — but suddenly we have posts that are no longer "just" runtime-agnostic HTML.

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Apr 24, 2020

I see, so basically with dynamic blocks, because of the delimiters being between elements, the whole document is still valid HTML and can be loaded, and the dynamic blocks will just be left out.

But, with inline tokens, that wouldn't be possible as the document would be invalid.

It wouldn't be "invalid" though, it would just be kind of broken. E.g., the image tag would have a broken href.

This makes me wonder if you want a block that depends on dynamic inline content like base URLs to render at all when opening the document statically. Wouldn't it make more sense to comment out all of the markup for the block, so it doesn't show unless the server renderer runs on the document and has a chance to deal with its inline tokens?

With translatable strings, it would be a bit different so, if the dynamic inline content has a default value, like a default locale, for example. We could leave an uncommented render of the markup in the document with those default values. Then under it include a commented version with the inline tokens that the server renderer can use to replace the uncommented one.

Does that make sense? We could still leverage inline tokens and still render as much as possible using default values when opening documents statically.

@p-jackson
Copy link
Member

@p-jackson p-jackson commented Jun 25, 2020

Maybe we could tag attributes as dynamic with something other than html comments, like using a data- attribute.

The src attribute could have a corresponding data-gb-src attribute. The syntax inside the data-gb-src attribute could be similar to the <!-- syntax, because the inline tokens are very similar to blocks. They're just rendered inside attributes instead of as child content. It would mean the mean the raw html could continue to be valid because data- attributes are inert.

<!-- wp:image {"sizeSlug":"large"} -->
<figure class="wp-block-image size-large">
<img
	data-gb-src="wp:themefile {'path':'image.jpg'} /wp:themefile"
	src="https://mysite.com/path-to-theme-files/image.jpg"
	alt=""
/>
</figure>
<!-- /wp:image -->

That would allow inline tokens to be used for theme files, but the same technique could be used to represent dynamic content for translations. Here the wp:18n inline token translates the image's alt-text.

<!-- wp:image {"sizeSlug":"large"} -->
<figure class="wp-block-image size-large">
<img
	data-gb-src="wp:themefile {'path':'image.jpg'} /wp:themefile"
	src="https://mysite.com/path-to-theme-files/image.jpg"
	data-gb-alt="wp:i18n {'text':'Text to translate'} /wp:i18n"
	alt="Text to translate"
/>
</figure>
<!-- /wp:image -->

Maybe the same 18n inline token could also work like a block too? For translating paragraph content.

<!-- wp:paragraph -->
<p>
<!-- wp:i18n {"text":"Text to translate"} -->
Text to translate
<!-- /wp:i18n -->
</p>
<!-- /wp:paragraph -->

@epiqueras
Copy link
Contributor

@epiqueras epiqueras commented Jun 25, 2020

That's very similar to what I proposed in #21932.

I think the main pushback is the necessity of expanding the grammar and/or parser too early, but I think it might be inevitable.

@aristath
Copy link
Member

@aristath aristath commented Aug 17, 2020

This is a bad idea for many reasons, but it's still an idea, and hasn't been mentioned before (probably because everyone knows it's too bad of an idea to warrant mentioning).
Right now we load template contents using this:

$content = file_get_contents( $path );

We could however allow PHP to be executed in the files using something like this instead:

ob_start();
include $path;
$content = ob_get_clean();

Pros:

  • Would allow translations to work
  • Would allow theme-relative folders to be used
  • theme-authors would be able to use familiar PHP

Cons:

  • It kinda defeats the purpose of using static html files
  • Sets a bad precedence
  • Perhaps security

@mcsf
Copy link
Contributor

@mcsf mcsf commented Aug 19, 2020

@aristath, what about something still PHP-based but simpler (more limited, but also more predictable) such as what is proposed in this particular comment at #21932 (comment)?

This idea already some consensus around it, and only hasn't been tried in a PR yet for lack of time. Now with WP 5.5 done, we'll have more people to see how it feels.

@aristath
Copy link
Member

@aristath aristath commented Aug 19, 2020

I assume you're referring to this comment?

writing templates with inline php.
when saved, it becomes static because it doesn't make sense to mix dynamic and static (edited values).

That is basically what would happen with the above change... When the templates get parsed, the editor sees the "compiled" HTML, and on change the raw HTML gets saved.
It just feels a bit hacky so a better method would be preferable 😅

@aristath
Copy link
Member

@aristath aristath commented Aug 19, 2020

As a sidenote, it would also allow for background-compatibility for non-FSE themes that would want to migrate to FSE... So if twentytwenty for example wanted to be an FSE theme while still mantaining any previous saved user options, things like this would be possible:

<?php if ( 'foo' === get_theme_mod( 'layout', 'foo' ) ) : ?>
BLOCKS CONTENT
<?php else : ?>
OTHER LAYOUT CONTENT
<?php endif; ?>

It would definitely ease transition to FSE themes

@mcsf
Copy link
Contributor

@mcsf mcsf commented Sep 14, 2020

That is basically what would happen with the above change... When the templates get parsed, the editor sees the "compiled" HTML, and on change the raw HTML gets saved.
It just feels a bit hacky so a better method would be preferable 😅

@aristath: right, you're proposing essentially the same thing. Somehow in my reading I interpreted something different. 😅 As you point out afterwards, there are nice advantages to working with the existing environment (PHP).

@cr0ybot
Copy link
Contributor

@cr0ybot cr0ybot commented Feb 26, 2021

All of the problems and proposed solutions in this thread are solved with PHP. Literally all of them.

Introducing a new templating language—whether something established (i.e. Twig) or a custom syntax inserted into HTML comments—does not simplify template development, it complicates it. PHP is already a templating language.

Why do I get the impression that the problem being solved here isn't "how do we make dynamic templates from static files" but rather "how do we get rid of that pesky PHP"? If that is the case can we at least be honest about it?

If the real problem is "themes developed with PHP don't follow the rules often enough because of the low barrier to entry and bad code" then we have to decide if the likely number 1 reason why WordPress powers 40% of the web is worth discarding. Perhaps better documentation and educational resources would be a better approach, or maybe I am naïve. Or maybe the goal is to have less theme developers overall, instead relying on SquareSpace-style site building to increase that percentage further.

However, if the goal is for these theme files to be generated—as in, they are developed purely within the WordPress back-end and saved out/exported—and then imported on other sites, immediately pulled into the database as wp_template entries... I feel like I'm strangely ok with that? Is that the (potential) approach? If these are installed like any other theme with files sitting on the server and referenced during runtime then I would strongly advocate for PHP. But if they just serve as a reference package to be imported into the database and from there dynamically updated, I don't see why they couldn't just be the same kind of markup that WordPress already stores in post_content.

I'm sorry for bringing some sass here, especially fairly late-in-the-game sass. I've only recently discovered all of the discussions happening about FSE. Please feel free to tear me apart!

@pagelab
Copy link

@pagelab pagelab commented Feb 26, 2021

Why do I get the impression that the problem being solved here isn't "how do we make dynamic templates from static files" but rather "how do we get rid of that pesky PHP"? If that is the case can we at least be honest about it?

Maybe #27144 is a better place to discuss this topic, but the problem is not definitely with PHP itself. We owe PHP a lot to say that. But one of the main goals of the Site Editor is indeed to lower the barrier to theme creation, which, as a result, means reducing dependence on a powerful programming language.

By using HTML files for templates and JSON for configuration, we can better achieve this goal.

The issue is that, since WordPress never had a proper template system, simply using a php file gives access to the full spectrum of PHP features – and all the problems, idiosyncrasies and gotchas that come with it.

And let's not forget that traditional methods for theme creation will continue to exist. So there's not that much to lose, I think.

@cr0ybot
Copy link
Contributor

@cr0ybot cr0ybot commented Feb 26, 2021

Maybe #27144 is a better place to discuss this topic

No worries, I'm in there too, also late to the discussion.

By using HTML files for templates and JSON for configuration, we can better achieve this goal.

Is that objectively true, though, when this entire discussion has revolved around inserting more and more functionality into HTML comments or otherwise adding a new templating syntax into the mix? To your point, it would restrict (but not eliminate, considering some of this thread's suggestions) server-side logic for templates, forcing FSE theme developers to do things a certain way.

I'm curious why we are talking about coding these templates manually at all if the ultimate goal is to lower the barrier to theme creation. Why not consider these as static files generated and packaged up for the purpose of "exporting" and "importing" via some WordPress back-end interface for building these themes in a visual editor?

Perhaps I'm getting off-topic, I do apologize. This issue is specifically about how to have dynamic values inside static HTML files and here I am just saying "don't", so on the whole this is probably not useful.

@carlomanf
Copy link

@carlomanf carlomanf commented Feb 26, 2021

However, if the goal is for these theme files to be generated—as in, they are developed purely within the WordPress back-end and saved out/exported—and then imported on other sites, immediately pulled into the database as wp_template entries... I feel like I'm strangely ok with that? Is that the (potential) approach? If these are installed like any other theme with files sitting on the server and referenced during runtime then I would strongly advocate for PHP. But if they just serve as a reference package to be imported into the database and from there dynamically updated, I don't see why they couldn't just be the same kind of markup that WordPress already stores in post_content.

It's kind of a combination of both, since #27910 was merged. The file being pulled into the database as a wp_template entry does not happen immediately, it happens when the user "edits" it. Until that point, the file continues to be referenced during runtime, to allow the site to absorb any future updates that are released by the theme.

But one of the main goals of the Site Editor is indeed to lower the barrier to theme creation

Is it? Theme customisation, yes, but theme creation?

I'm curious why we are talking about coding these templates manually at all if the ultimate goal is to lower the barrier to theme creation. Why not consider these as static files generated and packaged up for the purpose of "exporting" and "importing" via some WordPress back-end interface for building these themes in a visual editor?

I agree with you on this, but I think it's more relevant to #27144, so see my reply there.

@pagelab
Copy link

@pagelab pagelab commented Feb 27, 2021

Is it? Theme customisation, yes, but theme creation?

Yes, this is an actual goal (see #27941).

@caseymilne
Copy link

@caseymilne caseymilne commented Aug 7, 2021

When it comes to images and paths I think it's worth considering that any path to an image could be defined as either:

  1. Valid Path (publicly accessible image, or local readable image)
  2. Invalid Path (cannot read due to faulty path or non-public URL)
  3. Bundled Object (file/image reference is available directly as a base_64 object)
  4. Bundled in Export Package Location (file/image exists in the package being parsed such as /files/ format in a zipped export).

I'm not sure if blocks should be exported with full URL's to their images (or if tokens should be used instead) but let's imagine we do move a block or template that contains full URL's to a different site. I think at this point it's the job of the Site Editor to do a routine on save to validate and fix the block, which would look like:

If valid path, import image and reference it. If invalid path, show validation error and put block in invalid state. If bundled object import to media and reference it. If bundled in export package, import to media and reference it.

Something in the process has to be smart(er). So the question is smarter blocks, smarter export, smarter import? I say put the focus on the importer/validator. Do validate/import on save. Presume that whatever goes into the editor could be copy/paste from a different site or template reload (after local file changes to FSE theme). Handle it there in a similar way to sanitization, provide importing when possible, parse tokens if possible, invalidate the block if needed (or just render broken).

@cr0ybot
Copy link
Contributor

@cr0ybot cr0ybot commented Aug 31, 2021

Is this still really an issue? Block templates and template parts use blocks. Those blocks can be dynamic blocks that get info server-side. Same way that content within a post can have dynamic values without some kind of custom filetype or markup (other than block comments, of course).

@johnstonphilip
Copy link
Contributor Author

@johnstonphilip johnstonphilip commented Aug 31, 2021

@cr0ybot I believe it is still an issue yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment