Skip to content
This repository was archived by the owner on Dec 8, 2025. It is now read-only.

Conversation

@asilano
Copy link
Collaborator

@asilano asilano commented Sep 29, 2025

Simply a merge of upstream commits. Locally, I had to fix a conflict in playground/package.json as upstream had pinned a v7.x version to fix a dependency alert which I had fixed with a v6.x pin.

Commit messages from upstream: - **Update Snapshot file**

marcoroth and others added 30 commits September 9, 2025 16:46
…ctory (marcoroth#493)

Bumps the npm_and_yarn group with 1 update in the / directory:
[vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).

Updates `vite` from 6.3.5 to 6.3.6

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This pull request updates the parser to allow HTML Attributes to start
with a colon, which is typical in the Vue.js style:

```html
<div :class="classes"></div>
```

Previously, this caused a syntax error: 
```js
@ UnexpectedError (location: (1:5)-(1:6))
├── message: "Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_COLON`."
├── description: "Unexpected Token"
├── expected: "TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE"
└── found: "TOKEN_COLON"
```

Now this parses as:

```js
@ HTMLAttributeNode (location: (1:5)-(1:21))
├── errors: []
├── name: 
│   └── @ HTMLAttributeNameNode (location: (1:5)-(1:11))
│       ├── errors: []
│       └── children: (1 item)
│           └── @ LiteralNode (location: (1:5)-(1:11))
│               ├── errors: []
│               └── content: ":class"
│                      
├── equals: "=" (location: (1:11)-(1:12))
└── value: 
    └── @ HTMLAttributeValueNode (location: (1:12)-(1:21))
        ├── errors: []
        ├── open_quote: """ (location: (1:12)-(1:13))
        ├── children: (1 item)
        │   └── @ LiteralNode (location: (1:13)-(1:20))
        │       ├── errors: []
        │       └── content: "classes"
        │       
        │   
        ├── close_quote: """ (location: (1:20)-(1:21))
        └── quoted: true
```
I noticed a problem where the symptom was a wrong font used in the
template. this is because the html was somehow escaped wrong. I removed
the escape and everything seems to work just fine.

<img width="1546" height="408" alt="CleanShot 2025-09-08 at 20 33 54@2x"
src="https://github.com/user-attachments/assets/d9be670b-e868-4eba-aa0f-274ecf61a9e7"
/>

Co-authored-by: Marco Roth <marco.roth@intergga.ch>
…LI (marcoroth#466)

This allows calling `herb-format` with arguments for customizing width (
`--indent-width` ) and line length ( `--max-line-length`)

The expected behavior is to use the json config, but allowing cli args
opens up to some workarounds while we don't have all integrations (eg:
Zed)
When opening a link on ReActionView there's no possibility to open the
source code with Cursor, it's opening VSCode by default.

By adding the editor here I can open cursor now.
This pull request updates the Ruby C-Extension to use
`rb_utf8_str_new_cstr()` over `rb_str_new_cstr()` when constructing Ruby
Strings from the C `char[]`.

This ensures we always have a UTF-8 string so we don't trigger a
`Encoding::CompatibilityError (incompatible character encodings: BINARY
(ASCII-8BIT) and UTF-8)` when concatenating strings.

It looks like `rb_str_new_cstr()` sometimes produces an `UTF-8` string
and sometimes an `ASCII-8BIT` string based on the content.

Resolves marcoroth#492
Resolves marcoroth/reactionview#4
…rom the opening div (marcoroth#501)

`parser_advance` consumes the `TOKEN_HTML_TAG_END`, which ends up not
closing the opening tag.

Snapshot diff (most notably, only a single `HTMLAttributeNode` and
`HTMLCloseTagNode` now appears):

<details><summary>Diff</summary>
<p>

```patch
diff --git a/test/snapshots/parser/attributes_test/test_0046_Empty_attribute_value_with_closing_bracket_immediatly_following_it_56df6b7e184a50db1eac62508206a332.txt b/test/snapshots/parser/attributes_test/test_0046_Empty_attribute_value_with_closing_bracket_immediatly_following_it_56df6b7e184a50db1eac62508206a332.txt
index 41997bb..0f1e93e 100644
--- a/test/snapshots/parser/attributes_test/test_0046_Empty_attribute_value_with_closing_bracket_immediatly_following_it_56df6b7e184a50db1eac62508206a332.txt
+++ b/test/snapshots/parser/attributes_test/test_0046_Empty_attribute_value_with_closing_bracket_immediatly_following_it_56df6b7e184a50db1eac62508206a332.txt
@@ -1,61 +1,49 @@
 @ DocumentNode (location: (1:0)-(1:38))
-├── errors: (1 error)
-│   └── @ UnclosedElementError (location: (1:38)-(1:38))
-│       ├── message: "Tag `<div>` opened at (1:1) was never closed before the end of document."
-│       └── opening_tag: "div" (location: (1:1)-(1:4))
-│
 └── children: (1 item)
     └── @ HTMLElementNode (location: (1:0)-(1:38))
-        ├── errors: (1 error)
-        │   └── @ MissingClosingTagError (location: (1:1)-(1:4))
-        │       ├── message: "Opening tag `<div>` at (1:1) doesn't have a matching closing tag `</div>`."
-        │       └── opening_tag: "div" (location: (1:1)-(1:4))
-        │
         ├── open_tag:
-        │   └── @ HTMLOpenTagNode (location: (1:0)-(1:38))
+        │   └── @ HTMLOpenTagNode (location: (1:0)-(1:21))
         │       ├── tag_opening: "<" (location: (1:0)-(1:1))
         │       ├── tag_name: "div" (location: (1:1)-(1:4))
-        │       ├── tag_closing: ">" (location: (1:37)-(1:38))
-        │       ├── children: (2 items)
-        │       │   ├── @ HTMLAttributeNode (location: (1:5)-(1:21))
-        │       │   │   ├── name:
-        │       │   │   │   └── @ HTMLAttributeNameNode (location: (1:5)-(1:19))
-        │       │   │   │       └── children: (1 item)
-        │       │   │   │           └── @ LiteralNode (location: (1:5)-(1:19))
-        │       │   │   │               └── content: "attribute-name"
-        │       │   │   │
-        │       │   │   │
-        │       │   │   ├── equals: "=" (location: (1:19)-(1:20))
-        │       │   │   └── value:
-        │       │   │       └── @ HTMLAttributeValueNode (location: (1:20)-(1:21))
-        │       │   │           ├── errors: (1 error)
-        │       │   │           │   └── @ UnexpectedError (location: (1:20)-(1:21))
-        │       │   │           │       ├── message: "Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_QUOTE, TOKEN_ERB_START`, found: `TOKEN_HTML_TAG_END`."
-        │       │   │           │       ├── description: "Unexpected Token"
-        │       │   │           │       ├── expected: "TOKEN_IDENTIFIER, TOKEN_QUOTE, TOKEN_ERB_START"
-        │       │   │           │       └── found: "TOKEN_HTML_TAG_END"
-        │       │   │           │
-        │       │   │           ├── open_quote: ∅
-        │       │   │           ├── children: []
-        │       │   │           ├── close_quote: ∅
-        │       │   │           └── quoted: false
-        │       │   │
-        │       │   │
-        │       │   └── @ HTMLAttributeNode (location: (1:21)-(1:37))
+        │       ├── tag_closing: ">" (location: (1:20)-(1:21))
+        │       ├── children: (1 item)
+        │       │   └── @ HTMLAttributeNode (location: (1:5)-(1:21))
         │       │       ├── name:
-        │       │       │   └── @ HTMLAttributeNameNode (location: (1:21)-(1:37))
+        │       │       │   └── @ HTMLAttributeNameNode (location: (1:5)-(1:19))
         │       │       │       └── children: (1 item)
-        │       │       │           └── @ LiteralNode (location: (1:21)-(1:37))
-        │       │       │               └── content: "div-content</div"
+        │       │       │           └── @ LiteralNode (location: (1:5)-(1:19))
+        │       │       │               └── content: "attribute-name"
         │       │       │
         │       │       │
-        │       │       ├── equals: ∅
-        │       │       └── value: ∅
+        │       │       ├── equals: "=" (location: (1:19)-(1:20))
+        │       │       └── value:
+        │       │           └── @ HTMLAttributeValueNode (location: (1:20)-(1:21))
+        │       │               ├── errors: (1 error)
+        │       │               │   └── @ UnexpectedError (location: (1:20)-(1:21))
+        │       │               │       ├── message: "Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_QUOTE, TOKEN_ERB_START`, found: `TOKEN_HTML_TAG_END`."
+        │       │               │       ├── description: "Unexpected Token"
+        │       │               │       ├── expected: "TOKEN_IDENTIFIER, TOKEN_QUOTE, TOKEN_ERB_START"
+        │       │               │       └── found: "TOKEN_HTML_TAG_END"
+        │       │               │
+        │       │               ├── open_quote: ∅
+        │       │               ├── children: []
+        │       │               ├── close_quote: ∅
+        │       │               └── quoted: false
+        │       │
         │       │
         │       └── is_void: false
         │
         ├── tag_name: "div" (location: (1:1)-(1:4))
-        ├── body: []
-        ├── close_tag: ∅
+        ├── body: (1 item)
+        │   └── @ HTMLTextNode (location: (1:21)-(1:32))
+        │       └── content: "div-content"
+        │
+        ├── close_tag:
+        │   └── @ HTMLCloseTagNode (location: (1:32)-(1:38))
+        │       ├── tag_opening: "</" (location: (1:32)-(1:34))
+        │       ├── tag_name: "div" (location: (1:34)-(1:37))
+        │       ├── children: []
+        │       └── tag_closing: ">" (location: (1:37)-(1:38))
+        │
         ├── is_void: false
         └── source: "HTML"
\ No newline at end of file
```

</p>
</details>
)

This pull request adds a `visitors` option to the `Herb::Engine` for
preprocessing the AST before the template gets compiled.

This allows us to refactor/soft-deprecate the `debug` option, since we
can just pass the `Herb::Engine::DebugVisitor` as a visitor for
preprocessing the AST before compiling the template.

It also allows to implement custom visitors that could implement new
syntax/transformations/rewrites etc. (i.e use `<Component
:class="vue-style">` syntax, erase all HTML Comments, strip certain
attributes, ...)
This seems to fix marcoroth#467 but I
might be missing some other bits and bobs
…oth#516)

Bumps the npm_and_yarn group with 2 updates in the / directory: [esbuild](https://github.com/evanw/esbuild) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).

Updates `esbuild` from 0.25.9 to 0.25.10

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…arcoroth#517)

This pull request updates the parser and the analyzer to only transform
an `ERBContentNode` node to an `ERBIfNode` or `ERBUnlessNode` when it
has both `if/unless` and `end` keywords.

Guard clauses or ternaries shouldn't be treated as `ERBIfNode` or
`ERBUnlessNode`. We might want to revisit this when we expose the actual
prism nodes for each `ERBContentNode`, but for the sake of
parsing/formatting we shouldn't treat those `ERBIfNode` or
`ERBUnlessNode` nodes for now.

Resolves marcoroth#505
…ctory (marcoroth#519)

Bumps the npm_and_yarn group with 1 update in the / directory:
[vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).

Updates `vite` from 7.0.7 to 7.1.5

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ctory (marcoroth#520)

Bumps the npm_and_yarn group with 1 update in the / directory:
[vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).

Updates `vite` from 7.1.5 to 7.1.6

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This pull request updates the `html-no-empty-attributes` linter rule to
allow for empty data attributes without an equal sign and attribute
value.

This **is not** allowed:
```html
<div data-turbo-permament=""></div>
```

This **is** now allowed with this pull request:
```html
<div data-turbo-permament></div>
```

Resolves marcoroth#483
…ctory (marcoroth#521)

Bumps the npm_and_yarn group with 1 update in the / directory:
[vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).

Updates `vite` from 7.1.6 to 7.1.7

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…oroth#522)

This pull request updates to formatter to fix an issue where HTML
elements inside `<pre>`, `<style>`, `<script>`, and `<textarea>` tags
lost spaces between tag names and attributes during formatting.

For example, `<tt id="test">` was incorrectly formatted as
`<ttid="test">`.

Resolves marcoroth#477
…coroth#523)

This pull request updates the formatter to also add surrounding spaces
for `ERBContentNode` nodes within HTML attribute values when formatting
HTML+ERB documents.

Resolves marcoroth#482
As painstakingly worked out with @marcoroth during Kaigi on Rails, macOS
26 Tahoe introduces a function named `parser_init` that can clobber the
Herb function with the same name. Precompiled gems no longer crash on
macOS 26 after this change to ensure the Herb functions will not be
clobbered by the OS functions.

From what we could tell, macOS has a new(?) framework called "Biome" which both defines `parser_parse` and `parse_init` functions. 

We believe the reason why this bug only occured in the precompiled version of the gem is because at compile time it wouldn't know about both of these functions. So at runtime  it would "choose" the first matching one, which happened to be the wrong one, thus messing with the stack/structs when calling the function here:

https://github.com/marcoroth/herb/blob/b93eba9f80e7828428e084efd103acdf77bee81a/src/herb.c#L32

which then lead to this `EXC_BAD_ACCESS (code=1, address=0x29)` error later in: 

https://github.com/marcoroth/herb/blob/b93eba9f80e7828428e084efd103acdf77bee81a/src/parser.c#L1210

Resolves marcoroth#484
Resolves marcoroth/reactionview#13

Co-Authored-By: Marco Roth <marco.roth@intergga.ch>
@asilano asilano changed the title update to upstream Merge upstream into main Sep 29, 2025
@asilano asilano marked this pull request as ready for review September 29, 2025 10:09
@asilano asilano merged commit 8327ac8 into main Sep 29, 2025
4 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.