Subject: bug#77255: Treesit font-lock override for embed ranges

From: Juri Linkov <[email-masked]>
Date: Tue, 25 Mar 2025 20:25:17 +0200

It looks like we need a new keyword like ':override t' for
'treesit-range-rules' that would override host font-lock rules.

I'm trying to create a generic minor mode for AlpineJS framework
where some known HTML attributes contain JS code.  For example:

  <div x-data="{ open: false }">
  <div x-bind:class="! open ? 'hidden' : ''">
  <span x-text="new Date().getFullYear()">

This works nicely with this code added for testing to mhtml-ts-mode:

#+begin_src emacs-lisp
    (setq-local treesit-range-settings
                (append treesit-range-settings
                        (treesit-range-rules
                         :embed 'javascript
                         :host 'html
                         :local t
                         `((attribute
                            (attribute_name) @_name
                            (:match ,(rx (or "x-data" "x-bind" "x-text")) @_name)
                            (quoted_attribute_value
                             (attribute_value) @cap))))))
#+end_src

But the problem is that its highlighting is not visible because
host html-ts-mode font-lock overrides embedded js-ts-mode font-lock.

html-ts-mode--font-lock-settings contains:

   :language 'html
   :override t
   :feature 'string
   `((quoted_attribute_value) @font-lock-string-face)

So only the whole attribute is highlighted by font-lock-string-face
that overrides js highlighting.

Probably there is no way to add ':override t' to all 'javascript' rules in
'js--treesit-font-lock-settings', like ':override t' is already added
to all 'jsdoc' rules in 'js--treesit-font-lock-settings'.