@eventcatalog/core 3.32.1 → 3.33.0

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.
Files changed (35) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-JJZ4XMYN.js → chunk-DN6F4AAQ.js} +1 -1
  6. package/dist/{chunk-CUTS7SO7.js → chunk-GBSBBBF5.js} +1 -1
  7. package/dist/{chunk-CC6EO52Y.js → chunk-TDRDRXOZ.js} +1 -1
  8. package/dist/{chunk-IQ7W6KWL.js → chunk-VRXBFCYB.js} +1 -1
  9. package/dist/{chunk-2AFDJJP4.js → chunk-YKTTWB2P.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.js +8 -8
  14. package/dist/generate.cjs +1 -1
  15. package/dist/generate.js +3 -3
  16. package/dist/utils/cli-logger.cjs +1 -1
  17. package/dist/utils/cli-logger.js +2 -2
  18. package/eventcatalog/src/components/MDX/Prompt/Prompt.astro +173 -0
  19. package/eventcatalog/src/components/MDX/Visibility.tsx +12 -0
  20. package/eventcatalog/src/components/MDX/components.tsx +4 -0
  21. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/[...path].mdx.ts +7 -3
  22. package/eventcatalog/src/pages/diagrams/[id]/[version].mdx.ts +3 -2
  23. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].md.ts +2 -1
  24. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].mdx.ts +2 -1
  25. package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +22 -13
  26. package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +34 -24
  27. package/eventcatalog/src/pages/docs/[type]/[id]/language.mdx.ts +9 -2
  28. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +2 -2
  29. package/eventcatalog/src/pages/docs/teams/[id].md.ts +4 -2
  30. package/eventcatalog/src/pages/docs/teams/[id].mdx.ts +4 -2
  31. package/eventcatalog/src/pages/docs/users/[id].md.ts +4 -2
  32. package/eventcatalog/src/pages/docs/users/[id].mdx.ts +4 -2
  33. package/eventcatalog/src/remark-plugins/directives.ts +43 -23
  34. package/eventcatalog/src/utils/llms.ts +22 -0
  35. package/package.json +3 -3
@@ -37,7 +37,7 @@ var import_axios = __toESM(require("axios"), 1);
37
37
  var import_os = __toESM(require("os"), 1);
38
38
 
39
39
  // package.json
40
- var version = "3.32.1";
40
+ var version = "3.33.0";
41
41
 
42
42
  // src/constants.ts
43
43
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-CC6EO52Y.js";
4
- import "../chunk-2AFDJJP4.js";
3
+ } from "../chunk-TDRDRXOZ.js";
4
+ import "../chunk-YKTTWB2P.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -111,7 +111,7 @@ var import_axios = __toESM(require("axios"), 1);
111
111
  var import_os = __toESM(require("os"), 1);
112
112
 
113
113
  // package.json
114
- var version = "3.32.1";
114
+ var version = "3.33.0";
115
115
 
116
116
  // src/constants.ts
117
117
  var VERSION = version;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-CUTS7SO7.js";
4
- import "../chunk-CC6EO52Y.js";
3
+ } from "../chunk-GBSBBBF5.js";
4
+ import "../chunk-TDRDRXOZ.js";
5
5
  import "../chunk-4UVFXLPI.js";
6
- import "../chunk-2AFDJJP4.js";
6
+ import "../chunk-YKTTWB2P.js";
7
7
  import "../chunk-5T63CXKU.js";
8
8
  export {
9
9
  log_build_default as default
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-2AFDJJP4.js";
3
+ } from "./chunk-YKTTWB2P.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-CC6EO52Y.js";
3
+ } from "./chunk-TDRDRXOZ.js";
4
4
  import {
5
5
  countResources,
6
6
  serializeCounts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-2AFDJJP4.js";
3
+ } from "./chunk-YKTTWB2P.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-JJZ4XMYN.js";
3
+ } from "./chunk-DN6F4AAQ.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "3.32.1";
2
+ var version = "3.33.0";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "3.32.1";
28
+ var version = "3.33.0";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-2AFDJJP4.js";
3
+ } from "./chunk-YKTTWB2P.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -114,7 +114,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
114
114
  var import_picocolors = __toESM(require("picocolors"), 1);
115
115
 
116
116
  // package.json
117
- var version = "3.32.1";
117
+ var version = "3.33.0";
118
118
 
119
119
  // src/constants.ts
120
120
  var VERSION = version;
@@ -1,18 +1,18 @@
1
+ import {
2
+ log_build_default
3
+ } from "./chunk-GBSBBBF5.js";
1
4
  import {
2
5
  resolve_catalog_dependencies_default
3
6
  } from "./chunk-WAJIJEI3.js";
4
7
  import {
5
8
  watch
6
9
  } from "./chunk-K3ZVEX2Y.js";
7
- import {
8
- log_build_default
9
- } from "./chunk-CUTS7SO7.js";
10
- import "./chunk-CC6EO52Y.js";
11
- import "./chunk-4UVFXLPI.js";
12
10
  import {
13
11
  runMigrations
14
12
  } from "./chunk-XUAF2H54.js";
15
13
  import "./chunk-CA4U2JP7.js";
14
+ import "./chunk-TDRDRXOZ.js";
15
+ import "./chunk-4UVFXLPI.js";
16
16
  import {
17
17
  catalogToAstro
18
18
  } from "./chunk-YDXB3BD2.js";
@@ -22,13 +22,13 @@ import {
22
22
  } from "./chunk-3KXCGYET.js";
