Considering Reacts popularity, it is an interesting question though if templating languages replaced php and asp or are on the way out again in favor of that style of coding.
Edit: I will add that I have some experience working on apps that do both ways - React mixing HTML and CSS into the JS code (JSX) and Vue with its strange template language which extends HTML for somewhat the opposite approach. I don't really like either one that much. I still actually prefer the string templating library era as cleaner but not without its flaws.
Where PHP got it wrong is that it did just such a hack job of pasting program output into HTML without HTML-aware, injection-free templating for us to endure in the form of DoS attacks. When all this was readily available - you just don't use SGML processing instructions (eg "<?php ..." which is just a fallback method of last resort) but regular, typed entity expansion, with escaping depending on markup context and content model checking for rejecting eg. script elements in user content.
--
[0] - HTML is a tree serialization format, and templates are assembling it by gluing raw, dumb strings together. It's a recipe for disaster. The equivalent thing in SQL is the source of SQL Injection category of bugs. You really should use a tool that respect the semantics of the language.
What tool are you referring to? If one does not exist, why is that?
So instead of reading a template file and interpolating it with strings, you'd write something like (using JS / PHP syntax):
const html =
['form', {action: myHandlerUrl, method: 'post'},
['input', {id: 'key', name: 'key', type: 'hidden', value: randomKey()}],
['button', {type: 'submit'}, "Send!"]];
OutputHtml(html);
With OutputHtml() being the replacement for templating engine. The above structure is semantically a tree, and you can't in any way screw it up as to leave tags incorrectly nested (it won't compile/interpret). It's composable too - you can concatenate a bunch of such representations and always get a result that represents a valid tree. OutputHtml() is relatively easy to write even by yourself, because at any given time, when turning a dynamic value into output HTML, it's apparent how the value has to be converted (and/or "escaped").SQL also has its equivalents of this idea. The most basic of which is "prepared statements" - an API in which, instead of:
query("SELECT foo, bar FROM baz WHERE bar = " + userInput
" AND foo > " + anotherInput);
you write: query(build("SELECT foo, bar FROM baz WHERE bar = ? AND foo > ?"), userInput, anotherInput)
which against gives the API the most basic ability to recognize and encode interpolated values correctly. There are of course more complex libraries available, which let you parametrize any part of an SQL query, while making the generation template respect SQL's semantics, and that use composable representations.