mirror of
https://github.com/go-gitea/gitea.git
synced 2026-03-12 02:24:21 -05:00
[Propsal] Dynamical Frontend Render Plugin #14685
Open
opened 2025-11-02 11:19:59 -06:00 by GiteaMirror
·
25 comments
No Branch/Tag Specified
main
release/v1.25
release/v1.24
release/v1.23
release/v1.22
release/v1.21
release/v1.20
release/v1.19
release/v1.18
release/v1.17
release/v1.16
release/v1.15
release/v1.14
release/v1.13
release/v1.12
release/v1.11
release/v1.10
release/v1.9
release/v1.8
v1.25.3
v1.25.2
v1.25.1
v1.25.0
v1.24.7
v1.25.0-rc0
v1.26.0-dev
v1.24.6
v1.24.5
v1.24.4
v1.24.3
v1.24.2
v1.24.1
v1.24.0
v1.23.8
v1.24.0-rc0
v1.25.0-dev
v1.23.7
v1.23.6
v1.23.5
v1.23.4
v1.23.3
v1.23.2
v1.23.1
v1.23.0
v1.23.0-rc0
v1.24.0-dev
v1.22.6
v1.22.5
v1.22.4
v1.22.3
v1.22.2
v1.22.1
v1.22.0
v1.23.0-dev
v1.22.0-rc1
v1.21.11
v1.22.0-rc0
v1.21.10
v1.21.9
v1.21.8
v1.21.7
v1.21.6
v1.21.5
v1.21.4
v1.21.3
v1.21.2
v1.20.6
v1.21.1
v1.21.0
v1.21.0-rc2
v1.21.0-rc1
v1.20.5
v1.22.0-dev
v1.21.0-rc0
v1.20.4
v1.20.3
v1.20.2
v1.20.1
v1.20.0
v1.19.4
v1.21.0-dev
v1.20.0-rc2
v1.20.0-rc1
v1.20.0-rc0
v1.19.3
v1.19.2
v1.19.1
v1.19.0
v1.19.0-rc1
v1.20.0-dev
v1.19.0-rc0
v1.18.5
v1.18.4
v1.18.3
v1.18.2
v1.18.1
v1.18.0
v1.17.4
v1.18.0-rc1
v1.19.0-dev
v1.18.0-rc0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.17.0-rc2
v1.16.9
v1.17.0-rc1
v1.18.0-dev
v1.16.8
v1.16.7
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.11
v1.17.0-dev
v1.16.0-rc1
v1.15.10
v1.15.9
v1.15.8
v1.15.7
v1.15.6
v1.15.5
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.14.7
v1.15.0
v1.15.0-rc3
v1.14.6
v1.15.0-rc2
v1.14.5
v1.16.0-dev
v1.15.0-rc1
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.13.7
v1.14.0-rc2
v1.13.6
v1.13.5
v1.14.0-rc1
v1.15.0-dev
v1.13.4
v1.13.3
v1.13.2
v1.13.1
v1.13.0
v1.12.6
v1.13.0-rc2
v1.14.0-dev
v1.13.0-rc1
v1.12.5
v1.12.4
v1.12.3
v1.12.2
v1.12.1
v1.11.8
v1.12.0
v1.11.7
v1.12.0-rc2
v1.11.6
v1.12.0-rc1
v1.13.0-dev
v1.11.5
v1.11.4
v1.11.3
v1.10.6
v1.12.0-dev
v1.11.2
v1.10.5
v1.11.1
v1.10.4
v1.11.0
v1.11.0-rc2
v1.10.3
v1.11.0-rc1
v1.10.2
v1.10.1
v1.10.0
v1.9.6
v1.9.5
v1.10.0-rc2
v1.11.0-dev
v1.10.0-rc1
v1.9.4
v1.9.3
v1.9.2
v1.9.1
v1.9.0
v1.9.0-rc2
v1.10.0-dev
v1.9.0-rc1
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.8.0-rc3
v1.7.6
v1.8.0-rc2
v1.7.5
v1.8.0-rc1
v1.9.0-dev
v1.7.4
v1.7.3
v1.7.2
v1.7.1
v1.7.0
v1.7.0-rc3
v1.6.4
v1.7.0-rc2
v1.6.3
v1.7.0-rc1
v1.7.0-dev
v1.6.2
v1.6.1
v1.6.0
v1.6.0-rc2
v1.5.3
v1.6.0-rc1
v1.6.0-dev
v1.5.2
v1.5.1
v1.5.0
v1.5.0-rc2
v1.5.0-rc1
v1.5.0-dev
v1.4.3
v1.4.2
v1.4.1
v1.4.0
v1.4.0-rc3
v1.4.0-rc2
v1.3.3
v1.4.0-rc1
v1.3.2
v1.3.1
v1.3.0
v1.3.0-rc2
v1.3.0-rc1
v1.2.3
v1.2.2
v1.2.1
v1.2.0
v1.2.0-rc3
v1.2.0-rc2
v1.1.4
v1.2.0-rc1
v1.1.3
v1.1.2
v1.1.1
v1.1.0
v1.0.2
v1.0.1
v1.0.0
v0.9.99
Labels
Clear labels
$20
$250
$50
$500
backport/done
💎 Bounty
docs-update-needed
good first issue
hacktoberfest
issue/bounty
issue/confirmed
issue/critical
issue/duplicate
issue/needs-feedback
issue/not-a-bug
issue/regression
issue/stale
issue/workaround
lgtm/need 2
modifies/api
modifies/translation
outdated/backport/v1.18
outdated/theme/markdown
outdated/theme/timetracker
performance/bigrepo
performance/cpu
performance/memory
performance/speed
pr/breaking
proposal/accepted
proposal/rejected
pr/wip
pull-request
reviewed/wontfix
💰 Rewarded
skip-changelog
status/blocked
topic/accessibility
topic/api
topic/authentication
topic/build
topic/code-linting
topic/commit-signing
topic/content-rendering
topic/deployment
topic/distribution
topic/federation
topic/gitea-actions
topic/issues
topic/lfs
topic/mobile
topic/moderation
topic/packages
topic/pr
topic/projects
topic/repo
topic/repo-migration
topic/security
topic/theme
topic/ui
topic/ui-interaction
topic/ux
topic/webhooks
topic/wiki
type/bug
type/deprecation
type/docs
type/enhancement
type/feature
type/miscellaneous
type/proposal
type/question
type/refactoring
type/summary
type/testing
type/upstream
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/gitea#14685
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @lunny on GitHub (Jun 30, 2025).
Originally assigned to: @kerwin612 on GitHub.
Preface
#34794 introduced a frontend static render plugin machism. I believe we can add more plugins in the future. But that will bloat the binary size and we cannot accept all the possible plugins. So that we need a machism to allow users(instance administrator) to find/install/uninstall Gitea Render Plugins.
Design Goals
There are 5 kinds of renders in Gitea.
This plugin system should support rendering a file in the git/git lfs at least.
The Gitea Frontend Render Plugin system aims to introduce a flexible, modular architecture that allows instance administrators to extend Gitea’s file rendering capabilities without modifying the core binary. Inspired by modern plugin-based ecosystems (e.g., VSCode extensions, browser plugins), this mechanism empowers the community to develop, share, and deploy custom renderers for specific file types (e.g., Markdown with diagrams, PDF, AsciiDoc, Jupyter notebooks, etc.).
A render plugin is a JavaScript (or TypeScript-transpiled) module that conforms to a defined Gitea rendering interface and is dynamically loaded by the frontend at runtime. It is designed to safely extend the rendering capabilities of Gitea views, in a secure and sandboxed way.
• Pluggability: Support multiple independently developed renderers.
• Discoverability: Administrators should be able to easily discover and install plugins.
• Configurability: Allow instance-level control over which plugins are enabled or disabled.
• Lightweight core: Keep the core Gitea binary minimal by externalizing optional renderers.
Relationship with current renderers
Gitea currently have supported backend renderers for markdown/csv and som other files. And recently Gitea introduced a frontend static plugin system which could render pdf and 3D images. The current plugin system could be kept there and the dynamic plugins mentioned in this proposal could be loaded as a special frontend static plugin. That means creating a plugin in
web_src/js/render/plugins/dynamic-plugin.ts. The dynamic plugins will be loaded according to the conditions in that file.Plugin Format
Each plugin could be a
.ziparchive or an online git url which containing the following structure:manifest.json example:
Plugin Storage and Delivery
To ensure security, performance, and compatibility with Gitea’s deployment model, all frontend render plugins must be downloaded and stored under a specific Gitea-managed directory, and served through Gitea’s internal HTTP router. This design avoids external dependency loading (e.g., from CDN or untrusted domains), ensuring all assets are locally verifiable and cacheable.
Storage Path
Uploaded/Downloaded plugin archives (.zip) will be extracted to a designated path inside the Gitea data/ directory. For example:
This allows Gitea to:
• Serve static assets securely via router
• Perform updates or uninstalls by removing plugin directories
Storage of Plugin State
Enabled status is stored in Gitea’s database under a new table (e.g., render_plugin):
Serving via Gitea Router
Gitea will expose plugin files through a well-defined route, e.g.
Admin UI Flow
On the Site Administration > Render Plugins page, admins will be able to:
• See a list of all installed plugins
• View plugin details (name, description, version)
• Enable/Disable plugin via toggle switch
• Delete plugin (removes files and DB entry)
Installation Flow
Delete Plugin
When delete plugin, it will be removed from disk assets/ directory and database.
Enable/Disable Plugin
When enable/disable plugins, the database will be updated and the plugins meta files will be updated.
@wxiaoguang commented on GitHub (Jul 1, 2025):
It needs to maintain the compatibility correctly. Propose a feasible plan before writing code.
@lunny commented on GitHub (Jul 1, 2025):
Maybe the current plugin system could be kept there and the dynamic plugins mentioned in this proposal could be loaded as a special plugin. That means creating a plugin in
web_src/js/render/plugins/dynamic-plugin.ts. The dynamic plugins will be loaded according to the conditions in that file.@silverwind commented on GitHub (Jul 1, 2025):
I think instead of
manifest.json, we could leverage the existingpackage.jsonspec. The script itself should export a async function as its ESM default export that is imported and called by our code with likely aFileblob to render and a destination DOM element to render to.optsfor any additional options passed from gitea. Here's an example:@kerwin612 commented on GitHub (Jul 2, 2025):
Here’s a concrete plan for how this can be implemented in Gitea, step by step:
1. Plugin Packaging
2. Backend: Storage & Serving
data/render-plugins/<plugin-id>/./assets/render-plugins/pdf-renderer/render.js.render_pluginto track installed plugins, their metadata, and enabled/disabled status.(Maybe we don't need a data table and can directly load the currently uploaded plugins dynamically?)3. Admin UI
4. Frontend: Plugin Loading & Registration
5. Security
6. Fallback
@silverwind commented on GitHub (Jul 2, 2025):
You can just use
package.jsononly, the properties there are not strict, so you can easily add additional custom properties:There is not need for a
entrybecause package.json already has that: https://nodejs.org/api/packages.html#package-entry-points. The spec for entry points is quite complicated, maybe initially only support"exports": "./index.js"syntax.The benefit of being a valid npm package is that it can be published to npm registry for easy distribution. The whole zip file stuff could be skipped and plugins could be specified as npm package name only (downloaded on startup).
@wxiaoguang commented on GitHub (Jul 2, 2025):
I do not think it is complete.
You should be able to answer the question by resolving "render a text-based STL 3D model correctly".
What if we need to change/re-design the plugin API in the future? https://github.com/go-gitea/gitea/issues/34917#issuecomment-3021670079 It needs to maintain the compatibility correctly.
@lunny commented on GitHub (Jul 6, 2025):
We cannot scanning the repositories and get to know which one is a plugin or not if using the
package.json?@silverwind commented on GitHub (Jul 7, 2025):
What do you mean by scanning?
@kerwin612 commented on GitHub (Jul 8, 2025):
When adding a plugin, you can directly add the Git repository address and then scan the source code files of the repository.
@silverwind commented on GitHub (Jul 8, 2025):
I don't follow. In above example you have
gitea.type == "render-plugin"which defines it as a render plugin. Also, npm packages can be declared as git urls too: https://docs.npmjs.com/cli/v11/configuring-npm/package-json#git-urls-as-dependencies.In any case, I'd strongly advice against defining a custom package format, just use the existing npm package format.
@kerwin612 commented on GitHub (Jul 10, 2025):
1. Plugin Manifest & API Versioning
To ensure long-term compatibility and smooth evolution of the plugin system, I propose that both the Gitea core and each plugin explicitly declare their API version(s):
In the plugin package.json:
In the Gitea core:
"1.0.0").apiVersionmatches the core’s supported version(s), it can be enabled.Benefits:
2. Plugin Interface & API Evolution
Each plugin must export the interface required by the plugin API version it declares in its manifest. For example, with API version
1.0.0, the required exports might be:If the plugin API evolves in the future (e.g., version
2.0.0introduces new or changed methods), plugins targeting that version must export the updated interface as specified by the new API contract. This ensures that each plugin is always compatible with the core’s expectations for its declared API version.Key points:
apiVersion.@wxiaoguang What do you think of this design?
@wxiaoguang commented on GitHub (Jul 10, 2025):
Better than before, I think there are still unresolved concerns https://github.com/go-gitea/gitea/issues/34917#issuecomment-3027624778 :
@kerwin612 commented on GitHub (Jul 10, 2025):
Do you think this design is feasible?:
1. Flexible canHandle Interface
The
canHandlefunction can optionally receive areadChunkcallback, allowing the plugin to read a small portion of the file content for more accurate detection:readChunkwhen necessary.2. Backward Compatibility
filenameandmimeTypeas before.3. Manifest Declaration
This design ensures:
@wxiaoguang commented on GitHub (Jul 10, 2025):
Backend already pre-fetched 1024 bytes from that file
@hiifong commented on GitHub (Jul 11, 2025):
I'm wondering if we should go for pluginization through the backend so that we can have more flexible operations, the backend we can handle the corresponding js, but a pure js implementation of a plugin doesn't provide the backend functionality. If we implement the plugin through the backend maybe we can use https://github.com/hashicorp/go-plugin.
@wxiaoguang commented on GitHub (Jul 11, 2025):
I don't see who has the ability&time to implement it. And ROI (return on investment) is very slow.
@kerwin612 commented on GitHub (Jul 15, 2025):
@wxiaoguang after the current discussion, do you have any other suggestions? I think we can first come up with a draft and start working on it, right? Only by taking action can we continuously improve it!
@wxiaoguang commented on GitHub (Jul 15, 2025):
package.json.asciicastandconsolefirst@silverwind commented on GitHub (Jul 15, 2025):
Why not use existing package infrastructure? The benefit is plugins could be published to the npm registry and directly used from there by only specifying package name. I'd certainly prefer to install a plugin with a simple command like
gitea plugin add <packagename>and not having to mess with any files.@wxiaoguang commented on GitHub (Jul 15, 2025):
Well, every time I say "it would cause problems", then it really causes problems.
@silverwind commented on GitHub (Jul 15, 2025):
Why you want to redesign a JS package system is beyond me.
@wxiaoguang commented on GitHub (Jul 15, 2025):
Why you want to abuse the JS package system to support Gitea frontend plugin? For example:
package.jsondefinition?gitea plugin add <packagename>behave likenpm installand handle various dependencies?package.jsonversion comparing logic in Gitea's Golang code?@wxiaoguang commented on GitHub (Jul 15, 2025):
These published npm packages are Gitea-only, no JS eco-system user can use them (these packages just don't work for non-Gitea environments). Isn't it an abuse to the npm package services and the JS eco-system?
@silverwind commented on GitHub (Jul 15, 2025):
package.json spec allows any additional root level properties and this is already in use by numerous other tools.
Ideally yes. And yes I realize this brings a dependency on
npm.It's just semver for which I'm sure a golang implementation exists. Edit: https://github.com/Masterminds/semver.
@silverwind commented on GitHub (Jul 15, 2025):
The entry file could be used standalone in a HTML file to test. See for example this. This is a npm package and I'm directly importing the entry file in HTML for preview purposes.