Move static outside HTML. Start work on TypeScript bundle

It's not strictly HTML, so that's just correct.

This is just worth doing while building the new TypeScript bundle
This commit is contained in:
Eli Ribble 2026-03-21 03:06:59 +00:00
parent 976a29b7d7
commit 31947c848a
No known key found for this signature in database
53 changed files with 7100 additions and 73 deletions

3
.gitignore vendored
View file

@ -3,12 +3,11 @@ cmd/geocode-test/geocode-test
cmd/passwordgen/passwordgen cmd/passwordgen/passwordgen
districts/ districts/
flogo.log flogo.log
html/static/css/bootstrap.css
html/static/css/bootstrap.css.map
nidus-sync nidus-sync
nidus-sync.log nidus-sync.log
result result
stadia/cmd/bulk-geocode/bulk-geocode stadia/cmd/bulk-geocode/bulk-geocode
stadia/cmd/reverse-geocode/reverse-geocode stadia/cmd/reverse-geocode/reverse-geocode
stadia/cmd/structured-geocode/structured-geocode stadia/cmd/structured-geocode/structured-geocode
static/gen/
tmp/ tmp/

View file

@ -93,10 +93,11 @@ esbuild ts/main.ts --bundle --outfile=html/static/bundle.js --format=iife --mini
``` ```
The only page that works right now is `https://sync.nidus.cloud/template-test` The only page that works right now is `https://sync.nidus.cloud/template-test`
### watchexec ### watchexec
For iterating on styles For iterating on styles
``` ```
watchexec -e scss sass scss/custom.scss:html/static/css/bootstrap.css watchexec -e scss sass scss/custom.scss:static/gen/css/bootstrap.css
``` ```

View file

@ -12,10 +12,14 @@ pkgs.buildGoModule rec {
vendorHash = "sha256-zXjryPAJYpc80cqYtrcp//i6OQi5V5QwhaKQYYfrlL8="; vendorHash = "sha256-zXjryPAJYpc80cqYtrcp//i6OQi5V5QwhaKQYYfrlL8=";
buildInputs = [ pkgs.proj ]; buildInputs = [ pkgs.proj ];
nativeBuildInputs = [ pkgs.pkg-config pkgs.dart-sass ]; nativeBuildInputs = [
pkgs.pkg-config
pkgs.dart-sass
pkgs.esbuild
];
preBuild = '' preBuild = ''
# Compile SCSS
SASS_SRC_DIR="./scss" SASS_SRC_DIR="./scss"
CSS_OUTPUT_DIR="./html/static/css/" CSS_OUTPUT_DIR="./html/static/css/"
@ -23,5 +27,26 @@ pkgs.buildGoModule rec {
echo "Compiling $SASS_SRC_DIR/custom.scss to $CSS_OUTPUT_DIR/bootstrap.css..." echo "Compiling $SASS_SRC_DIR/custom.scss to $CSS_OUTPUT_DIR/bootstrap.css..."
sass --style=compressed --trace "$SASS_SRC_DIR/custom.scss":"$CSS_OUTPUT_DIR/bootstrap.css" sass --style=compressed --trace "$SASS_SRC_DIR/custom.scss":"$CSS_OUTPUT_DIR/bootstrap.css"
# Bundle TypeScript
JS_OUTPUT_DIR="./html/static/gen/js/"
mkdir -p "$JS_OUTPUT_DIR"
echo "Bundling TypeScript..."
esbuild ts/main.ts --bundle --minify --outfile="$JS_OUTPUT_DIR/bundle.js"
# Generate hash and rename bundle
BUNDLE_HASH=$(sha256sum "$JS_OUTPUT_DIR/bundle.js" | cut -c1-12)
mv "$JS_OUTPUT_DIR/bundle.js" "$JS_OUTPUT_DIR/bundle.$BUNDLE_HASH.js"
# Generate gen.go with bundle path
cat > gen.go <<EOF
package main
// Generated by Nix build - do not edit manually
const JsBundlePath = "/static/js/bundel.$BUNDLE_HASH.js"
EOF
echo "Generated JS bundle with hash: $BUNDLE_HASH"
''; '';
} }

