From 704027ae024c194987fcffaf75991c3a367ad74b Mon Sep 17 00:00:00 2001 From: Peter Muessig Date: Mon, 1 Jun 2026 13:11:28 +0200 Subject: [PATCH] build: preserve handlebars placeholders in code snippets GitHub Pages renders the markdown via Jekyll/Liquid, which uses the same {{ ... }} / {% ... %} syntax that several tutorial code snippets need to display verbatim (e.g. {{appTitle}} and {{appDescription}} in manifest.json examples). Without escaping, Liquid replaces them with empty strings on the published page. Wrap fenced code blocks and inline code spans with {% raw %} ... {% endraw %} in rewriteLinks() before writing the README.md files to dist/. Inline spans are only wrapped when they actually contain {{ or {% to keep the output minimal. The downloadable source copies under dist//steps are not touched, so the unzipped projects keep the original UI5 i18n placeholders intact. --- tools/builder/prepare-gh-pages.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/builder/prepare-gh-pages.js b/tools/builder/prepare-gh-pages.js index 5b9ae0e2..a1f1d0e6 100644 --- a/tools/builder/prepare-gh-pages.js +++ b/tools/builder/prepare-gh-pages.js @@ -70,6 +70,24 @@ function removeTSfromUI5YAML(ui5yaml) { mkdirSync(join(cwd, "dist"), { recursive: true }); console.log(`👉 Copying root README.md...`); + function escapeCodeBlocks(content) { + // Jekyll/Liquid (used by GitHub Pages) interprets `{{ ... }}` and `{% ... %}` + // inside the markdown. Code snippets (fenced blocks and inline code) often + // contain handlebars-style placeholders like `{{appTitle}}` that must be + // preserved verbatim. Wrap them in `{% raw %}` / `{% endraw %}` so Liquid + // leaves them untouched. + // Fenced code blocks (``` ... ``` or ~~~ ... ~~~). + content = content.replace(/(^|\n)(```|~~~)([^\n]*)\n([\s\S]*?)\n\2(?=\n|$)/g, + (match, lead, fence, info, body) => `${lead}{% raw %}\n${fence}${info}\n${body}\n${fence}\n{% endraw %}`); + // Inline code spans (single or double backticks) on a single line. + content = content.replace(/(`+)(?!`)([^\n`][^\n]*?)\1/g, (match, ticks, body) => { + if (!body.includes("{{") && !body.includes("{%")) { + return match; + } + return `{% raw %}${ticks}${body}${ticks}{% endraw %}`; + }); + return content; + } function rewriteLinks(file) { let permalink = file.split("dist/")[1].replace(".md", ".html"); const title = "UI5 Tutorials"; @@ -77,6 +95,7 @@ function removeTSfromUI5YAML(ui5yaml) { content = content.replace(/README\.md/g, "index.html"); content = content.replace(/\.\/packages\//g, "./"); content = content.replace(/\[LICENSE\]\([\.\/\w]*\)/g, "[LICENSE](https://github.com/UI5/tutorials/blob/-/LICENSE)"); + content = escapeCodeBlocks(content); writeFileSync(file, content, { encoding: "utf8" }); }