feat: Option to serve Bootstrap from the filesystem
All checks were successful
/ pre-commit (push) Successful in 1m7s

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2025-09-16 09:36:10 +02:00
commit ff92e30232
Signed by: jriou
GPG key ID: 9A099EDA51316854
8 changed files with 94 additions and 6 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ releases
collerd.db collerd.db
!docker/collerd.json !docker/collerd.json
collerd.json collerd.json
node_modules

View file

@ -55,6 +55,9 @@ releases: build_linux_amd64 build_darwin_arm64 archive_linux_amd64 archive_darwi
releases_with_docker: releases_with_docker:
docker run -it -v $(shell pwd):/mnt -w /mnt -e "UID=$(shell id -u)" -e "GID=$(shell id -g)" ${DOCKER_IMAGE} ./docker/build.sh docker run -it -v $(shell pwd):/mnt -w /mnt -e "UID=$(shell id -u)" -e "GID=$(shell id -g)" ${DOCKER_IMAGE} ./docker/build.sh
dependencies:
npm install
test: test:
cd src \ cd src \
&& go test internal/*.go \ && go test internal/*.go \

40
package-lock.json generated Normal file
View file

@ -0,0 +1,40 @@
{
"name": "coller",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"bootstrap": "^5.3.8"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/bootstrap": {
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
}
}
}

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"bootstrap": "^5.3.8"
}
}

View file

@ -36,6 +36,7 @@ The file format is **JSON**:
* **enable_upload_file_button** (bool): Display the upload file button in the UI (default true) * **enable_upload_file_button** (bool): Display the upload file button in the UI (default true)
* **tls_cert_file** (string): Path to TLS certificate file to enable HTTPS * **tls_cert_file** (string): Path to TLS certificate file to enable HTTPS
* **tls_key_file** (string): Path to TLS key file to enable HTTPS * **tls_key_file** (string): Path to TLS key file to enable HTTPS
* **bootstrap_directory** (string): Serve [Bootstrap](https://getbootstrap.com/) assets from this local directory (ex: "./node_modules/bootstrap/dist"). See **Dependencies** for details.
The configuration file is not required but the service might not be exposed to the public. The configuration file is not required but the service might not be exposed to the public.
@ -79,3 +80,34 @@ If the note is encrypted, the encrypted value is returned (application/octet-str
Errors return **500 Server Internal Error** with the **JSON** payload: Errors return **500 Server Internal Error** with the **JSON** payload:
* **message** (string): context of the error * **message** (string): context of the error
* **error** (string): error message * **error** (string): error message
## Dependencies
The web interface depends on:
- [Bootstrap](https://getbootstrap.com/)
- [Monaco Editor](https://github.com/microsoft/monaco-editor/)
By default, those dependencies are fetched from **remote CDN** services by the client.
If you would like to download them to serve them locally:
```
npm install
```
or via `make`:
```
make dependencies
```
Then configure the local directories:
```json
{
"bootstrap_directory": "./node_modules/bootstrap/dist"
}
```
Downloading Monaco Editor is not supported yet.

View file

@ -28,6 +28,7 @@ type Config struct {
EnableUploadFileButton bool `json:"enable_upload_file_button"` EnableUploadFileButton bool `json:"enable_upload_file_button"`
TLSCertFile string `json:"tls_cert_file"` TLSCertFile string `json:"tls_cert_file"`
TLSKeyFile string `json:"tls_key_file"` TLSKeyFile string `json:"tls_key_file"`
BootstrapDirectory string `json:"bootstrap_directory"`
} }
func NewConfig() *Config { func NewConfig() *Config {

View file

@ -196,6 +196,7 @@ type PageData struct {
URL string URL string
Note *Note Note *Note
EnableUploadFileButton bool EnableUploadFileButton bool
BootstrapDirectory string
} }
type HomeHandler struct { type HomeHandler struct {
@ -434,6 +435,7 @@ func (s *Server) Start() error {
Expirations: s.config.Expirations, Expirations: s.config.Expirations,
Expiration: s.config.Expiration, Expiration: s.config.Expiration,
Languages: s.config.Languages, Languages: s.config.Languages,
BootstrapDirectory: s.config.BootstrapDirectory,
} }
if s.config.ShowVersion { if s.config.ShowVersion {
@ -470,6 +472,10 @@ func (s *Server) Start() error {
} }
r.Path("/{id:[a-zA-Z0-9]+}.html").Handler(webNoteHandler).Methods("GET") r.Path("/{id:[a-zA-Z0-9]+}.html").Handler(webNoteHandler).Methods("GET")
if s.config.BootstrapDirectory != "" {
r.PathPrefix("/static/bootstrap/").Handler(http.StripPrefix("/static/bootstrap/", http.FileServer(http.Dir(s.config.BootstrapDirectory))))
}
r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET") r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET")
addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort) addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort)

View file

@ -4,6 +4,6 @@
<title>{{.Title}}</title> <title>{{.Title}}</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="{{if ne .BootstrapDirectory ``}}/static/bootstrap/css/bootstrap.min.css{{else}}https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css{{end}}" rel="stylesheet">
</head> </head>
{{end}} {{end}}