View file

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/config" "github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/static"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -19,6 +20,15 @@ import (
// static files from a http.FileSystem. // static files from a http.FileSystem.
var startedTime time.Time = time.Now() var startedTime time.Time = time.Now()
var localFS http.Dir
func AddStaticRoute(r chi.Router, path string) {
if localFS == "" {
localFS = http.Dir("./static")
}
fileServer(r, "/static", localFS, static.EmbeddedStaticFS, "static")
}
func fileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embed.FS, embeddedPath string) { func fileServer(r chi.Router, path string, root http.FileSystem, embeddedFS embed.FS, embeddedPath string) {
if strings.ContainsAny(path, "{}*") { if strings.ContainsAny(path, "{}*") {
panic("FileServer does not permit any URL parameters.") panic("FileServer does not permit any URL parameters.")

View file

@ -12,6 +12,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/static"
"github.com/aarondl/opt/null" "github.com/aarondl/opt/null"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@ -22,6 +23,8 @@ import (
func addFuncMap(t *template.Template) { func addFuncMap(t *template.Template) {
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"bigNumber": bigNumber, "bigNumber": bigNumber,
"bundlePathCSS": bundlePathCSS,
"bundlePathJS": bundlePathJS,
"displayUploadStatus": displayUploadStatus, "displayUploadStatus": displayUploadStatus,
"displayUploadType": displayUploadType, "displayUploadType": displayUploadType,
"duration": duration, "duration": duration,
@ -59,6 +62,12 @@ func bigNumber(n int) string {
return result.String() return result.String()
} }
func bundlePathCSS() string {
return static.BundlePathCSS
}
func bundlePathJS() string {
return static.BundlePathJS
}
func displayUploadStatus(s string) string { func displayUploadStatus(s string) string {
switch s { switch s {
case "committed": case "committed":

View file

@ -1,20 +0,0 @@
package html
import (
"embed"
"net/http"
"github.com/go-chi/chi/v5"
)
//go:embed static/*
var EmbeddedStaticFS embed.FS
var localFS http.Dir
func AddStaticRoute(r chi.Router, path string) {
if localFS == "" {
localFS = http.Dir("./html/static")
}
fileServer(r, "/static", localFS, EmbeddedStaticFS, "static")
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,8 +8,7 @@
<link href="/static/css/bootstrap.css" rel="stylesheet" /> <link href="/static/css/bootstrap.css" rel="stylesheet" />
<!-- Bootstrap Icons --> <!-- Bootstrap Icons -->
<link rel="stylesheet" href="/static/vendor/css/bootstrap-icons.min.css" /> <link rel="stylesheet" href="/static/vendor/css/bootstrap-icons.min.css" />
<!-- favicon --> <link rel="icon" href="/static/ico/favicon-rmo.ico" type="image/x-icon" />
<link rel="icon" href="/static/favicon-rmo.ico" type="image/x-icon" />
{{ block "extraheader" . }}{{ end }} {{ block "extraheader" . }}{{ end }}
<script> <script>
var tooltipByElementId = {}; var tooltipByElementId = {};

View file

@ -4,14 +4,12 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ template "title" . }} - Nidus Sync</title> <title>{{ template "title" . }} - Nidus Sync</title>
<!-- Bootstrap CSS --> <link href="{{ bundlePathCSS }}" rel="stylesheet" />
<link href="/static/css/bootstrap.css" rel="stylesheet" />
<!-- Fontawesome Icons --> <!-- Fontawesome Icons -->
<link rel="stylesheet" href="/static/vendor/css/bootstrap-icons.min.css" /> <link rel="stylesheet" href="/static/vendor/css/bootstrap-icons.min.css" />
<!-- favicon --> <link rel="icon" href="/static/ico/favicon-sync.ico" type="image/x-icon" />
<link rel="icon" href="/static/favicon-sync.ico" type="image/x-icon" />
<script src="/static/js/events.js"></script> <script src="/static/js/events.js"></script>
<script defer src="/static/js/alpine-3.15.8-min.js"></script> <script src="{{ bundlePathJS }}" defer></script>
{{ block "extraheader" . }}{{ end }} {{ block "extraheader" . }}{{ end }}
<script> <script>
const USER = {{ .User.AsJSON|json }}; const USER = {{ .User.AsJSON|json }};

View file

@ -8,8 +8,7 @@
<link href="/static/vendor/css/bootstrap.min.css" rel="stylesheet" /> <link href="/static/vendor/css/bootstrap.min.css" rel="stylesheet" />
<!-- Bootstrap Icons --> <!-- Bootstrap Icons -->
<link href="/static/css/bootstrap.css" rel="stylesheet" /> <link href="/static/css/bootstrap.css" rel="stylesheet" />
<!-- favicon --> <link rel="icon" href="/static/ico/favicon-sync.ico" type="image/x-icon" />
<link rel="icon" href="/static/favicon-sync.ico" type="image/x-icon" />
{{ block "extraheader" . }}{{ end }} {{ block "extraheader" . }}{{ end }}
{{ if not .Config.IsProductionEnvironment }} {{ if not .Config.IsProductionEnvironment }}
<script src="/.flogo/injector.js"></script> <script src="/.flogo/injector.js"></script>

6
static/gen.go Normal file
View file

@ -0,0 +1,6 @@
package static
// gen.go - checked into git
// This file is overwritten during Nix builds with hashed paths
const BundlePathCSS = "/static/gen/css/bootstrap.css"
const BundlePathJS = "/static/gen/js/bundle.js"

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 191 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

View file

@ -3,7 +3,7 @@ class AddressDisplay extends HTMLElement {
super(); super();
// Create a shadow DOM // Create a shadow DOM
this.attachShadow({mode: "open" }); this.attachShadow({ mode: "open" });
// Initial render // Initial render
this.render(); this.render();
@ -99,29 +99,33 @@ class AddressDisplay extends HTMLElement {
// Populate structured fields // Populate structured fields
// Street Address - combine address, street, housenumber if available // Street Address - combine address, street, housenumber if available
let addressStr = ''; let addressStr = "";
if (context.address) addressStr += context.address.address_number; if (context.address) addressStr += context.address.address_number;
if (context.street) { if (context.street) {
if (addressStr) addressStr += ' '; if (addressStr) addressStr += " ";
addressStr += context.street.name; addressStr += context.street.name;
} }
if (addressStr === '') { if (addressStr === "") {
addressStr = props.name || props.full_address || '-'; addressStr = props.name || props.full_address || "-";
} }
this._streetAddress.textContent = addressStr; this._streetAddress.textContent = addressStr;
// Post Code // Post Code
this._postCode.textContent = context.postcode.name || '-'; this._postCode.textContent = context.postcode.name || "-";
// District (could be district, locality, or place) // District (could be district, locality, or place)
this._district.textContent = context.district.name || context.place.name || context.locality.name || '-'; this._district.textContent =
context.district.name ||
context.place.name ||
context.locality.name ||
"-";
// Region (state, province, etc.) // Region (state, province, etc.)
this._region.textContent = context.region.name || '-'; this._region.textContent = context.region.name || "-";
// Country // Country
this._country.textContent = context.country.name || '-'; this._country.textContent = context.country.name || "-";
} }
} }
customElements.define('address-display', AddressDisplay); customElements.define("address-display", AddressDisplay);

View file

@ -10,14 +10,14 @@ function getGeolocation(options) {
const geolocationOptions = options || { const geolocationOptions = options || {
enableHighAccuracy: true, enableHighAccuracy: true,
timeout: 5000, timeout: 5000,
maximumAge: 0 maximumAge: 0,
}; };
// Call the geolocation API // Call the geolocation API
navigator.geolocation.getCurrentPosition( navigator.geolocation.getCurrentPosition(
position => resolve(position), (position) => resolve(position),
error => reject(error), (error) => reject(error),
geolocationOptions geolocationOptions,
); );
}); });
} }

8
static/static.go Normal file
View file

@ -0,0 +1,8 @@
package static
import (
"embed"
)
//go:embed css gen file ico js vendor
var EmbeddedStaticFS embed.FS

4107
static/vendor/js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because it is too large Load diff

2892
static/vendor/js/bootstrap.min.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,12 @@
import Alpine from './vendor/alpinejs-3.15.8.js'; import Alpine from './vendor/alpinejs-3.15.8.js';
// Make Alpine available on window for inline Alpine
window.Alpine = Alpine;
// Wait for DOM to be ready, then initialize Alpine
document.addEventListener("DOMContentLoaded", () => {
Alpine.start();
});
interface GreetingComponent { interface GreetingComponent {
message: string; message: string;
name: string; name: string;
@ -14,6 +21,3 @@ Alpine.data('greeting', (): GreetingComponent => ({
this.message = 'Message updated at ' + new Date().toLocaleTimeString(); this.message = 'Message updated at ' + new Date().toLocaleTimeString();
} }
})); }));
Alpine.start();