feat: end types at void, end values at a postfix !, and read delete as an operator - #253
Merged
DylanPiercey merged 2 commits intoSep 28, 2026
Conversation
…tor, and stop after an empty-placeholder error
Inside a type, `void` was read as a prefix operator, so a type ending in
`void` (`export type H = () => void`, `<let/x: void>`, `(): void {`) carried
on into the next line, the open tag end, or the function body. In a type it
is always the `void` type, so it is now only a unary keyword outside types.
A trailing `!` was always read as a prefix operator waiting for an operand,
so a TypeScript non-null assertion ending an unenclosed value (`x!`, `f()!`,
`a[0]!`) swallowed what followed. Directly after an operand it is now
postfix; after a keyword operator (`typeof!`, `in!`) it stays prefix.
`isValidStatement` skipped the `type `/`interface `/`declare ` look-ahead
that statement tags use, so it lexed types as JavaScript and disagreed with
the parser. Both now share `prepareStatement`.
`delete` was missing from the prefix keywords, so `<div a=delete x.y/>` split
into two attributes. It now continues like `typeof` and `void`. `return`,
`throw` and `yield` stay out: JavaScript allows no line break after them.
An empty placeholder (`${}`) reported its error and then still emitted
`onPlaceholder` with an end past the input. It now stops at the error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A misparse fix changes events only for input that errored or compiled to the wrong code, so it ships as a feature. Raising the parser floor in the compiler and prettier-plugin-marko together keeps them agreeing on which values need parentheses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: c821771 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
DylanPiercey
added this pull request to stack #257
September 28, 2026 16:36
void, end values at a postfix !, and read delete as an operator
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #253 +/- ##
=======================================
Coverage 99.95% 99.95%
=======================================
Files 35 35
Lines 4611 4652 +41
Branches 888 896 +8
=======================================
+ Hits 4609 4650 +41
Misses 2 2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes expression misparses that changed events only for input that errored or compiled to the wrong code. Inside a type,
voidis the void type rather than a prefix operator, so a type ending invoid(export type H = () => void,(): void {) no longer runs into the next line or the function body. A!directly after an operand is a TypeScript non-null assertion, so<div title=x! id="a"/>is two attributes; after a keyword operator (typeof!,in!) it stays prefix.deletenow continues a value liketypeofandvoid.isValidStatementshares the parser's type-statement look-ahead, and an empty placeholder stops at its error instead of also emitting a placeholder past the input.Also narrows the AGENTS.md rule: changing events for input that already parses and compiles correctly is breaking, while fixing a misparse ships as a minor.
🤖 Generated with Claude Code