23
23
  import {
24
24
  generate
25
- } from "./chunk-IQ7W6KWL.js";
25
+ } from "./chunk-VRXBFCYB.js";
26
26
  import {
27
27
  logger
28
- } from "./chunk-JJZ4XMYN.js";
28
+ } from "./chunk-DN6F4AAQ.js";
29
29
  import {
30
30
  VERSION
31
- } from "./chunk-2AFDJJP4.js";
31
+ } from "./chunk-YKTTWB2P.js";
32
32
  import {
33
33
  getEventCatalogConfigFile,
34
34
  verifyRequiredFieldsAreInCatalogConfigFile
package/dist/generate.cjs CHANGED
@@ -78,7 +78,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
78
78
  var import_picocolors = __toESM(require("picocolors"), 1);
79
79
 
80
80
  // package.json
81
- var version = "3.32.1";
81
+ var version = "3.33.0";
82
82
 
83
83
  // src/constants.ts
84
84
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-IQ7W6KWL.js";
4
- import "./chunk-JJZ4XMYN.js";
5
- import "./chunk-2AFDJJP4.js";
3
+ } from "./chunk-VRXBFCYB.js";
4
+ import "./chunk-DN6F4AAQ.js";
5
+ import "./chunk-YKTTWB2P.js";
6
6
  import "./chunk-5T63CXKU.js";
