Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
type: unclear
impact: low
effort: low
site: README.md › # Options
---

# Say in the README that `<html-style>`/`<html-script>` bodies are formatted and that `embeddedLanguageFormatting: "off"` is the only (global) way to keep them as written

`getTagParser` in `src/utils/get-parser-name.ts` returns `"css"` for `html-style` with no `type=` test, and `getScriptTagParser` returns `babel-ts`/`json` for `html-script` unless its `type=` falls outside module/text/javascript/application/javascript/importmap/speculationrules/application/json, so both bodies are reprinted by prettier's embedded printers. Marko writes those bodies out verbatim (`packages/runtime-tags/src/translator/core/html-style.ts` parses them with `text: true, preserveWhitespace: true`), so a `--write` changes the rendered bytes of every page that uses the tags, and a project holding a "formatting must not change the rendered output" gate has to read the plugin's source to learn that this is intended. It is intended: `src/__tests__/fixtures/html-style-element` and `src/__tests__/fixtures/script-with-type` pin it, and `getCompiledText` in `src/__tests__/index.test.ts` skips `script`, `html-script`, `style` and `html-style` before asserting the compiled text is unchanged. README.md's only option section is `markoSyntax` and never mentions any of it. Add a paragraph under `# Options` naming the tag bodies that get reformatted, saying that Prettier's `embeddedLanguageFormatting: "off"` is the only lever and that it is global (prettier 3.9.6 returns from `printEmbeddedLanguages` before running `embed` whenever the option is not `"auto"`, so it also stops formatting `<style>`, `<script>`, `static`, attribute values and `${}` placeholders), and that `<html-style>` ignores `type=` entirely while `<html-script>` with an unrecognised `type=` is left as written.

Check: `grep -n -i 'embedded\|html-style\|html-script\|preserve\|verbatim' README.md` exits 1 with no output. Then `pnpm run build && printf '<html-style type="text/css">\n body { margin: 0; padding: 0; }\n</html-style>\n<html-style>#incidents-placeholder { display: none; }</html-style>\n' > /tmp/hs.marko && pnpm exec prettier --no-config --plugin ./dist/index.mjs --parser marko /tmp/hs.marko` expands both bodies to one declaration per line, while adding `--embedded-language-formatting=off` returns the input byte-identical.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
type: bug
impact: high
effort: med
site: src/utils/to-valid-doc.ts › toValidAttrValue
---

# Keep the parentheses around an attribute value that ends in a postfix `!`

`toValidAttrValue` asks htmljs-parser's `isValidAttrValue(code, concise)` whether the printed value has to be wrapped, and that check parses the bare expression to EOF without the `>` terminator, so a value ending in a TypeScript non-null `!` answers `Validity.enclosed` and the function returns the doc untouched, never building the `b.ifBreak("(")` group. htmljs-parser cannot parse that value unparenthesised (`lookBehindForOperator` in its `src/states/EXPRESSION.ts` treats char 33 as a pending operator, so `<const/tenant=input.tenant!>` runs past the `>` and the CompileError lands on the following tag), which makes the parentheses load-bearing rather than cosmetic: `--write` rewrites `<const/tenant=(input.tenant!)>` to `<const/tenant=input.tenant!>`, the template stops compiling, and `--check` then reports the broken file as already formatted. Dropping redundant parentheses is otherwise wanted, and `<div disabled=(1 > 2)>` in the same run keeps its own because that value validates as `invalid`, so the fix is narrow: treat a printed value whose last non-whitespace character is `!` as needing the group. Handing the checker the terminator is not enough on its own, since `isValidAttrValue("input.tenant!>", false)` is also `enclosed`, and a guard keyed on `Validity.valid` would miss the case entirely. No fixture under `src/__tests__/fixtures` puts a postfix `!` at the end of an attribute value, so one belongs with the fix.

Check: `pnpm run build && printf '<const/tenant=(input.tenant!)>\n<const/item=(list[0]!)>\n<div disabled=(1 > 2)>x</div>\n' > /tmp/x.marko && pnpm exec prettier --no-config --plugin ./dist/index.mjs --parser marko /tmp/x.marko` prints `<const/tenant=input.tenant!>`, `<const/item=list[0]!>` and an unchanged `<div disabled=(1 > 2)>x</div>`; compiling that output with `@marko/compiler` at `output: "html"` fails with `Unexpected token, expected "</>/<=/>="` pointing at the next line, while the parenthesised input compiles. Root cause: `node -e 'const {isValidAttrValue,Validity}=require("htmljs-parser");console.log(Validity,isValidAttrValue("input.tenant!",false),isValidAttrValue("input.tenant!>",false),isValidAttrValue("1 > 2",false))'` prints `{ enclosed: 2, invalid: 0, valid: 1 } 2 2 0`.