@backmatter/next 0.0.31 → 0.0.32
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.
- package/dist/config.cjs +15 -0
- package/package.json +3 -3
- package/src/config.ts +17 -0
- package/src/devbar-client.tsx +65 -11
- package/src/devbar.tsx +6 -1
- package/src/site-editor.tsx +8 -1
package/dist/config.cjs
CHANGED
|
@@ -73,6 +73,7 @@ __export(exports_config, {
|
|
|
73
73
|
withBackmatter: () => withBackmatter
|
|
74
74
|
});
|
|
75
75
|
module.exports = __toCommonJS(exports_config);
|
|
76
|
+
var import_node_module = require("node:module");
|
|
76
77
|
var import_node_fs4 = require("node:fs");
|
|
77
78
|
var import_node_path4 = __toESM(require("node:path"));
|
|
78
79
|
|
|
@@ -741,6 +742,18 @@ function matchBrace(source, open) {
|
|
|
741
742
|
}
|
|
742
743
|
|
|
743
744
|
// src/config.ts
|
|
745
|
+
var require2 = import_node_module.createRequire("file:///home/runner/work/backmatter/backmatter/packages/next/src/config.ts");
|
|
746
|
+
function studioWidgetAlias() {
|
|
747
|
+
try {
|
|
748
|
+
const studioRoot = import_node_path4.default.dirname(require2.resolve("@backmatter/studio/package.json"));
|
|
749
|
+
const dist = import_node_path4.default.join(studioRoot, "dist/site-widget.js");
|
|
750
|
+
if (!import_node_fs4.existsSync(dist))
|
|
751
|
+
return {};
|
|
752
|
+
return { "@backmatter/studio/widget": dist };
|
|
753
|
+
} catch {
|
|
754
|
+
return {};
|
|
755
|
+
}
|
|
756
|
+
}
|
|
744
757
|
var LOADER = "@backmatter/next/loader";
|
|
745
758
|
var SDK = "@backmatter/next";
|
|
746
759
|
function warnMissingInstrumentation(root) {
|
|
@@ -807,6 +820,7 @@ function withBackmatter(nextConfig = {}, options = {}) {
|
|
|
807
820
|
...existingTurbo,
|
|
808
821
|
resolveAlias: {
|
|
809
822
|
...registryTurbopackAlias(loaderOptions.root, loaderOptions.outDir),
|
|
823
|
+
...studioWidgetAlias(),
|
|
810
824
|
...existingAlias
|
|
811
825
|
},
|
|
812
826
|
rules: { ...existingRules, [glob]: turbopackRule }
|
|
@@ -820,6 +834,7 @@ function withBackmatter(nextConfig = {}, options = {}) {
|
|
|
820
834
|
const prev = prevAlias && typeof prevAlias === "object" && !Array.isArray(prevAlias) ? prevAlias : {};
|
|
821
835
|
config.resolve.alias = {
|
|
822
836
|
...registryWebpackAlias(loaderOptions.root, loaderOptions.outDir),
|
|
837
|
+
...studioWidgetAlias(),
|
|
823
838
|
...prev
|
|
824
839
|
};
|
|
825
840
|
return cfg.webpack ? cfg.webpack(config, context) : config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backmatter/next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Experimental Next.js adapter for Backmatter. APIs will break. Not ready for production.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"test": "bun test"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@backmatter/core": "^0.0.
|
|
50
|
+
"@backmatter/core": "^0.0.26",
|
|
51
51
|
"@mdx-js/mdx": "^3.1.1",
|
|
52
52
|
"remark-gfm": "^4.0.1",
|
|
53
|
-
"@backmatter/studio": "^0.0.
|
|
53
|
+
"@backmatter/studio": "^0.0.9"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"next": ">=16.3.0",
|
package/src/config.ts
CHANGED
|
@@ -7,8 +7,23 @@
|
|
|
7
7
|
// (Next 16 default) and webpack (`next build --webpack`). The loader declares
|
|
8
8
|
// `models/`, `blocks/`, `richtext/`, and `mdx/` as context dependencies, so the bundler's
|
|
9
9
|
// own file watcher keeps the registry fresh — no polling, no second watcher process.
|
|
10
|
+
import { createRequire } from "node:module";
|
|
10
11
|
import { existsSync } from "node:fs";
|
|
11
12
|
import path from "node:path";
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
|
|
16
|
+
/** Prebuilt widget (StyleX CSS must match JS). Avoids Next transpiling `src/site-widget.tsx`. */
|
|
17
|
+
function studioWidgetAlias(): Record<string, string> {
|
|
18
|
+
try {
|
|
19
|
+
const studioRoot = path.dirname(require.resolve("@backmatter/studio/package.json"));
|
|
20
|
+
const dist = path.join(studioRoot, "dist/site-widget.js");
|
|
21
|
+
if (!existsSync(dist)) return {};
|
|
22
|
+
return { "@backmatter/studio/widget": dist };
|
|
23
|
+
} catch {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
12
27
|
import { DEFAULT_DIRS } from "@backmatter/core/generate";
|
|
13
28
|
import {
|
|
14
29
|
DEFAULT_OUT_DIR,
|
|
@@ -159,6 +174,7 @@ export function withBackmatter<T extends object>(
|
|
|
159
174
|
...existingTurbo,
|
|
160
175
|
resolveAlias: {
|
|
161
176
|
...registryTurbopackAlias(loaderOptions.root, loaderOptions.outDir),
|
|
177
|
+
...studioWidgetAlias(),
|
|
162
178
|
...existingAlias,
|
|
163
179
|
},
|
|
164
180
|
rules: { ...existingRules, [glob]: turbopackRule },
|
|
@@ -175,6 +191,7 @@ export function withBackmatter<T extends object>(
|
|
|
175
191
|
prevAlias && typeof prevAlias === "object" && !Array.isArray(prevAlias) ? prevAlias : {};
|
|
176
192
|
config.resolve.alias = {
|
|
177
193
|
...registryWebpackAlias(loaderOptions.root, loaderOptions.outDir),
|
|
194
|
+
...studioWidgetAlias(),
|
|
178
195
|
...prev,
|
|
179
196
|
};
|
|
180
197
|
return cfg.webpack ? cfg.webpack(config, context) : config;
|
package/src/devbar-client.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// packages/next/src/devbar-client.tsx
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
|
-
import { Suspense, lazy, useEffect, useState, type CSSProperties, type ReactNode } from "react";
|
|
4
|
+
import { Suspense, lazy, startTransition, useCallback, useEffect, useLayoutEffect, useState, type CSSProperties, type Dispatch, type ReactNode, type SetStateAction } from "react";
|
|
5
|
+
import { useRouter } from "next/navigation";
|
|
5
6
|
import {
|
|
6
7
|
clearHostPreviewSession,
|
|
7
8
|
fetchCmsSession,
|
|
@@ -60,6 +61,26 @@ export function sessionGateAction(input: {
|
|
|
60
61
|
return "quiet";
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
/** Mode switch keeps a ready bar mounted. A closed gate stays hidden. */
|
|
65
|
+
export function withHostMode(state: DevModeState, mode: "preview" | "live"): DevModeState {
|
|
66
|
+
if (state.status !== "ready") return state;
|
|
67
|
+
return { ...state, mode };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Last verified session in this document. A refresh can remount the client
|
|
72
|
+
* bar; restoring this before paint keeps it on screen. Server renders stay
|
|
73
|
+
* hidden so one request cannot leak into the next.
|
|
74
|
+
*/
|
|
75
|
+
let shownSession: DevModeState = { status: "hidden" };
|
|
76
|
+
let shownRev = 0;
|
|
77
|
+
|
|
78
|
+
function rememberShown(next: DevModeState) {
|
|
79
|
+
if (typeof window === "undefined") return;
|
|
80
|
+
shownSession = next;
|
|
81
|
+
shownRev += 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
63
84
|
export function devModeState(
|
|
64
85
|
user: CmsSessionUser | null,
|
|
65
86
|
session: {
|
|
@@ -340,14 +361,23 @@ function useGate(): Gate {
|
|
|
340
361
|
* Only an explicit enter with no session leaves the page, and it leaves
|
|
341
362
|
* top-level. A stale marker stays on the public page.
|
|
342
363
|
*/
|
|
343
|
-
function useSiteSession(
|
|
364
|
+
function useSiteSession(
|
|
365
|
+
gate: Gate,
|
|
366
|
+
previewEntryPath: string,
|
|
367
|
+
): [DevModeState, Dispatch<SetStateAction<DevModeState>>] {
|
|
344
368
|
const [state, setState] = useState<DevModeState>({ status: "hidden" });
|
|
345
369
|
|
|
370
|
+
useLayoutEffect(() => {
|
|
371
|
+
if (shownSession.status !== "ready") return;
|
|
372
|
+
setState(shownSession);
|
|
373
|
+
}, []);
|
|
374
|
+
|
|
346
375
|
useEffect(() => {
|
|
347
376
|
if (gate === "closed") return;
|
|
377
|
+
const rev = shownRev;
|
|
348
378
|
let cancelled = false;
|
|
349
379
|
void loadDevModeState("").then((next) => {
|
|
350
|
-
if (cancelled) return;
|
|
380
|
+
if (cancelled || rev !== shownRev) return;
|
|
351
381
|
const showBar = next.status === "ready";
|
|
352
382
|
const reason = next.status === "hidden" ? (next.reason ?? "anonymous") : "anonymous";
|
|
353
383
|
const action = sessionGateAction({
|
|
@@ -358,6 +388,7 @@ function useSiteSession(gate: Gate, previewEntryPath: string): DevModeState {
|
|
|
358
388
|
});
|
|
359
389
|
if (action === "show") {
|
|
360
390
|
sessionStorage.removeItem(ENTER_ATTEMPT_KEY);
|
|
391
|
+
rememberShown(next);
|
|
361
392
|
setState(next);
|
|
362
393
|
return;
|
|
363
394
|
}
|
|
@@ -379,36 +410,57 @@ function useSiteSession(gate: Gate, previewEntryPath: string): DevModeState {
|
|
|
379
410
|
};
|
|
380
411
|
}, [gate, previewEntryPath]);
|
|
381
412
|
|
|
382
|
-
return state;
|
|
413
|
+
return [state, setState];
|
|
383
414
|
}
|
|
384
415
|
|
|
385
416
|
export function DevBarClient({
|
|
386
417
|
studioPath,
|
|
387
418
|
previewEntryPath = DEFAULT_PREVIEW_ENTRY_PATH,
|
|
388
419
|
previewFrame,
|
|
420
|
+
previewFrameRadius,
|
|
421
|
+
dashboardUrl,
|
|
389
422
|
}: {
|
|
390
423
|
/** Unused since the bar stopped calling the CMS origin; kept for host layouts that still pass it. */
|
|
391
424
|
apiUrl?: string;
|
|
392
425
|
studioPath?: string;
|
|
393
426
|
previewEntryPath?: string;
|
|
394
427
|
previewFrame?: boolean;
|
|
428
|
+
previewFrameRadius?: number;
|
|
429
|
+
dashboardUrl?: string;
|
|
395
430
|
}) {
|
|
396
431
|
const gate = useGate();
|
|
397
|
-
const state = useSiteSession(gate, previewEntryPath);
|
|
432
|
+
const [state, setState] = useSiteSession(gate, previewEntryPath);
|
|
433
|
+
const router = useRouter();
|
|
434
|
+
const refreshHost = useCallback(() => {
|
|
435
|
+
startTransition(() => {
|
|
436
|
+
router.refresh();
|
|
437
|
+
});
|
|
438
|
+
}, [router]);
|
|
398
439
|
const [exiting, setExiting] = useState(false);
|
|
399
440
|
const [entering, setEntering] = useState(false);
|
|
441
|
+
|
|
400
442
|
const goLive = () => {
|
|
401
|
-
if (exiting) return;
|
|
443
|
+
if (exiting || entering) return;
|
|
402
444
|
setExiting(true);
|
|
403
|
-
void goHostSiteLive(
|
|
404
|
-
|
|
445
|
+
void goHostSiteLive(setHostSiteLive, () => {
|
|
446
|
+
const next = withHostMode(state, "live");
|
|
447
|
+
rememberShown(next);
|
|
448
|
+
setState(next);
|
|
449
|
+
refreshHost();
|
|
450
|
+
}).then(() => {
|
|
451
|
+
setExiting(false);
|
|
405
452
|
});
|
|
406
453
|
};
|
|
407
454
|
const goPreview = () => {
|
|
408
|
-
if (entering) return;
|
|
455
|
+
if (exiting || entering) return;
|
|
409
456
|
setEntering(true);
|
|
410
|
-
void enterHostPreview(
|
|
411
|
-
|
|
457
|
+
void enterHostPreview(setHostSitePreview, () => {
|
|
458
|
+
const next = withHostMode(state, "preview");
|
|
459
|
+
rememberShown(next);
|
|
460
|
+
setState(next);
|
|
461
|
+
refreshHost();
|
|
462
|
+
}).then(() => {
|
|
463
|
+
setEntering(false);
|
|
412
464
|
});
|
|
413
465
|
};
|
|
414
466
|
if (state.status !== "ready") return null;
|
|
@@ -424,6 +476,8 @@ export function DevBarClient({
|
|
|
424
476
|
studioPath={studioPath}
|
|
425
477
|
previewEntryPath={previewEntryPath}
|
|
426
478
|
previewFrame={state.mode === "preview" ? previewFrame : false}
|
|
479
|
+
previewFrameRadius={previewFrameRadius}
|
|
480
|
+
dashboardUrl={dashboardUrl}
|
|
427
481
|
/>
|
|
428
482
|
</Suspense>
|
|
429
483
|
);
|
package/src/devbar.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// packages/next/src/devbar.tsx
|
|
2
|
-
import { resolveDevBarApiUrl } from "@backmatter/core";
|
|
2
|
+
import { resolveDashboardUrl, resolveDevBarApiUrl } from "@backmatter/core";
|
|
3
3
|
import { DevBarClient } from "./devbar-client";
|
|
4
4
|
|
|
5
5
|
export {
|
|
@@ -10,6 +10,7 @@ export {
|
|
|
10
10
|
loadDevModeState,
|
|
11
11
|
sessionGateAction,
|
|
12
12
|
useDevMode,
|
|
13
|
+
withHostMode,
|
|
13
14
|
type CmsSessionUser,
|
|
14
15
|
type DevModeState,
|
|
15
16
|
type SessionGateAction,
|
|
@@ -31,11 +32,13 @@ export function DevBar({
|
|
|
31
32
|
studioPath,
|
|
32
33
|
previewEntryPath,
|
|
33
34
|
previewFrame,
|
|
35
|
+
previewFrameRadius,
|
|
34
36
|
}: {
|
|
35
37
|
apiUrl?: string;
|
|
36
38
|
studioPath?: string;
|
|
37
39
|
previewEntryPath?: string;
|
|
38
40
|
previewFrame?: boolean;
|
|
41
|
+
previewFrameRadius?: number;
|
|
39
42
|
} = {}) {
|
|
40
43
|
return (
|
|
41
44
|
<DevBarClient
|
|
@@ -43,6 +46,8 @@ export function DevBar({
|
|
|
43
46
|
studioPath={studioPath}
|
|
44
47
|
previewEntryPath={previewEntryPath}
|
|
45
48
|
previewFrame={previewFrame}
|
|
49
|
+
previewFrameRadius={previewFrameRadius}
|
|
50
|
+
dashboardUrl={resolveDashboardUrl()}
|
|
46
51
|
/>
|
|
47
52
|
);
|
|
48
53
|
}
|
package/src/site-editor.tsx
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { usePathname, useRouter } from "next/navigation";
|
|
7
7
|
import { startTransition, useCallback, useEffect, useRef, useState } from "react";
|
|
8
|
-
import "@backmatter/studio/
|
|
8
|
+
import "@backmatter/studio/site-widget.css";
|
|
9
9
|
import studioPkg from "@backmatter/studio/package.json";
|
|
10
10
|
import { SiteWidget } from "@backmatter/studio/widget";
|
|
11
11
|
import { markerCookie } from "./gate";
|
|
@@ -68,6 +68,8 @@ export function SiteChrome({
|
|
|
68
68
|
onEnterPreview,
|
|
69
69
|
previewEntryPath = DEFAULT_PREVIEW_ENTRY_PATH,
|
|
70
70
|
previewFrame,
|
|
71
|
+
previewFrameRadius,
|
|
72
|
+
dashboardUrl,
|
|
71
73
|
}: {
|
|
72
74
|
branch?: string;
|
|
73
75
|
tree?: string;
|
|
@@ -80,6 +82,8 @@ export function SiteChrome({
|
|
|
80
82
|
/** Ticket route. `POST ?renew=1` slides the site session. A 401 drops the bar. */
|
|
81
83
|
previewEntryPath?: string;
|
|
82
84
|
previewFrame?: boolean;
|
|
85
|
+
previewFrameRadius?: number;
|
|
86
|
+
dashboardUrl?: string;
|
|
83
87
|
}) {
|
|
84
88
|
const router = useRouter();
|
|
85
89
|
const doc = useSiteDoc();
|
|
@@ -139,7 +143,10 @@ export function SiteChrome({
|
|
|
139
143
|
onSessionExpired={leave}
|
|
140
144
|
previewEntryPath={previewEntryPath}
|
|
141
145
|
previewFrame={previewFrame}
|
|
146
|
+
previewFrameRadius={previewFrameRadius}
|
|
142
147
|
version={studioPkg.version}
|
|
148
|
+
dashboardHref={dashboardUrl}
|
|
149
|
+
onSignOut={leave}
|
|
143
150
|
/>
|
|
144
151
|
);
|
|
145
152
|
}
|