@ofidj/generator-fidj 3.21.0 → 3.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"privacy:rehearse": "npm run build && node --test test/server.test.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@ofidj/entry": "^3.21.
|
|
19
|
-
"@ofidj/node": "^3.21.
|
|
18
|
+
"@ofidj/entry": "^3.21.1",
|
|
19
|
+
"@ofidj/node": "^3.21.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|
|
@@ -31,7 +31,7 @@ function mountedHead(config) {
|
|
|
31
31
|
}
|
|
32
32
|
export function renderContent(config) {
|
|
33
33
|
// HTML is supplied by the developer at generation time, never by an app visitor.
|
|
34
|
-
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="referrer" content="no-referrer"><title>${escape(config.title)}</title><link rel="icon" href="${escape(config.favicon)}"><link rel="stylesheet" href="./main.css">${mountedHead(config)}</head><body>
|
|
34
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="referrer" content="no-referrer"><meta name="description" content="${escape(config.description)}"><title>${escape(config.title)}</title><link rel="icon" href="${escape(config.favicon)}"><link rel="preload" href="./fonts/InstrumentSerif-400-latin.woff2" as="font" type="font/woff2" crossorigin><link rel="stylesheet" href="./main.css">${mountedHead(config)}</head><body>
|
|
35
35
|
<header class="topbar"><a class="brand" href="#/content"><img src="${escape(config.logo)}" alt=""><span class="brand-name">${escape(config.title)}</span></a><nav class="content-nav" id="app-nav" aria-label="App navigation" hidden></nav></header>
|
|
36
36
|
<main><template id="public-content"><section class="card public-content"><h1>${escape(config.welcome)}</h1><div>${config.content}</div></section></template><div id="app" aria-live="polite"></div><footer>Built with Fidj · Your choices belong to this app.</footer></main><script type="module" src="./main.js"></script></body></html>`;
|
|
37
37
|
}
|
|
@@ -100,11 +100,7 @@ function appNav(current: "content" | "account") {
|
|
|
100
100
|
const tab = (id: string, label: string, selected: boolean) =>
|
|
101
101
|
`<button id="${id}"${selected ? ' class="selected" aria-current="page"' : ""}><span class="tab-label">${label}</span></button>`;
|
|
102
102
|
const account = signedIn
|
|
103
|
-
? tab(
|
|
104
|
-
"account-tab",
|
|
105
|
-
accountEmail ? `Profile (${escape(accountEmail)})` : "Profile",
|
|
106
|
-
current === "account",
|
|
107
|
-
)
|
|
103
|
+
? tab("account-tab", "Profile", current === "account")
|
|
108
104
|
: tab("account-tab", "Sign in", false);
|
|
109
105
|
return tab("content-tab", "Content", current === "content") + account;
|
|
110
106
|
}
|
|
@@ -112,7 +108,7 @@ function appNav(current: "content" | "account") {
|
|
|
112
108
|
function profileSummary() {
|
|
113
109
|
const publicUrl = `${config.dashboardUrl}/#/pub/${encodeURIComponent(config.appId)}`;
|
|
114
110
|
const badgeUrl = `${config.apiEndpoint}/apps/${encodeURIComponent(config.appId)}/badge`;
|
|
115
|
-
return `<header class="profile-summary"><div class="profile-summary-copy"><
|
|
111
|
+
return `<header class="profile-summary"><div class="profile-summary-copy"><h1 class="eyebrow">Profile</h1><strong>${escape(accountEmail)}</strong><span>${escape(config.title)}</span></div><a class="profile-public" href="${escape(publicUrl)}" target="_blank" rel="noopener"><img src="${escape(badgeUrl)}" alt="${escape(config.title)} public badge" width="133" height="20"></a><button id="exit" class="sign-out">Sign out</button></header>`;
|
|
116
112
|
}
|
|
117
113
|
|
|
118
114
|
// The bar belongs to the document, not to the screen being drawn: it survives
|
|
@@ -521,6 +517,9 @@ function startModule() {
|
|
|
521
517
|
} | null;
|
|
522
518
|
if (!mount) return;
|
|
523
519
|
moduleStarted = true;
|
|
520
|
+
// The entry may have been on screen a moment ago (a refused request, a
|
|
521
|
+
// redirect); its class drops the page margins the app relies on.
|
|
522
|
+
document.body.classList.remove("signin-view");
|
|
524
523
|
document.body.classList.add("has-module");
|
|
525
524
|
// The app takes the whole document, not a corner of the shell's. A built
|
|
526
525
|
// single-page app positions itself against the body — Ionic, for one, fixes
|
|
@@ -809,7 +808,12 @@ function render() {
|
|
|
809
808
|
signInThroughProvider(submitter);
|
|
810
809
|
return;
|
|
811
810
|
}
|
|
812
|
-
|
|
811
|
+
// Enter arrives through the unseen twin of Continue; the wait is shown on
|
|
812
|
+
// the Continue a person can see.
|
|
813
|
+
const shown = submitter?.classList.contains("implicit-submit")
|
|
814
|
+
? root.querySelector<HTMLButtonElement>('button.primary[value="credentials"]')
|
|
815
|
+
: submitter;
|
|
816
|
+
shown?.setAttribute("data-busy", "true");
|
|
813
817
|
void action(async () => {
|
|
814
818
|
if (oidc && (!email || !password)) {
|
|
815
819
|
throw new Error("Enter your email and password, or sign in with Fidj.");
|
package/lib/module-mount.cjs
CHANGED
|
@@ -27,7 +27,9 @@ function describeMount(html, file) {
|
|
|
27
27
|
for (const tag of head.match(/<link\b[^>]*>/gi) || []) {
|
|
28
28
|
const rel = (attribute(tag, "rel") || "").toLowerCase();
|
|
29
29
|
const href = attribute(tag, "href");
|
|
30
|
-
|
|
30
|
+
// Once each: Angular repeats its deferred stylesheet inside <noscript>.
|
|
31
|
+
if (rel === "stylesheet" && href && !styles.includes(resolve(href)))
|
|
32
|
+
styles.push(resolve(href));
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
const scripts = [];
|