7
7
  export {
8
8
  generate
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "3.32.1";
39
+ var version = "3.33.0";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-JJZ4XMYN.js";
4
- import "../chunk-2AFDJJP4.js";
3
+ } from "../chunk-DN6F4AAQ.js";
4
+ import "../chunk-YKTTWB2P.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -0,0 +1,173 @@
1
+ ---
2
+ import { LUCIDE_ICON_MAP } from '@utils/icon-map';
3
+
4
+ type ActionType = 'copy' | 'cursor';
5
+
6
+ interface Props {
7
+ description: string;
8
+ actions?: ActionType[];
9
+ icon?: string;
10
+ }
11
+
12
+ const { description, actions = ['copy'], icon } = Astro.props;
13
+
14
+ const showCopy = actions.includes('copy');
15
+ const showCursor = actions.includes('cursor');
16
+
17
+ const toPascalCase = (input: string): string =>
18
+ input
19
+ .split(/[-_\s]+/)
20
+ .filter(Boolean)
21
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
22
+ .join('');
23
+
24
+ const Icon = icon ? (LUCIDE_ICON_MAP[toPascalCase(icon)] ?? null) : null;
25
+
26
+ // Render the slotted content to a string so we can use it as the prompt text
27
+ // (for clipboard + the Cursor deep link).
28
+ const slotHtml = await Astro.slots.render('default');
29
+ const promptText = (slotHtml ?? '')
30
+ .replace(/<[^>]+>/g, '')
31
+ .replace(/&nbsp;/g, ' ')
32
+ .replace(/&amp;/g, '&')
33
+ .replace(/&lt;/g, '<')
34
+ .replace(/&gt;/g, '>')
35
+ .replace(/&quot;/g, '"')
36
+ .replace(/&#39;/g, "'")
37
+ .trim();
38
+
39
+ const cursorUrl = `https://cursor.com/link/prompt?text=${encodeURIComponent(promptText)}`;
40
+ ---
41
+
42
+ <ec-prompt
43
+ class="not-prose my-4 block rounded-xl border border-[rgb(var(--ec-page-border))] bg-gray-50 dark:bg-[rgb(var(--ec-rail-bg))]"
44
+ data-prompt-text={promptText}
45
+ >
46
+ <div class="flex items-center gap-2.5 px-4 py-3">
47
+ {Icon && <Icon className="w-4 h-4 shrink-0 text-[rgb(var(--ec-page-text-muted))]" />}
48
+ <div class="flex-1 min-w-0">
49
+ <div class="text-sm font-medium text-[rgb(var(--ec-page-text))] leading-snug">{description}</div>
50
+ </div>
51
+ <div class="flex items-center gap-1.5 shrink-0">
52
+ {
53
+ showCopy && (
54
+ <button
55
+ type="button"
56
+ data-prompt-copy
57
+ data-copied="false"
58
+ aria-label="Copy prompt"
59
+ aria-live="polite"
60
+ class="ec-prompt-copy inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded-md border transition-all duration-150 border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] data-[copied=true]:border-emerald-500/70 data-[copied=true]:bg-emerald-50 data-[copied=true]:text-emerald-700 dark:data-[copied=true]:bg-emerald-950/50 dark:data-[copied=true]:text-emerald-300 dark:data-[copied=true]:border-emerald-500/60"
61
+ >
62
+ <span data-prompt-copy-idle class="inline-flex items-center gap-1.5">
63
+ <svg
64
+ xmlns="http://www.w3.org/2000/svg"
65
+ width="14"
66
+ height="14"
67
+ viewBox="0 0 24 24"
68
+ fill="none"
69
+ stroke="currentColor"
70
+ stroke-width="2"
71
+ stroke-linecap="round"
72
+ stroke-linejoin="round"
73
+ >
74
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
75
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
76
+ </svg>
77
+ <span>Copy</span>
78
+ </span>
79
+ <span data-prompt-copy-done class="inline-flex items-center gap-1.5" style="display:none;">
80
+ <svg
81
+ xmlns="http://www.w3.org/2000/svg"
82
+ width="14"
83
+ height="14"
84
+ viewBox="0 0 24 24"
85
+ fill="none"
86
+ stroke="currentColor"
87
+ stroke-width="2.5"
88
+ stroke-linecap="round"
89
+ stroke-linejoin="round"
90
+ >
91
+ <polyline points="20 6 9 17 4 12" />
92
+ </svg>
93
+ <span>Copied!</span>
94
+ </span>
95
+ </button>
96
+ )
97
+ }
98
+ {
99
+ showCursor && (
100
+ <a
101
+ href={cursorUrl}
102
+ target="_blank"
103
+ rel="noopener noreferrer"
104
+ aria-label="Open in Cursor"
105
+ class="inline-flex items-center gap-1.5 px-2 py-1 text-xs font-medium rounded-md border border-black bg-black !text-white hover:bg-black/85 transition-colors no-underline"
106
+ >
107
+ <svg
108
+ height="1em"
109
+ width="1em"
110
+ viewBox="0 0 16 16"
111
+ xmlns="http://www.w3.org/2000/svg"
112
+ aria-hidden="true"
113
+ class="w-3 h-3 shrink-0"
114
+ >
115
+ <path
116
+ fill="currentColor"
117
+ d="M14.4734 3.9527L8.31773 0.398522C8.22052 0.342485 8.11029 0.312988 7.99809 0.312988C7.88589 0.312988 7.77566 0.342485 7.67846 0.398522L1.52355 3.9527C1.44182 3.99989 1.37394 4.06773 1.32671 4.14942C1.27948 4.23112 1.25457 4.32379 1.25446 4.41816V11.584C1.25457 11.6783 1.27948 11.771 1.32671 11.8527C1.37394 11.9344 1.44182 12.0022 1.52355 12.0494L7.67918 15.6036C7.77636 15.6597 7.8866 15.6893 7.99882 15.6893C8.11103 15.6893 8.22127 15.6597 8.31846 15.6036L14.4741 12.0502C14.5558 12.003 14.6237 11.9351 14.6709 11.8534C14.7182 11.7717 14.7431 11.6791 14.7432 11.5847V4.41743C14.7431 4.32307 14.7182 4.23039 14.6709 4.14869C14.6237 4.067 14.5558 3.99916 14.4741 3.95198L14.4734 3.9527ZM14.0872 4.70543L8.14464 14.9978C8.10464 15.0669 7.99846 15.0385 7.99846 14.9578V8.21889C7.99841 8.15254 7.98092 8.08738 7.94773 8.02993C7.91454 7.97249 7.86682 7.92478 7.80936 7.89161L1.97373 4.52361C1.90391 4.48289 1.93227 4.3767 2.013 4.3767H13.8966C14.0661 4.3767 14.1715 4.55925 14.0872 4.70543Z"
118
+ />
119
+ </svg>
120
+ <span>Open in Cursor</span>
121
+ </a>
122
+ )
123
+ }
124
+ </div>
125
+ </div>
126
+ <div hidden><slot /></div>
127
+ </ec-prompt>
128
+
129
+ <script>
130
+ if (!customElements.get('ec-prompt')) {
131
+ class ECPromptElement extends HTMLElement {
132
+ private resetTimer: number | null = null;
133
+ private button: HTMLButtonElement | null = null;
134
+ private boundHandler = this.handleCopy.bind(this);
135
+
136
+ connectedCallback() {
137
+ this.button = this.querySelector<HTMLButtonElement>('[data-prompt-copy]');
138
+ this.button?.addEventListener('click', this.boundHandler);
139
+ }
140
+
141
+ disconnectedCallback() {
142
+ this.button?.removeEventListener('click', this.boundHandler);
143
+ if (this.resetTimer != null) {
144
+ window.clearTimeout(this.resetTimer);
145
+ this.resetTimer = null;
146
+ }
147
+ }
148
+
149
+ private async handleCopy() {
150
+ const text = this.dataset.promptText ?? '';
151
+ try {
152
+ await navigator.clipboard.writeText(text);
153
+ } catch {
154
+ return;
155
+ }
156
+ this.setCopied(true);
157
+ if (this.resetTimer != null) window.clearTimeout(this.resetTimer);
158
+ this.resetTimer = window.setTimeout(() => this.setCopied(false), 1500);
159
+ }
160
+
161
+ private setCopied(copied: boolean) {
162
+ if (!this.button) return;
163
+ this.button.dataset.copied = copied ? 'true' : 'false';
164
+ this.button.setAttribute('aria-label', copied ? 'Copied to clipboard' : 'Copy prompt');
165
+ const idle = this.button.querySelector<HTMLElement>('[data-prompt-copy-idle]');
166
+ const done = this.button.querySelector<HTMLElement>('[data-prompt-copy-done]');
167
+ if (idle) idle.style.display = copied ? 'none' : '';
168
+ if (done) done.style.display = copied ? '' : 'none';
169
+ }
170
+ }
171
+ customElements.define('ec-prompt', ECPromptElement);
172
+ }
173
+ </script>
@@ -0,0 +1,12 @@
1
+ type VisibilityProps = {
2
+ for: 'agents' | 'humans';
3
+ children?: any;
4
+ };
5
+
6
+ const Visibility = ({ for: audience, children }: VisibilityProps) => {
7
+ if (audience !== 'humans') return null;
8
+
9
+ return <>{children}</>;
10
+ };
11
+
12
+ export default Visibility;
@@ -10,6 +10,7 @@ import Tile from '@components/MDX/Tiles/Tile.astro';
10
10
  import Steps from '@components/MDX/Steps/Steps.astro';
11
11
  import Step from '@components/MDX/Steps/Step.astro';
12
12
  import Admonition from '@components/MDX/Admonition';
13
+ import Prompt from '@components/MDX/Prompt/Prompt.astro';
13
14
  import OpenAPI from '@components/MDX/OpenAPI/OpenAPI.astro';
14
15
  import AsyncAPI from '@components/MDX/AsyncAPI/AsyncAPI.astro';
15
16
  import ChannelInformation from '@components/MDX/ChannelInformation/ChannelInformation';
@@ -34,6 +35,7 @@ import NodeGraphPortal from '@components/MDX/NodeGraph/NodeGraphPortal';
34
35
  import SchemaViewerPortal from '@components/MDX/SchemaViewer/SchemaViewerPortal';
35
36
  import { jsx } from 'astro/jsx-runtime';
36
37
  import RemoteSchema from '@components/MDX/RemoteSchema.astro';
38
+ import Visibility from '@components/MDX/Visibility';
37
39
 
38
40
  const components = (props: any) => {
39
41
  return {
@@ -53,6 +55,7 @@ const components = (props: any) => {
53
55
  NodeGraph: (mdxProp: any) => jsx(NodeGraphPortal, { ...props.data, ...mdxProp, props, mdxProp }),
54
56
  EntityMap: (mdxProp: any) => jsx(EntityMap, { ...props, ...mdxProp }),
55
57
  OpenAPI,
58
+ Prompt: (mdxProp: any) => jsx(Prompt, { ...props, ...mdxProp }),
56
59
  ResourceGroupTable: (mdxProp: any) => jsx(ResourceGroupTable, { ...props, ...mdxProp }),
57
60
  ResourceLink: (mdxProp: any) => jsx(ResourceLink, { ...props, ...mdxProp }),
58
61
  ResourceRef: (mdxProp: any) => jsx(ResourceRef, { ...props, ...mdxProp }),
@@ -64,6 +67,7 @@ const components = (props: any) => {
64
67
  Tabs,
65
68
  Tile,
66
69
  Tiles,
70
+ Visibility,
67
71
  Miro: (mdxProp: any) => jsx(Miro, { ...props, ...mdxProp }),
68
72
  Lucid: (mdxProp: any) => jsx(Lucid, { ...props, ...mdxProp }),
69
73
  DrawIO: (mdxProp: any) => jsx(DrawIO, { ...props, ...mdxProp }),
@@ -6,9 +6,11 @@ import type { APIRoute, GetStaticPaths } from 'astro';
6
6
  import { getCollection } from 'astro:content';
7
7
  import fs from 'fs';
8
8
  import { isLLMSTxtEnabled } from '@utils/feature';
9
+ import { filterMarkdownForAgents } from '@utils/llms';
10
+
11
+ const docs = await getCollection('customPages');
9
12
 
10
13
  export const getStaticPaths = (async () => {
11
- const docs = await getCollection('customPages');
12
14
  const paths = docs.map((doc) => ({
13
15
  params: { path: doc.id.replace('docs/', '') },
14
16
  props: doc,
@@ -23,8 +25,10 @@ export const GET: APIRoute = async ({ params, props }) => {
23
25
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
24
26
  }
25
27
 
26
- if (props.filePath) {
27
- const file = fs.readFileSync(props.filePath, 'utf8');
28
+ const docPath = Array.isArray(params.path) ? params.path.join('/') : params.path;
29
+ const content = props?.filePath ? props : docs.find((doc) => doc.id.replace('docs/', '') === docPath);
30
+ if (content?.filePath) {
31
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
28
32
  return new Response(file, { status: 200 });
29
33
  }
30
34
 
@@ -7,6 +7,7 @@ import type { APIRoute } from 'astro';
7
7
  import { getCollection } from 'astro:content';
8
8
  import fs from 'fs';
9
9
  import { isLLMSTxtEnabled, isSSR } from '@utils/feature';
10
+ import { filterMarkdownForAgents } from '@utils/llms';
10
11
 
11
12
  const diagrams = await getCollection('diagrams');
12
13
 
@@ -34,11 +35,11 @@ export const GET: APIRoute = async ({ params, props }) => {
34
35
  if (!diagram?.filePath) {
35
36
  return new Response('Not found', { status: 404 });
36
37
  }
37
- const file = fs.readFileSync(diagram.filePath, 'utf8');
38
+ const file = filterMarkdownForAgents(fs.readFileSync(diagram.filePath, 'utf8'));
38
39
  return new Response(file, { status: 200 });
39
40
  } else {
40
41
  if (props?.content?.filePath) {
41
- const file = fs.readFileSync(props.content.filePath, 'utf8');
42
+ const file = filterMarkdownForAgents(fs.readFileSync(props.content.filePath, 'utf8'));
42
43
  return new Response(file, { status: 200 });
43
44
  }
44
45
  }
@@ -6,6 +6,7 @@ import type { APIRoute } from 'astro';
6
6
  import fs from 'fs';
7
7
  import { isLLMSTxtEnabled, isResourceDocsEnabled, isSSR } from '@utils/feature';
8
8
  import { getResourceDocs, getResourceDocsForResource, type ResourceCollection } from '@utils/collections/resource-docs';
9
+ import { filterMarkdownForAgents } from '@utils/llms';
9
10
 
10
11
  const supportedResourceCollections = new Set<ResourceCollection>([
11
12
  'domains',
@@ -70,6 +71,6 @@ export const GET: APIRoute = async ({ params, props }) => {
70
71
  return new Response('Not found', { status: 404 });
71
72
  }
72
73
 
73
- const file = fs.readFileSync(filePath, 'utf8');
74
+ const file = filterMarkdownForAgents(fs.readFileSync(filePath, 'utf8'));
74
75
  return new Response(file, { status: 200, headers: { 'Content-Type': 'text/markdown; charset=utf-8' } });
75
76
  };
@@ -6,6 +6,7 @@ import type { APIRoute } from 'astro';
6
6
  import fs from 'fs';
7
7
  import { isLLMSTxtEnabled, isResourceDocsEnabled, isSSR } from '@utils/feature';
8
8
  import { getResourceDocs, getResourceDocsForResource, type ResourceCollection } from '@utils/collections/resource-docs';
9
+ import { filterMarkdownForAgents } from '@utils/llms';
9
10
 
10
11
  const supportedResourceCollections = new Set<ResourceCollection>([
11
12
  'domains',
@@ -70,6 +71,6 @@ export const GET: APIRoute = async ({ params, props }) => {
70
71
  return new Response('Not found', { status: 404 });
71
72
  }
72
73
 
73
- const file = fs.readFileSync(filePath, 'utf8');
74
+ const file = filterMarkdownForAgents(fs.readFileSync(filePath, 'utf8'));
74
75
  return new Response(file, { status: 200, headers: { 'Content-Type': 'text/markdown; charset=utf-8' } });
75
76
  };
@@ -8,6 +8,7 @@ import { getEntities } from '@utils/collections/entities';
8
8
  import config from '@config';
9
9
  import fs from 'fs';
10
10
  import { isLLMSTxtEnabled } from '@utils/feature';
11
+ import { filterMarkdownForAgents } from '@utils/llms';
11
12
 
12
13
  const events = await getCollection('events');
13
14
  const commands = await getCollection('commands');
@@ -18,23 +19,30 @@ const flows = await getCollection('flows');
18
19
  const channels = await getCollection('channels');
19
20
  const containers = await getCollection('containers');
20
21
  const entities = await getEntities();
22
+
23
+ const collections = {
24
+ events,
25
+ commands,
26
+ queries,
27
+ services,
28
+ domains,
29
+ flows,
30
+ channels,
31
+ containers,
32
+ entities,
33
+ };
34
+
35
+ const findContent = (params: Record<string, string | undefined>) => {
36
+ const collection = collections[params.type as keyof typeof collections];
37
+ return collection?.find((item: any) => item.data.id === params.id && item.data.version === params.version);
38
+ };
39
+
21
40
  export async function getStaticPaths() {
22
41
  // Just return empty array if LLMs are not enabled
23
42
  if (!isLLMSTxtEnabled()) {
24
43
  return [];
25
44
  }
26
45
 
27
- const collections = {
28
- events,
29
- commands,
30
- queries,
31
- services,
32
- domains,
33
- flows,
34
- channels,
35
- containers,
36
- entities,
37
- };
38
46
  const paths = Object.keys(collections).map((type) => {
39
47
  return collections[type as keyof typeof collections].map((item: { data: { id: string; version: string } }) => ({
40
48
  params: { type, id: item.data.id, version: item.data.version },
@@ -51,8 +59,9 @@ export const GET: APIRoute = async ({ params, props }) => {
51
59
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
52
60
  }
53
61
 
54
- if (props?.content?.filePath) {
55
- const file = fs.readFileSync(props.content.filePath, 'utf8');
62
+ const content = props?.content ?? findContent(params);
63
+ if (content?.filePath) {
64
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
56
65
  return new Response(file, { status: 200 });
57
66
  }
58
67
 
@@ -6,7 +6,7 @@ import type { APIRoute } from 'astro';
6
6
  import { getCollection } from 'astro:content';
7
7
  import config from '@config';
8
8
  import fs from 'fs';
9
- import { addSchemaToMarkdown } from '@utils/llms';
9
+ import { addSchemaToMarkdown, filterMarkdownForAgents } from '@utils/llms';
10
10
  import { isLLMSTxtEnabled, isSSR } from '@utils/feature';
11
11
  const events = await getCollection('events');
12
12
  const commands = await getCollection('commands');
@@ -15,25 +15,34 @@ const services = await getCollection('services');
15
15
  const domains = await getCollection('domains');
16
16
  const flows = await getCollection('flows');
17
17
  const channels = await getCollection('channels');
18
+ const containers = await getCollection('containers');
18
19
  const entities = await getCollection('entities');
19
20
 
20
21
  import utils from '@eventcatalog/sdk';
21
22
 
23
+ const collections = {
24
+ events,
25
+ commands,
26
+ queries,
27
+ services,
28
+ domains,
29
+ flows,
30
+ channels,
31
+ containers,
32
+ entities,
33
+ };
34
+
35
+ const findContent = (params: Record<string, string | undefined>) => {
36
+ const collection = collections[params.type as keyof typeof collections];
37
+ return collection?.find((item) => item.data.id === params.id && item.data.version === params.version);
38
+ };
39
+
22
40
  export async function getStaticPaths() {
23
41
  // Just return empty array if LLMs are not enabled
24
42
  if (!isLLMSTxtEnabled()) {
25
43
  return [];
26
44
  }
27
- const collections = {
28
- events,
29
- commands,
30
- queries,
31
- services,
32
- domains,
33
- flows,
34
- channels,
35
- entities,
36
- };
45
+
37
46
  const paths = Object.keys(collections).map((type) => {
38
47
  return collections[type as keyof typeof collections].map((item: { data: { id: string; version: string } }) => ({
39
48
  params: { type, id: item.data.id, version: item.data.version },
@@ -50,26 +59,27 @@ export const GET: APIRoute = async ({ params, props }) => {
50
59
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
51
60
  }
52
61
 
62
+ const content = props?.content ?? findContent(params);
63
+ if (content?.filePath) {
64
+ let file = fs.readFileSync(content.filePath, 'utf8');
65
+
66
+ try {
67
+ file = addSchemaToMarkdown(content, file);
68
+ } catch (error) {
69
+ console.log('Warning: Cant find the schema for', content.data.id, content.data.version);
70
+ }
71
+
72
+ return new Response(filterMarkdownForAgents(file), { status: 200 });
73
+ }
74
+
53
75
  if (isSSR()) {
54
76
  const { getResourcePath } = utils(process.env.PROJECT_DIR ?? '');
55
77
  const filePath = await getResourcePath(process.env.PROJECT_DIR ?? '', params.id ?? '', params.version ?? '');
56
78
  if (!filePath) {
57
79
  return new Response('Not found', { status: 404 });
58
80
  }
59
- const file = fs.readFileSync(filePath.fullPath, 'utf8');
81
+ const file = filterMarkdownForAgents(fs.readFileSync(filePath.fullPath, 'utf8'));
60
82
  return new Response(file, { status: 200 });
61
- } else {
62
- if (props?.content?.filePath) {
63
- let file = fs.readFileSync(props.content.filePath, 'utf8');
64
-
65
- try {
66
- file = addSchemaToMarkdown(props.content, file);
67
- } catch (error) {
68
- console.log('Warning: Cant find the schema for', props.content.data.id, props.content.data.version);
69
- }
70
-
71
- return new Response(file, { status: 200 });
72
- }
73
83
  }
74
84
 
75
85
  return new Response('Not found', { status: 404 });
@@ -4,6 +4,7 @@ import type { APIRoute } from 'astro';
4
4
  import config from '@config';
5
5
  import fs from 'fs';
6
6
  import { isLLMSTxtEnabled } from '@utils/feature';
7
+ import { filterMarkdownForAgents } from '@utils/llms';
7
8
 
8
9
  export async function getStaticPaths() {
9
10
  const domains = await getDomains({ getAllVersions: false });
@@ -30,11 +31,17 @@ export const GET: APIRoute = async ({ params, props }) => {
30
31
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
31
32
  }
32
33
 
33
- const ubiquitousLanguages = await getUbiquitousLanguage(props as CollectionEntry<'domains'>);
34
+ const domains = await getDomains({ getAllVersions: false });
35
+ const domain = props?.data ? (props as CollectionEntry<'domains'>) : domains.find((item) => item.data.id === params.id);
36
+ if (!domain) {
37
+ return new Response('Not found', { status: 404 });
38
+ }
39
+
40
+ const ubiquitousLanguages = await getUbiquitousLanguage(domain as CollectionEntry<'domains'>);
34
41
  const ubiquitousLanguage = ubiquitousLanguages[0];
35
42
 
36
43
  if (ubiquitousLanguage?.filePath) {
37
- let file = fs.readFileSync(ubiquitousLanguage.filePath, 'utf8');
44
+ let file = filterMarkdownForAgents(fs.readFileSync(ubiquitousLanguage.filePath, 'utf8'));
38
45
 
39
46
  return new Response(file, { status: 200 });
40
47
  }
@@ -2,7 +2,7 @@ import { getCollection, type CollectionEntry } from 'astro:content';
2
2
  import type { APIRoute } from 'astro';
3
3
  import fs from 'fs';
4
4
  import { isCustomDocsEnabled, isResourceDocsEnabled, isLLMSTxtEnabled } from '@utils/feature';
5
- import { addSchemaToMarkdown } from '@utils/llms';
5
+ import { addSchemaToMarkdown, filterMarkdownForAgents } from '@utils/llms';
6
6
 
7
7
  type AllowedCollections =
8
8
  | 'events'
@@ -74,7 +74,7 @@ export const GET: APIRoute = async ({ params, request }) => {
74
74
  // just skip the resource if it has no schema
75
75
  }
76
76
 
77
- return file;
77
+ return filterMarkdownForAgents(file);
78
78
  })
79
79
  .join('\n');
80
80
 
@@ -7,6 +7,7 @@ import { getCollection } from 'astro:content';
7
7
  import config from '@config';
8
8
  import fs from 'fs';
9
9
  import { isLLMSTxtEnabled } from '@utils/feature';
10
+ import { filterMarkdownForAgents } from '@utils/llms';
10
11
 
11
12
  const teams = await getCollection('teams');
12
13
 
@@ -28,8 +29,9 @@ export const GET: APIRoute = async ({ params, props }) => {
28
29
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
29
30
  }
30
31
 
31
- if (props?.content?.filePath) {
32
- const file = fs.readFileSync(props.content.filePath, 'utf8');
32
+ const content = props?.content ?? teams.find((team) => team.data.id === params.id);
33
+ if (content?.filePath) {
34
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
33
35
  return new Response(file, { status: 200 });
34
36
  }
35
37
 
@@ -6,6 +6,7 @@ import type { APIRoute } from 'astro';
6
6
  import { getCollection } from 'astro:content';
7
7
  import { isLLMSTxtEnabled } from '@utils/feature';
8
8
  import fs from 'fs';
9
+ import { filterMarkdownForAgents } from '@utils/llms';
9
10
 
10
11
  const teams = await getCollection('teams');
11
12
 
@@ -27,8 +28,9 @@ export const GET: APIRoute = async ({ params, props }) => {
27
28
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
28
29
  }
29
30
 
30
- if (props?.content?.filePath) {
31
- const file = fs.readFileSync(props.content.filePath, 'utf8');
31
+ const content = props?.content ?? teams.find((team) => team.data.id === params.id);
32
+ if (content?.filePath) {
33
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
32
34
  return new Response(file, { status: 200 });
33
35
  }
34
36
 
@@ -7,6 +7,7 @@ import { getCollection } from 'astro:content';
7
7
  import config from '@config';
8
8
  import fs from 'fs';
9
9
  import { isLLMSTxtEnabled } from '@utils/feature';
10
+ import { filterMarkdownForAgents } from '@utils/llms';
10
11
 
11
12
  const users = await getCollection('users');
12
13
 
@@ -28,8 +29,9 @@ export const GET: APIRoute = async ({ params, props }) => {
28
29
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
29
30
  }
30
31
 
31
- if (props?.content?.filePath) {
32
- const file = fs.readFileSync(props.content?.filePath, 'utf8');
32
+ const content = props?.content ?? users.find((user) => user.data.id === params.id);
33
+ if (content?.filePath) {
34
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
33
35
  return new Response(file, { status: 200 });
34
36
  }
35
37
 
@@ -6,6 +6,7 @@ import type { APIRoute } from 'astro';
6
6
  import { getCollection } from 'astro:content';
7
7
  import { isLLMSTxtEnabled } from '@utils/feature';
8
8
  import fs from 'fs';
9
+ import { filterMarkdownForAgents } from '@utils/llms';
9
10
 
10
11
  const users = await getCollection('users');
11
12
 
@@ -27,8 +28,9 @@ export const GET: APIRoute = async ({ params, props }) => {
27
28
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
28
29
  }
29
30
 
30
- if (props?.content?.filePath) {
31
- const file = fs.readFileSync(props.content?.filePath, 'utf8');
31
+ const content = props?.content ?? users.find((user) => user.data.id === params.id);
32
+ if (content?.filePath) {
33
+ const file = filterMarkdownForAgents(fs.readFileSync(content.filePath, 'utf8'));
32
34
  return new Response(file, { status: 200 });
33
35
  }
34
36
 
@@ -5,29 +5,48 @@ export function remarkDirectives() {
5
5
  return (tree: any) => {
6
6
  visit(tree, (node) => {
7
7
  if (node.type === 'containerDirective') {
8
+ // Subtle, tinted backgrounds with a coloured left bar and icon.
9
+ // Body text inherits the page's normal text colour for readability.
8
10
  const blockTypes = {
9
- info: 'bg-blue-50 dark:bg-blue-950/50 border-l-4 border-blue-500 text-blue-700 dark:text-blue-200',
10
- warning: 'bg-yellow-50 dark:bg-yellow-950/50 border-l-4 border-yellow-500 text-yellow-700 dark:text-yellow-200',
11
- danger: 'bg-red-50 dark:bg-red-950/50 border-l-4 border-red-500 text-red-700 dark:text-red-200',
12
- tip: 'bg-green-50 dark:bg-green-950/50 border-l-4 border-green-500 text-green-700 dark:text-green-200',
13
- note: 'bg-gray-50 dark:bg-gray-950/50 border-l-4 border-gray-500 text-gray-700 dark:text-gray-200',
11
+ info: 'ec-admonition ec-admonition--info bg-blue-50/60 dark:bg-blue-950/30 border border-blue-200/70 dark:border-blue-900/60',
12
+ warning:
13
+ 'ec-admonition ec-admonition--warning bg-amber-50/60 dark:bg-amber-950/30 border border-amber-200/70 dark:border-amber-900/60',
14
+ danger:
15
+ 'ec-admonition ec-admonition--danger bg-red-50/60 dark:bg-red-950/30 border border-red-200/70 dark:border-red-900/60',
16
+ tip: 'ec-admonition ec-admonition--tip bg-emerald-50/60 dark:bg-emerald-900/40 border border-emerald-200/70 dark:border-emerald-700/80',
17
+ note: 'ec-admonition ec-admonition--note bg-slate-50/70 dark:bg-slate-900/40 border border-slate-200/70 dark:border-slate-700/60',
14
18
  };
15
19
 
16
- // Lucide icon paths
20
+ // Distinct Lucide icons per intent (warning vs danger no longer share).
17
21
  const iconPaths = {
18
- info: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
19
- warning:
20
- 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z',
21
- danger:
22
- 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z',
23
- tip: 'M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z',
24
- note: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z',
22
+ // Info circle with "i"
23
+ info: 'M12 2a10 10 0 100 20 10 10 0 000-20zM12 8h.01M11 12h1v4h1',
24
+ // Warning triangle with !
25
+ warning: 'M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0zM12 9v4 M12 17h.01',
26
+ // Danger octagon with !
27
+ danger: 'M7.86 2h8.28L22 7.86v8.28L16.14 22H7.86L2 16.14V7.86L7.86 2z M12 8v4 M12 16h.01',
28
+ // Tip lightbulb
29
+ tip: 'M9 18h6 M10 22h4 M12 2a7 7 0 0 0-4 12.74V17h8v-2.26A7 7 0 0 0 12 2z',
30
+ // Note — pencil-line
31
+ note: 'M12 20h9 M16.5 3.5a2.121 2.121 0 1 1 3 3L7 19l-4 1 1-4 12.5-12.5z',
25
32
  };
26
33
 
34
+ // Coloured icon + title classes (intent accent colours).
35
+ const accentTextClasses = {
36
+ info: 'text-blue-700 dark:text-blue-300',
37
+ warning: 'text-amber-700 dark:text-amber-300',
38
+ danger: 'text-red-700 dark:text-red-300',
39
+ tip: 'text-emerald-700 dark:text-emerald-300',
40
+ note: 'text-slate-600 dark:text-slate-300',
41
+ };
42
+
43
+ const intent = node.name as keyof typeof blockTypes;
44
+ const accentClass = accentTextClasses[intent] || accentTextClasses.note;
45
+
27
46
  node.data = node.data || {};
28
47
  node.data.hName = 'div';
29
48
  node.data.hProperties = {
30
- class: `rounded-lg p-4 my-4 ${blockTypes[node.name as keyof typeof blockTypes] || ''}`,
49
+ class: `rounded-md px-3 py-2.5 my-4 text-[0.85rem] leading-relaxed ${blockTypes[intent] || ''}`,
31
50
  };
32
51
 
33
52
  // Check if there's a custom title (label) provided via :::note[Custom Title]
@@ -62,26 +81,26 @@ export function remarkDirectives() {
62
81
  data: {
63
82
  hName: 'div',
64
83
  hProperties: {
65
- class: 'flex items-center gap-2 font-semibold mb-2',
84
+ class: `flex items-center gap-1.5 mb-1 ${accentClass}`,
66
85
  },
67
86
  },
68
87
  children: [
69
- // Lucide Icon SVG
88
+ // Lucide Icon SVG (smaller, accent-coloured)
70
89
  {
71
90
  type: 'element',
72
91
  data: {
73
92
  hName: 'svg',
74
93
  hProperties: {
75
94
  xmlns: 'http://www.w3.org/2000/svg',
76
- width: '26',
77
- height: '26',
95
+ width: '14',
96
+ height: '14',
78
97
  viewBox: '0 0 24 24',
79
98
  fill: 'none',
80
99
  stroke: 'currentColor',
81
- strokeWidth: '2',
100
+ strokeWidth: '2.25',
82
101
  strokeLinecap: 'round',
83
102
  strokeLinejoin: 'round',
84
- class: 'lucide',
103
+ class: 'lucide shrink-0',
85
104
  },
86
105
  },
87
106
  children: [
@@ -96,13 +115,13 @@ export function remarkDirectives() {
96
115
  },
97
116
  ],
98
117
  },
99
- // Title (with support for markdown)
118
+ // Title small, uppercase, tracked
100
119
  {
101
120
  type: 'element',
102
121
  data: {
103
122
  hName: 'span',
104
123
  hProperties: {
105
- class: '',
124
+ class: 'text-[0.7rem] font-semibold uppercase tracking-wider',
106
125
  },
107
126
  },
108
127
  children: titleChildren,
@@ -116,7 +135,8 @@ export function remarkDirectives() {
116
135
  data: {
117
136
  hName: 'div',
118
137
  hProperties: {
119
- class: 'prose prose-md dark:prose-invert w-full max-w-none! prose-p:my-1 prose-p:text-inherit',
138
+ class:
139
+ 'prose prose-sm dark:prose-invert w-full max-w-none! prose-p:my-0.5 prose-p:text-inherit prose-p:text-[0.85rem] prose-p:leading-relaxed prose-code:text-[0.8rem]',
120
140
  },
121
141
  },
122
142
  children: contentChildren,
@@ -33,3 +33,25 @@ export const addSchemaToMarkdown = (collection: CollectionEntry<CollectionTypes>
33
33
 
34
34
  return file;
35
35
  };
36
+
37
+ type VisibilityAudience = 'agents' | 'humans';
38
+
39
+ const visibilityPattern =
40
+ /(?:\r?\n){0,2}<Visibility\b(?=[^>]*\bfor=(?:"agents"|'agents'|{["']agents["']}|"humans"|'humans'|{["']humans["']}))[^>]*\bfor=(?:"(agents|humans)"|'(agents|humans)'|{["'](agents|humans)["']})[^>]*>\s*([\s\S]*?)\s*<\/Visibility>(?:\r?\n){0,2}/g;
41
+
42
+ export const filterMarkdownForAudience = (file: string, audience: VisibilityAudience) => {
43
+ visibilityPattern.lastIndex = 0;
44
+ if (!visibilityPattern.test(file)) {
45
+ return file;
46
+ }
47
+ visibilityPattern.lastIndex = 0;
48
+
49
+ return file
50
+ .replace(visibilityPattern, (_match, doubleQuoted, singleQuoted, expressionQuoted, content) => {
51
+ const visibilityAudience = doubleQuoted || singleQuoted || expressionQuoted;
52
+ return visibilityAudience === audience ? `\n\n${content.trim()}\n\n` : '\n\n';
53
+ })
54
+ .trim();
55
+ };
56
+
57
+ export const filterMarkdownForAgents = (file: string) => filterMarkdownForAudience(file, 'agents');
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "3.32.1",
10
+ "version": "3.33.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -106,8 +106,8 @@
106
106
  "uuid": "^10.0.0",
107
107
  "zod": "^4.3.6",
108
108
  "@eventcatalog/linter": "1.0.22",
109
- "@eventcatalog/visualiser": "^3.20.0",
110
- "@eventcatalog/sdk": "2.21.0"
109
+ "@eventcatalog/sdk": "2.21.0",
110
+ "@eventcatalog/visualiser": "^3.20.0"
111
111
  },
112
112
  "devDependencies": {
113
113
  "@astrojs/check": "^0.9.8",