Skip to content

Remove htmx#37079

Draft
silverwind wants to merge 3 commits intogo-gitea:mainfrom
silverwind:nohtmx
Draft

Remove htmx#37079
silverwind wants to merge 3 commits intogo-gitea:mainfrom
silverwind:nohtmx

Conversation

@silverwind
Copy link
Copy Markdown
Member

@silverwind silverwind commented Apr 2, 2026

Replace all htmx-driven interactions with lightweight custom JS handlers:

  • Extend form-fetch-action with data-swap attribute for HTML response swapping (star, watch, follow, issue subscribe, notifications)
  • Add individual init functions for special patterns (admin dashboard polling, workflow dispatch, last commit loader, user cards refresh, editor diff preview, code expander buttons)
  • Replace HX-Request/HX-Redirect/hx-trigger headers with X-Gitea-Page-Action/X-Gitea-Redirect/X-Gitea-Dispatch-Event
  • Remove htmx.org and idiomorph packages, all hx-* template attributes, htmx.process() calls, htmx event listeners, and related config

Fixes: #35059


This PR was written with the help of Claude Opus 4.6

Replace all htmx-driven interactions with lightweight custom JS handlers:

- Extend form-fetch-action with `data-swap` attribute for HTML response
  swapping (star, watch, follow, issue subscribe, notifications)
- Add individual init functions for special patterns (admin dashboard
  polling, workflow dispatch, last commit loader, user cards refresh,
  editor diff preview, code expander buttons)
- Replace HX-Request/HX-Redirect/hx-trigger headers with
  X-Gitea-Page-Action/X-Gitea-Redirect/X-Gitea-Dispatch-Event
- Remove htmx.org and idiomorph packages, all hx-* template attributes,
  htmx.process() calls, htmx event listeners, and related config

Ref: go-gitea#35059

Co-Authored-By: Claude (Opus 4.6) <[email protected]>
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Apr 2, 2026
@github-actions github-actions bot added topic/code-linting modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files modifies/dependencies modifies/frontend labels Apr 2, 2026
@silverwind
Copy link
Copy Markdown
Member Author

WIP, currently this was only tested using those e2e tests in the commit. We may evaluate dropping some of these tests later if not valuable, they are primarily there to aid in this migration.

@silverwind silverwind changed the title Drop htmx and idiomorph dependencies Drop htmx Apr 2, 2026
@wxiaoguang
Copy link
Copy Markdown
Contributor

I think we need to manually rewrite some parts. Some AI code really looks like slop and isn't the proper way.

Teaching AI to make it right will definitely spend more time than I just rewrite them with a proper design.

@silverwind silverwind changed the title Drop htmx Remove htmx Apr 2, 2026
@silverwind
Copy link
Copy Markdown
Member Author

silverwind commented Apr 2, 2026

Yes, this is only a starting point. Still better than manually starting from scratch imho. I'm not so well-versed around form-fetch-action, any feedback appreciated about it.

The `.form-fetch-action` selector now matches multiple forms on the
page since watch/unwatch also uses this class. Use a more specific
selector that includes the `.comment` class.

Co-Authored-By: Claude (Opus 4.6) <[email protected]>
@wxiaoguang
Copy link
Copy Markdown
Contributor

Will take a look when I get some time (if no hurry). Some brief ideas after I proposed #35059

  1. We don't need to 100% follow the old behavior, as long as the result is good
  2. Maybe we can write our own morph logic for our cases (only update the elements which have changed)
    • I have a brief idea, maybe it won't be too complex
    • If it is too complex, then just use innerHTML
  3. link-action and form-fetch-action can share the same data-fetch-swap logic, then we can remove many abused "form" elements
  4. The "watch" problem, I think there are only 2 cases:
    • On non-watches page, only reload the button
    • On watches page, just do a full page reload
    • The Go template can tell the button which page it is on
    • Then we don't need to simulate HX-Trigger / X-Gitea-Dispatch-Event, it it still too fragile and hacky.

@silverwind
Copy link
Copy Markdown
Member Author

silverwind commented Apr 2, 2026

Note that idiomorph could be kept as a dependency, it can be used standalone. Would rather not like to implement morphing our own.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the htmx dependency and replaces its usage across templates, frontend JS, and backend response headers with custom lightweight fetch/swap handlers and data-global-init initializers.

