Re-theme
This commit is contained in:
@@ -50,6 +50,10 @@ from core.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path("__debug__/", include("debug_toolbar.urls")),
|
||||
path(
|
||||
"favicon.ico",
|
||||
RedirectView.as_view(url=f"{settings.STATIC_URL}favicon.ico", permanent=False),
|
||||
),
|
||||
path("", base.Home.as_view(), name="home"),
|
||||
path("admin/", admin.site.urls),
|
||||
path(
|
||||
|
||||
87
artifacts/frontend_asset_playbook.md
Normal file
87
artifacts/frontend_asset_playbook.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Frontend Asset Vendoring Playbook
|
||||
|
||||
This is the repeatable process used in GIA to self-host third-party frontend assets, pin versions, record provenance, and keep template SRI hashes maintainable.
|
||||
|
||||
## Goals
|
||||
|
||||
- Avoid runtime CDN dependencies for core UI assets.
|
||||
- Pin exact upstream versions and package integrity in source control.
|
||||
- Record provenance, license, and SRI for each third-party asset.
|
||||
- Keep a simple manifest-driven workflow that can be copied into other projects.
|
||||
|
||||
## Files
|
||||
|
||||
- `tools/frontend_assets/package.json`
|
||||
- Exact npm dependency pins for vendored frontend libraries.
|
||||
- `tools/frontend_assets/package-lock.json`
|
||||
- npm lockfile integrity and tarball resolution source of truth.
|
||||
- `tools/frontend_assets/asset-manifest.json`
|
||||
- Maps upstream package files and URL bundles into local `core/static/` targets.
|
||||
- `scripts/vendor_frontend_assets.py`
|
||||
- Copies npm assets, downloads non-npm bundles, computes local SHA-256 and SRI SHA-512, and emits inventory reports.
|
||||
- `artifacts/frontend_libraries.md`
|
||||
- Human-readable inventory with versions, licenses, official URLs, tarballs, upstream integrity, and local SHA/SRI.
|
||||
- `artifacts/frontend_libraries.json`
|
||||
- Machine-readable inventory for template updates and audits.
|
||||
|
||||
## Standard Workflow
|
||||
|
||||
1. Add or update exact versions in `tools/frontend_assets/package.json`.
|
||||
2. Confirm each package is the official distribution, not a typosquat or community fork.
|
||||
3. Update `tools/frontend_assets/asset-manifest.json` with the exact files to vendor.
|
||||
4. Run `npm install --ignore-scripts` in `tools/frontend_assets/`.
|
||||
5. Run `./genv/bin/python scripts/vendor_frontend_assets.py`.
|
||||
6. Copy the emitted `sri_sha512` values into template tags in `core/templates/base.html`.
|
||||
7. Restart the stack so `collectstatic` republishes the new files.
|
||||
8. Verify in the browser that assets load from local static URLs with no CDN fallbacks.
|
||||
|
||||
## Provenance Rules
|
||||
|
||||
- Prefer official project docs or official extension listings before trusting npm search results.
|
||||
- For Bulma extensions, treat `https://bulma.io/extensions/` as the discovery source and verify the linked package/repo matches the npm package name.
|
||||
- Confirm npm metadata matches the expected project:
|
||||
- homepage
|
||||
- repository
|
||||
- maintainers
|
||||
- license
|
||||
- publish recency
|
||||
- Keep exact versions in `package.json`; do not use ranges.
|
||||
- Use `package-lock.json` as the immutable record of tarball URLs and upstream integrity.
|
||||
- If a library is not safely available from npm, vendor it from the official upstream URL as a `url_bundle`.
|
||||
- Do not silently substitute a “free” or differently-scoped package if the templates rely on another asset family.
|
||||
|
||||
## GIA Decisions
|
||||
|
||||
- Font Awesome:
|
||||
- GIA templates use icon classes that are not safely replaceable with `@fortawesome/fontawesome-free`.
|
||||
- The existing Font Awesome Pro `site-assets` v6.1.1 bundle is self-hosted under `core/static/vendor/fontawesome/` instead.
|
||||
- jQuery:
|
||||
- Latest npm is 4.x, but GIA stays on `3.7.1` to avoid breaking older plugins.
|
||||
- Bulma extensions:
|
||||
- `bulma-calendar`, `bulma-tagsinput`, `bulma-switch`, `bulma-slider`, and `bulma-tooltip` were matched against Bulma's official extensions page before pinning.
|
||||
- `bulma-calendar` and `bulma-tooltip` are deprecated on npm, but Bulma still points to the Wikiki ecosystem for these extensions, so they were kept and documented instead of replaced ad hoc.
|
||||
|
||||
## Theme Strategy
|
||||
|
||||
- `core/static/css/gia-theme.css` is now the project override layer instead of an inline `<style>` block in `base.html`.
|
||||
- This is the low-friction step that works with the current stack immediately.
|
||||
- If we want a true Bulma theme build later, add `sass` to `tools/frontend_assets`, create a `gia-bulma.scss` entrypoint that sets Bulma theme variables before importing Bulma, and vendor the compiled output through the same manifest process.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cd /code/xf/GIA/tools/frontend_assets
|
||||
npm install --ignore-scripts
|
||||
|
||||
cd /code/xf/GIA
|
||||
./genv/bin/python scripts/vendor_frontend_assets.py
|
||||
bash ./scripts/quadlet/manage.sh restart
|
||||
./genv/bin/python manage.py check
|
||||
```
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- `core/templates/base.html` only references local static URLs for vendored libraries.
|
||||
- Each included stylesheet/script in `base.html` has an `integrity="sha512-..."` attribute.
|
||||
- Browser network panel shows local asset hits and no unexpected CDN requests.
|
||||
- `artifacts/frontend_libraries.md` reflects the exact deployed asset set.
|
||||
469
artifacts/frontend_libraries.json
Normal file
469
artifacts/frontend_libraries.json
Normal file
@@ -0,0 +1,469 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": "bulma_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma",
|
||||
"version": "1.0.4",
|
||||
"license": "MIT",
|
||||
"homepage": "https://bulma.io",
|
||||
"official_url": "https://bulma.io",
|
||||
"purpose": "Bulma core stylesheet",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma/-/bulma-1.0.4.tgz",
|
||||
"dist_integrity": "sha512-Ffb6YGXDiZYX3cqvSbHWqQ8+LkX6tVoTcZuVB3lm93sbAVXlO0D6QlOTMnV6g18gILpAXqkG2z9hf9z4hCjz2g==",
|
||||
"source_path": "css/bulma.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma.min.css",
|
||||
"sha256": "67fa26df1ca9e95d8f2adc7c04fa1b15fa3d24257470ebc10cc68b9aab914bee",
|
||||
"sri_sha512": "sha512-yh2RE0wZCVZeysGiqTwDTO/dKelCbS9bP2L94UvOFtl/FKXcNAje3Y2oBg/ZMZ3LS1sicYk4dYVGtDex75fvvA=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_tooltip_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tooltip",
|
||||
"version": "3.0.2",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-tooltip#readme",
|
||||
"official_url": "https://wikiki.github.io/elements/tooltip",
|
||||
"purpose": "Official Bulma tooltip extension from Bulma's extensions page",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-tooltip/-/bulma-tooltip-3.0.2.tgz",
|
||||
"dist_integrity": "sha512-CsT3APjhlZScskFg38n8HYL8oYNUHQtcu4sz6ERarxkUpBRbk9v0h/5KAvXeKapVSn2dp9l7bOGit5SECP8EWQ==",
|
||||
"source_path": "dist/css/bulma-tooltip.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma-tooltip.min.css",
|
||||
"sha256": "5c79d12a40b3532aaec159faa0b85fd3d500e192467761b71e0bda0fd04f3076",
|
||||
"sri_sha512": "sha512-SNDNIUvSYhnqDV9FFXaH/e0xZ6NzkG4Qm5dafLLf0PCMkzICKaOmMTgI3y2t2jZK+hAtP6A7UBcFqjWMhsujIg=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_slider_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-slider",
|
||||
"version": "2.0.5",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-slider#readme",
|
||||
"official_url": "https://wikiki.github.io/form/slider",
|
||||
"purpose": "Official Bulma slider extension from Bulma's extensions page",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-slider/-/bulma-slider-2.0.5.tgz",
|
||||
"dist_integrity": "sha512-6woD/1E7q1o5bfEaQjNqpWZaCItC1oHe9bN15WYB2ELqz2gDaJYZkf+rlozGpAYOXQGDQGCCv3y+QuKjx6sQuw==",
|
||||
"source_path": "dist/css/bulma-slider.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma-slider.min.css",
|
||||
"sha256": "f9d952627d388b8ba267e1388d6923274cf9e62e758d459c5a045f3933e9dc8a",
|
||||
"sri_sha512": "sha512-9o5SkCRCA9thttRH3Gb5QXLxKdRiuRLdO6ToEPwRHGLXjrhTZwFj0rEHjrCcJvDN9/aNaWMpGOIEA2vZsHmEqw=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_slider_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-slider",
|
||||
"version": "2.0.5",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-slider#readme",
|
||||
"official_url": "https://wikiki.github.io/form/slider",
|
||||
"purpose": "Official Bulma slider extension runtime",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-slider/-/bulma-slider-2.0.5.tgz",
|
||||
"dist_integrity": "sha512-6woD/1E7q1o5bfEaQjNqpWZaCItC1oHe9bN15WYB2ELqz2gDaJYZkf+rlozGpAYOXQGDQGCCv3y+QuKjx6sQuw==",
|
||||
"source_path": "dist/js/bulma-slider.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/bulma-slider.min.js",
|
||||
"sha256": "db68ebe154a25597913c5635f31500fe7a32e5a205fb9a98c9642d0c2de47d9e",
|
||||
"sri_sha512": "sha512-WLKXHCsMXTSIPsmQShJRE6K4IzwvNkhwxr/Oo8N3z+kzjhGleHibspmWLTawNMdl2z9E23XK20+yvUTDZ+zeNQ=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_calendar_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-calendar",
|
||||
"version": "7.1.1",
|
||||
"license": "MIT",
|
||||
"homepage": "https://doc.mh-s.de/bulma-calendar",
|
||||
"official_url": "https://wikiki.github.io/components/calendar",
|
||||
"purpose": "Official Bulma calendar extension from Bulma's extensions page",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-calendar/-/bulma-calendar-7.1.1.tgz",
|
||||
"dist_integrity": "sha512-E08i25KOfqMKBndgDF3y3eoQ0dUzVkgV9R53EDRM65GQUQKLzt8gcXVJYs3mYnpq6L3DiLuUt47Fl09tSv9OpA==",
|
||||
"source_path": "src/demo/assets/css/bulma-calendar.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma-calendar.min.css",
|
||||
"sha256": "d18b488ca52584bcd6ea3fb84bf06380e47a3cd18660a235617da017d13ab269",
|
||||
"sri_sha512": "sha512-IOnJQkgQpezPDPTJcRiWD7YVI3sF2RYzYDl4isbDT2geSaEHRQ615UN/8GhJbSkvqkKRZu8SBCQ7XwKMqsqLFQ=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_calendar_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-calendar",
|
||||
"version": "7.1.1",
|
||||
"license": "MIT",
|
||||
"homepage": "https://doc.mh-s.de/bulma-calendar",
|
||||
"official_url": "https://wikiki.github.io/components/calendar",
|
||||
"purpose": "Official Bulma calendar extension runtime",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-calendar/-/bulma-calendar-7.1.1.tgz",
|
||||
"dist_integrity": "sha512-E08i25KOfqMKBndgDF3y3eoQ0dUzVkgV9R53EDRM65GQUQKLzt8gcXVJYs3mYnpq6L3DiLuUt47Fl09tSv9OpA==",
|
||||
"source_path": "src/demo/assets/js/bulma-calendar.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/bulma-calendar.min.js",
|
||||
"sha256": "58160c87c4d17f9d98ec366fe019492acde50efbc0297af7045547952b306680",
|
||||
"sri_sha512": "sha512-kkEtEtypXzruevjkoxhyEkqkZBtlhK7s8zt7IV2yPabgBwy5xbKL9uWeCS37ldS9AaNTSnveWTu4ivUvGMJUWA=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_tagsinput_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tagsinput",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-tagsinput#readme",
|
||||
"official_url": "https://wikiki.github.io/form/tagsinput",
|
||||
"purpose": "Official Bulma tagsinput extension from Bulma's extensions page",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-tagsinput/-/bulma-tagsinput-2.0.0.tgz",
|
||||
"dist_integrity": "sha512-BFvd0oaxgeWHOEh3d4cgETy5vpSSjRRBA9w+8TWEuhjFQg38Rb+3vjDCavL+udpdjf+dRV0SK5T4kYCXTOrz5A==",
|
||||
"source_path": "dist/css/bulma-tagsinput.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma-tagsinput.min.css",
|
||||
"sha256": "8d1de24619c05ddf9045638b52059ab492d4887ce74119eed545d66af859da89",
|
||||
"sri_sha512": "sha512-NWTkcDRubZ3pyXbZZLQBILuVsRFs8c6QGgnfe4dm5/d6yp50U+xdoCDLIcSo51fFy/GXH0O2Oed1Z1sF1faxDA=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_tagsinput_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tagsinput",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-tagsinput#readme",
|
||||
"official_url": "https://wikiki.github.io/form/tagsinput",
|
||||
"purpose": "Official Bulma tagsinput extension runtime",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-tagsinput/-/bulma-tagsinput-2.0.0.tgz",
|
||||
"dist_integrity": "sha512-BFvd0oaxgeWHOEh3d4cgETy5vpSSjRRBA9w+8TWEuhjFQg38Rb+3vjDCavL+udpdjf+dRV0SK5T4kYCXTOrz5A==",
|
||||
"source_path": "dist/js/bulma-tagsinput.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/bulma-tagsinput.min.js",
|
||||
"sha256": "b355aa94ec519e374d7edf569e3dbde8bbe30ff3a193cb96f2930ee7815939d6",
|
||||
"sri_sha512": "sha512-Je6J++MjmmpxF30JCmRwM2KiK3uWQBQtqiNCjwzEMJKExLaa0BqerlYNa/fJAl5Rra4hMgRZF2fzg+V2vjE4Kw=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "bulma_switch_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-switch",
|
||||
"version": "2.0.4",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Wikiki/bulma-switch#readme",
|
||||
"official_url": "https://wikiki.github.io/form/switch",
|
||||
"purpose": "Official Bulma switch extension from Bulma's extensions page",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/bulma-switch/-/bulma-switch-2.0.4.tgz",
|
||||
"dist_integrity": "sha512-kMu4H0Pr0VjvfsnT6viRDCgptUq0Rvy7y7PX6q+IHg1xUynsjszPjhAdal5ysAlCG5HNO+5YXxeiu92qYGQolw==",
|
||||
"source_path": "dist/css/bulma-switch.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/bulma-switch.min.css",
|
||||
"sha256": "f0460ddebdd95425a50590908503a170f5ff08b28bd53573c71791fc7cd1e6f5",
|
||||
"sri_sha512": "sha512-zjrHYubQoNgDVqVKTyGjKcvIeQlduZTvXCvcBwQ0iqJYKLKiz9cuFAN7e98zfKqCTpI/EgFRBRcTwJw20yAFuw=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gridstack_css",
|
||||
"kind": "npm_file",
|
||||
"package": "gridstack",
|
||||
"version": "12.4.2",
|
||||
"license": "MIT",
|
||||
"homepage": "http://gridstackjs.com/",
|
||||
"official_url": "https://gridstackjs.com/",
|
||||
"purpose": "GridStack stylesheet",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/gridstack/-/gridstack-12.4.2.tgz",
|
||||
"dist_integrity": "sha512-aXbJrQpi3LwpYXYOr4UriPM5uc/dPcjK01SdOE5PDpx2vi8tnLhU7yBg/1i4T59UhNkG/RBfabdFUObuN+gMnw==",
|
||||
"source_path": "dist/gridstack.min.css",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/css/gridstack.min.css",
|
||||
"sha256": "55e9d4ea6d8c6f8f1ea8a449b8af18d8571487c0afc6b433cccf877047cb8457",
|
||||
"sri_sha512": "sha512-ttQfsDTO64bamkJHeLDf0kzMP1NKfkootudPWS2V8Pwy+9z1wexSYjIT6/HXGg/bmtD+DRwsUnQoYEB0yePjbw=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gridstack_js",
|
||||
"kind": "npm_file",
|
||||
"package": "gridstack",
|
||||
"version": "12.4.2",
|
||||
"license": "MIT",
|
||||
"homepage": "http://gridstackjs.com/",
|
||||
"official_url": "https://gridstackjs.com/",
|
||||
"purpose": "GridStack bundle used by the dashboard",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/gridstack/-/gridstack-12.4.2.tgz",
|
||||
"dist_integrity": "sha512-aXbJrQpi3LwpYXYOr4UriPM5uc/dPcjK01SdOE5PDpx2vi8tnLhU7yBg/1i4T59UhNkG/RBfabdFUObuN+gMnw==",
|
||||
"source_path": "dist/gridstack-all.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/gridstack-all.js",
|
||||
"sha256": "e055ca4eb8bdc65f14f38c966ec31960c4c8dc6dc42e91f421bd629808185518",
|
||||
"sri_sha512": "sha512-djBPxwvBhDep1SvOhliatweHMORhVO3HabrfBjaW6nYsa7UcJYHty31x42m4HBSJXcJSQdoEgRPLVYGGIuIaDQ=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "jquery_js",
|
||||
"kind": "npm_file",
|
||||
"package": "jquery",
|
||||
"version": "3.7.1",
|
||||
"license": "MIT",
|
||||
"homepage": "https://jquery.com",
|
||||
"official_url": "https://jquery.com",
|
||||
"purpose": "Latest jQuery 3.x release for compatibility with legacy plugins",
|
||||
"notes": "The latest npm release is jQuery 4.x, but this project still vendors 3.7.1 to avoid breaking older plugins.",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
||||
"dist_integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"source_path": "dist/jquery.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/jquery.min.js",
|
||||
"sha256": "fc9a93dd241f6b045cbff0481cf4e1901becd0e12fb45166a8f17f95823f0b1a",
|
||||
"sri_sha512": "sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "htmx_js",
|
||||
"kind": "npm_file",
|
||||
"package": "htmx.org",
|
||||
"version": "2.0.8",
|
||||
"license": "0BSD",
|
||||
"homepage": "https://htmx.org/",
|
||||
"official_url": "https://htmx.org/",
|
||||
"purpose": "htmx runtime",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.8.tgz",
|
||||
"dist_integrity": "sha512-fm297iru0iWsNJlBrjvtN7V9zjaxd+69Oqjh4F/Vq9Wwi2kFisLcrLCiv5oBX0KLfOX/zG8AUo9ROMU5XUB44Q==",
|
||||
"source_path": "dist/htmx.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/htmx.min.js",
|
||||
"sha256": "22283ef68cb7545914f0a88a1bdedc7256a703d1d580c1d255217d0a50d31313",
|
||||
"sri_sha512": "sha512-CGXFnDNv5q48ciFeIyWFcfZhqYW0sSBiPO+HZDO3XLM+p8xjhezz5CCxtkXVDKfCbvF+iUhel7xoeSp19o7x7g=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "hyperscript_js",
|
||||
"kind": "npm_file",
|
||||
"package": "hyperscript.org",
|
||||
"version": "0.9.14",
|
||||
"license": "BSD 2-Clause",
|
||||
"homepage": "https://hyperscript.org/",
|
||||
"official_url": "https://hyperscript.org/",
|
||||
"purpose": "_hyperscript runtime",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/hyperscript.org/-/hyperscript.org-0.9.14.tgz",
|
||||
"dist_integrity": "sha512-ugmojsQQUMmXcnwaXYiYf8L3GbeANy/m59EmE/0Z6C5eQ52fOuSrvFkuEIejG9BdpbYB4iTtoYGqV99eYqDVMA==",
|
||||
"source_path": "dist/_hyperscript.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/hyperscript.min.js",
|
||||
"sha256": "3e834a3ffc0334fee54ecff4e37a6ae951cd83e6daa96651ca7cfd8f751ad4d2",
|
||||
"sri_sha512": "sha512-l43sZzpnAddmYhJyfPrgv46XhJvA95gsA28/+eW4XZLSekQ8wlP68i9f22KGkRjY0HNiZrLc5MXGo4z/tM2QNA=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "magnet_js",
|
||||
"kind": "npm_file",
|
||||
"package": "@lf2com/magnet.js",
|
||||
"version": "2.0.1",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lf2com/magnet.js",
|
||||
"official_url": "https://github.com/lf2com/magnet.js",
|
||||
"purpose": "Magnet.js drag attraction component",
|
||||
"notes": "",
|
||||
"resolved": "https://registry.npmjs.org/@lf2com/magnet.js/-/magnet.js-2.0.1.tgz",
|
||||
"dist_integrity": "sha512-MDgv1s0aNOuftuhY9c9Ve6Yadkmn7G+Ww91cVciyHHMhPPdxTxX3XUSJXFYD3VraGFzcnI4uilik9/I76AsJEg==",
|
||||
"source_path": "dist/magnet.min.js",
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/js/magnet.min.js",
|
||||
"sha256": "05ff8858b5fb7b3ad2a618212571162e2108f580b08527716f4e63c648dcccb1",
|
||||
"sri_sha512": "sha512-aoQ3V4iCM8zTcdMDSUTRG1K9wqZzmDSisuaCLQexk9DdFy92oWvTUoAfCVLnGzzJClst8PmtasZg219REwyNkw=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fontawesome_bundle",
|
||||
"kind": "url_bundle",
|
||||
"version": "6.1.1",
|
||||
"license": "Font Awesome Pro commercial terms via site-assets.fontawesome.com",
|
||||
"homepage": "https://fontawesome.com",
|
||||
"official_url": "https://fontawesome.com",
|
||||
"purpose": "Existing Font Awesome asset family, self-hosted locally to preserve the currently used icon set",
|
||||
"notes": "",
|
||||
"entry_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css",
|
||||
"downloaded_files": [
|
||||
{
|
||||
"relative_path": "css/all.css",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-brands-400.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-brands-400.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-brands-400.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-brands-400.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-duotone-900.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-duotone-900.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-duotone-900.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-duotone-900.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-light-300.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-light-300.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-light-300.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-light-300.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-regular-400.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-regular-400.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-regular-400.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-regular-400.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-solid-900.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-solid-900.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-solid-900.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-solid-900.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-thin-100.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-thin-100.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-thin-100.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-thin-100.ttf"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-v4compatibility.woff2",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-v4compatibility.woff2"
|
||||
},
|
||||
{
|
||||
"relative_path": "css/../webfonts/fa-v4compatibility.ttf",
|
||||
"download_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-v4compatibility.ttf"
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/all.css",
|
||||
"sha256": "a35f901d01118e5649091bd03ac5784a7db52e111fb3806524c412f3d1dcfc5d",
|
||||
"sri_sha512": "sha512-UKBBxJ5N3/MYiSsYTlEsARsp4vELKVRIklED4Mb6wpuVFOgy5Blt+sXUdz1TDReqWsm64xxBA2QoBJRCxI0x5Q=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-brands-400.woff2",
|
||||
"sha256": "3701cbff3acccd80b1f2eede4311050514f7a64c2039eb77a77368fcd6e3de28",
|
||||
"sri_sha512": "sha512-50+1yWldN03if6k/4jyncfSZyT44ev20Q7jmIGEiKG7v2qeB1nBOcVF9HD0mjSvAxmpS3+RDzoPfqbB4GfCkJg=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-brands-400.ttf",
|
||||
"sha256": "06f6dc20f535066f0e069105329ad69d526d7a16215e7ff8af3dbc2cd0894186",
|
||||
"sri_sha512": "sha512-klNly6qz+BwYPusuoZ0BIE01WW0CbrJszi5GrgZ6yFXQCrxAQRus6vMMATIxwPNYOYXu+UOd2KbRAsenhIkAGQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-duotone-900.woff2",
|
||||
"sha256": "6f28dce91f45bc4687582137bb5d82d9771efc774e3b2b83c30018469d191ad8",
|
||||
"sri_sha512": "sha512-Sz0g1G5m7symrIy2LfJOdASOrJQUo+IDIMpLKhFKm4RM7MLjV6wqlVGtDf2lEqE/tSzU5LQTtsc3djfZwDXCFQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-duotone-900.ttf",
|
||||
"sha256": "6687687c70d502ff006750978f55d6d5108c364eec78db9b845adcfc838b78a4",
|
||||
"sri_sha512": "sha512-1301N0n8/h7Kjp6E7LbEe7LWCyDPkfvYn9COlQ6ISbQTP/uPThs8NLhSr+nQskAPzjDoMqfojg0EyNfsD84s/w=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-light-300.woff2",
|
||||
"sha256": "515954fe1dc163277d36b51f79fe56265f6b6cf79f99e307bbf6e52b477b9c87",
|
||||
"sri_sha512": "sha512-xdrnQ7rYHIz80KJgGizTu80jCcWF4tGt/inACAoWT3dl3BleiIjq/g90RA42wJNcLpz3n8JAM1Z0ayUGROP5RQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-light-300.ttf",
|
||||
"sha256": "7c41f14e1e8bbe7780049512c631b5301936a985dc6bbadd74a0cbc05549769c",
|
||||
"sri_sha512": "sha512-i3tSu80Wfsx/12vQQziHhYQLjBNYLGQZfeXfyurZhCBibO+lq6kX1zARiktltXxBszu513BIKbnfzLTRYamoMQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-regular-400.woff2",
|
||||
"sha256": "121b176974226dbc9b1ab227becb657d40b88d2bb7010a746c2360c31d7c373e",
|
||||
"sri_sha512": "sha512-qioT43fXB5q4Bbpn8sPQE9OIZLjKD0c0lVmpm6KmT8k34LM6gkRcOOMi1BOl2lohFG/7p9tzKfTP5G563BQq1g=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-regular-400.ttf",
|
||||
"sha256": "daa07950214eae5603ebb5a582a694da7b31a4c93f3bf38e9f616122860d83a5",
|
||||
"sri_sha512": "sha512-1Ttr+eWt+Z7Na3gRZklbYEnBYGbQUATusZ4oeYLamI4iIjN8ILNV/upwk/h8qIJ2lf/Mukkj5zBVhUdXWJWLwQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-solid-900.woff2",
|
||||
"sha256": "f350c708b5e7748a452b4b98600fa49127166d995686e260ccafb58d51a4ea62",
|
||||
"sri_sha512": "sha512-Ph1xTLhfMycYSW+wUN8oL3Ggl56nGIS95EHiKWggcL/GbMNjPdib1Hreb1D4COlMxdiGCkk43nspQnpDuTjgQg=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-solid-900.ttf",
|
||||
"sha256": "bbab2beb558f176d68d3e6002e4ea608633f7e6347dc6245dc67f8ad1c9ca18a",
|
||||
"sri_sha512": "sha512-c/IBq1JAYcB6z9QnrVqSJREvhrp3NudGg8phmemZ1P41RTIc/z2txqbzP/dWVZYzZl9mPxDnDNLGTFWIQsAfPQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-thin-100.woff2",
|
||||
"sha256": "92fb7777eb1a6a9c8e94048403db3e197e5e541bfd8142255e74ac69141081b2",
|
||||
"sri_sha512": "sha512-U61hRcHKBdwKMsPzon6yDsO7ReY5gCHX3uztO+D48ynrqy4ZESWdoBtKohmJuXxry3epUhLQLsMd62nb6zmzhA=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-thin-100.ttf",
|
||||
"sha256": "b8ef1ff99503a5611531d09bf5815261c1fb2f8291ae562711a7d7b651f92b9f",
|
||||
"sri_sha512": "sha512-kFuJup+kEGELeelH6CXGKPaQ+cJfpLbOtbFFae6CwZfAidwsoM74wYu1Kzwb+pgeK9ODZc7SQMXpFWj5Mn7KtQ=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-v4compatibility.woff2",
|
||||
"sha256": "4468a4ec439fecc93d86936bc3b5b5db7d0b98ce173faefd18938b2cef79245b",
|
||||
"sri_sha512": "sha512-DzAaC0v4WatRDbN7LVoGXD5pmuOmveGoBimQLfnQFz74+L+hhZVatKhENPHAVkeNtRTBQ63B8w0fOlrQ3bERuw=="
|
||||
},
|
||||
{
|
||||
"path": "core/static/vendor/fontawesome/css/../webfonts/fa-v4compatibility.ttf",
|
||||
"sha256": "0f40286f817bb931f65fc1a5963f1450af855547fa9d2c02a009ad389fcc7d95",
|
||||
"sri_sha512": "sha512-emfG/sIso1lhi9tNNmqIGP2xNU8SP47qPspS7g8V7ltbotbznl/wy00DxyjrtfxhYw3OfYYlxtyiGyoyRAFXTg=="
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
315
artifacts/frontend_libraries.md
Normal file
315
artifacts/frontend_libraries.md
Normal file
@@ -0,0 +1,315 @@
|
||||
# Frontend Library Inventory
|
||||
|
||||
This report is generated by `scripts/vendor_frontend_assets.py` from `tools/frontend_assets/asset-manifest.json`.
|
||||
|
||||
## bulma_css
|
||||
|
||||
- Source: `bulma`
|
||||
- Version: `1.0.4`
|
||||
- Official URL: https://bulma.io
|
||||
- Homepage: https://bulma.io
|
||||
- License: `MIT`
|
||||
- Purpose: Bulma core stylesheet
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma/-/bulma-1.0.4.tgz`
|
||||
- Upstream package integrity: `sha512-Ffb6YGXDiZYX3cqvSbHWqQ8+LkX6tVoTcZuVB3lm93sbAVXlO0D6QlOTMnV6g18gILpAXqkG2z9hf9z4hCjz2g==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma.min.css`
|
||||
- SHA-256: `67fa26df1ca9e95d8f2adc7c04fa1b15fa3d24257470ebc10cc68b9aab914bee`
|
||||
- SRI sha512: `sha512-yh2RE0wZCVZeysGiqTwDTO/dKelCbS9bP2L94UvOFtl/FKXcNAje3Y2oBg/ZMZ3LS1sicYk4dYVGtDex75fvvA==`
|
||||
|
||||
|
||||
## bulma_tooltip_css
|
||||
|
||||
- Source: `bulma-tooltip`
|
||||
- Version: `3.0.2`
|
||||
- Official URL: https://wikiki.github.io/elements/tooltip
|
||||
- Homepage: https://github.com/Wikiki/bulma-tooltip#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma tooltip extension from Bulma's extensions page
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-tooltip/-/bulma-tooltip-3.0.2.tgz`
|
||||
- Upstream package integrity: `sha512-CsT3APjhlZScskFg38n8HYL8oYNUHQtcu4sz6ERarxkUpBRbk9v0h/5KAvXeKapVSn2dp9l7bOGit5SECP8EWQ==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma-tooltip.min.css`
|
||||
- SHA-256: `5c79d12a40b3532aaec159faa0b85fd3d500e192467761b71e0bda0fd04f3076`
|
||||
- SRI sha512: `sha512-SNDNIUvSYhnqDV9FFXaH/e0xZ6NzkG4Qm5dafLLf0PCMkzICKaOmMTgI3y2t2jZK+hAtP6A7UBcFqjWMhsujIg==`
|
||||
|
||||
|
||||
## bulma_slider_css
|
||||
|
||||
- Source: `bulma-slider`
|
||||
- Version: `2.0.5`
|
||||
- Official URL: https://wikiki.github.io/form/slider
|
||||
- Homepage: https://github.com/Wikiki/bulma-slider#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma slider extension from Bulma's extensions page
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-slider/-/bulma-slider-2.0.5.tgz`
|
||||
- Upstream package integrity: `sha512-6woD/1E7q1o5bfEaQjNqpWZaCItC1oHe9bN15WYB2ELqz2gDaJYZkf+rlozGpAYOXQGDQGCCv3y+QuKjx6sQuw==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma-slider.min.css`
|
||||
- SHA-256: `f9d952627d388b8ba267e1388d6923274cf9e62e758d459c5a045f3933e9dc8a`
|
||||
- SRI sha512: `sha512-9o5SkCRCA9thttRH3Gb5QXLxKdRiuRLdO6ToEPwRHGLXjrhTZwFj0rEHjrCcJvDN9/aNaWMpGOIEA2vZsHmEqw==`
|
||||
|
||||
|
||||
## bulma_slider_js
|
||||
|
||||
- Source: `bulma-slider`
|
||||
- Version: `2.0.5`
|
||||
- Official URL: https://wikiki.github.io/form/slider
|
||||
- Homepage: https://github.com/Wikiki/bulma-slider#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma slider extension runtime
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-slider/-/bulma-slider-2.0.5.tgz`
|
||||
- Upstream package integrity: `sha512-6woD/1E7q1o5bfEaQjNqpWZaCItC1oHe9bN15WYB2ELqz2gDaJYZkf+rlozGpAYOXQGDQGCCv3y+QuKjx6sQuw==`
|
||||
- Local targets:
|
||||
- `core/static/js/bulma-slider.min.js`
|
||||
- SHA-256: `db68ebe154a25597913c5635f31500fe7a32e5a205fb9a98c9642d0c2de47d9e`
|
||||
- SRI sha512: `sha512-WLKXHCsMXTSIPsmQShJRE6K4IzwvNkhwxr/Oo8N3z+kzjhGleHibspmWLTawNMdl2z9E23XK20+yvUTDZ+zeNQ==`
|
||||
|
||||
|
||||
## bulma_calendar_css
|
||||
|
||||
- Source: `bulma-calendar`
|
||||
- Version: `7.1.1`
|
||||
- Official URL: https://wikiki.github.io/components/calendar
|
||||
- Homepage: https://doc.mh-s.de/bulma-calendar
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma calendar extension from Bulma's extensions page
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-calendar/-/bulma-calendar-7.1.1.tgz`
|
||||
- Upstream package integrity: `sha512-E08i25KOfqMKBndgDF3y3eoQ0dUzVkgV9R53EDRM65GQUQKLzt8gcXVJYs3mYnpq6L3DiLuUt47Fl09tSv9OpA==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma-calendar.min.css`
|
||||
- SHA-256: `d18b488ca52584bcd6ea3fb84bf06380e47a3cd18660a235617da017d13ab269`
|
||||
- SRI sha512: `sha512-IOnJQkgQpezPDPTJcRiWD7YVI3sF2RYzYDl4isbDT2geSaEHRQ615UN/8GhJbSkvqkKRZu8SBCQ7XwKMqsqLFQ==`
|
||||
|
||||
|
||||
## bulma_calendar_js
|
||||
|
||||
- Source: `bulma-calendar`
|
||||
- Version: `7.1.1`
|
||||
- Official URL: https://wikiki.github.io/components/calendar
|
||||
- Homepage: https://doc.mh-s.de/bulma-calendar
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma calendar extension runtime
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-calendar/-/bulma-calendar-7.1.1.tgz`
|
||||
- Upstream package integrity: `sha512-E08i25KOfqMKBndgDF3y3eoQ0dUzVkgV9R53EDRM65GQUQKLzt8gcXVJYs3mYnpq6L3DiLuUt47Fl09tSv9OpA==`
|
||||
- Local targets:
|
||||
- `core/static/js/bulma-calendar.min.js`
|
||||
- SHA-256: `58160c87c4d17f9d98ec366fe019492acde50efbc0297af7045547952b306680`
|
||||
- SRI sha512: `sha512-kkEtEtypXzruevjkoxhyEkqkZBtlhK7s8zt7IV2yPabgBwy5xbKL9uWeCS37ldS9AaNTSnveWTu4ivUvGMJUWA==`
|
||||
|
||||
|
||||
## bulma_tagsinput_css
|
||||
|
||||
- Source: `bulma-tagsinput`
|
||||
- Version: `2.0.0`
|
||||
- Official URL: https://wikiki.github.io/form/tagsinput
|
||||
- Homepage: https://github.com/Wikiki/bulma-tagsinput#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma tagsinput extension from Bulma's extensions page
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-tagsinput/-/bulma-tagsinput-2.0.0.tgz`
|
||||
- Upstream package integrity: `sha512-BFvd0oaxgeWHOEh3d4cgETy5vpSSjRRBA9w+8TWEuhjFQg38Rb+3vjDCavL+udpdjf+dRV0SK5T4kYCXTOrz5A==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma-tagsinput.min.css`
|
||||
- SHA-256: `8d1de24619c05ddf9045638b52059ab492d4887ce74119eed545d66af859da89`
|
||||
- SRI sha512: `sha512-NWTkcDRubZ3pyXbZZLQBILuVsRFs8c6QGgnfe4dm5/d6yp50U+xdoCDLIcSo51fFy/GXH0O2Oed1Z1sF1faxDA==`
|
||||
|
||||
|
||||
## bulma_tagsinput_js
|
||||
|
||||
- Source: `bulma-tagsinput`
|
||||
- Version: `2.0.0`
|
||||
- Official URL: https://wikiki.github.io/form/tagsinput
|
||||
- Homepage: https://github.com/Wikiki/bulma-tagsinput#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma tagsinput extension runtime
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-tagsinput/-/bulma-tagsinput-2.0.0.tgz`
|
||||
- Upstream package integrity: `sha512-BFvd0oaxgeWHOEh3d4cgETy5vpSSjRRBA9w+8TWEuhjFQg38Rb+3vjDCavL+udpdjf+dRV0SK5T4kYCXTOrz5A==`
|
||||
- Local targets:
|
||||
- `core/static/js/bulma-tagsinput.min.js`
|
||||
- SHA-256: `b355aa94ec519e374d7edf569e3dbde8bbe30ff3a193cb96f2930ee7815939d6`
|
||||
- SRI sha512: `sha512-Je6J++MjmmpxF30JCmRwM2KiK3uWQBQtqiNCjwzEMJKExLaa0BqerlYNa/fJAl5Rra4hMgRZF2fzg+V2vjE4Kw==`
|
||||
|
||||
|
||||
## bulma_switch_css
|
||||
|
||||
- Source: `bulma-switch`
|
||||
- Version: `2.0.4`
|
||||
- Official URL: https://wikiki.github.io/form/switch
|
||||
- Homepage: https://github.com/Wikiki/bulma-switch#readme
|
||||
- License: `MIT`
|
||||
- Purpose: Official Bulma switch extension from Bulma's extensions page
|
||||
- Resolved tarball: `https://registry.npmjs.org/bulma-switch/-/bulma-switch-2.0.4.tgz`
|
||||
- Upstream package integrity: `sha512-kMu4H0Pr0VjvfsnT6viRDCgptUq0Rvy7y7PX6q+IHg1xUynsjszPjhAdal5ysAlCG5HNO+5YXxeiu92qYGQolw==`
|
||||
- Local targets:
|
||||
- `core/static/css/bulma-switch.min.css`
|
||||
- SHA-256: `f0460ddebdd95425a50590908503a170f5ff08b28bd53573c71791fc7cd1e6f5`
|
||||
- SRI sha512: `sha512-zjrHYubQoNgDVqVKTyGjKcvIeQlduZTvXCvcBwQ0iqJYKLKiz9cuFAN7e98zfKqCTpI/EgFRBRcTwJw20yAFuw==`
|
||||
|
||||
|
||||
## gridstack_css
|
||||
|
||||
- Source: `gridstack`
|
||||
- Version: `12.4.2`
|
||||
- Official URL: https://gridstackjs.com/
|
||||
- Homepage: http://gridstackjs.com/
|
||||
- License: `MIT`
|
||||
- Purpose: GridStack stylesheet
|
||||
- Resolved tarball: `https://registry.npmjs.org/gridstack/-/gridstack-12.4.2.tgz`
|
||||
- Upstream package integrity: `sha512-aXbJrQpi3LwpYXYOr4UriPM5uc/dPcjK01SdOE5PDpx2vi8tnLhU7yBg/1i4T59UhNkG/RBfabdFUObuN+gMnw==`
|
||||
- Local targets:
|
||||
- `core/static/css/gridstack.min.css`
|
||||
- SHA-256: `55e9d4ea6d8c6f8f1ea8a449b8af18d8571487c0afc6b433cccf877047cb8457`
|
||||
- SRI sha512: `sha512-ttQfsDTO64bamkJHeLDf0kzMP1NKfkootudPWS2V8Pwy+9z1wexSYjIT6/HXGg/bmtD+DRwsUnQoYEB0yePjbw==`
|
||||
|
||||
|
||||
## gridstack_js
|
||||
|
||||
- Source: `gridstack`
|
||||
- Version: `12.4.2`
|
||||
- Official URL: https://gridstackjs.com/
|
||||
- Homepage: http://gridstackjs.com/
|
||||
- License: `MIT`
|
||||
- Purpose: GridStack bundle used by the dashboard
|
||||
- Resolved tarball: `https://registry.npmjs.org/gridstack/-/gridstack-12.4.2.tgz`
|
||||
- Upstream package integrity: `sha512-aXbJrQpi3LwpYXYOr4UriPM5uc/dPcjK01SdOE5PDpx2vi8tnLhU7yBg/1i4T59UhNkG/RBfabdFUObuN+gMnw==`
|
||||
- Local targets:
|
||||
- `core/static/js/gridstack-all.js`
|
||||
- SHA-256: `e055ca4eb8bdc65f14f38c966ec31960c4c8dc6dc42e91f421bd629808185518`
|
||||
- SRI sha512: `sha512-djBPxwvBhDep1SvOhliatweHMORhVO3HabrfBjaW6nYsa7UcJYHty31x42m4HBSJXcJSQdoEgRPLVYGGIuIaDQ==`
|
||||
|
||||
|
||||
## jquery_js
|
||||
|
||||
- Source: `jquery`
|
||||
- Version: `3.7.1`
|
||||
- Official URL: https://jquery.com
|
||||
- Homepage: https://jquery.com
|
||||
- License: `MIT`
|
||||
- Purpose: Latest jQuery 3.x release for compatibility with legacy plugins
|
||||
- Resolved tarball: `https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz`
|
||||
- Upstream package integrity: `sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==`
|
||||
- Notes: The latest npm release is jQuery 4.x, but this project still vendors 3.7.1 to avoid breaking older plugins.
|
||||
- Local targets:
|
||||
- `core/static/js/jquery.min.js`
|
||||
- SHA-256: `fc9a93dd241f6b045cbff0481cf4e1901becd0e12fb45166a8f17f95823f0b1a`
|
||||
- SRI sha512: `sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==`
|
||||
|
||||
|
||||
## htmx_js
|
||||
|
||||
- Source: `htmx.org`
|
||||
- Version: `2.0.8`
|
||||
- Official URL: https://htmx.org/
|
||||
- Homepage: https://htmx.org/
|
||||
- License: `0BSD`
|
||||
- Purpose: htmx runtime
|
||||
- Resolved tarball: `https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.8.tgz`
|
||||
- Upstream package integrity: `sha512-fm297iru0iWsNJlBrjvtN7V9zjaxd+69Oqjh4F/Vq9Wwi2kFisLcrLCiv5oBX0KLfOX/zG8AUo9ROMU5XUB44Q==`
|
||||
- Local targets:
|
||||
- `core/static/js/htmx.min.js`
|
||||
- SHA-256: `22283ef68cb7545914f0a88a1bdedc7256a703d1d580c1d255217d0a50d31313`
|
||||
- SRI sha512: `sha512-CGXFnDNv5q48ciFeIyWFcfZhqYW0sSBiPO+HZDO3XLM+p8xjhezz5CCxtkXVDKfCbvF+iUhel7xoeSp19o7x7g==`
|
||||
|
||||
|
||||
## hyperscript_js
|
||||
|
||||
- Source: `hyperscript.org`
|
||||
- Version: `0.9.14`
|
||||
- Official URL: https://hyperscript.org/
|
||||
- Homepage: https://hyperscript.org/
|
||||
- License: `BSD 2-Clause`
|
||||
- Purpose: _hyperscript runtime
|
||||
- Resolved tarball: `https://registry.npmjs.org/hyperscript.org/-/hyperscript.org-0.9.14.tgz`
|
||||
- Upstream package integrity: `sha512-ugmojsQQUMmXcnwaXYiYf8L3GbeANy/m59EmE/0Z6C5eQ52fOuSrvFkuEIejG9BdpbYB4iTtoYGqV99eYqDVMA==`
|
||||
- Local targets:
|
||||
- `core/static/js/hyperscript.min.js`
|
||||
- SHA-256: `3e834a3ffc0334fee54ecff4e37a6ae951cd83e6daa96651ca7cfd8f751ad4d2`
|
||||
- SRI sha512: `sha512-l43sZzpnAddmYhJyfPrgv46XhJvA95gsA28/+eW4XZLSekQ8wlP68i9f22KGkRjY0HNiZrLc5MXGo4z/tM2QNA==`
|
||||
|
||||
|
||||
## magnet_js
|
||||
|
||||
- Source: `@lf2com/magnet.js`
|
||||
- Version: `2.0.1`
|
||||
- Official URL: https://github.com/lf2com/magnet.js
|
||||
- Homepage: https://github.com/lf2com/magnet.js
|
||||
- License: `MIT`
|
||||
- Purpose: Magnet.js drag attraction component
|
||||
- Resolved tarball: `https://registry.npmjs.org/@lf2com/magnet.js/-/magnet.js-2.0.1.tgz`
|
||||
- Upstream package integrity: `sha512-MDgv1s0aNOuftuhY9c9Ve6Yadkmn7G+Ww91cVciyHHMhPPdxTxX3XUSJXFYD3VraGFzcnI4uilik9/I76AsJEg==`
|
||||
- Local targets:
|
||||
- `core/static/js/magnet.min.js`
|
||||
- SHA-256: `05ff8858b5fb7b3ad2a618212571162e2108f580b08527716f4e63c648dcccb1`
|
||||
- SRI sha512: `sha512-aoQ3V4iCM8zTcdMDSUTRG1K9wqZzmDSisuaCLQexk9DdFy92oWvTUoAfCVLnGzzJClst8PmtasZg219REwyNkw==`
|
||||
|
||||
|
||||
## fontawesome_bundle
|
||||
|
||||
- Source: `https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css`
|
||||
- Version: `6.1.1`
|
||||
- Official URL: https://fontawesome.com
|
||||
- Homepage: https://fontawesome.com
|
||||
- License: `Font Awesome Pro commercial terms via site-assets.fontawesome.com`
|
||||
- Purpose: Existing Font Awesome asset family, self-hosted locally to preserve the currently used icon set
|
||||
- Downloaded bundle files:
|
||||
- `css/all.css` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css`
|
||||
- `css/../webfonts/fa-brands-400.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-brands-400.woff2`
|
||||
- `css/../webfonts/fa-brands-400.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-brands-400.ttf`
|
||||
- `css/../webfonts/fa-duotone-900.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-duotone-900.woff2`
|
||||
- `css/../webfonts/fa-duotone-900.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-duotone-900.ttf`
|
||||
- `css/../webfonts/fa-light-300.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-light-300.woff2`
|
||||
- `css/../webfonts/fa-light-300.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-light-300.ttf`
|
||||
- `css/../webfonts/fa-regular-400.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-regular-400.woff2`
|
||||
- `css/../webfonts/fa-regular-400.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-regular-400.ttf`
|
||||
- `css/../webfonts/fa-solid-900.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-solid-900.woff2`
|
||||
- `css/../webfonts/fa-solid-900.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-solid-900.ttf`
|
||||
- `css/../webfonts/fa-thin-100.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-thin-100.woff2`
|
||||
- `css/../webfonts/fa-thin-100.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-thin-100.ttf`
|
||||
- `css/../webfonts/fa-v4compatibility.woff2` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-v4compatibility.woff2`
|
||||
- `css/../webfonts/fa-v4compatibility.ttf` from `https://site-assets.fontawesome.com/releases/v6.1.1/css/webfonts/fa-v4compatibility.ttf`
|
||||
- Local targets:
|
||||
- `core/static/vendor/fontawesome/css/all.css`
|
||||
- SHA-256: `a35f901d01118e5649091bd03ac5784a7db52e111fb3806524c412f3d1dcfc5d`
|
||||
- SRI sha512: `sha512-UKBBxJ5N3/MYiSsYTlEsARsp4vELKVRIklED4Mb6wpuVFOgy5Blt+sXUdz1TDReqWsm64xxBA2QoBJRCxI0x5Q==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-brands-400.woff2`
|
||||
- SHA-256: `3701cbff3acccd80b1f2eede4311050514f7a64c2039eb77a77368fcd6e3de28`
|
||||
- SRI sha512: `sha512-50+1yWldN03if6k/4jyncfSZyT44ev20Q7jmIGEiKG7v2qeB1nBOcVF9HD0mjSvAxmpS3+RDzoPfqbB4GfCkJg==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-brands-400.ttf`
|
||||
- SHA-256: `06f6dc20f535066f0e069105329ad69d526d7a16215e7ff8af3dbc2cd0894186`
|
||||
- SRI sha512: `sha512-klNly6qz+BwYPusuoZ0BIE01WW0CbrJszi5GrgZ6yFXQCrxAQRus6vMMATIxwPNYOYXu+UOd2KbRAsenhIkAGQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-duotone-900.woff2`
|
||||
- SHA-256: `6f28dce91f45bc4687582137bb5d82d9771efc774e3b2b83c30018469d191ad8`
|
||||
- SRI sha512: `sha512-Sz0g1G5m7symrIy2LfJOdASOrJQUo+IDIMpLKhFKm4RM7MLjV6wqlVGtDf2lEqE/tSzU5LQTtsc3djfZwDXCFQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-duotone-900.ttf`
|
||||
- SHA-256: `6687687c70d502ff006750978f55d6d5108c364eec78db9b845adcfc838b78a4`
|
||||
- SRI sha512: `sha512-1301N0n8/h7Kjp6E7LbEe7LWCyDPkfvYn9COlQ6ISbQTP/uPThs8NLhSr+nQskAPzjDoMqfojg0EyNfsD84s/w==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-light-300.woff2`
|
||||
- SHA-256: `515954fe1dc163277d36b51f79fe56265f6b6cf79f99e307bbf6e52b477b9c87`
|
||||
- SRI sha512: `sha512-xdrnQ7rYHIz80KJgGizTu80jCcWF4tGt/inACAoWT3dl3BleiIjq/g90RA42wJNcLpz3n8JAM1Z0ayUGROP5RQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-light-300.ttf`
|
||||
- SHA-256: `7c41f14e1e8bbe7780049512c631b5301936a985dc6bbadd74a0cbc05549769c`
|
||||
- SRI sha512: `sha512-i3tSu80Wfsx/12vQQziHhYQLjBNYLGQZfeXfyurZhCBibO+lq6kX1zARiktltXxBszu513BIKbnfzLTRYamoMQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-regular-400.woff2`
|
||||
- SHA-256: `121b176974226dbc9b1ab227becb657d40b88d2bb7010a746c2360c31d7c373e`
|
||||
- SRI sha512: `sha512-qioT43fXB5q4Bbpn8sPQE9OIZLjKD0c0lVmpm6KmT8k34LM6gkRcOOMi1BOl2lohFG/7p9tzKfTP5G563BQq1g==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-regular-400.ttf`
|
||||
- SHA-256: `daa07950214eae5603ebb5a582a694da7b31a4c93f3bf38e9f616122860d83a5`
|
||||
- SRI sha512: `sha512-1Ttr+eWt+Z7Na3gRZklbYEnBYGbQUATusZ4oeYLamI4iIjN8ILNV/upwk/h8qIJ2lf/Mukkj5zBVhUdXWJWLwQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-solid-900.woff2`
|
||||
- SHA-256: `f350c708b5e7748a452b4b98600fa49127166d995686e260ccafb58d51a4ea62`
|
||||
- SRI sha512: `sha512-Ph1xTLhfMycYSW+wUN8oL3Ggl56nGIS95EHiKWggcL/GbMNjPdib1Hreb1D4COlMxdiGCkk43nspQnpDuTjgQg==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-solid-900.ttf`
|
||||
- SHA-256: `bbab2beb558f176d68d3e6002e4ea608633f7e6347dc6245dc67f8ad1c9ca18a`
|
||||
- SRI sha512: `sha512-c/IBq1JAYcB6z9QnrVqSJREvhrp3NudGg8phmemZ1P41RTIc/z2txqbzP/dWVZYzZl9mPxDnDNLGTFWIQsAfPQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-thin-100.woff2`
|
||||
- SHA-256: `92fb7777eb1a6a9c8e94048403db3e197e5e541bfd8142255e74ac69141081b2`
|
||||
- SRI sha512: `sha512-U61hRcHKBdwKMsPzon6yDsO7ReY5gCHX3uztO+D48ynrqy4ZESWdoBtKohmJuXxry3epUhLQLsMd62nb6zmzhA==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-thin-100.ttf`
|
||||
- SHA-256: `b8ef1ff99503a5611531d09bf5815261c1fb2f8291ae562711a7d7b651f92b9f`
|
||||
- SRI sha512: `sha512-kFuJup+kEGELeelH6CXGKPaQ+cJfpLbOtbFFae6CwZfAidwsoM74wYu1Kzwb+pgeK9ODZc7SQMXpFWj5Mn7KtQ==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-v4compatibility.woff2`
|
||||
- SHA-256: `4468a4ec439fecc93d86936bc3b5b5db7d0b98ce173faefd18938b2cef79245b`
|
||||
- SRI sha512: `sha512-DzAaC0v4WatRDbN7LVoGXD5pmuOmveGoBimQLfnQFz74+L+hhZVatKhENPHAVkeNtRTBQ63B8w0fOlrQ3bERuw==`
|
||||
- `core/static/vendor/fontawesome/css/../webfonts/fa-v4compatibility.ttf`
|
||||
- SHA-256: `0f40286f817bb931f65fc1a5963f1450af855547fa9d2c02a009ad389fcc7d95`
|
||||
- SRI sha512: `sha512-emfG/sIso1lhi9tNNmqIGP2xNU8SP47qPspS7g8V7ltbotbznl/wy00DxyjrtfxhYw3OfYYlxtyiGyoyRAFXTg==`
|
||||
@@ -8,124 +8,135 @@
|
||||
<head>
|
||||
<script>
|
||||
(function () {
|
||||
var storedTheme = "light";
|
||||
var storedTheme = null;
|
||||
try {
|
||||
storedTheme = localStorage.getItem("theme") || "light";
|
||||
storedTheme = localStorage.getItem("theme");
|
||||
} catch (error) {
|
||||
}
|
||||
var resolvedTheme = storedTheme === "dark" ? "dark" : "light";
|
||||
document.documentElement.dataset.theme = resolvedTheme;
|
||||
if (resolvedTheme === "dark") {
|
||||
document.documentElement.style.backgroundColor = "#090d16";
|
||||
document.documentElement.style.color = "#f8fafc";
|
||||
if (storedTheme === "dark" || storedTheme === "light") {
|
||||
document.documentElement.dataset.theme = storedTheme;
|
||||
} else {
|
||||
document.documentElement.style.backgroundColor = "#f3f4f6";
|
||||
document.documentElement.style.color = "#1b2433";
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
}
|
||||
var faviconHref = resolvedTheme === "dark"
|
||||
? "{% static 'favicon-dark.svg' %}"
|
||||
: "{% static 'favicon-light.svg' %}";
|
||||
document.querySelectorAll("link[data-gia-favicon]").forEach(function (link) {
|
||||
link.setAttribute("href", faviconHref);
|
||||
});
|
||||
document.querySelectorAll(".js-theme-logo").forEach(function (image) {
|
||||
image.setAttribute("src", faviconHref);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
html[data-theme="dark"],
|
||||
html[data-theme="dark"] body {
|
||||
background: #090d16 !important;
|
||||
color: #f8fafc !important;
|
||||
}
|
||||
html[data-theme="light"],
|
||||
html[data-theme="light"] body {
|
||||
background: #f3f4f6 !important;
|
||||
color: #1b2433 !important;
|
||||
}
|
||||
</style>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block browser_title %}{% firstof page_browser_title page_title as explicit_title %}{% if explicit_title %}{{ explicit_title }} · GIA{% else %}{% with route_value=request.resolver_match.url_name|default:request.path_info|humanize_route %}{% if route_value %}{{ route_value }} · GIA{% else %}GIA{% endif %}{% endwith %}{% endif %}{% endblock %}</title>
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'favicon-light.svg' %}" data-gia-favicon>
|
||||
<link rel="shortcut icon" href="{% static 'favicon-light.svg' %}" data-gia-favicon>
|
||||
<link rel="icon" type="image/png" href="{% static 'favicon.png' %}?v=sq3" data-gia-favicon="icon">
|
||||
<link rel="shortcut icon" href="{% static 'favicon.png' %}?v=sq3" data-gia-favicon="shortcut">
|
||||
<link rel="manifest" href="{% static 'manifest.webmanifest' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-tooltip.min.css' %}">
|
||||
<link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-slider.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-calendar.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-tagsinput.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-switch.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/gridstack.min.css' %}">
|
||||
<script src="{% static 'js/bulma-calendar.min.js' %}" integrity="sha384-DThNif0xGXbopX7+PE+UabkuClfI/zELNhaVqoGLutaWB76dyMw0vIQBGmUxSfVQ" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/bulma-slider.min.js' %}" integrity="sha384-wbyps8iLG8QzJE02viYc/27BtT5HSa11+b5V7QPR1/huVuA8f4LRTNGc82qAIeIZ" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/htmx.min.js' %}" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>
|
||||
<script defer src="{% static 'js/remove-me.js' %}" integrity="sha384-6fHcFNoQ8QEI3ZDgw9Z/A6Brk64gF7AnFbLgdrumo8/kBbsKQ/wo7wPegj5WkzuG" crossorigin="anonymous"></script>
|
||||
<script defer src="{% static 'js/hyperscript.min.js' %}" integrity="sha384-6GYN8BDHOJkkru6zcpGOUa//1mn+5iZ/MyT6mq34WFIpuOeLF52kSi721q0SsYF9" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/bulma-tagsinput.min.js' %}"></script>
|
||||
<script src="{% static 'js/jquery.min.js' %}"></script>
|
||||
<script src="{% static 'js/gridstack-all.js' %}"></script>
|
||||
<script defer src="{% static 'js/magnet.min.js' %}"></script>
|
||||
{# Managed by tools/frontend_assets/asset-manifest.json and scripts/vendor_frontend_assets.py. #}
|
||||
<link rel="preload" href="{% static 'vendor/fontawesome/webfonts/fa-solid-900.woff2' %}" as="font" type="font/woff2" integrity="sha512-Ph1xTLhfMycYSW+wUN8oL3Ggl56nGIS95EHiKWggcL/GbMNjPdib1Hreb1D4COlMxdiGCkk43nspQnpDuTjgQg==" crossorigin="anonymous">
|
||||
<link rel="preload" href="{% static 'vendor/fontawesome/webfonts/fa-regular-400.woff2' %}" as="font" type="font/woff2" integrity="sha512-qioT43fXB5q4Bbpn8sPQE9OIZLjKD0c0lVmpm6KmT8k34LM6gkRcOOMi1BOl2lohFG/7p9tzKfTP5G563BQq1g==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma.min.css' %}" integrity="sha512-yh2RE0wZCVZeysGiqTwDTO/dKelCbS9bP2L94UvOFtl/FKXcNAje3Y2oBg/ZMZ3LS1sicYk4dYVGtDex75fvvA==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-tooltip.min.css' %}" integrity="sha512-SNDNIUvSYhnqDV9FFXaH/e0xZ6NzkG4Qm5dafLLf0PCMkzICKaOmMTgI3y2t2jZK+hAtP6A7UBcFqjWMhsujIg==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'vendor/fontawesome/css/all.css' %}" integrity="sha512-UKBBxJ5N3/MYiSsYTlEsARsp4vELKVRIklED4Mb6wpuVFOgy5Blt+sXUdz1TDReqWsm64xxBA2QoBJRCxI0x5Q==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-slider.min.css' %}" integrity="sha512-9o5SkCRCA9thttRH3Gb5QXLxKdRiuRLdO6ToEPwRHGLXjrhTZwFj0rEHjrCcJvDN9/aNaWMpGOIEA2vZsHmEqw==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-calendar.min.css' %}" integrity="sha512-IOnJQkgQpezPDPTJcRiWD7YVI3sF2RYzYDl4isbDT2geSaEHRQ615UN/8GhJbSkvqkKRZu8SBCQ7XwKMqsqLFQ==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-tagsinput.min.css' %}" integrity="sha512-NWTkcDRubZ3pyXbZZLQBILuVsRFs8c6QGgnfe4dm5/d6yp50U+xdoCDLIcSo51fFy/GXH0O2Oed1Z1sF1faxDA==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/bulma-switch.min.css' %}" integrity="sha512-zjrHYubQoNgDVqVKTyGjKcvIeQlduZTvXCvcBwQ0iqJYKLKiz9cuFAN7e98zfKqCTpI/EgFRBRcTwJw20yAFuw==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/gridstack.min.css' %}" integrity="sha512-ttQfsDTO64bamkJHeLDf0kzMP1NKfkootudPWS2V8Pwy+9z1wexSYjIT6/HXGg/bmtD+DRwsUnQoYEB0yePjbw==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static 'css/gia-theme.css' %}" integrity="sha512-J/sff1E15uvn7df8Yv/C3Y+CE75bnxZF4vj4wEtfuIaXhECzC0cJTpocvTt7jdB5iMRry8MQ3ZH6Pg/ckh4QNA==" crossorigin="anonymous">
|
||||
<script src="{% static 'js/bulma-calendar.min.js' %}" integrity="sha512-kkEtEtypXzruevjkoxhyEkqkZBtlhK7s8zt7IV2yPabgBwy5xbKL9uWeCS37ldS9AaNTSnveWTu4ivUvGMJUWA==" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/bulma-slider.min.js' %}" integrity="sha512-WLKXHCsMXTSIPsmQShJRE6K4IzwvNkhwxr/Oo8N3z+kzjhGleHibspmWLTawNMdl2z9E23XK20+yvUTDZ+zeNQ==" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/htmx.min.js' %}" integrity="sha512-CGXFnDNv5q48ciFeIyWFcfZhqYW0sSBiPO+HZDO3XLM+p8xjhezz5CCxtkXVDKfCbvF+iUhel7xoeSp19o7x7g==" crossorigin="anonymous"></script>
|
||||
<script defer src="{% static 'js/remove-me.js' %}" integrity="sha512-uhE4kDw2+tXdJPDKSttOEYhVnwYq310+d5DMQnTjafJ58QLlYPyx0RTCNbjcrTiGfCjAhaQob4AumEUa2m3TaQ==" crossorigin="anonymous"></script>
|
||||
<script defer src="{% static 'js/hyperscript.min.js' %}" integrity="sha512-l43sZzpnAddmYhJyfPrgv46XhJvA95gsA28/+eW4XZLSekQ8wlP68i9f22KGkRjY0HNiZrLc5MXGo4z/tM2QNA==" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/bulma-tagsinput.min.js' %}" integrity="sha512-Je6J++MjmmpxF30JCmRwM2KiK3uWQBQtqiNCjwzEMJKExLaa0BqerlYNa/fJAl5Rra4hMgRZF2fzg+V2vjE4Kw==" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/jquery.min.js' %}" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous"></script>
|
||||
<script src="{% static 'js/gridstack-all.js' %}" integrity="sha512-djBPxwvBhDep1SvOhliatweHMORhVO3HabrfBjaW6nYsa7UcJYHty31x42m4HBSJXcJSQdoEgRPLVYGGIuIaDQ==" crossorigin="anonymous"></script>
|
||||
<script defer src="{% static 'js/magnet.min.js' %}" integrity="sha512-aoQ3V4iCM8zTcdMDSUTRG1K9wqZzmDSisuaCLQexk9DdFy92oWvTUoAfCVLnGzzJClst8PmtasZg219REwyNkw==" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
(function () {
|
||||
function applyFavicon(theme) {
|
||||
var href = theme === "dark"
|
||||
? "{% static 'favicon-dark.svg' %}"
|
||||
: "{% static 'favicon-light.svg' %}";
|
||||
document.querySelectorAll("link[data-gia-favicon]").forEach(function (link) {
|
||||
link.setAttribute("href", href);
|
||||
});
|
||||
document.querySelectorAll(".js-theme-logo").forEach(function (image) {
|
||||
image.setAttribute("src", href);
|
||||
var FAVICON_VERSION = "sq3";
|
||||
var STORAGE_KEY = "theme";
|
||||
var THEME_DARK = "dark";
|
||||
var THEME_LIGHT = "light";
|
||||
var root = document.documentElement;
|
||||
var darkMedia = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
function getStoredTheme() {
|
||||
try {
|
||||
var raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (raw === THEME_DARK || raw === THEME_LIGHT) {
|
||||
return raw;
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getResolvedTheme() {
|
||||
var stored = getStoredTheme();
|
||||
if (stored === THEME_DARK || stored === THEME_LIGHT) {
|
||||
return stored;
|
||||
}
|
||||
return darkMedia.matches ? THEME_DARK : THEME_LIGHT;
|
||||
}
|
||||
|
||||
function applyFavicon() {
|
||||
var href = "{% static 'favicon.png' %}?v=" + FAVICON_VERSION;
|
||||
var iconLink = document.querySelector("link[data-gia-favicon='icon']");
|
||||
if (iconLink) {
|
||||
iconLink.setAttribute("href", href);
|
||||
}
|
||||
var shortcutLink = document.querySelector("link[data-gia-favicon='shortcut']");
|
||||
if (shortcutLink) {
|
||||
shortcutLink.setAttribute("href", href);
|
||||
}
|
||||
}
|
||||
|
||||
function persistTheme(mode) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, mode);
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateToggleUI(mode) {
|
||||
document.querySelectorAll(".js-theme-toggle").forEach(function (button) {
|
||||
var nextMode = mode === THEME_DARK ? THEME_LIGHT : THEME_DARK;
|
||||
button.setAttribute("data-theme-mode", mode);
|
||||
button.setAttribute("aria-label", "Theme: " + mode + ". Click to switch to " + nextMode + ".");
|
||||
button.setAttribute("title", "Theme: " + mode);
|
||||
var label = button.querySelector("[data-theme-label]");
|
||||
if (label) {
|
||||
label.textContent = mode === THEME_DARK ? "Dark" : "Light";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applyTheme(mode) {
|
||||
var validMode = mode === "dark" ? "dark" : "light";
|
||||
document.documentElement.dataset.theme = validMode;
|
||||
applyFavicon(validMode);
|
||||
try {
|
||||
localStorage.setItem("theme", validMode);
|
||||
} catch (error) {
|
||||
function applyTheme(mode, shouldPersist) {
|
||||
var validMode = mode === THEME_DARK ? THEME_DARK : THEME_LIGHT;
|
||||
root.dataset.theme = validMode;
|
||||
applyFavicon();
|
||||
updateToggleUI(validMode);
|
||||
if (shouldPersist !== false) {
|
||||
persistTheme(validMode);
|
||||
}
|
||||
document.querySelectorAll(".js-theme-toggle").forEach(function (button) {
|
||||
var nextMode = validMode === "dark" ? "light" : "dark";
|
||||
button.setAttribute("data-theme-mode", validMode);
|
||||
button.setAttribute("aria-label", "Theme: " + validMode + ". Click to switch to " + nextMode + ".");
|
||||
button.setAttribute("title", "Theme: " + validMode);
|
||||
var label = button.querySelector("[data-theme-label]");
|
||||
if (label) {
|
||||
label.textContent = validMode === "dark" ? "Dark" : "Light";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cycleTheme() {
|
||||
var currentTheme = "light";
|
||||
try {
|
||||
currentTheme = localStorage.getItem("theme") || "light";
|
||||
} catch (error) {
|
||||
}
|
||||
if (currentTheme === "dark") {
|
||||
applyTheme("light");
|
||||
return;
|
||||
}
|
||||
applyTheme("dark");
|
||||
var currentTheme = root.dataset.theme === THEME_DARK ? THEME_DARK : THEME_LIGHT;
|
||||
applyTheme(currentTheme === THEME_DARK ? THEME_LIGHT : THEME_DARK, true);
|
||||
}
|
||||
|
||||
try {
|
||||
applyTheme(localStorage.getItem("theme") || "light");
|
||||
} catch (error) {
|
||||
applyTheme("light");
|
||||
applyTheme(getResolvedTheme(), false);
|
||||
|
||||
if (darkMedia && darkMedia.addEventListener) {
|
||||
darkMedia.addEventListener("change", function () {
|
||||
if (!getStoredTheme()) {
|
||||
applyTheme(getResolvedTheme(), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
document.querySelectorAll(".js-theme-toggle").forEach(function (button) {
|
||||
button.addEventListener("click", cycleTheme);
|
||||
});
|
||||
applyTheme(document.documentElement.dataset.theme || "light");
|
||||
applyTheme(getResolvedTheme(), false);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -188,325 +199,6 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.icon { border-bottom: 0px !important;}
|
||||
.wrap {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.nowrap-parent {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nowrap-child {
|
||||
display: inline-block;
|
||||
}
|
||||
.htmx-indicator{
|
||||
opacity:0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.htmx-request .htmx-indicator,
|
||||
.htmx-request.htmx-indicator{
|
||||
opacity:1
|
||||
}
|
||||
|
||||
.tooltiptext {
|
||||
visibility: hidden;
|
||||
background-color: black;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 5px 0;
|
||||
border-radius: 6px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rounded-tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.table {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
tr {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
a.panel-block {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
tr:hover,
|
||||
a.panel-block:hover {
|
||||
cursor:pointer;
|
||||
background-color:rgba(221, 224, 255, 0.3) !important;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background-color: rgba(84, 84, 84, 0.9) !important;
|
||||
--modal-color: rgba(81, 81, 81, 0.9) !important;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--background-color-light: rgba(210, 210, 210, 0.9) !important;
|
||||
--background-color-dark: rgba(84, 84, 84, 0.9) !important;
|
||||
--background-color-modal-light: rgba(250, 250, 250, 0.5) !important;
|
||||
--background-color-modal-dark: rgba(210, 210, 210, 0.9) !important;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
--background-color: var(--background-color-light);
|
||||
--modal-color: var(--background-color-modal-light);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--background-color: var(--background-color-dark);
|
||||
--modal-color: var(--background-color-modal-dark);
|
||||
}
|
||||
|
||||
.panel, .box, .modal {
|
||||
background-color: var(--modal-color) !important;
|
||||
}
|
||||
.box {
|
||||
border: 1px solid rgba(25, 33, 52, 0.08);
|
||||
box-shadow: 0 18px 48px rgba(20, 28, 45, 0.08);
|
||||
}
|
||||
.modal, .modal.box{
|
||||
background-color: var(--background-color) !important;
|
||||
}
|
||||
.modal-background{
|
||||
background-color:rgba(255, 255, 255, 0.3) !important;
|
||||
}
|
||||
#modals-here .modal-background {
|
||||
background-color: rgba(0, 0, 0, 0.34) !important;
|
||||
}
|
||||
#modals-here .modal-content > .box {
|
||||
background-color: rgba(255, 255, 255, 0.97) !important;
|
||||
color: inherit;
|
||||
}
|
||||
#modals-here .modal-content .input,
|
||||
#modals-here .modal-content .textarea,
|
||||
#modals-here .modal-content .select select {
|
||||
background-color: rgba(255, 255, 255, 0.98) !important;
|
||||
}
|
||||
[data-theme="dark"] #modals-here .modal-content > .box {
|
||||
background-color: rgba(45, 45, 45, 0.97) !important;
|
||||
}
|
||||
[data-theme="dark"] #modals-here .modal-content .input,
|
||||
[data-theme="dark"] #modals-here .modal-content .textarea,
|
||||
[data-theme="dark"] #modals-here .modal-content .select select {
|
||||
background-color: rgba(33, 33, 33, 0.98) !important;
|
||||
}
|
||||
|
||||
.has-background-grey-lighter{
|
||||
background-color:rgba(219, 219, 219, 0.5) !important;
|
||||
}
|
||||
.navbar {
|
||||
background-color:rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
.gia-brand-shell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
.gia-brand-logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.45rem 0.75rem;
|
||||
border-radius: 16px;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
border: 1px solid rgba(21, 28, 39, 0.08);
|
||||
box-shadow: 0 10px 24px rgba(21, 28, 39, 0.08);
|
||||
}
|
||||
.gia-brand-logo img {
|
||||
display: block;
|
||||
}
|
||||
[data-theme="dark"] .gia-brand-logo {
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-color: rgba(255, 255, 255, 0.82);
|
||||
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.34);
|
||||
}
|
||||
.section > .container.gia-page-shell,
|
||||
.section > .container {
|
||||
max-width: 1340px;
|
||||
}
|
||||
.gia-page-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.gia-page-header .title,
|
||||
.gia-page-header .subtitle {
|
||||
max-width: 72ch;
|
||||
}
|
||||
.gia-page-header .subtitle {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.table thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: rgba(248, 250, 252, 0.96) !important;
|
||||
color: #1b1f2a !important;
|
||||
backdrop-filter: blur(6px);
|
||||
z-index: 1;
|
||||
}
|
||||
[data-theme="dark"] .table thead th {
|
||||
background: rgba(44, 44, 44, 0.96) !important;
|
||||
color: #f3f5f8 !important;
|
||||
}
|
||||
.table td,
|
||||
.table th {
|
||||
vertical-align: top;
|
||||
}
|
||||
.help {
|
||||
max-width: 78ch;
|
||||
}
|
||||
.button.is-light {
|
||||
border-color: rgba(27, 38, 59, 0.12);
|
||||
}
|
||||
.input,
|
||||
.textarea,
|
||||
.select select {
|
||||
border-color: rgba(27, 38, 59, 0.18);
|
||||
box-shadow: none;
|
||||
}
|
||||
.input:focus,
|
||||
.textarea:focus,
|
||||
.select select:focus {
|
||||
border-color: rgba(27, 99, 214, 0.8);
|
||||
box-shadow: 0 0 0 0.125em rgba(27, 99, 214, 0.14);
|
||||
}
|
||||
|
||||
.grid-stack-item-content,
|
||||
.floating-window {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
|
||||
.panel {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel-block {
|
||||
overflow-y:auto;
|
||||
overflow-x:auto;
|
||||
min-height: 90%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.floating-window {
|
||||
max-height: 300px;
|
||||
z-index: 9000;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
.floating-window .panel {
|
||||
background-color:rgba(250, 250, 250, 0.8) !important;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.grid-stack-item:hover .ui-resizable-handle {
|
||||
display: block !important;
|
||||
}
|
||||
.ui-resizable-handle {
|
||||
z-index: 39 !important;
|
||||
}
|
||||
|
||||
.osint-table-shell {
|
||||
border: 1px solid rgba(127, 127, 127, 0.2);
|
||||
border-radius: 14px;
|
||||
padding: 0.9rem;
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
.osint-table-toolbar {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.osint-results-table-wrap {
|
||||
border-radius: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.task-ui-badge {
|
||||
background: #f5f5f5 !important;
|
||||
border: 1px solid #dbdbdb !important;
|
||||
color: #1f1f1f !important;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5;
|
||||
padding: 0.25em 0.75em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.osint-results-table th {
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.osint-sort-link {
|
||||
color: inherit;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.osint-sort-link:hover {
|
||||
color: #3273dc;
|
||||
}
|
||||
|
||||
.osint-search-form .button.is-fullwidth {
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-dropdown .navbar-item.is-current-route {
|
||||
background-color: rgba(50, 115, 220, 0.14) !important;
|
||||
color: #1f4f99 !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
.theme-toggle-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.brand-theme-toggle {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
border: 0 !important;
|
||||
background: transparent !important;
|
||||
box-shadow: none !important;
|
||||
line-height: 1;
|
||||
width: 3.15rem;
|
||||
height: 3.15rem;
|
||||
}
|
||||
.brand-theme-logo {
|
||||
display: block;
|
||||
width: 3.15rem;
|
||||
height: 3.15rem;
|
||||
}
|
||||
.security-page-tabs a {
|
||||
transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
|
||||
}
|
||||
.reduced-motion,
|
||||
.reduced-motion * {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
{% get_accessibility_settings request.user as a11y_settings %}
|
||||
<body{% if a11y_settings and a11y_settings.disable_animations %} class="reduced-motion"{% endif %}>
|
||||
@@ -517,12 +209,28 @@
|
||||
<span class="gia-brand-shell">
|
||||
{% if user.is_authenticated %}
|
||||
<button class="button is-light theme-toggle-button gia-brand-logo brand-theme-toggle js-theme-toggle" type="button" data-theme-mode="light" aria-label="Theme toggle">
|
||||
<img class="brand-theme-logo js-theme-logo" src="{% static 'favicon-light.svg' %}" alt="" aria-hidden="true">
|
||||
<svg class="brand-theme-logo" viewBox="0 0 213.35 150.85" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(38.831 -7.4316)">
|
||||
<g transform="matrix(.99287 0 0 .99911 1.2367 -30.308)">
|
||||
<path class="brand-theme-stroke" d="m-32.645 113.03a115.16 122.5 0 0 1 99.73-61.25 115.16 122.5 0 0 1 99.73 61.25" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="15.42"/>
|
||||
<path class="brand-theme-stroke" d="m67.006 89.591a42.374 42.374 0 0 1 39.148 26.158 42.374 42.374 0 0 1-9.1855 46.179 42.374 42.374 0 0 1-46.179 9.1855 42.374 42.374 0 0 1-26.158-39.148" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16.251"/>
|
||||
<circle cx="67.003" cy="131.96" r="13.151" fill="#740101"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<span class="is-sr-only" data-theme-label>Auto</span>
|
||||
</button>
|
||||
{% else %}
|
||||
<a href="{% url 'home' %}" class="gia-brand-logo" aria-label="GIA home">
|
||||
<img class="brand-theme-logo" src="{% static 'favicon-light.svg' %}" alt="logo">
|
||||
<svg class="brand-theme-logo" viewBox="0 0 213.35 150.85" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(38.831 -7.4316)">
|
||||
<g transform="matrix(.99287 0 0 .99911 1.2367 -30.308)">
|
||||
<path class="brand-theme-stroke" d="m-32.645 113.03a115.16 122.5 0 0 1 99.73-61.25 115.16 122.5 0 0 1 99.73 61.25" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="15.42"/>
|
||||
<path class="brand-theme-stroke" d="m67.006 89.591a42.374 42.374 0 0 1 39.148 26.158 42.374 42.374 0 0 1-9.1855 46.179 42.374 42.374 0 0 1-46.179 9.1855 42.374 42.374 0 0 1-26.158-39.148" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16.251"/>
|
||||
<circle cx="67.003" cy="131.96" r="13.151" fill="#740101"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
@@ -6,7 +6,11 @@ upstream django {
|
||||
server {
|
||||
listen 9999;
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /favicon.ico {
|
||||
alias /conf/static/favicon.ico;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
root /conf;
|
||||
|
||||
@@ -6,7 +6,11 @@ upstream django {
|
||||
server {
|
||||
listen 9999;
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /favicon.ico {
|
||||
alias /conf/static/favicon.ico;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
root /conf;
|
||||
|
||||
267
scripts/vendor_frontend_assets.py
Normal file
267
scripts/vendor_frontend_assets.py
Normal file
@@ -0,0 +1,267 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Any
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
|
||||
URL_PATTERN = re.compile(r"url\(([^)]+)\)")
|
||||
|
||||
|
||||
def load_json(path: Path) -> dict[str, Any]:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def ensure_parent(path: Path) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def sri(path: Path, algorithm: str) -> str:
|
||||
digest = hashlib.new(algorithm, path.read_bytes()).digest()
|
||||
return f"{algorithm}-" + base64.b64encode(digest).decode("ascii")
|
||||
|
||||
|
||||
def sha256_hex(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def read_package_lock(path: Path) -> dict[str, Any]:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(
|
||||
f"Missing {path}. Run `npm install --ignore-scripts` in {path.parent} first."
|
||||
)
|
||||
return load_json(path)
|
||||
|
||||
|
||||
def lock_entry(lock_data: dict[str, Any], package_name: str) -> dict[str, Any]:
|
||||
packages = lock_data.get("packages", {})
|
||||
key = "node_modules/" + package_name
|
||||
entry = packages.get(key)
|
||||
if not entry:
|
||||
raise KeyError(f"Package {package_name!r} not found in package-lock.json")
|
||||
return entry
|
||||
|
||||
|
||||
def read_package_metadata(package_root: Path) -> dict[str, Any]:
|
||||
package_json = package_root / "package.json"
|
||||
if not package_json.exists():
|
||||
raise FileNotFoundError(f"Missing package metadata: {package_json}")
|
||||
return load_json(package_json)
|
||||
|
||||
|
||||
def package_root(npm_root: Path, package_name: str) -> Path:
|
||||
return npm_root / "node_modules" / Path(*package_name.split("/"))
|
||||
|
||||
|
||||
def normalize_manifest_path(path: str) -> str:
|
||||
pure = PurePosixPath(path)
|
||||
normalized = pure.as_posix()
|
||||
if normalized.startswith("../") or normalized == "..":
|
||||
raise ValueError(f"Refusing to write outside target root: {path}")
|
||||
return normalized
|
||||
|
||||
|
||||
def copy_file(source: Path, targets: list[Path]) -> None:
|
||||
if not source.exists():
|
||||
raise FileNotFoundError(f"Missing vendored source file: {source}")
|
||||
for target in targets:
|
||||
ensure_parent(target)
|
||||
shutil.copy2(source, target)
|
||||
|
||||
|
||||
def fetch_bytes(url: str) -> bytes:
|
||||
request = Request(url, headers={"User-Agent": "GIA frontend asset vendoring"})
|
||||
with urlopen(request) as response:
|
||||
return response.read()
|
||||
|
||||
|
||||
def download_url_bundle(
|
||||
asset: dict[str, Any],
|
||||
repo_root: Path,
|
||||
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
||||
target_roots = [repo_root / entry for entry in asset["target_roots"]]
|
||||
entry_target = normalize_manifest_path(asset["entry_target"])
|
||||
entry_url = asset["entry_url"]
|
||||
css_bytes = fetch_bytes(entry_url)
|
||||
text = css_bytes.decode("utf-8")
|
||||
|
||||
downloaded: dict[str, bytes] = {entry_target: css_bytes}
|
||||
for match in URL_PATTERN.finditer(text):
|
||||
raw_ref = match.group(1).strip().strip("'\"")
|
||||
if not raw_ref or raw_ref.startswith("data:"):
|
||||
continue
|
||||
resolved_url = urljoin(entry_url, raw_ref)
|
||||
target_rel = normalize_manifest_path(
|
||||
PurePosixPath(entry_target).parent.joinpath(raw_ref).as_posix()
|
||||
)
|
||||
downloaded[target_rel] = fetch_bytes(resolved_url)
|
||||
|
||||
report_files: list[dict[str, Any]] = []
|
||||
copied_targets: list[dict[str, Any]] = []
|
||||
for relative_path, content in downloaded.items():
|
||||
for target_root in target_roots:
|
||||
target = target_root / relative_path
|
||||
ensure_parent(target)
|
||||
target.write_bytes(content)
|
||||
copied_targets.append(
|
||||
{
|
||||
"path": str(target.relative_to(repo_root)),
|
||||
"sha256": sha256_hex(target),
|
||||
"sri_sha512": sri(target, "sha512"),
|
||||
}
|
||||
)
|
||||
report_files.append(
|
||||
{
|
||||
"relative_path": relative_path,
|
||||
"download_url": urljoin(entry_url, relative_path)
|
||||
if relative_path != entry_target
|
||||
else entry_url,
|
||||
}
|
||||
)
|
||||
return report_files, copied_targets
|
||||
|
||||
|
||||
def vendor_npm_file(
|
||||
asset: dict[str, Any],
|
||||
repo_root: Path,
|
||||
npm_root: Path,
|
||||
lock_data: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
pkg_name = asset["package"]
|
||||
pkg_root = package_root(npm_root, pkg_name)
|
||||
metadata = read_package_metadata(pkg_root)
|
||||
source = pkg_root / asset["source_path"]
|
||||
targets = [repo_root / target for target in asset["targets"]]
|
||||
copy_file(source, targets)
|
||||
|
||||
copied_targets = [
|
||||
{
|
||||
"path": str(target.relative_to(repo_root)),
|
||||
"sha256": sha256_hex(target),
|
||||
"sri_sha512": sri(target, "sha512"),
|
||||
}
|
||||
for target in targets
|
||||
]
|
||||
lock = lock_entry(lock_data, pkg_name)
|
||||
return {
|
||||
"id": asset["id"],
|
||||
"kind": asset["kind"],
|
||||
"package": pkg_name,
|
||||
"version": metadata["version"],
|
||||
"license": metadata.get("license", ""),
|
||||
"homepage": metadata.get("homepage", asset.get("official_url", "")),
|
||||
"official_url": asset.get("official_url", ""),
|
||||
"purpose": asset.get("purpose", ""),
|
||||
"notes": asset.get("notes", ""),
|
||||
"resolved": lock.get("resolved", ""),
|
||||
"dist_integrity": lock.get("integrity", ""),
|
||||
"source_path": asset["source_path"],
|
||||
"targets": copied_targets,
|
||||
}
|
||||
|
||||
|
||||
def vendor_url_bundle(asset: dict[str, Any], repo_root: Path) -> dict[str, Any]:
|
||||
downloaded_files, copied_targets = download_url_bundle(asset, repo_root)
|
||||
return {
|
||||
"id": asset["id"],
|
||||
"kind": asset["kind"],
|
||||
"version": asset["version"],
|
||||
"license": asset.get("license", ""),
|
||||
"homepage": asset.get("official_url", ""),
|
||||
"official_url": asset.get("official_url", ""),
|
||||
"purpose": asset.get("purpose", ""),
|
||||
"notes": asset.get("notes", ""),
|
||||
"entry_url": asset["entry_url"],
|
||||
"downloaded_files": downloaded_files,
|
||||
"targets": copied_targets,
|
||||
}
|
||||
|
||||
|
||||
def markdown_report(entries: list[dict[str, Any]]) -> str:
|
||||
lines = [
|
||||
"# Frontend Library Inventory",
|
||||
"",
|
||||
"This report is generated by `scripts/vendor_frontend_assets.py` from `tools/frontend_assets/asset-manifest.json`.",
|
||||
"",
|
||||
]
|
||||
for entry in entries:
|
||||
title = entry["id"]
|
||||
package_or_url = entry.get("package") or entry.get("entry_url", "")
|
||||
lines.extend(
|
||||
[
|
||||
f"## {title}",
|
||||
"",
|
||||
f"- Source: `{package_or_url}`",
|
||||
f"- Version: `{entry.get('version', 'n/a')}`",
|
||||
f"- Official URL: {entry.get('official_url') or entry.get('homepage') or 'n/a'}",
|
||||
f"- Homepage: {entry.get('homepage') or 'n/a'}",
|
||||
f"- License: `{entry.get('license') or 'n/a'}`",
|
||||
f"- Purpose: {entry.get('purpose') or 'n/a'}",
|
||||
]
|
||||
)
|
||||
if entry.get("resolved"):
|
||||
lines.append(f"- Resolved tarball: `{entry['resolved']}`")
|
||||
if entry.get("dist_integrity"):
|
||||
lines.append(f"- Upstream package integrity: `{entry['dist_integrity']}`")
|
||||
if entry.get("notes"):
|
||||
lines.append(f"- Notes: {entry['notes']}")
|
||||
if entry.get("downloaded_files"):
|
||||
lines.append("- Downloaded bundle files:")
|
||||
for file_entry in entry["downloaded_files"]:
|
||||
lines.append(
|
||||
f" - `{file_entry['relative_path']}` from `{file_entry['download_url']}`"
|
||||
)
|
||||
lines.append("- Local targets:")
|
||||
for target in entry["targets"]:
|
||||
lines.append(f" - `{target['path']}`")
|
||||
lines.append(f" - SHA-256: `{target['sha256']}`")
|
||||
lines.append(f" - SRI sha512: `{target['sri_sha512']}`")
|
||||
lines.extend(["", ""])
|
||||
return "\n".join(lines).rstrip() + "\n"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Vendor pinned frontend assets into Django static files.")
|
||||
parser.add_argument(
|
||||
"--manifest",
|
||||
default="tools/frontend_assets/asset-manifest.json",
|
||||
help="Path to the asset manifest, relative to the repo root.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
repo_root = Path(__file__).resolve().parent.parent
|
||||
manifest_path = repo_root / args.manifest
|
||||
manifest = load_json(manifest_path)
|
||||
|
||||
npm_root = repo_root / manifest["npm_root"]
|
||||
lock_data = read_package_lock(npm_root / "package-lock.json")
|
||||
|
||||
entries: list[dict[str, Any]] = []
|
||||
for asset in manifest["assets"]:
|
||||
if asset["kind"] == "npm_file":
|
||||
entries.append(vendor_npm_file(asset, repo_root, npm_root, lock_data))
|
||||
elif asset["kind"] == "url_bundle":
|
||||
entries.append(vendor_url_bundle(asset, repo_root))
|
||||
else:
|
||||
raise ValueError(f"Unsupported asset kind: {asset['kind']}")
|
||||
|
||||
report_json_path = repo_root / manifest["report_json"]
|
||||
report_markdown_path = repo_root / manifest["report_markdown"]
|
||||
ensure_parent(report_json_path)
|
||||
ensure_parent(report_markdown_path)
|
||||
report_json_path.write_text(json.dumps({"entries": entries}, indent=2) + "\n", encoding="utf-8")
|
||||
report_markdown_path.write_text(markdown_report(entries), encoding="utf-8")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
187
tools/frontend_assets/asset-manifest.json
Normal file
187
tools/frontend_assets/asset-manifest.json
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"npm_root": "tools/frontend_assets",
|
||||
"report_markdown": "artifacts/frontend_libraries.md",
|
||||
"report_json": "artifacts/frontend_libraries.json",
|
||||
"assets": [
|
||||
{
|
||||
"id": "bulma_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma",
|
||||
"source_path": "css/bulma.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma.min.css"
|
||||
],
|
||||
"purpose": "Bulma core stylesheet",
|
||||
"official_url": "https://bulma.io"
|
||||
},
|
||||
{
|
||||
"id": "bulma_tooltip_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tooltip",
|
||||
"source_path": "dist/css/bulma-tooltip.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma-tooltip.min.css"
|
||||
],
|
||||
"purpose": "Official Bulma tooltip extension from Bulma's extensions page",
|
||||
"official_url": "https://wikiki.github.io/elements/tooltip"
|
||||
},
|
||||
{
|
||||
"id": "bulma_slider_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-slider",
|
||||
"source_path": "dist/css/bulma-slider.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma-slider.min.css"
|
||||
],
|
||||
"purpose": "Official Bulma slider extension from Bulma's extensions page",
|
||||
"official_url": "https://wikiki.github.io/form/slider"
|
||||
},
|
||||
{
|
||||
"id": "bulma_slider_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-slider",
|
||||
"source_path": "dist/js/bulma-slider.min.js",
|
||||
"targets": [
|
||||
"core/static/js/bulma-slider.min.js"
|
||||
],
|
||||
"purpose": "Official Bulma slider extension runtime",
|
||||
"official_url": "https://wikiki.github.io/form/slider"
|
||||
},
|
||||
{
|
||||
"id": "bulma_calendar_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-calendar",
|
||||
"source_path": "src/demo/assets/css/bulma-calendar.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma-calendar.min.css"
|
||||
],
|
||||
"purpose": "Official Bulma calendar extension from Bulma's extensions page",
|
||||
"official_url": "https://wikiki.github.io/components/calendar"
|
||||
},
|
||||
{
|
||||
"id": "bulma_calendar_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-calendar",
|
||||
"source_path": "src/demo/assets/js/bulma-calendar.min.js",
|
||||
"targets": [
|
||||
"core/static/js/bulma-calendar.min.js"
|
||||
],
|
||||
"purpose": "Official Bulma calendar extension runtime",
|
||||
"official_url": "https://wikiki.github.io/components/calendar"
|
||||
},
|
||||
{
|
||||
"id": "bulma_tagsinput_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tagsinput",
|
||||
"source_path": "dist/css/bulma-tagsinput.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma-tagsinput.min.css"
|
||||
],
|
||||
"purpose": "Official Bulma tagsinput extension from Bulma's extensions page",
|
||||
"official_url": "https://wikiki.github.io/form/tagsinput"
|
||||
},
|
||||
{
|
||||
"id": "bulma_tagsinput_js",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-tagsinput",
|
||||
"source_path": "dist/js/bulma-tagsinput.min.js",
|
||||
"targets": [
|
||||
"core/static/js/bulma-tagsinput.min.js"
|
||||
],
|
||||
"purpose": "Official Bulma tagsinput extension runtime",
|
||||
"official_url": "https://wikiki.github.io/form/tagsinput"
|
||||
},
|
||||
{
|
||||
"id": "bulma_switch_css",
|
||||
"kind": "npm_file",
|
||||
"package": "bulma-switch",
|
||||
"source_path": "dist/css/bulma-switch.min.css",
|
||||
"targets": [
|
||||
"core/static/css/bulma-switch.min.css"
|
||||
],
|
||||
"purpose": "Official Bulma switch extension from Bulma's extensions page",
|
||||
"official_url": "https://wikiki.github.io/form/switch"
|
||||
},
|
||||
{
|
||||
"id": "gridstack_css",
|
||||
"kind": "npm_file",
|
||||
"package": "gridstack",
|
||||
"source_path": "dist/gridstack.min.css",
|
||||
"targets": [
|
||||
"core/static/css/gridstack.min.css"
|
||||
],
|
||||
"purpose": "GridStack stylesheet",
|
||||
"official_url": "https://gridstackjs.com/"
|
||||
},
|
||||
{
|
||||
"id": "gridstack_js",
|
||||
"kind": "npm_file",
|
||||
"package": "gridstack",
|
||||
"source_path": "dist/gridstack-all.js",
|
||||
"targets": [
|
||||
"core/static/js/gridstack-all.js"
|
||||
],
|
||||
"purpose": "GridStack bundle used by the dashboard",
|
||||
"official_url": "https://gridstackjs.com/"
|
||||
},
|
||||
{
|
||||
"id": "jquery_js",
|
||||
"kind": "npm_file",
|
||||
"package": "jquery",
|
||||
"source_path": "dist/jquery.min.js",
|
||||
"targets": [
|
||||
"core/static/js/jquery.min.js"
|
||||
],
|
||||
"purpose": "Latest jQuery 3.x release for compatibility with legacy plugins",
|
||||
"official_url": "https://jquery.com",
|
||||
"notes": "The latest npm release is jQuery 4.x, but this project still vendors 3.7.1 to avoid breaking older plugins."
|
||||
},
|
||||
{
|
||||
"id": "htmx_js",
|
||||
"kind": "npm_file",
|
||||
"package": "htmx.org",
|
||||
"source_path": "dist/htmx.min.js",
|
||||
"targets": [
|
||||
"core/static/js/htmx.min.js"
|
||||
],
|
||||
"purpose": "htmx runtime",
|
||||
"official_url": "https://htmx.org/"
|
||||
},
|
||||
{
|
||||
"id": "hyperscript_js",
|
||||
"kind": "npm_file",
|
||||
"package": "hyperscript.org",
|
||||
"source_path": "dist/_hyperscript.min.js",
|
||||
"targets": [
|
||||
"core/static/js/hyperscript.min.js"
|
||||
],
|
||||
"purpose": "_hyperscript runtime",
|
||||
"official_url": "https://hyperscript.org/"
|
||||
},
|
||||
{
|
||||
"id": "magnet_js",
|
||||
"kind": "npm_file",
|
||||
"package": "@lf2com/magnet.js",
|
||||
"source_path": "dist/magnet.min.js",
|
||||
"targets": [
|
||||
"core/static/js/magnet.min.js"
|
||||
],
|
||||
"purpose": "Magnet.js drag attraction component",
|
||||
"official_url": "https://github.com/lf2com/magnet.js"
|
||||
},
|
||||
{
|
||||
"id": "fontawesome_bundle",
|
||||
"kind": "url_bundle",
|
||||
"version": "6.1.1",
|
||||
"entry_url": "https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css",
|
||||
"entry_target": "css/all.css",
|
||||
"target_roots": [
|
||||
"core/static/vendor/fontawesome"
|
||||
],
|
||||
"official_url": "https://fontawesome.com",
|
||||
"license": "Font Awesome Pro commercial terms via site-assets.fontawesome.com",
|
||||
"purpose": "Existing Font Awesome asset family, self-hosted locally to preserve the currently used icon set"
|
||||
}
|
||||
]
|
||||
}
|
||||
2160
tools/frontend_assets/package-lock.json
generated
Normal file
2160
tools/frontend_assets/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
tools/frontend_assets/package.json
Normal file
23
tools/frontend_assets/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "gia-frontend-assets",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "Pinned frontend asset sources for vendoring into Django static files.",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"vendor": "../../genv/bin/python ../../scripts/vendor_frontend_assets.py"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lf2com/magnet.js": "2.0.1",
|
||||
"bulma": "1.0.4",
|
||||
"bulma-calendar": "7.1.1",
|
||||
"bulma-slider": "2.0.5",
|
||||
"bulma-switch": "2.0.4",
|
||||
"bulma-tagsinput": "2.0.0",
|
||||
"bulma-tooltip": "3.0.2",
|
||||
"gridstack": "12.4.2",
|
||||
"htmx.org": "2.0.8",
|
||||
"hyperscript.org": "0.9.14",
|
||||
"jquery": "3.7.1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user