@eventcatalog/core 3.29.2 → 3.31.1
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/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-36IA4UE4.js → chunk-7IGMIOQF.js} +1 -1
- package/dist/{chunk-EGQGCB2B.js → chunk-HVOLSUC2.js} +1 -1
- package/dist/{chunk-DB4IQ3GB.js → chunk-LWVHWR77.js} +1 -1
- package/dist/{chunk-VEUNSJ6Z.js → chunk-QIJOBQZ7.js} +1 -1
- package/dist/{chunk-MEJOYC5Z.js → chunk-UY5QDWK7.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +5 -5
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/astro.config.mjs +11 -7
- package/eventcatalog/public/logo.png +0 -0
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +29 -24
- package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
- package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
- package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
- package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
- package/eventcatalog/src/components/Header.astro +9 -19
- package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
- package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
- package/eventcatalog/src/components/MDX/Design/Design.astro +1 -1
- package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
- package/eventcatalog/src/components/MDX/Tiles/Tile.astro +11 -8
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
- package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
- package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
- package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
- package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
- package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
- package/eventcatalog/src/components/Search/Search.astro +1 -1
- package/eventcatalog/src/components/Seo.astro +1 -1
- package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +218 -0
- package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +265 -0
- package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +371 -0
- package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +183 -0
- package/eventcatalog/src/components/Settings/LogoUpload.tsx +137 -0
- package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +91 -0
- package/eventcatalog/src/components/Settings/ReadOnlyBanner.tsx +18 -0
- package/eventcatalog/src/components/Settings/Row.tsx +59 -0
- package/eventcatalog/src/components/Settings/SettingsShared.tsx +176 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +233 -261
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +116 -68
- package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +2 -2
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
- package/eventcatalog/src/components/Tables/Table.tsx +21 -18
- package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
- package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
- package/eventcatalog/src/content.config.ts +1 -1
- package/eventcatalog/src/enterprise/auth/error.astro +1 -1
- package/eventcatalog/src/enterprise/auth/login.astro +1 -1
- package/eventcatalog/src/enterprise/auth/middleware/middleware-auth.ts +11 -7
- package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +97 -95
- package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +232 -181
- package/eventcatalog/src/enterprise/feature.ts +2 -1
- package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
- package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
- package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
- package/eventcatalog/src/layouts/SettingsLayout.astro +116 -0
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +562 -141
- package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
- package/eventcatalog/src/pages/_index.astro +253 -256
- package/eventcatalog/src/pages/api/settings/ai.ts +57 -0
- package/eventcatalog/src/pages/api/settings/general.ts +71 -0
- package/eventcatalog/src/pages/api/settings/logo.ts +113 -0
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
- package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +130 -30
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +147 -53
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +22 -19
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +71 -61
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +3 -3
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +6 -32
- package/eventcatalog/src/pages/docs/llm/llms.txt.ts +5 -1
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +12 -5
- package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
- package/eventcatalog/src/pages/settings/assistant.astro +37 -0
- package/eventcatalog/src/pages/settings/billing.astro +17 -0
- package/eventcatalog/src/pages/settings/general.astro +32 -0
- package/eventcatalog/src/pages/settings/index.astro +21 -0
- package/eventcatalog/src/pages/settings/llm-access.astro +34 -0
- package/eventcatalog/src/pages/settings/mcp.astro +14 -0
- package/eventcatalog/src/pages/studio.astro +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/styles/theme.css +95 -30
- package/eventcatalog/src/styles/themes/forest.css +17 -9
- package/eventcatalog/src/styles/themes/ocean.css +10 -2
- package/eventcatalog/src/styles/themes/sapphire.css +10 -2
- package/eventcatalog/src/styles/themes/sunset.css +25 -17
- package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
- package/eventcatalog/src/utils/eventcatalog-config/config-schema.ts +49 -0
- package/eventcatalog/src/utils/eventcatalog-config/config-writer.ts +149 -0
- package/eventcatalog/src/utils/url-builder.ts +4 -2
- package/package.json +7 -5
- package/eventcatalog/public/logo.svg +0 -14
- package/eventcatalog/src/enterprise/plans/index.astro +0 -319
- package/eventcatalog/src/pages/docs/llm/llms-services.txt.ts +0 -81
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { APIRoute } from 'astro';
|
|
2
|
+
import { isDevMode } from '@utils/feature';
|
|
3
|
+
import { aiSettingsSchema } from '@utils/eventcatalog-config/config-schema';
|
|
4
|
+
import {
|
|
5
|
+
applyConfigUpdate,
|
|
6
|
+
readConfigSource,
|
|
7
|
+
writeConfigUpdate,
|
|
8
|
+
type ConfigUpdate,
|
|
9
|
+
} from '@utils/eventcatalog-config/config-writer';
|
|
10
|
+
|
|
11
|
+
export const prerender = !isDevMode();
|
|
12
|
+
|
|
13
|
+
const json = (status: number, body: unknown) =>
|
|
14
|
+
new Response(JSON.stringify(body), {
|
|
15
|
+
status,
|
|
16
|
+
headers: { 'Content-Type': 'application/json' },
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
20
|
+
if (!isDevMode()) {
|
|
21
|
+
return json(403, { error: 'Settings can only be edited when running in dev mode (EVENTCATALOG_DEV_MODE=true).' });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let body: unknown;
|
|
25
|
+
try {
|
|
26
|
+
body = await request.json();
|
|
27
|
+
} catch {
|
|
28
|
+
return json(400, { error: 'Invalid JSON body' });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const parsed = aiSettingsSchema.safeParse(body);
|
|
32
|
+
if (!parsed.success) {
|
|
33
|
+
return json(400, { error: 'Validation failed', issues: parsed.error.issues });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let source: string;
|
|
37
|
+
try {
|
|
38
|
+
source = readConfigSource();
|
|
39
|
+
} catch (err) {
|
|
40
|
+
return json(500, { error: `Could not read eventcatalog.config.js: ${(err as Error).message}` });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const data = parsed.data;
|
|
44
|
+
const update: ConfigUpdate = {
|
|
45
|
+
llmsTxt: { enabled: data.llmsTxtEnabled },
|
|
46
|
+
chat: { enabled: data.chatEnabled },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
applyConfigUpdate(source, update);
|
|
51
|
+
writeConfigUpdate(update);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return json(500, { error: `Could not update eventcatalog.config.js: ${(err as Error).message}` });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return json(200, { ok: true, settings: data });
|
|
57
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { APIRoute } from 'astro';
|
|
2
|
+
import { isDevMode } from '@utils/feature';
|
|
3
|
+
import { generalSettingsSchema } from '@utils/eventcatalog-config/config-schema';
|
|
4
|
+
import {
|
|
5
|
+
applyConfigUpdate,
|
|
6
|
+
readConfigSource,
|
|
7
|
+
writeConfigUpdate,
|
|
8
|
+
type ConfigUpdate,
|
|
9
|
+
} from '@utils/eventcatalog-config/config-writer';
|
|
10
|
+
|
|
11
|
+
export const prerender = !isDevMode();
|
|
12
|
+
|
|
13
|
+
const json = (status: number, body: unknown) =>
|
|
14
|
+
new Response(JSON.stringify(body), {
|
|
15
|
+
status,
|
|
16
|
+
headers: { 'Content-Type': 'application/json' },
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
20
|
+
if (!isDevMode()) {
|
|
21
|
+
return json(403, { error: 'Settings can only be edited when running in dev mode (EVENTCATALOG_DEV_MODE=true).' });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let body: unknown;
|
|
25
|
+
try {
|
|
26
|
+
body = await request.json();
|
|
27
|
+
} catch {
|
|
28
|
+
return json(400, { error: 'Invalid JSON body' });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const parsed = generalSettingsSchema.safeParse(body);
|
|
32
|
+
if (!parsed.success) {
|
|
33
|
+
return json(400, { error: 'Validation failed', issues: parsed.error.issues });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Verify the config file exists and is parseable before we attempt the write.
|
|
37
|
+
let source: string;
|
|
38
|
+
try {
|
|
39
|
+
source = readConfigSource();
|
|
40
|
+
} catch (err) {
|
|
41
|
+
return json(500, { error: `Could not read eventcatalog.config.js: ${(err as Error).message}` });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const data = parsed.data;
|
|
45
|
+
const update: ConfigUpdate = {
|
|
46
|
+
title: data.title,
|
|
47
|
+
tagline: data.tagline ?? null,
|
|
48
|
+
organizationName: data.organizationName ?? null,
|
|
49
|
+
homepageLink: data.homepageLink ?? null,
|
|
50
|
+
editUrl: data.editUrl ?? null,
|
|
51
|
+
repositoryUrl: data.repositoryUrl ?? null,
|
|
52
|
+
theme: data.theme,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
if (data.logo) {
|
|
56
|
+
update.logo = {
|
|
57
|
+
alt: data.logo.alt ?? null,
|
|
58
|
+
text: data.logo.text ?? null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
// Dry-run the write first to surface parse errors before touching disk.
|
|
64
|
+
applyConfigUpdate(source, update);
|
|
65
|
+
writeConfigUpdate(update);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
return json(500, { error: `Could not update eventcatalog.config.js: ${(err as Error).message}` });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return json(200, { ok: true, settings: data });
|
|
71
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { APIRoute } from 'astro';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { isDevMode } from '@utils/feature';
|
|
5
|
+
import { writeConfigUpdate } from '@utils/eventcatalog-config/config-writer';
|
|
6
|
+
|
|
7
|
+
export const prerender = !isDevMode();
|
|
8
|
+
|
|
9
|
+
const MAX_BYTES = 2 * 1024 * 1024;
|
|
10
|
+
const ALLOWED: Record<string, string> = {
|
|
11
|
+
'image/png': 'png',
|
|
12
|
+
'image/jpeg': 'jpg',
|
|
13
|
+
'image/svg+xml': 'svg',
|
|
14
|
+
'image/webp': 'webp',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const json = (status: number, body: unknown) =>
|
|
18
|
+
new Response(JSON.stringify(body), {
|
|
19
|
+
status,
|
|
20
|
+
headers: { 'Content-Type': 'application/json' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const projectRoot = () => process.env.PROJECT_DIR ?? process.cwd();
|
|
24
|
+
const publicDir = () => path.join(projectRoot(), 'public');
|
|
25
|
+
const LOGO_BASENAME = 'eventcatalog-logo';
|
|
26
|
+
|
|
27
|
+
const removeExistingLogos = () => {
|
|
28
|
+
const dir = publicDir();
|
|
29
|
+
if (!fs.existsSync(dir)) return;
|
|
30
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
31
|
+
if (entry.startsWith(`${LOGO_BASENAME}.`)) {
|
|
32
|
+
fs.unlinkSync(path.join(dir, entry));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Best-effort SVG sanitization: strips <script> blocks and on* event handlers.
|
|
39
|
+
* Not a full sanitizer; we accept this as a v1 limitation for SVG uploads.
|
|
40
|
+
*/
|
|
41
|
+
const sanitizeSvg = (svg: string): string =>
|
|
42
|
+
svg
|
|
43
|
+
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
44
|
+
.replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, '')
|
|
45
|
+
.replace(/\son[a-z]+\s*=\s*'[^']*'/gi, '')
|
|
46
|
+
.replace(/javascript:/gi, '');
|
|
47
|
+
|
|
48
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
49
|
+
if (!isDevMode()) {
|
|
50
|
+
return json(403, { error: 'Logo can only be changed when running in dev mode (EVENTCATALOG_DEV_MODE=true).' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let form: FormData;
|
|
54
|
+
try {
|
|
55
|
+
form = await request.formData();
|
|
56
|
+
} catch {
|
|
57
|
+
return json(400, { error: 'Expected multipart/form-data body' });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const file = form.get('logo');
|
|
61
|
+
if (!(file instanceof File)) {
|
|
62
|
+
return json(400, { error: 'Missing `logo` file field' });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const ext = ALLOWED[file.type];
|
|
66
|
+
if (!ext) {
|
|
67
|
+
return json(400, { error: `Unsupported logo type: ${file.type}. Allowed: PNG, JPG, SVG, WebP.` });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (file.size > MAX_BYTES) {
|
|
71
|
+
return json(413, { error: `Logo exceeds 2MB size limit (got ${file.size} bytes).` });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
75
|
+
const dir = publicDir();
|
|
76
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
77
|
+
|
|
78
|
+
removeExistingLogos();
|
|
79
|
+
|
|
80
|
+
const targetName = `${LOGO_BASENAME}.${ext}`;
|
|
81
|
+
const targetPath = path.join(dir, targetName);
|
|
82
|
+
|
|
83
|
+
if (ext === 'svg') {
|
|
84
|
+
const sanitized = sanitizeSvg(buffer.toString('utf8'));
|
|
85
|
+
fs.writeFileSync(targetPath, sanitized, 'utf8');
|
|
86
|
+
} else {
|
|
87
|
+
fs.writeFileSync(targetPath, buffer);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const src = `/${targetName}`;
|
|
91
|
+
try {
|
|
92
|
+
writeConfigUpdate({ logo: { src } });
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return json(500, { error: `Logo saved but config update failed: ${(err as Error).message}` });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return json(200, { ok: true, src });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const DELETE: APIRoute = async () => {
|
|
101
|
+
if (!isDevMode()) {
|
|
102
|
+
return json(403, { error: 'Logo can only be changed when running in dev mode.' });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
removeExistingLogos();
|
|
106
|
+
try {
|
|
107
|
+
writeConfigUpdate({ logo: { src: null } });
|
|
108
|
+
} catch (err) {
|
|
109
|
+
return json(500, { error: `Logo files removed but config update failed: ${(err as Error).message}` });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return json(200, { ok: true });
|
|
113
|
+
};
|
|
@@ -22,9 +22,9 @@ const specifications = type === 'services' ? getSpecificationsForService(props)
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
24
|
<VerticalSideBarLayout title={pageTitle}>
|
|
25
|
-
<main class="flex docs-layout h-full bg-[rgb(var(--ec-page-bg))]">
|
|
26
|
-
<div class="flex docs-layout w-full
|
|
27
|
-
<div class="w-full lg:mr-2 pr-
|
|
25
|
+
<main class="flex docs-layout min-h-full bg-[rgb(var(--ec-page-bg))]">
|
|
26
|
+
<div class="flex docs-layout w-full">
|
|
27
|
+
<div class="w-full lg:mr-2 pr-24 py-8 bg-[rgb(var(--ec-page-bg))]">
|
|
28
28
|
{type === 'domains' && <DomainGrid domain={domain} client:load />}
|
|
29
29
|
{type === 'services' && <MessageGrid service={props} specifications={specifications} client:load />}
|
|
30
30
|
</div>
|
|
@@ -5,7 +5,7 @@ import VisualiserLayout from '@layouts/VisualiserLayout.astro';
|
|
|
5
5
|
import components from '@components/MDX/components';
|
|
6
6
|
import config from '@config';
|
|
7
7
|
import { buildUrl } from '@utils/url-builder';
|
|
8
|
-
import {
|
|
8
|
+
import { GitCompare, X, Rocket, AlignLeft, HistoryIcon } from 'lucide-react';
|
|
9
9
|
import CopyAsMarkdown from '@components/CopyAsMarkdown';
|
|
10
10
|
import { isLLMSTxtEnabled, isEventCatalogChatEnabled, isDiagramComparisonEnabled } from '@utils/feature';
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ export const prerender = Page.prerender;
|
|
|
15
15
|
export const getStaticPaths = Page.getStaticPaths;
|
|
16
16
|
|
|
17
17
|
const props = await Page.getData(Astro);
|
|
18
|
-
const { Content } = await render(props);
|
|
18
|
+
const { Content, headings } = await render(props);
|
|
19
19
|
|
|
20
20
|
const pageTitle = `Diagram | ${props.data.name}`;
|
|
21
21
|
const currentVersion = props.data.version;
|
|
@@ -29,73 +29,123 @@ const chatQuery = `Tell me about the "${props.data.name}" diagram (version ${pro
|
|
|
29
29
|
|
|
30
30
|
<VisualiserLayout title={pageTitle} description={props.data.summary}>
|
|
31
31
|
<div class="diagram-page min-h-[calc(100vh-64px)] bg-[rgb(var(--ec-page-bg))]">
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
32
|
+
<div
|
|
33
|
+
class="flex docs-layout w-full"
|
|
34
|
+
style="padding-left: var(--ec-app-content-padding-left, 5rem); padding-right: var(--ec-app-content-padding-right, 5rem);"
|
|
35
|
+
>
|
|
36
|
+
<main class="diagram-content w-full lg:mr-2 pr-24 py-8 bg-[rgb(var(--ec-page-bg))]">
|
|
37
|
+
<div class="border-b border-[rgb(var(--ec-page-border))] md:pb-2">
|
|
38
|
+
<div class="flex items-start justify-between gap-4">
|
|
39
|
+
<div class="min-w-0">
|
|
40
|
+
<h1 class="text-2xl md:text-4xl font-bold text-[rgb(var(--ec-page-text))] truncate">
|
|
41
|
+
{props.data.name}
|
|
42
|
+
</h1>
|
|
43
|
+
{
|
|
44
|
+
props.data.summary && (
|
|
45
|
+
<p class="pt-2 text-base font-light text-[rgb(var(--ec-page-text-muted))]">{props.data.summary}</p>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="flex items-center gap-2">
|
|
51
|
+
<CopyAsMarkdown
|
|
52
|
+
client:only="react"
|
|
53
|
+
schemas={[]}
|
|
54
|
+
chatQuery={chatQuery}
|
|
55
|
+
chatEnabled={chatEnabled}
|
|
56
|
+
editUrl=""
|
|
57
|
+
markdownDownloadEnabled={markdownDownloadEnabled}
|
|
58
|
+
rssFeedEnabled={false}
|
|
59
|
+
preferChatAsDefault={chatEnabled}
|
|
60
|
+
chatButtonText="Ask about this diagram"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
59
63
|
</div>
|
|
60
|
-
{props.data.summary && <p class="mt-1 text-sm text-[rgb(var(--ec-page-text-muted))]">{props.data.summary}</p>}
|
|
61
64
|
</div>
|
|
62
65
|
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
data-scale-enabled={scaleEnabled}
|
|
70
|
-
class="inline-flex items-center justify-center gap-1.5 px-3 py-1.5 text-sm font-medium text-[rgb(var(--ec-dropdown-text))] bg-[rgb(var(--ec-dropdown-bg))] border border-[rgb(var(--ec-dropdown-border))] rounded-md shadow-xs hover:bg-[rgb(var(--ec-dropdown-hover))] focus:outline-hidden focus:ring-1 focus:ring-[rgb(var(--ec-accent))] transition-colors"
|
|
71
|
-
>
|
|
72
|
-
<GitCompare className="w-4 h-4" />
|
|
73
|
-
Compare diagram versions
|
|
74
|
-
</button>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
<CopyAsMarkdown
|
|
78
|
-
client:only="react"
|
|
79
|
-
schemas={[]}
|
|
80
|
-
chatQuery={chatQuery}
|
|
81
|
-
chatEnabled={chatEnabled}
|
|
82
|
-
editUrl=""
|
|
83
|
-
markdownDownloadEnabled={markdownDownloadEnabled}
|
|
84
|
-
rssFeedEnabled={false}
|
|
85
|
-
preferChatAsDefault={chatEnabled}
|
|
86
|
-
chatButtonText="Ask about this diagram"
|
|
87
|
-
/>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
</header>
|
|
66
|
+
<article
|
|
67
|
+
class="diagram-article prose prose-md w-full max-w-none py-4 text-[15px] dark:prose-invert prose-headings:text-[rgb(var(--ec-page-text))] prose-p:text-[rgb(var(--ec-page-text))] prose-strong:text-[rgb(var(--ec-page-text))] prose-code:text-[rgb(var(--ec-page-text))]"
|
|
68
|
+
>
|
|
69
|
+
<Content components={components(props)} />
|
|
70
|
+
</article>
|
|
71
|
+
</main>
|
|
91
72
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
73
|
+
{
|
|
74
|
+
headings.length > 0 && (
|
|
75
|
+
<aside
|
|
76
|
+
id="eventcatalog-docs-sidebar"
|
|
77
|
+
class="hidden xl:block sticky top-[4rem] self-start w-[280px] max-h-[calc(100vh-4rem)] overflow-y-auto py-2 flex-shrink-0 pr-10 bg-[rgb(var(--ec-page-bg))]"
|
|
78
|
+
>
|
|
79
|
+
<div class="mt-8 space-y-8">
|
|
80
|
+
<div>
|
|
81
|
+
<h3 class="text-xs text-[rgb(var(--ec-page-text))] font-semibold capitalize flex items-center gap-2 mb-4">
|
|
82
|
+
<AlignLeft className="w-4 h-4" />
|
|
83
|
+
On this page
|
|
84
|
+
</h3>
|
|
85
|
+
<nav class="text-xs border-l border-[rgb(var(--ec-page-border))]">
|
|
86
|
+
{headings.map((heading) => {
|
|
87
|
+
const level = heading.depth > 2 ? heading.depth : 1;
|
|
88
|
+
if (heading.depth > 3) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return (
|
|
92
|
+
<a
|
|
93
|
+
href={`#${heading.slug}`}
|
|
94
|
+
class="block py-1.5 pr-2.5 leading-5 text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-page-border))] hover:text-[rgb(var(--ec-page-text))] border-l-2 border-transparent -ml-px transition-all duration-200"
|
|
95
|
+
style={`padding-left: ${level * 0.75}rem`}
|
|
96
|
+
>
|
|
97
|
+
{heading.text}
|
|
98
|
+
</a>
|
|
99
|
+
);
|
|
100
|
+
})}
|
|
101
|
+
</nav>
|
|
102
|
+
</div>
|
|
103
|
+
{hasMultipleVersions && (
|
|
104
|
+
<div>
|
|
105
|
+
<h3 class="text-xs text-[rgb(var(--ec-page-text))] font-semibold capitalize flex items-center gap-2 mb-4">
|
|
106
|
+
<HistoryIcon className="w-4 h-4" />
|
|
107
|
+
{`Versions (${allVersions.length})`}
|
|
108
|
+
</h3>
|
|
109
|
+
<ul role="list" class="space-y-2">
|
|
110
|
+
{allVersions.map((version: string) => {
|
|
111
|
+
const isCurrent = version === currentVersion;
|
|
112
|
+
return (
|
|
113
|
+
<li>
|
|
114
|
+
<a
|
|
115
|
+
href={buildUrl(`/diagrams/${props.data.id}/${version}`)}
|
|
116
|
+
class={`flex items-center gap-2 text-xs transition-colors ${
|
|
117
|
+
isCurrent
|
|
118
|
+
? 'text-[rgb(var(--ec-accent))] font-medium'
|
|
119
|
+
: 'text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))]'
|
|
120
|
+
}`}
|
|
121
|
+
>
|
|
122
|
+
<HistoryIcon className="h-4 w-4 flex-shrink-0" />
|
|
123
|
+
<span>{version === props.data.latestVersion ? `v${version} (latest)` : `v${version}`}</span>
|
|
124
|
+
</a>
|
|
125
|
+
</li>
|
|
126
|
+
);
|
|
127
|
+
})}
|
|
128
|
+
</ul>
|
|
129
|
+
</div>
|
|
130
|
+
)}
|
|
131
|
+
{hasMultipleVersions && (
|
|
132
|
+
<div>
|
|
133
|
+
<button
|
|
134
|
+
id="compare-btn"
|
|
135
|
+
type="button"
|
|
136
|
+
data-scale-enabled={scaleEnabled}
|
|
137
|
+
class="inline-flex w-full items-center justify-center gap-1.5 rounded-md border border-[rgb(var(--ec-dropdown-border))] bg-[rgb(var(--ec-dropdown-bg))] px-3 py-2 text-sm font-medium text-[rgb(var(--ec-dropdown-text))] shadow-xs transition-colors hover:bg-[rgb(var(--ec-dropdown-hover))] focus:outline-hidden focus:ring-1 focus:ring-[rgb(var(--ec-accent))]"
|
|
138
|
+
>
|
|
139
|
+
<GitCompare className="w-4 h-4" />
|
|
140
|
+
Compare diagram versions
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
</div>
|
|
145
|
+
</aside>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
</div>
|
|
99
149
|
</div>
|
|
100
150
|
|
|
101
151
|
{/* Upgrade modal - shown when Scale is not enabled */}
|
|
@@ -203,6 +253,21 @@ const chatQuery = `Tell me about the "${props.data.name}" diagram (version ${pro
|
|
|
203
253
|
<ClientRouter />
|
|
204
254
|
</VisualiserLayout>
|
|
205
255
|
|
|
256
|
+
<style is:global>
|
|
257
|
+
.diagram-page .prose {
|
|
258
|
+
max-width: none;
|
|
259
|
+
overflow: auto;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.toc-active-text {
|
|
263
|
+
color: rgb(var(--ec-accent));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.toc-active-border {
|
|
267
|
+
border-color: rgb(var(--ec-accent));
|
|
268
|
+
}
|
|
269
|
+
</style>
|
|
270
|
+
|
|
206
271
|
<script is:inline define:vars={{ config, baseUrl: import.meta.env.BASE_URL }}>
|
|
207
272
|
window.eventcatalog = window.eventcatalog || {};
|
|
208
273
|
window.eventcatalog.mermaid = config?.mermaid;
|
|
@@ -213,14 +278,6 @@ const chatQuery = `Tell me about the "${props.data.name}" diagram (version ${pro
|
|
|
213
278
|
import { destroyZoomInstances, renderMermaidWithZoom } from '@utils/mermaid-zoom';
|
|
214
279
|
|
|
215
280
|
function initDiagramPage() {
|
|
216
|
-
// Version selector
|
|
217
|
-
const versionSelect = document.getElementById('version-select') as HTMLSelectElement;
|
|
218
|
-
if (versionSelect) {
|
|
219
|
-
versionSelect.onchange = () => {
|
|
220
|
-
window.location.href = versionSelect.value;
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
281
|
// Compare modal (Scale) and Upgrade modal (non-Scale)
|
|
225
282
|
const compareBtn = document.getElementById('compare-btn') as HTMLButtonElement;
|
|
226
283
|
const compareModal = document.getElementById('compare-modal');
|
|
@@ -316,6 +373,99 @@ const chatQuery = `Tell me about the "${props.data.name}" diagram (version ${pro
|
|
|
316
373
|
document.addEventListener('astro:page-load', initDiagramPage);
|
|
317
374
|
</script>
|
|
318
375
|
|
|
376
|
+
<script>
|
|
377
|
+
// @ts-nocheck
|
|
378
|
+
function setupDiagramTocObserver() {
|
|
379
|
+
try {
|
|
380
|
+
const tocRoot = document.getElementById('eventcatalog-docs-sidebar');
|
|
381
|
+
if (!tocRoot) return;
|
|
382
|
+
|
|
383
|
+
const observerOptions = {
|
|
384
|
+
rootMargin: '0px 0px -40% 0px',
|
|
385
|
+
threshold: 0.1,
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
let observerPaused = false;
|
|
389
|
+
|
|
390
|
+
function highlightTocItem(id) {
|
|
391
|
+
tocRoot.querySelectorAll('.active-toc-item').forEach((link) => {
|
|
392
|
+
link.classList.remove('active-toc-item', 'toc-active-text', 'font-medium', 'toc-active-border');
|
|
393
|
+
link.classList.add('border-transparent');
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const tocLink = tocRoot.querySelector(`nav a[href="#${id}"]`);
|
|
397
|
+
if (tocLink) {
|
|
398
|
+
tocLink.classList.add('active-toc-item', 'toc-active-text', 'font-medium', 'toc-active-border');
|
|
399
|
+
tocLink.classList.remove('border-transparent');
|
|
400
|
+
|
|
401
|
+
setTimeout(() => {
|
|
402
|
+
tocLink.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
|
|
403
|
+
}, 10);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const observer = new IntersectionObserver((entries) => {
|
|
408
|
+
if (observerPaused) return;
|
|
409
|
+
|
|
410
|
+
entries.forEach((entry) => {
|
|
411
|
+
try {
|
|
412
|
+
const id = entry.target.getAttribute('id');
|
|
413
|
+
if (entry.isIntersecting && id) {
|
|
414
|
+
highlightTocItem(id);
|
|
415
|
+
}
|
|
416
|
+
} catch (entryError) {
|
|
417
|
+
console.error('Error processing intersection entry:', entryError);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}, observerOptions);
|
|
421
|
+
|
|
422
|
+
const prose = document.querySelector('.diagram-article.prose');
|
|
423
|
+
if (!prose) return;
|
|
424
|
+
|
|
425
|
+
const proseHeadings = prose.querySelectorAll('h1[id], h2[id], h3[id]');
|
|
426
|
+
|
|
427
|
+
if (proseHeadings.length > 0) {
|
|
428
|
+
proseHeadings.forEach((heading) => observer.observe(heading));
|
|
429
|
+
} else {
|
|
430
|
+
const allHeadings = prose.querySelectorAll('h1, h2, h3');
|
|
431
|
+
|
|
432
|
+
allHeadings.forEach((heading) => {
|
|
433
|
+
if (!heading.id) {
|
|
434
|
+
const text = heading.textContent || '';
|
|
435
|
+
const slug = text
|
|
436
|
+
.toLowerCase()
|
|
437
|
+
.replace(/[^\w\s-]/g, '')
|
|
438
|
+
.replace(/\s+/g, '-');
|
|
439
|
+
heading.id = slug;
|
|
440
|
+
}
|
|
441
|
+
observer.observe(heading);
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const tocLinks = tocRoot.querySelectorAll('nav a[href^="#"]');
|
|
446
|
+
tocLinks.forEach((link) => {
|
|
447
|
+
link.addEventListener('click', () => {
|
|
448
|
+
const hrefAttr = link.getAttribute('href');
|
|
449
|
+
if (!hrefAttr) return;
|
|
450
|
+
|
|
451
|
+
const id = hrefAttr.substring(1);
|
|
452
|
+
highlightTocItem(id);
|
|
453
|
+
observerPaused = true;
|
|
454
|
+
|
|
455
|
+
setTimeout(() => {
|
|
456
|
+
observerPaused = false;
|
|
457
|
+
}, 500);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
} catch (error) {
|
|
461
|
+
console.error('Error setting up diagram TOC highlighting:', error);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
setupDiagramTocObserver();
|
|
466
|
+
document.addEventListener('astro:page-load', setupDiagramTocObserver);
|
|
467
|
+
</script>
|
|
468
|
+
|
|
319
469
|
<script>
|
|
320
470
|
import { renderPlantUMLWithZoom } from '@utils/mermaid-zoom';
|
|
321
471
|
|