Changes:

  • Remove htmx/idiomorph packages, global window.htmx wiring, and all hx-* template usage.
  • Add/extend custom JS handlers for HTML swapping (form-fetch-action + data-swap) and page-specific dynamic behaviors (polling, loaders, dispatch inputs, code expanders, editor diff preview, user card refresh).
  • Replace HTMX-specific request/response headers with X-Gitea-Page-Action / X-Gitea-Redirect / X-Gitea-Dispatch-Event, and update tests accordingly.

Reviewed changes

Copilot reviewed 36 out of 39 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web_src/js/vitest.setup.ts Removes Happy DOM polyfill that was only needed for htmx evaluation.
web_src/js/index.ts Drops global htmx error listeners and related imports.
web_src/js/globals.ts Removes htmx/idiomorph global setup and config.
web_src/js/globals.d.ts Removes window.htmx type declaration.
web_src/js/features/repo-issue-sidebar-combolist.ts Removes htmx.process() calls after DOM replacements.
web_src/js/features/repo-home.ts Adds data-global-init handler to load last-commit content via POST.
web_src/js/features/repo-editor.ts Adds editor “diff” tab preview via custom POST + innerHTML swap.
web_src/js/features/repo-diff.ts Removes htmx.process() and adds click handler for code-expander-button using data-url.
web_src/js/features/repo-actions.ts Adds workflow-dispatch ref change handler to fetch and swap input HTML.
web_src/js/features/notification.ts Removes htmx.process() after notification DOM replacement.
web_src/js/features/common-page.ts Adds user-cards refresh listener driven by a dispatched DOM event and HTML parsing.
web_src/js/features/common-fetch-action.ts Extends form-fetch-action with data-swap HTML swapping + new headers/redirect/event handling.
web_src/js/features/admin/common.ts Adds admin system status polling init via data-global-init.
vite.config.ts Removes eval: false exception previously required by htmx.
types.d.ts Removes htmx ESM module shim declaration.
tests/integration/editor_test.go Updates selector for upload form to match updated markup.
tests/integration/compare_test.go Updates code expander button attribute assertions from hx-get to data-url.
tests/e2e/page-actions.test.ts Adds Playwright coverage for replaced page-actions and polling/loader behaviors.
templates/user/notification/notification_div.tmpl Switches notification actions to form-fetch-action + data-swap.
templates/shared/user/profile_big_avatar.tmpl Replaces follow/unfollow htmx button with form-fetch-action swap form.
templates/repo/watch_unwatch.tmpl Replaces watch/unwatch htmx boosting/targeting with swap form.
templates/repo/view_list.tmpl Replaces htmx last-commit loader attributes with data-global-init + URL attribute.
templates/repo/user_cards.tmpl Removes htmx-driven auto-refresh wiring; relies on dispatched event + JS refresh.
templates/repo/star_unstar.tmpl Replaces star/unstar htmx boosting/targeting with swap form.
templates/repo/issue/view_content/watching.tmpl Replaces issue subscribe toggle htmx with swap form.
templates/repo/editor/edit.tmpl Removes htmx diff preview attributes; adds data-diff-* used by JS.
templates/repo/actions/workflow_dispatch.tmpl Replaces htmx change-triggered inputs reload with data-global-init handler.
templates/repo/actions/workflow_dispatch_inputs.tmpl Updates comments to reflect new dynamic-loading behavior without htmx.
templates/org/follow_unfollow.tmpl Replaces org follow/unfollow htmx button with swap form.
templates/base/head.tmpl Removes htmx attributes from <body>.
templates/admin/dashboard.tmpl Replaces htmx polling with data-global-init polling.
services/gitdiff/gitdiff.go Replaces hx-get/hx-target button HTML with data-url for expander.
services/context/base.go Replaces HTMX redirect handling with X-Gitea-Page-Action / X-Gitea-Redirect.
services/context/base_test.go Updates redirect test to assert new headers.
routers/web/repo/watch.go Switches response event header from hx-trigger to X-Gitea-Dispatch-Event.
routers/web/repo/star.go Switches response event header from hx-trigger to X-Gitea-Dispatch-Event.
package.json Removes htmx.org and idiomorph dependencies.
pnpm-lock.yaml Removes locked packages for htmx.org and idiomorph.
eslint.config.ts Removes restricted-import rules and global for htmx.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Clear is-loading class from commit message cells when the POST
request fails or returns a non-OK status, preventing the file list
from being stuck in a permanent loading state.

Co-Authored-By: Claude (Opus 4.6) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. modifies/dependencies modifies/frontend modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files topic/code-linting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: drop htmx

4 participants