@backmatter/studio 0.0.12 → 0.0.14
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/chunks/{UiKitApp-ZZXQt3zy.js → UiKitApp-fYeVEf4-.js} +323 -321
- package/dist/chunks/{WorkspaceRoutes-CCDPtLla.js → WorkspaceRoutes-Dt7JvEWT.js} +33082 -33099
- package/dist/chunks/{dashboard-Dw0zfTXg.js → dashboard-BuY2aGkO.js} +2 -2
- package/dist/chunks/{index-DhZGCAru.js → index-NWDqEZYW.js} +1 -1
- package/dist/dashboard.js +2 -2
- package/dist/index.js +2 -2
- package/dist/site-widget.js +8491 -9824
- package/package.json +2 -2
- package/src/api.ts +8 -23
- package/src/chat/ChangeCard.tsx +6 -2
- package/src/chat/ChatMessage.tsx +23 -18
- package/src/chat/ChatProvider.tsx +13 -11
- package/src/chat/chat-helpers.ts +56 -8
- package/src/chrome/ContentExplorerSidebar.tsx +51 -88
- package/src/chrome/EditorFocusContext.tsx +3 -3
- package/src/chrome/EditorStatusContext.tsx +0 -3
- package/src/chrome/WorkspaceNavContext.tsx +0 -2
- package/src/chrome/content-api-url.ts +3 -12
- package/src/chrome/content-repo-path.ts +8 -25
- package/src/chrome/content-type-groups.ts +0 -3
- package/src/chrome/folder-create-context.ts +15 -39
- package/src/pages/DocEditorPage.tsx +17 -33
- package/src/pages/LegacyWorkspaceRedirect.tsx +2 -9
- package/src/pages/WorkspaceLayout.tsx +0 -5
- package/src/pages/preview-url.ts +6 -20
- package/src/preview-frame.tsx +10 -4
- package/src/replica/store.ts +1 -1
- package/src/site-bar.tsx +3 -6
- package/src/site-dashboard-href.ts +1 -3
- package/src/workspace-path.ts +3 -23
|
@@ -60,7 +60,7 @@ import { BodyField } from "./BodyProse";
|
|
|
60
60
|
import { BlocksList } from "./BlocksList";
|
|
61
61
|
import { blocksFromFrontmatter } from "./blocks-list";
|
|
62
62
|
import type { WorkspaceOutletContext } from "../workspace/types";
|
|
63
|
-
import { contentDocPath,
|
|
63
|
+
import { contentDocPath, settingsPath } from "../workspace-path";
|
|
64
64
|
import { bindPreviewEditor, previewFrameTransport } from "./preview-bridge";
|
|
65
65
|
import { editorGrabAction } from "./editor-grab";
|
|
66
66
|
import { useChatUI } from "../chat/ChatProvider";
|
|
@@ -190,10 +190,6 @@ export function DocEditorPage() {
|
|
|
190
190
|
const model = models.find((m) => m.type === type);
|
|
191
191
|
const embed = searchParams.get("embed") === "1";
|
|
192
192
|
const showPreview = !embed && model?.route !== false;
|
|
193
|
-
const locale = model?.path.includes("{locale}")
|
|
194
|
-
? searchParams.get("locale") || defaultLocaleOf(workspace.locales)
|
|
195
|
-
: "";
|
|
196
|
-
|
|
197
193
|
const [source, setSource] = useState<ContentSource | null>(null);
|
|
198
194
|
const [docStatus, setDocStatus] = useState<DocStatus | null>(null);
|
|
199
195
|
const [branch, setBranch] = useState<string | null>(null);
|
|
@@ -233,7 +229,7 @@ export function DocEditorPage() {
|
|
|
233
229
|
useSetEditorStatus();
|
|
234
230
|
const editorActions = useSetEditorActions();
|
|
235
231
|
const { setFocus: setEditorFocus, aiEditingDocKey } = useEditorFocus();
|
|
236
|
-
const docRef = useMemo(() => ({
|
|
232
|
+
const docRef = useMemo(() => ({ type, slug }), [type, slug]);
|
|
237
233
|
const aiEditing = aiEditingDocKey !== null && aiEditingDocKey === docKey(docRef);
|
|
238
234
|
const aiEditingRef = useRef(aiEditing);
|
|
239
235
|
aiEditingRef.current = aiEditing;
|
|
@@ -250,9 +246,8 @@ export function DocEditorPage() {
|
|
|
250
246
|
// Mirrors docStatus for event handlers that must not re-subscribe on change.
|
|
251
247
|
const docStatusRef = useRef<DocStatus | null>(null);
|
|
252
248
|
docStatusRef.current = docStatus;
|
|
253
|
-
const channelRef = useRef<PreviewChannelRef>({
|
|
249
|
+
const channelRef = useRef<PreviewChannelRef>({ type, slug });
|
|
254
250
|
channelRef.current = {
|
|
255
|
-
locale,
|
|
256
251
|
type,
|
|
257
252
|
slug,
|
|
258
253
|
...(branch ? { branch } : {}),
|
|
@@ -269,11 +264,10 @@ export function DocEditorPage() {
|
|
|
269
264
|
const blocksFieldRef = useRef(blocksField);
|
|
270
265
|
blocksFieldRef.current = blocksField;
|
|
271
266
|
const siteUrl = primarySiteUrl(workspace.siteUrls ?? []);
|
|
272
|
-
const liveUrl = productionDocUrl(siteUrl, modelForType(models, type),
|
|
267
|
+
const liveUrl = productionDocUrl(siteUrl, modelForType(models, type), slug);
|
|
273
268
|
const previewPath = editorPreviewPath(
|
|
274
269
|
modelForType(models, type),
|
|
275
270
|
slug,
|
|
276
|
-
locale,
|
|
277
271
|
branch,
|
|
278
272
|
tree,
|
|
279
273
|
);
|
|
@@ -340,7 +334,6 @@ export function DocEditorPage() {
|
|
|
340
334
|
});
|
|
341
335
|
if (decision.action === "add") {
|
|
342
336
|
addPointer({
|
|
343
|
-
locale: channelRef.current.locale,
|
|
344
337
|
type: channelRef.current.type,
|
|
345
338
|
slug: channelRef.current.slug,
|
|
346
339
|
blockId: decision.blockId,
|
|
@@ -545,7 +538,7 @@ export function DocEditorPage() {
|
|
|
545
538
|
|
|
546
539
|
async function reload() {
|
|
547
540
|
try {
|
|
548
|
-
const data = await fetchDoc(workspaceId,
|
|
541
|
+
const data = await fetchDoc(workspaceId, type, slug);
|
|
549
542
|
hydrated.current = false;
|
|
550
543
|
setSource(data.doc.source);
|
|
551
544
|
setDocStatus(data.doc.status);
|
|
@@ -588,7 +581,7 @@ export function DocEditorPage() {
|
|
|
588
581
|
hydrated.current = true;
|
|
589
582
|
});
|
|
590
583
|
try {
|
|
591
|
-
const res = await saveDoc(workspaceId,
|
|
584
|
+
const res = await saveDoc(workspaceId, type, slug, {
|
|
592
585
|
frontmatter: next,
|
|
593
586
|
body: "",
|
|
594
587
|
});
|
|
@@ -596,7 +589,6 @@ export function DocEditorPage() {
|
|
|
596
589
|
setSource("tree");
|
|
597
590
|
notifyTreeChanged({
|
|
598
591
|
workspaceId,
|
|
599
|
-
locale,
|
|
600
592
|
type,
|
|
601
593
|
slug,
|
|
602
594
|
status: res.doc.status,
|
|
@@ -623,7 +615,7 @@ export function DocEditorPage() {
|
|
|
623
615
|
}
|
|
624
616
|
function onDocChanged(e: Event) {
|
|
625
617
|
const detail = (e as CustomEvent<DocChangedDetail>).detail;
|
|
626
|
-
if (!sameDocRef(detail?.docRef, {
|
|
618
|
+
if (!sameDocRef(detail?.docRef, { type, slug })) return;
|
|
627
619
|
onChanged();
|
|
628
620
|
}
|
|
629
621
|
// Chat publishes status with the tool result. Flip the badge before the reload returns.
|
|
@@ -632,7 +624,7 @@ export function DocEditorPage() {
|
|
|
632
624
|
if (!detail?.status || detail.remove) return;
|
|
633
625
|
const ws = detail.workspaceId;
|
|
634
626
|
if (ws && ws !== workspace.id && ws !== workspace.slug) return;
|
|
635
|
-
if (detail.
|
|
627
|
+
if (detail.type !== type || detail.slug !== slug) return;
|
|
636
628
|
docStatusRef.current = detail.status;
|
|
637
629
|
setDocStatus(detail.status);
|
|
638
630
|
setSource(detail.status === "clean" ? "head" : "tree");
|
|
@@ -645,7 +637,7 @@ export function DocEditorPage() {
|
|
|
645
637
|
onChanged();
|
|
646
638
|
return;
|
|
647
639
|
}
|
|
648
|
-
void fetchDoc(workspaceId,
|
|
640
|
+
void fetchDoc(workspaceId, type, slug)
|
|
649
641
|
.then((data) => setDocStatus(data.doc.status))
|
|
650
642
|
.catch(() => {});
|
|
651
643
|
}
|
|
@@ -660,7 +652,7 @@ export function DocEditorPage() {
|
|
|
660
652
|
window.removeEventListener(DOC_CHANGED_EVENT, onDocChanged);
|
|
661
653
|
};
|
|
662
654
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
663
|
-
}, [workspaceId, workspace.slug,
|
|
655
|
+
}, [workspaceId, workspace.slug, type, slug]);
|
|
664
656
|
|
|
665
657
|
// Publish the focused document to the global AI chat (debounced).
|
|
666
658
|
useEffect(() => {
|
|
@@ -698,14 +690,13 @@ export function DocEditorPage() {
|
|
|
698
690
|
setStatus(null);
|
|
699
691
|
}
|
|
700
692
|
try {
|
|
701
|
-
const res = await saveDoc(workspaceId,
|
|
693
|
+
const res = await saveDoc(workspaceId, type, slug, payload);
|
|
702
694
|
if (gen !== saveGen.current) return;
|
|
703
695
|
setSource("tree");
|
|
704
696
|
setDocStatus(res.doc.status);
|
|
705
697
|
setSaveState("saved");
|
|
706
698
|
notifyTreeChanged({
|
|
707
699
|
workspaceId,
|
|
708
|
-
locale,
|
|
709
700
|
type,
|
|
710
701
|
slug,
|
|
711
702
|
status: res.doc.status,
|
|
@@ -747,9 +738,9 @@ export function DocEditorPage() {
|
|
|
747
738
|
setStatus(null);
|
|
748
739
|
saveGen.current += 1;
|
|
749
740
|
try {
|
|
750
|
-
await revertDoc(workspaceId,
|
|
741
|
+
await revertDoc(workspaceId, type, slug);
|
|
751
742
|
setStatus("Reverted to the committed version");
|
|
752
|
-
notifyTreeChanged({ workspaceId,
|
|
743
|
+
notifyTreeChanged({ workspaceId, type, slug, status: "clean" });
|
|
753
744
|
await reload();
|
|
754
745
|
remountPreview();
|
|
755
746
|
} catch (err) {
|
|
@@ -766,7 +757,7 @@ export function DocEditorPage() {
|
|
|
766
757
|
setStatus(null);
|
|
767
758
|
saveGen.current += 1;
|
|
768
759
|
try {
|
|
769
|
-
await resolveDoc(workspaceId,
|
|
760
|
+
await resolveDoc(workspaceId, type, slug, strategy);
|
|
770
761
|
notifyTreeChanged();
|
|
771
762
|
if (strategy === "theirs") {
|
|
772
763
|
setStatus("Took the committed version");
|
|
@@ -774,7 +765,7 @@ export function DocEditorPage() {
|
|
|
774
765
|
remountPreview();
|
|
775
766
|
} else {
|
|
776
767
|
setStatus("Kept your version; it will overwrite theirs on commit");
|
|
777
|
-
const data = await fetchDoc(workspaceId,
|
|
768
|
+
const data = await fetchDoc(workspaceId, type, slug);
|
|
778
769
|
setDocStatus(data.doc.status);
|
|
779
770
|
}
|
|
780
771
|
} catch (err) {
|
|
@@ -806,12 +797,11 @@ export function DocEditorPage() {
|
|
|
806
797
|
const statusLabel = docStatusLabel(docStatus);
|
|
807
798
|
useEffect(() => {
|
|
808
799
|
setEditorStatus({
|
|
809
|
-
locale,
|
|
810
800
|
status: statusLabel,
|
|
811
801
|
saveLabel,
|
|
812
802
|
saveTone,
|
|
813
803
|
});
|
|
814
|
-
}, [setEditorStatus,
|
|
804
|
+
}, [setEditorStatus, saveLabel, saveTone, statusLabel]);
|
|
815
805
|
|
|
816
806
|
const hasTreeCopy = source === "tree";
|
|
817
807
|
useEffect(() => {
|
|
@@ -903,13 +893,7 @@ export function DocEditorPage() {
|
|
|
903
893
|
{...stylex.props(styles.editPage)}
|
|
904
894
|
onClick={() => {
|
|
905
895
|
navigate(
|
|
906
|
-
contentDocPath(
|
|
907
|
-
workspace.slug,
|
|
908
|
-
previewOffer.type,
|
|
909
|
-
previewOffer.slug,
|
|
910
|
-
previewOffer.locale,
|
|
911
|
-
defaultLocaleOf(workspace.locales),
|
|
912
|
-
),
|
|
896
|
+
contentDocPath(workspace.slug, previewOffer.type, previewOffer.slug),
|
|
913
897
|
);
|
|
914
898
|
}}
|
|
915
899
|
>
|
|
@@ -4,10 +4,7 @@ import { Navigate, useLocation, useParams } from "react-router";
|
|
|
4
4
|
import { fetchWorkspace } from "../api";
|
|
5
5
|
import { PageFrame } from "../ui/Page";
|
|
6
6
|
import { Text } from "../ui/Text";
|
|
7
|
-
import {
|
|
8
|
-
defaultLocaleOf,
|
|
9
|
-
rewriteLegacyWorkspacePath,
|
|
10
|
-
} from "../workspace-path";
|
|
7
|
+
import { rewriteLegacyWorkspacePath } from "../workspace-path";
|
|
11
8
|
|
|
12
9
|
export function LegacyWorkspaceRedirect() {
|
|
13
10
|
const { workspaceId = "", "*": rest } = useParams();
|
|
@@ -26,11 +23,7 @@ export function LegacyWorkspaceRedirect() {
|
|
|
26
23
|
const pathname = rest
|
|
27
24
|
? `/workspaces/${workspaceId}/${rest}`
|
|
28
25
|
: `/workspaces/${workspaceId}`;
|
|
29
|
-
const rewritten = rewriteLegacyWorkspacePath(
|
|
30
|
-
pathname,
|
|
31
|
-
workspace.slug,
|
|
32
|
-
defaultLocaleOf(workspace.locales),
|
|
33
|
-
);
|
|
26
|
+
const rewritten = rewriteLegacyWorkspacePath(pathname, workspace.slug);
|
|
34
27
|
const url = new URL(rewritten, "http://local");
|
|
35
28
|
new URLSearchParams(location.search).forEach((value, key) => {
|
|
36
29
|
url.searchParams.set(key, value);
|
|
@@ -12,7 +12,6 @@ import { PageFrame } from "../ui/Page";
|
|
|
12
12
|
import { Text } from "../ui/Text";
|
|
13
13
|
import type { WorkspaceOutletContext } from "../workspace/types";
|
|
14
14
|
import {
|
|
15
|
-
defaultLocaleOf,
|
|
16
15
|
isWorkspaceEditorPath,
|
|
17
16
|
isWorkspaceMediaPath,
|
|
18
17
|
isWorkspaceSettingsPath,
|
|
@@ -65,10 +64,6 @@ export function WorkspaceLayout() {
|
|
|
65
64
|
workspaceSlug: workspace.slug,
|
|
66
65
|
workspaceName: workspace.name,
|
|
67
66
|
role: workspace.role,
|
|
68
|
-
defaultLocale: defaultLocaleOf(workspace.locales),
|
|
69
|
-
locales: workspace.locales?.length
|
|
70
|
-
? workspace.locales
|
|
71
|
-
: [defaultLocaleOf(workspace.locales)],
|
|
72
67
|
contentTypes: models.map((m) => m.type),
|
|
73
68
|
contentModels: models.map((m) => ({
|
|
74
69
|
type: m.type,
|
package/src/pages/preview-url.ts
CHANGED
|
@@ -1,35 +1,23 @@
|
|
|
1
1
|
// packages/studio/src/pages/preview-url.ts
|
|
2
|
-
import {
|
|
3
|
-
encodeDocLocale,
|
|
4
|
-
PREVIEW_LOCALE_QUERY,
|
|
5
|
-
revalidateUrl,
|
|
6
|
-
routeFor,
|
|
7
|
-
routeTemplate,
|
|
8
|
-
type RouteModel,
|
|
9
|
-
} from "@backmatter/core";
|
|
2
|
+
import { revalidateUrl, routeFor, type RouteModel } from "@backmatter/core";
|
|
10
3
|
|
|
11
4
|
export function modelForType(models: readonly RouteModel[], type: string): RouteModel {
|
|
12
5
|
return models.find((m) => m.type === type) ?? { type };
|
|
13
6
|
}
|
|
14
7
|
|
|
15
|
-
export function publicDocPath(model: RouteModel,
|
|
16
|
-
return routeFor(model,
|
|
8
|
+
export function publicDocPath(model: RouteModel, slug: string): string {
|
|
9
|
+
return routeFor(model, slug);
|
|
17
10
|
}
|
|
18
11
|
|
|
19
12
|
/** Public path once checkout is known. Null holds the iframe off HEAD. */
|
|
20
13
|
export function editorPreviewPath(
|
|
21
14
|
model: RouteModel,
|
|
22
15
|
slug: string,
|
|
23
|
-
locale = "en",
|
|
24
16
|
branch?: string | null,
|
|
25
17
|
tree?: string | null,
|
|
26
18
|
): string | null {
|
|
27
19
|
if (!branch?.trim() || !tree?.trim()) return null;
|
|
28
|
-
|
|
29
|
-
if (!path || routeTemplate(model).includes("{locale}")) return path || null;
|
|
30
|
-
const params = new URLSearchParams();
|
|
31
|
-
params.set(PREVIEW_LOCALE_QUERY, encodeDocLocale(locale));
|
|
32
|
-
return `${path}?${params.toString()}`;
|
|
20
|
+
return publicDocPath(model, slug) || null;
|
|
33
21
|
}
|
|
34
22
|
|
|
35
23
|
/**
|
|
@@ -80,12 +68,11 @@ export function primarySiteUrl(
|
|
|
80
68
|
export function productionDocUrl(
|
|
81
69
|
siteUrl: string | null | undefined,
|
|
82
70
|
model: RouteModel,
|
|
83
|
-
locale: string,
|
|
84
71
|
slug: string,
|
|
85
72
|
): string | null {
|
|
86
73
|
const origin = siteUrl?.trim().replace(/\/$/, "");
|
|
87
74
|
if (!origin) return null;
|
|
88
|
-
return `${origin}${publicDocPath(model,
|
|
75
|
+
return `${origin}${publicDocPath(model, slug)}`;
|
|
89
76
|
}
|
|
90
77
|
|
|
91
78
|
export function revalidateWebhookUrl(siteUrl: string | null | undefined): string | null {
|
|
@@ -108,11 +95,10 @@ export function buildPreviewSiteUrl(
|
|
|
108
95
|
base: string,
|
|
109
96
|
model: RouteModel,
|
|
110
97
|
slug: string,
|
|
111
|
-
locale = "en",
|
|
112
98
|
branch?: string | null,
|
|
113
99
|
tree?: string | null,
|
|
114
100
|
ticket?: string | null,
|
|
115
101
|
): string | null {
|
|
116
|
-
if (!editorPreviewPath(model, slug,
|
|
102
|
+
if (!editorPreviewPath(model, slug, branch, tree) || !ticket) return null;
|
|
117
103
|
return previewEnableUrl(base, ticket);
|
|
118
104
|
}
|
package/src/preview-frame.tsx
CHANGED
|
@@ -38,10 +38,16 @@ export function guessPreviewFrameRadius(): number {
|
|
|
38
38
|
export function resolvePreviewFrameRadius(override?: number): number {
|
|
39
39
|
if (override !== undefined && Number.isFinite(override) && override >= 0) return override;
|
|
40
40
|
if (typeof document !== "undefined") {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
try {
|
|
42
|
+
const raw = getComputedStyle(document.documentElement)
|
|
43
|
+
.getPropertyValue("--bm-preview-frame-radius")
|
|
44
|
+
.trim();
|
|
45
|
+
if (raw) {
|
|
46
|
+
const parsed = Number.parseFloat(raw);
|
|
47
|
+
if (Number.isFinite(parsed) && parsed >= 0) return parsed;
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// happy-dom and other minimal runtimes may not implement layout styles.
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
return guessPreviewFrameRadius();
|
package/src/replica/store.ts
CHANGED
|
@@ -21,7 +21,7 @@ const OVERLAY_STATUSES = new Set(["modified", "added", "conflict", "deleted"]);
|
|
|
21
21
|
|
|
22
22
|
function validOverlay(row: ReplicaHit["overlay"][number]) {
|
|
23
23
|
return Boolean(
|
|
24
|
-
row.locale &&
|
|
24
|
+
typeof row.locale === "string" &&
|
|
25
25
|
row.type &&
|
|
26
26
|
row.slug &&
|
|
27
27
|
OVERLAY_STATUSES.has(row.status),
|
package/src/site-bar.tsx
CHANGED
|
@@ -61,7 +61,6 @@ const DEFAULT_PREVIEW_ENTRY = "/api/backmatter/preview";
|
|
|
61
61
|
export type { DevbarActivity, DevbarStep };
|
|
62
62
|
|
|
63
63
|
export type PageMenuDoc = {
|
|
64
|
-
locale: string;
|
|
65
64
|
type: string;
|
|
66
65
|
slug: string;
|
|
67
66
|
};
|
|
@@ -184,7 +183,6 @@ export function SiteBar({
|
|
|
184
183
|
const [settingsPane, setSettingsPane] = useState<"main" | "shortcuts">("main");
|
|
185
184
|
const [hostName, setHostName] = useState("");
|
|
186
185
|
const [workspaceSlug, setWorkspaceSlug] = useState<string | null>(null);
|
|
187
|
-
const [workspaceDefaultLocale, setWorkspaceDefaultLocale] = useState("en");
|
|
188
186
|
|
|
189
187
|
useEffect(() => {
|
|
190
188
|
const id = doc?.workspaceId;
|
|
@@ -197,7 +195,6 @@ export function SiteBar({
|
|
|
197
195
|
.then(({ workspace }) => {
|
|
198
196
|
if (cancelled) return;
|
|
199
197
|
setWorkspaceSlug(workspace.slug);
|
|
200
|
-
setWorkspaceDefaultLocale(workspace.locales[0] ?? "en");
|
|
201
198
|
})
|
|
202
199
|
.catch(() => {
|
|
203
200
|
if (!cancelled) setWorkspaceSlug(null);
|
|
@@ -208,8 +205,8 @@ export function SiteBar({
|
|
|
208
205
|
}, [doc?.workspaceId]);
|
|
209
206
|
|
|
210
207
|
const dashboardOpenHref = useMemo(
|
|
211
|
-
() => resolveDashboardOpenHref(dashboardHref, doc, workspaceSlug
|
|
212
|
-
[dashboardHref, doc, workspaceSlug
|
|
208
|
+
() => resolveDashboardOpenHref(dashboardHref, doc, workspaceSlug),
|
|
209
|
+
[dashboardHref, doc, workspaceSlug],
|
|
213
210
|
);
|
|
214
211
|
|
|
215
212
|
const setBar = useCallback((node: HTMLElement | null) => {
|
|
@@ -478,7 +475,7 @@ export function SiteBar({
|
|
|
478
475
|
try {
|
|
479
476
|
const { workspace } = await fetchWorkspace(doc.workspaceId);
|
|
480
477
|
href =
|
|
481
|
-
resolveDashboardOpenHref(dashboardHref, doc, workspace.slug
|
|
478
|
+
resolveDashboardOpenHref(dashboardHref, doc, workspace.slug) ??
|
|
482
479
|
href;
|
|
483
480
|
} catch {
|
|
484
481
|
// Keep the dashboard origin.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { contentDocPath } from "./workspace-path";
|
|
3
3
|
|
|
4
4
|
export type DashboardDocRef = {
|
|
5
|
-
locale: string;
|
|
6
5
|
type: string;
|
|
7
6
|
slug: string;
|
|
8
7
|
};
|
|
@@ -12,10 +11,9 @@ export function resolveDashboardOpenHref(
|
|
|
12
11
|
dashboardOrigin: string | undefined,
|
|
13
12
|
doc: DashboardDocRef | null,
|
|
14
13
|
workspaceSlug: string | null,
|
|
15
|
-
defaultLocale = "en",
|
|
16
14
|
): string | undefined {
|
|
17
15
|
if (!dashboardOrigin?.trim()) return undefined;
|
|
18
16
|
const base = dashboardOrigin.replace(/\/+$/, "");
|
|
19
17
|
if (!doc || !workspaceSlug) return base;
|
|
20
|
-
return `${base}${contentDocPath(workspaceSlug, doc.type, doc.slug
|
|
18
|
+
return `${base}${contentDocPath(workspaceSlug, doc.type, doc.slug)}`;
|
|
21
19
|
}
|
package/src/workspace-path.ts
CHANGED
|
@@ -7,18 +7,8 @@ export function contentTypePath(slug: string, type: string) {
|
|
|
7
7
|
return `/${slug}/content/${type}`;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export function contentDocPath(
|
|
11
|
-
slug
|
|
12
|
-
type: string,
|
|
13
|
-
docSlug: string,
|
|
14
|
-
locale: string,
|
|
15
|
-
defaultLocale: string,
|
|
16
|
-
) {
|
|
17
|
-
const path = `/${slug}/content/${type}/${docSlug}`;
|
|
18
|
-
if (locale && locale !== defaultLocale) {
|
|
19
|
-
return `${path}?locale=${encodeURIComponent(locale)}`;
|
|
20
|
-
}
|
|
21
|
-
return path;
|
|
10
|
+
export function contentDocPath(slug: string, type: string, docSlug: string) {
|
|
11
|
+
return `/${slug}/content/${type}/${docSlug}`;
|
|
22
12
|
}
|
|
23
13
|
|
|
24
14
|
export function mediaPath(slug: string) {
|
|
@@ -50,11 +40,7 @@ export function cmsWorkspaceSlug(pathname: string): string | null {
|
|
|
50
40
|
return first;
|
|
51
41
|
}
|
|
52
42
|
|
|
53
|
-
export function rewriteLegacyWorkspacePath(
|
|
54
|
-
pathname: string,
|
|
55
|
-
slug: string,
|
|
56
|
-
defaultLocale = "en",
|
|
57
|
-
): string {
|
|
43
|
+
export function rewriteLegacyWorkspacePath(pathname: string, slug: string): string {
|
|
58
44
|
const rest = pathname.match(/^\/workspaces\/[^/]+(?:\/(.*))?$/)?.[1] ?? "";
|
|
59
45
|
if (!rest) return workspaceHomePath(slug);
|
|
60
46
|
const types = rest.match(/^types\/([^/]+)\/?$/);
|
|
@@ -65,8 +51,6 @@ export function rewriteLegacyWorkspacePath(
|
|
|
65
51
|
slug,
|
|
66
52
|
decodeURIComponent(docs[2]!),
|
|
67
53
|
decodeURIComponent(docs[3]!),
|
|
68
|
-
decodeURIComponent(docs[1]!),
|
|
69
|
-
defaultLocale,
|
|
70
54
|
);
|
|
71
55
|
}
|
|
72
56
|
if (rest === "github" || rest.startsWith("settings/")) {
|
|
@@ -75,10 +59,6 @@ export function rewriteLegacyWorkspacePath(
|
|
|
75
59
|
return workspaceHomePath(slug);
|
|
76
60
|
}
|
|
77
61
|
|
|
78
|
-
export function defaultLocaleOf(locales: string[] | null | undefined) {
|
|
79
|
-
return locales?.[0] || "en";
|
|
80
|
-
}
|
|
81
|
-
|
|
82
62
|
export function isWorkspaceEditorPath(pathname: string) {
|
|
83
63
|
return /\/content\/[^/]+\/[^/]+\/?$/.test(pathname);
|
|
84
64
|
}
|