fix: svelte missing expression parsing#10275
Conversation
🦋 Changeset detectedLatest commit: bc4bca0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR adds a changeset and updates Svelte/HTML parsing: the lexer’s Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_html_parser/src/lexer/mod.rs (1)
501-538: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winAdd regression test for empty and whitespace-only expressions (
{}and{ }).Per project guidelines, bug fixes require tests that reproduce and validate the fix. Add a parser snapshot test (or Svelte fixture) covering at minimum
{}(empty expression) and{ }(whitespace-only expression) to prevent regression of the fix to issue#10274.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_html_parser/src/lexer/mod.rs` around lines 501 - 538, Add a regression test that exercises the lexer/parser behavior fixed in consume_single_text_expression: create a parser snapshot (or Svelte fixture) that includes at minimum the HTML snippets containing `{}` and `{ }`, parse them and assert the resulting token/AST snapshot so we verify that `{}` yields an R_CURLY token (no HTML_LITERAL) and that `{ }` treats the space as trivia (whitespace token/newline handling) rather than part of an expression literal; name the test to reference issue `#10274` and place it alongside existing parser/lexer snapshot tests so it runs in CI.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/biome_html_parser/src/lexer/mod.rs`:
- Around line 502-513: The WHS guard currently triggers for any leading
whitespace in consume_single_text_expression() and should be narrowed to only
handle truly empty expressions (e.g., `{}` / `{ }`). Change the branch so that
when current byte is whitespace (lookup_byte(current) == WHS) you scan ahead for
the next non-whitespace byte and only call consume_newline_or_whitespaces() if
that next non-whitespace byte is a right-curly (b'}'); otherwise leave the
whitespace to be part of the expression as before. Use the existing
current_byte()/lookup_byte() helpers and the existing
consume_newline_or_whitespaces()/advance() logic; add a small lookahead loop (or
helper) to find the next non-whitespace byte and compare it to b'}' before
consuming trivia.
---
Outside diff comments:
In `@crates/biome_html_parser/src/lexer/mod.rs`:
- Around line 501-538: Add a regression test that exercises the lexer/parser
behavior fixed in consume_single_text_expression: create a parser snapshot (or
Svelte fixture) that includes at minimum the HTML snippets containing `{}` and
`{ }`, parse them and assert the resulting token/AST snapshot so we verify that
`{}` yields an R_CURLY token (no HTML_LITERAL) and that `{ }` treats the space
as trivia (whitespace token/newline handling) rather than part of an expression
literal; name the test to reference issue `#10274` and place it alongside existing
parser/lexer snapshot tests so it runs in CI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: da92c6c8-15e3-49a3-b530-50f058c25876
⛔ Files ignored due to path filters (53)
crates/biome_html_parser/tests/html_specs/error/svelte/attach.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_before_then.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_catch_only_missing_binding.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_catch.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_duplicate_then.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_catch_only_with_clause.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_invalid_shorthand_with_clause.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_catch_binding.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_close.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_then_binding.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_shorthand_missing_binding.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/await_unclosed.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/const.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/const_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/html.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/if_else_if_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/if_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/key_missing_close.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/key_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/render.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_close.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/snippet_missing_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/snippet_unclosed.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/svelte/spread.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/attach.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_array_destructuring.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_no_then.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_catch_only.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_complex_expression.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_destructuring.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_dynamic_import.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_nested.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_no_catch.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_shorthand.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/const.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/directives/out_combined_with_in.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/html.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/if.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/if_else.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/if_else_if_else.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/key.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/render.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_array_destructuring.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_basic.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_default_values.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_destructuring.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_multiple.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_nested.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_recursive.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/snippet_with_params.svelte.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (2)
.changeset/ninety-lions-rescue.mdcrates/biome_html_parser/src/lexer/mod.rs
| if let Some(current) = self.current_byte() { | ||
| // emit leading whitespace as trivia so it's not part of the expression literal | ||
| if lookup_byte(current) == WHS { | ||
| return self.consume_newline_or_whitespaces(); | ||
| } | ||
| // when immediately at `}`, lex it as R_CURLY so the parser can recognize | ||
| // it as the closing brace rather than emitting an empty HTML_LITERAL | ||
| if current == b'}' { | ||
| self.advance(1); | ||
| return R_CURLY; | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check existing snapshot fixtures for Svelte single-expression patterns
# to confirm leading-whitespace cases are covered.
rg -rn --type=txt "^\{[ \t]" crates/biome_html_parser/
rg -rn --type=txt "^\{[ \t]" crates/ --iglob "*.snap"Repository: biomejs/biome
Length of output: 26608
🏁 Script executed:
# Find HTML parser test files
find crates/biome_html_parser -type f -name "*.rs" -path "*/tests/*" | head -20Repository: biomejs/biome
Length of output: 191
🏁 Script executed:
# Look for snapshot files in HTML parser tests
fd -e snap crates/biome_html_parser/tests/ | head -20Repository: biomejs/biome
Length of output: 487
🏁 Script executed:
# Search for HtmlSyntaxKind definition and R_CURLY token
rg "enum HtmlSyntaxKind" crates/biome_html_parser/ -A 50Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for R_CURLY definition
rg "R_CURLY|r_curly" crates/biome_html_parser/Repository: biomejs/biome
Length of output: 50370
🏁 Script executed:
# Look for issue `#10274` references
rg "10274" crates/biome_html_parser/Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find .svelte test input files in the HTML parser tests
find crates/biome_html_parser/tests -name "*.svelte" | head -20Repository: biomejs/biome
Length of output: 1784
🏁 Script executed:
# Look at one of the test files that likely has empty expressions
cat crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelte.snap | head -50Repository: biomejs/biome
Length of output: 1969
🏁 Script executed:
# Try to find the original .svelte input file (if it exists separately)
find crates/biome_html_parser/tests -type f -name "*await_one_linter*"Repository: biomejs/biome
Length of output: 214
🏁 Script executed:
# Search for HtmlSyntaxKind in the syntax module
rg "R_CURLY" crates/biome_html_parser/src/ | head -30Repository: biomejs/biome
Length of output: 511
🏁 Script executed:
# Search for the source of HTML syntax definitions
fd -e rs "syntax" crates/biome_html_parser/src/ | head -10Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Read the actual test input file for await_one_linter
cat crates/biome_html_parser/tests/html_specs/ok/svelte/await_one_linter.svelteRepository: biomejs/biome
Length of output: 137
🏁 Script executed:
# Search for empty single text expression test cases
rg "^\{ *\}" crates/biome_html_parser/tests/html_specs/ -t svelteRepository: biomejs/biome
Length of output: 88
🏁 Script executed:
# Look at the lexer tests to understand the token better
cat crates/biome_html_parser/src/lexer/tests.rs | head -100Repository: biomejs/biome
Length of output: 3328
🏁 Script executed:
# Search for the issue number or PR reference in the modified file
rg "10274" crates/biome_html_parser/Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check the git history or comments around the modified lines
sed -n '490,530p' crates/biome_html_parser/src/lexer/mod.rsRepository: biomejs/biome
Length of output: 1501
🏁 Script executed:
# Search for test files with empty braces in Svelte tests
rg -g "*.svelte" "\{\}" crates/biome_html_parser/tests/html_specs/Repository: biomejs/biome
Length of output: 165
🏁 Script executed:
# Look for any test with just whitespace between braces
rg -g "*.svelte" "\{[ ]*\}" crates/biome_html_parser/tests/html_specs/ | head -20Repository: biomejs/biome
Length of output: 165
🏁 Script executed:
# Check if there's a specific test file or PR info mentioning the fix
rg "empty.*expression\|expression.*literal" crates/biome_html_parser/src/lexer/ -iRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look at the entire consume_single_text_expression function
sed -n '502,540p' crates/biome_html_parser/src/lexer/mod.rsRepository: biomejs/biome
Length of output: 1330
🏁 Script executed:
# Search for any test cases that specifically test this function or the WHS behavior
rg "consume_single_text_expression\|TextExpression.*Single" crates/biome_html_parser/ -A 3Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for any test input files (ok or error) that might test empty expressions
find crates/biome_html_parser/tests/html_specs -type f -name "*.svelte" | xargs grep -l "^{}"Repository: biomejs/biome
Length of output: 41
🏁 Script executed:
# Search for test files mentioning "empty"
find crates/biome_html_parser/tests/html_specs -type f -name "*.svelte" | xargs basename -a | grep -i emptyRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look at the test runner to understand how snapshots are generated
cat crates/biome_html_parser/tests/spec_test.rs | head -80Repository: biomejs/biome
Length of output: 2208
🏁 Script executed:
# Check if there's a test input file for the fix (may have been added recently)
ls -lah crates/biome_html_parser/tests/html_specs/ok/svelte/ | grep -i "expression\|empty" | head -20Repository: biomejs/biome
Length of output: 709
🏁 Script executed:
# Search for any document or changelog mentioning this change
rg "leading.*whitespace\|whitespace.*leading" crates/biome_html_parser/ -iRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look for any recent test files or check the git history for added test files
git log --oneline --name-only --all -- "crates/biome_html_parser/tests/html_specs/ok/svelte/*.svelte" 2>/dev/null | head -50Repository: biomejs/biome
Length of output: 4097
🏁 Script executed:
# Alternative: search the snapshots themselves for evidence of the fix being tested
# Look for snapshots with both empty literals or R_CURLY with specific patterns
rg "HTML_LITERAL.*@.*\.\." crates/biome_html_parser/tests/html_specs/ok/svelte/ | grep -E "\@[0-9]+\.\.[0-9]+" | head -10Repository: biomejs/biome
Length of output: 1548
🏁 Script executed:
# Final check: See if there's any test mentioning "TextExpression" or single expression
rg "TextExpression.*Single\|HtmlTextExpression" crates/biome_html_parser/tests/ -A 2Repository: biomejs/biome
Length of output: 39
Wider-than-intended scope: the WHS guard applies to ALL single text expressions with leading whitespace, not just empty ones.
The new whitespace guard (lines 504–507) fires on any call to consume_single_text_expression where the next byte is whitespace, regardless of whether the expression is empty or not. A template like { foo } now emits whitespace as trivia before lexing the expression content, altering the CST for every leading-whitespace case—not only {} / { }.
The PR description acknowledges this is intentional ("Removes leading whitespace from parsed expressions"), but the scope change warrants confirming that downstream consumers (formatter, etc.) handle the new trivia token structure correctly. Existing snapshot tests should surface regressions if the CST change causes issues, though a targeted regression test for the empty-expression case ({}) would be helpful for clarity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/biome_html_parser/src/lexer/mod.rs` around lines 502 - 513, The WHS
guard currently triggers for any leading whitespace in
consume_single_text_expression() and should be narrowed to only handle truly
empty expressions (e.g., `{}` / `{ }`). Change the branch so that when current
byte is whitespace (lookup_byte(current) == WHS) you scan ahead for the next
non-whitespace byte and only call consume_newline_or_whitespaces() if that next
non-whitespace byte is a right-curly (b'}'); otherwise leave the whitespace to
be part of the expression as before. Use the existing
current_byte()/lookup_byte() helpers and the existing
consume_newline_or_whitespaces()/advance() logic; add a small lookahead loop (or
helper) to find the next non-whitespace byte and compare it to b'}' before
consuming trivia.
There was a problem hiding this comment.
Unsure if this is a valid concern, would appreciate input from humans on this comment
Merging this PR will not alter performance
Comparing Footnotes
|
dyc3
left a comment
There was a problem hiding this comment.
Not entirely convinced this is the right way to fix this.
|
also, you didn't add any tests |
|
imo the snap fixtures cover enough, but i can add explicit tests as well |
|
There were a lot of snapshot changes. if you think an existing one already covers this case, then you can just point me to it |
|
if_missing_expression.svelte.snap displays the correct parsing behaviour now. there's nothing to throw up something is wrong when this is parsed incorrectly though. i have a thought on a more explicit test i'd like to add regardless, will commit soon. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_html_parser/src/lexer/mod.rs (1)
501-536:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd an explicit test covering the fixed path in
consume_single_text_expression.The existing new test files (
if_missing_expression.svelte,await_missing_expression.svelte, etc.) exercise block constructs that route throughconsume_restricted_single_text_expression, not through the code changed here (HtmlLexContext::TextExpression(TextExpressionKind::Single)). The actual regression — a plain{}or{ }expression interpolation in Svelte text content — has no dedicated test input yet.A minimal
error/svelte/fixture that reproduces issue#10274would look like:<p>{}</p> <p>{ }</p>Per coding guidelines: "bug fixes require tests that reproduce and validate the fix."
Happy to draft the snapshot fixture if useful — just say the word.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_html_parser/src/lexer/mod.rs` around lines 501 - 536, The change to consume_single_text_expression (and the HtmlLexContext::TextExpression(TextExpressionKind::Single) path) lacks a regression test: add a new snapshot fixture under error/svelte/ that contains a minimal Svelte file exercising an empty interpolation (e.g. a file with "<p>{}</p>" and another with "<p>{ }</p>" or a single fixture containing both) so the lexer path in consume_single_text_expression is executed and the parser snapshot verifies the fix; ensure the new test is named to match other error fixtures and is included in the test discovery so the empty `{}` interpolation case is covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/biome_html_parser/src/lexer/mod.rs`:
- Around line 501-536: The change to consume_single_text_expression (and the
HtmlLexContext::TextExpression(TextExpressionKind::Single) path) lacks a
regression test: add a new snapshot fixture under error/svelte/ that contains a
minimal Svelte file exercising an empty interpolation (e.g. a file with
"<p>{}</p>" and another with "<p>{ }</p>" or a single fixture containing both)
so the lexer path in consume_single_text_expression is executed and the parser
snapshot verifies the fix; ensure the new test is named to match other error
fixtures and is included in the test discovery so the empty `{}` interpolation
case is covered.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1095e313-21da-49f1-b2fa-f3bd5b63e99d
📒 Files selected for processing (1)
crates/biome_html_parser/src/lexer/mod.rs
|
@dyc3 i've moved the rcurly handling out of the lexer into the parser in |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/biome_html_parser/src/lexer/mod.rs (1)
502-505:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftWHS guard scope: trivia-strips leading whitespace from ALL single-text expressions, not only empty ones.
For
{ foo }, the CST changes from a singleHTML_LITERAL(" foo ")token toWHITESPACE(" ") + HTML_LITERAL("foo "). This is acknowledged in the PR description as intentional, but — as the previous review flagged — it's broader than the minimal fix for{}/{ }. It's worth explicitly confirming that:
- Snapshot diffs for non-empty expressions are intentional (not accidental regressions).
- The Svelte formatter handles the new trivia structure for
{ foo }correctly.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_html_parser/src/lexer/mod.rs` around lines 502 - 505, The current guard on emitting leading whitespace as trivia (the if using self.current_byte(), lookup_byte, WHS and calling consume_newline_or_whitespaces()) is too broad and strips whitespace for all single-text expressions like `{ foo }`; restrict it so it only strips trivia when the braces contain no non-whitespace (i.e., truly empty or only newline/space before the closing brace). Update the condition in the lexer to scan forward from the current position to the next non-whitespace byte and only call consume_newline_or_whitespaces() when that byte is the closing brace `}` (or EOF), leaving whitespace as part of HTML_LITERAL for non-empty expressions; use the existing helpers (current_byte(), lookup_byte(), WHS, consume_newline_or_whitespaces()) or a small inline scan loop to find the next non-WHS byte before deciding.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/biome_html_parser/src/syntax/mod.rs`:
- Around line 851-857: Add a unit/integration test that reproduces the original
bug fixed in the parsing logic around
p.cur_text()/p.re_lex(HtmlReLexContext::Svelte) returning Absent: create an
input fixture (e.g. if_missing_expression.svelte) that previously produced the
failing snapshot, add a test that parses this fixture through the same
entrypoint used in crates/biome_html_parser (calling into the module containing
the logic with p.cur_text()/p.re_lex and expecting the Absent behavior), and
assert the parser output matches the updated snapshot (or explicit expected
AST); ensure the test lands in the crate test suite and references the updated
snapshot file so CI will validate the regression is prevented going forward.
---
Duplicate comments:
In `@crates/biome_html_parser/src/lexer/mod.rs`:
- Around line 502-505: The current guard on emitting leading whitespace as
trivia (the if using self.current_byte(), lookup_byte, WHS and calling
consume_newline_or_whitespaces()) is too broad and strips whitespace for all
single-text expressions like `{ foo }`; restrict it so it only strips trivia
when the braces contain no non-whitespace (i.e., truly empty or only
newline/space before the closing brace). Update the condition in the lexer to
scan forward from the current position to the next non-whitespace byte and only
call consume_newline_or_whitespaces() when that byte is the closing brace `}`
(or EOF), leaving whitespace as part of HTML_LITERAL for non-empty expressions;
use the existing helpers (current_byte(), lookup_byte(), WHS,
consume_newline_or_whitespaces()) or a small inline scan loop to find the next
non-WHS byte before deciding.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0edbef65-3706-4f72-8a49-20a050412ecf
⛔ Files ignored due to path filters (1)
crates/biome_html_parser/tests/html_specs/error/svelte/await_missing_expression.svelte.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (2)
crates/biome_html_parser/src/lexer/mod.rscrates/biome_html_parser/src/syntax/mod.rs
| if p.cur_text().is_empty() { | ||
| p.bump_remap(HTML_LITERAL); | ||
| p.re_lex(HtmlReLexContext::Svelte); | ||
| return Absent; | ||
| } | ||
| if p.cur_text().trim().is_empty() { | ||
| return Absent; | ||
| } |
There was a problem hiding this comment.
Missing test for the bug fix, as required by coding guidelines.
The coding guidelines mandate that bug fixes include a test that reproduces and validates the fix. The snapshot files update for if_missing_expression.svelte.snap is a good signal, but there is no dedicated input fixture (or explicit unit test) that was committed as part of this PR. The PR thread confirms one was promised but not yet delivered.
As per coding guidelines: "bug fixes require tests that reproduce and validate the fix."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@crates/biome_html_parser/src/syntax/mod.rs` around lines 851 - 857, Add a
unit/integration test that reproduces the original bug fixed in the parsing
logic around p.cur_text()/p.re_lex(HtmlReLexContext::Svelte) returning Absent:
create an input fixture (e.g. if_missing_expression.svelte) that previously
produced the failing snapshot, add a test that parses this fixture through the
same entrypoint used in crates/biome_html_parser (calling into the module
containing the logic with p.cur_text()/p.re_lex and expecting the Absent
behavior), and assert the parser output matches the updated snapshot (or
explicit expected AST); ensure the test lands in the crate test suite and
references the updated snapshot file so CI will validate the regression is
prevented going forward.
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2415) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15) ##### Patch Changes - [#​9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about. - [#​10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`. For example, the following snippet triggers the rule: ```js import { nextTick } from "vue"; nextTick(() => { updateDom(); }); ``` - [#​10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives. For example, the following snippet triggers the rule: ```vue <input @​keyup.13="submit" /> ``` - [#​10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables. - [#​10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available. - [#​10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@​realknove](https://github.com/realknove)! - Fixed [#​10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers. - [#​9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is. - [#​10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group. The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group. ```json { "assist": { "actions": { "source": { "organizeImports": { "options": { "groups": [":INEXISTENT:"] } } } } } } ``` - [#​10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`). These functions are now reported because `null` and `number` are included in the return annotations but never returned: ```ts function getUser(): string | null { return "hello"; } // null is never returned function getCode(): string | number { return "hello"; } // number is never returned ``` - [#​10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line. - [#​10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`. This function is now reported because the return annotation widens a property initialized with `as const`: ```ts function f(): { value: string } { return { value: "text" as const }; } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`. This conversion is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "text" as const }; String(message.value); ``` - [#​9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`. The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options. **Invalid**: ```js class Foo { bar() { // does not use `this`, invalid console.log("Hello Biome"); } } ``` - [#​10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@​ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated. - [#​10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts. - [#​9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option. - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`. This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it: ```ts const status = { kind: "ready" as const }; switch (status.kind) { } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`. This comparison is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "hello" as const }; message.value[0] === "h"; ``` </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/12
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2415) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15) ##### Patch Changes - [#​9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about. - [#​10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`. For example, the following snippet triggers the rule: ```js import { nextTick } from "vue"; nextTick(() => { updateDom(); }); ``` - [#​10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives. For example, the following snippet triggers the rule: ```vue <input @​keyup.13="submit" /> ``` - [#​10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables. - [#​10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available. - [#​10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@​realknove](https://github.com/realknove)! - Fixed [#​10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers. - [#​9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is. - [#​10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group. The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group. ```json { "assist": { "actions": { "source": { "organizeImports": { "options": { "groups": [":INEXISTENT:"] } } } } } } ``` - [#​10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`). These functions are now reported because `null` and `number` are included in the return annotations but never returned: ```ts function getUser(): string | null { return "hello"; } // null is never returned function getCode(): string | number { return "hello"; } // number is never returned ``` - [#​10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line. - [#​10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`. This function is now reported because the return annotation widens a property initialized with `as const`: ```ts function f(): { value: string } { return { value: "text" as const }; } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`. This conversion is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "text" as const }; String(message.value); ``` - [#​9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`. The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options. **Invalid**: ```js class Foo { bar() { // does not use `this`, invalid console.log("Hello Biome"); } } ``` - [#​10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@​ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated. - [#​10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts. - [#​9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option. - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`. This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it: ```ts const status = { kind: "ready" as const }; switch (status.kind) { } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`. This comparison is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "hello" as const }; message.value[0] === "h"; ``` </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/3
Summary
#10140 introduced messy parsing for templates without expressions. This PR addresses it by firstly parsing whitespace before the beginning of expressions as whitespace trivia, and then checking for an immediate
b'}'before attempting to parse an expression.Fixes #10274.
Test Plan
Existing tests satisfy changes.
Notes
This touches a lot of svelte parsing behaviour by removing the whitespace from the beginning of parsed expressions. Not fully certain that this doesn't affect other functionality.