chore(embedded): cut v0.0.17-beta
This commit is contained in:
parent
7fd96c7c78
commit
cf5d7c2ea6
8 changed files with 645 additions and 15 deletions
|
|
@ -628,6 +628,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Archive-specific base overrides
|
/* Archive-specific base overrides
|
||||||
Reset, tokens, and font are provided by shared/base.css */
|
Reset, tokens, and font are provided by shared/base.css */
|
||||||
|
|
||||||
|
|
@ -2245,7 +2267,7 @@ td[data-field="trackingNumber"] {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC Archive</span>
|
<span class="app-header__title">ZDDC Archive</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
||||||
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh Data">⟳</button>
|
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh Data">⟳</button>
|
||||||
|
|
@ -3369,6 +3391,89 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC — shared preview helpers
|
* ZDDC — shared preview helpers
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* browse-specific layout on top of shared/base.css */
|
/* browse-specific layout on top of shared/base.css */
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
|
|
@ -947,7 +969,7 @@ body {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC Browse</span>
|
<span class="app-header__title">ZDDC Browse</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
||||||
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh listing" aria-label="Refresh listing">⟳</button>
|
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh listing" aria-label="Refresh listing">⟳</button>
|
||||||
|
|
@ -1904,6 +1926,89 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC shared help panel — open/close logic.
|
* ZDDC shared help panel — open/close logic.
|
||||||
* Works with all four tools regardless of their module pattern.
|
* Works with all four tools regardless of their module pattern.
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Classifier-specific base overrides
|
/* Classifier-specific base overrides
|
||||||
Reset, tokens, buttons, and font are provided by shared/base.css */
|
Reset, tokens, buttons, and font are provided by shared/base.css */
|
||||||
|
|
||||||
|
|
@ -1464,7 +1486,7 @@ body.help-open .app-header {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC Classifier</span>
|
<span class="app-header__title">ZDDC Classifier</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
<button id="addDirectoryBtn" class="btn btn-primary">Add Local Directory</button>
|
||||||
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh and rescan directory" aria-label="Refresh" style="font-size:1.1rem;">⟳</button>
|
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh and rescan directory" aria-label="Refresh" style="font-size:1.1rem;">⟳</button>
|
||||||
|
|
@ -2855,6 +2877,89 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC — shared preview helpers
|
* ZDDC — shared preview helpers
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Landing page layout */
|
/* Landing page layout */
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
@ -988,7 +1010,7 @@ body {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC</span>
|
<span class="app-header__title">ZDDC</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
|
|
@ -1941,6 +1963,89 @@ body {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC shared help panel — open/close logic.
|
* ZDDC shared help panel — open/close logic.
|
||||||
* Works with all four tools regardless of their module pattern.
|
* Works with all four tools regardless of their module pattern.
|
||||||
|
|
|
||||||
|
|
@ -848,6 +848,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* mdedit component styles — reset and tokens from shared/base.css */
|
/* mdedit component styles — reset and tokens from shared/base.css */
|
||||||
|
|
||||||
/* Pane resizer */
|
/* Pane resizer */
|
||||||
|
|
@ -1903,7 +1925,7 @@ body.help-open .app-header {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC Markdown</span>
|
<span class="app-header__title">ZDDC Markdown</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
<button id="addDirectoryBtn" class="btn btn-primary" title="Add a local directory">Add Local Directory</button>
|
<button id="addDirectoryBtn" class="btn btn-primary" title="Add a local directory">Add Local Directory</button>
|
||||||
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh directory" aria-label="Refresh">⟳</button>
|
<button id="refreshHeaderBtn" class="btn btn-secondary hidden" title="Refresh directory" aria-label="Refresh">⟳</button>
|
||||||
|
|
@ -3094,6 +3116,89 @@ body.help-open .app-header {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC — shared preview helpers
|
* ZDDC — shared preview helpers
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -632,6 +632,28 @@ body.help-open .app-header {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shared/logo.css — paired with shared/logo.js. The wrapping anchor
|
||||||
|
inherits the logo's box and adds a subtle hover/focus affordance
|
||||||
|
so it reads as clickable without altering the logo's visual weight. */
|
||||||
|
|
||||||
|
.app-header__logo-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
transition: opacity 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:hover .app-header__logo,
|
||||||
|
.app-header__logo-link:focus-visible .app-header__logo {
|
||||||
|
opacity: 0.82;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header__logo-link:focus-visible {
|
||||||
|
outline: 2px solid var(--primary);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Placeholder for contenteditable elements */
|
/* Placeholder for contenteditable elements */
|
||||||
[data-placeholder]:empty::before {
|
[data-placeholder]:empty::before {
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
|
|
@ -2263,7 +2285,7 @@ dialog.modal--narrow {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title">ZDDC Transmittal</span>
|
<span class="app-header__title">ZDDC Transmittal</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · snail-candle-citrus</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
<span id="no-js-notice" class="text-gray-400 text-xs italic">JavaScript not available</span>
|
<span id="no-js-notice" class="text-gray-400 text-xs italic">JavaScript not available</span>
|
||||||
<!-- Publish split-button (Transmittal-specific primary action;
|
<!-- Publish split-button (Transmittal-specific primary action;
|
||||||
|
|
@ -3874,6 +3896,89 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// shared/logo.js — turn the inert <svg class="app-header__logo"> on
|
||||||
|
// every tool's header into a clickable link. The destination is the
|
||||||
|
// nearest "home" the user can sensibly back out to:
|
||||||
|
//
|
||||||
|
// file:// → no wrap (no server home)
|
||||||
|
// http(s)://host/ → wrap, href = /
|
||||||
|
// http(s)://host/<tool>.html (deployment root)→ wrap, href = /
|
||||||
|
// http(s)://host/<project>/... → wrap, href = /<project>
|
||||||
|
//
|
||||||
|
// When inside a project, the logo takes the user to the project
|
||||||
|
// landing (synthetic page with the four lifecycle-stage cards + MDL
|
||||||
|
// instructions). When at the deployment root, the logo points at /
|
||||||
|
// (the project picker). Offline, the logo stays decorative — there's
|
||||||
|
// no real "home" to go to.
|
||||||
|
//
|
||||||
|
// Mounts as a sibling-replacement on DOMContentLoaded: wraps the
|
||||||
|
// existing logo SVG in an <a>, preserving classes and attributes.
|
||||||
|
// Idempotent: re-mounting on an already-wrapped logo is a no-op.
|
||||||
|
//
|
||||||
|
// Tools that want to override (e.g. a deployment that pins logo to
|
||||||
|
// an external URL) can set window.zddc.logo.disabled = true before
|
||||||
|
// DOMContentLoaded and inject their own anchor.
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!window.zddc) window.zddc = {};
|
||||||
|
if (window.zddc.logo) return;
|
||||||
|
|
||||||
|
function projectSegment(pathname) {
|
||||||
|
var parts = pathname.split('/').filter(Boolean);
|
||||||
|
if (parts.length === 0) return null;
|
||||||
|
var first = parts[0];
|
||||||
|
// Tool HTMLs at the deployment root (index.html, archive.html
|
||||||
|
// with ?projects=...) don't carry a project segment.
|
||||||
|
if (first.indexOf('.') !== -1) return null;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetHref() {
|
||||||
|
if (typeof location === 'undefined') return null;
|
||||||
|
if (location.protocol !== 'http:' && location.protocol !== 'https:') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (window.zddc.logo && window.zddc.logo.disabled) return null;
|
||||||
|
var seg = projectSegment(location.pathname);
|
||||||
|
return seg ? '/' + encodeURIComponent(seg) : '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount() {
|
||||||
|
var logo = document.querySelector('.app-header__logo');
|
||||||
|
if (!logo) return;
|
||||||
|
// Already wrapped (template-supplied anchor, or a previous mount).
|
||||||
|
if (logo.parentElement && logo.parentElement.tagName === 'A' &&
|
||||||
|
logo.parentElement.classList.contains('app-header__logo-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var href = targetHref();
|
||||||
|
if (!href) return;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = href;
|
||||||
|
a.className = 'app-header__logo-link';
|
||||||
|
var label = href === '/' ? 'ZDDC home' : 'Project home';
|
||||||
|
a.title = label;
|
||||||
|
a.setAttribute('aria-label', label);
|
||||||
|
logo.parentNode.insertBefore(a, logo);
|
||||||
|
a.appendChild(logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.zddc.logo = {
|
||||||
|
mount: mount,
|
||||||
|
// Test seam.
|
||||||
|
_projectSegment: projectSegment,
|
||||||
|
_targetHref: targetHref,
|
||||||
|
disabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', mount, { once: true });
|
||||||
|
} else {
|
||||||
|
mount();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZDDC — shared preview helpers
|
* ZDDC — shared preview helpers
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# Generated by build.sh — do not edit. One <app>=<build label> per line.
|
# Generated by build.sh — do not edit. One <app>=<build label> per line.
|
||||||
archive=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
archive=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
transmittal=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
transmittal=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
classifier=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
classifier=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
mdedit=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
mdedit=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
landing=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
landing=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
form=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
form=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
tables=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
tables=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
browse=v0.0.17-beta · 2026-05-10 · snail-candle-citrus
|
browse=v0.0.17-beta · 2026-05-10 · locust-boat-sage
|
||||||
|
|
|
||||||
|
|
@ -1092,7 +1092,7 @@ body.help-open .app-header {
|
||||||
</svg>
|
</svg>
|
||||||
<div class="header-title-group">
|
<div class="header-title-group">
|
||||||
<span class="app-header__title" id="table-title">ZDDC Table</span>
|
<span class="app-header__title" id="table-title">ZDDC Table</span>
|
||||||
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-alpha · 2026-05-10 12:33:10 · 837cf47-dirty</span></span>
|
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.17-beta · 2026-05-10 · locust-boat-sage</span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue