@eventcatalog/core 5.0.0-beta.14 → 5.0.0-beta.16

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 (31) 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/catalog-runtime.cjs +1 -1
  6. package/dist/{chunk-4KE3EUDJ.js → chunk-3GABQPQZ.js} +1 -1
  7. package/dist/{chunk-WY6M3RPT.js → chunk-3ZZK2SD5.js} +1 -1
  8. package/dist/{chunk-PI5YNZZZ.js → chunk-DTUGKNST.js} +1 -1
  9. package/dist/{chunk-OFK7U7BX.js → chunk-FQMVEUYE.js} +1 -1
  10. package/dist/{chunk-I3XDOICA.js → chunk-X5Z67IFB.js} +1 -1
  11. package/dist/constants.cjs +1 -1
  12. package/dist/constants.js +1 -1
  13. package/dist/eventcatalog.cjs +2 -2
  14. package/dist/eventcatalog.js +5 -5
  15. package/dist/generate.cjs +1 -1
  16. package/dist/generate.js +3 -3
  17. package/dist/runtime-dependencies/htmlparser2.mjs +3 -0
  18. package/dist/runtime-dependencies/manifest.json +2 -0
  19. package/dist/runtime-dependencies/react-syntax-highlighter__dist__cjs__create-element.js.mjs +3 -0
  20. package/dist/utils/cli-logger.cjs +1 -1
  21. package/dist/utils/cli-logger.js +2 -2
  22. package/eventcatalog/astro.config.mjs +5 -0
  23. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +2 -0
  24. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +2 -0
  25. package/eventcatalog/src/components/SchemaExplorer/SchemaCodeModal.tsx +2 -0
  26. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +2 -0
  27. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +10 -0
  28. package/eventcatalog/src/utils/link-validation.ts +25 -19
  29. package/eventcatalog/src/utils/node-graphs/layout-node-graph.ts +20 -1
  30. package/eventcatalog/src/utils/syntax-highlighter-renderer.ts +64 -0
  31. package/package.json +8 -7
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(analytics_exports);
36
36
  var import_os = __toESM(require("os"), 1);
37
37
 
38
38
  // package.json
39
- var version = "5.0.0-beta.14";
39
+ var version = "5.0.0-beta.16";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-PI5YNZZZ.js";
3
+ } from "../chunk-DTUGKNST.js";
4
4
  import "../chunk-CPW6G62V.js";
5
- import "../chunk-I3XDOICA.js";
5
+ import "../chunk-X5Z67IFB.js";
6
6
  export {
7
7
  raiseEvent
8
8
  };
@@ -176,7 +176,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
176
176
  var import_os = __toESM(require("os"), 1);
177
177
 
178
178
  // package.json
179
- var version = "5.0.0-beta.14";
179
+ var version = "5.0.0-beta.16";
180
180
 
181
181
  // src/constants.ts
182
182
  var VERSION = version;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-WY6M3RPT.js";
3
+ } from "../chunk-3ZZK2SD5.js";
4
4
  import "../chunk-AWOO63ME.js";
5
5
  import "../chunk-ZAZHAVKB.js";
6
- import "../chunk-PI5YNZZZ.js";
6
+ import "../chunk-DTUGKNST.js";
7
7
  import "../chunk-CPW6G62V.js";
8
- import "../chunk-I3XDOICA.js";
8
+ import "../chunk-X5Z67IFB.js";
9
9
  import "../chunk-RFIXKATC.js";
10
10
  export {
11
11
  log_build_default as default
@@ -36,7 +36,7 @@ __export(catalog_runtime_exports, {
36
36
  });
37
37
  module.exports = __toCommonJS(catalog_runtime_exports);
38
38
 
39
- // ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.7.0_postcss@8.5.29_tsx@4.23.15_typescript@5.9.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js
39
+ // ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.7.0_postcss@8.5.29_tsx@4.23.15_typescript@5.9.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js
40
40
  var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
41
41
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
42
42
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-OFK7U7BX.js";
3
+ } from "./chunk-FQMVEUYE.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-ZAZHAVKB.js";
9
9
  import {
10
10
  raiseEvent
11
- } from "./chunk-PI5YNZZZ.js";
11
+ } from "./chunk-DTUGKNST.js";
12
12
  import {
13
13
  TELEMETRY_REQUEST_TIMEOUT_MS,
14
14
  isTelemetryDisabled
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-CPW6G62V.js";
5
5
  import {
6
6
  VERSION
7
- } from "./chunk-I3XDOICA.js";
7
+ } from "./chunk-X5Z67IFB.js";
8
8
 
9
9
  // src/analytics/analytics.js
10
10
  import os from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-I3XDOICA.js";
3
+ } from "./chunk-X5Z67IFB.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "5.0.0-beta.14";
2
+ var version = "5.0.0-beta.16";
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 = "5.0.0-beta.14";
28
+ var version = "5.0.0-beta.16";
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-I3XDOICA.js";
3
+ } from "./chunk-X5Z67IFB.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -22,7 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
 
25
- // ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.7.0_postcss@8.5.29_tsx@4.23.15_typescript@5.9.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js
25
+ // ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.7.0_postcss@8.5.29_tsx@4.23.15_typescript@5.9.3_yaml@2.9.1/node_modules/tsup/assets/cjs_shims.js
26
26
  var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
27
27
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
28
28
 
@@ -181,7 +181,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
181
181
  var import_picocolors = __toESM(require("picocolors"), 1);
182
182
 
183
183
  // package.json
184
- var version = "5.0.0-beta.14";
184
+ var version = "5.0.0-beta.16";
185
185
 
186
186
  // src/constants.ts
187
187
  var VERSION = version;
@@ -4,7 +4,7 @@ import {
4
4
  import "./chunk-CA4U2JP7.js";
5
5
  import {
6
6
  log_build_default
7
- } from "./chunk-WY6M3RPT.js";
7
+ } from "./chunk-3ZZK2SD5.js";
8
8
  import {
9
9
  getLicenseStatus,
10
10
  printLicenseStatus
@@ -33,10 +33,10 @@ import {
33
33
  } from "./chunk-MDWB5HLO.js";
34
34
  import {
35
35
  generate
36
- } from "./chunk-4KE3EUDJ.js";
36
+ } from "./chunk-3GABQPQZ.js";
37
37
  import {
38
38
  logger
39
- } from "./chunk-OFK7U7BX.js";
39
+ } from "./chunk-FQMVEUYE.js";
40
40
  import {
41
41
  resolve_catalog_dependencies_default
42
42
  } from "./chunk-36RYTYT5.js";
@@ -50,7 +50,7 @@ import {
50
50
  import {
51
51
  watch
52
52
  } from "./chunk-U63GDPPY.js";
53
- import "./chunk-PI5YNZZZ.js";
53
+ import "./chunk-DTUGKNST.js";
54
54
  import "./chunk-CPW6G62V.js";
55
55
  import {
56
56
  getAstroConfigPath
@@ -67,7 +67,7 @@ import {
67
67
  } from "./chunk-LFQJXLHG.js";
68
68
  import {
69
69
  VERSION
70
- } from "./chunk-I3XDOICA.js";
70
+ } from "./chunk-X5Z67IFB.js";
71
71
  import {
72
72
  getEventCatalogConfigFile,
73
73
  verifyRequiredFieldsAreInCatalogConfigFile
package/dist/generate.cjs CHANGED
@@ -112,7 +112,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
112
112
  var import_picocolors = __toESM(require("picocolors"), 1);
113
113
 
114
114
  // package.json
115
- var version = "5.0.0-beta.14";
115
+ var version = "5.0.0-beta.16";
116
116
 
117
117
  // src/constants.ts
118
118
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-4KE3EUDJ.js";
4
- import "./chunk-OFK7U7BX.js";
5
- import "./chunk-I3XDOICA.js";
3
+ } from "./chunk-3GABQPQZ.js";
4
+ import "./chunk-FQMVEUYE.js";
5
+ import "./chunk-X5Z67IFB.js";
6
6
  import "./chunk-RFIXKATC.js";
7
7
  export {
8
8
  generate
@@ -0,0 +1,3 @@
1
+ export * from "htmlparser2";
2
+ import * as dependency from "htmlparser2";
3
+ export default dependency.default;
@@ -94,6 +94,7 @@
94
94
  "gray-matter": "gray-matter.mjs",
95
95
  "hono": "hono.mjs",
96
96
  "html-to-image": "html-to-image.mjs",
97
+ "htmlparser2": "htmlparser2.mjs",
97
98
  "js-yaml": "js-yaml.mjs",
98
99
  "jsonpath-plus": "jsonpath-plus.mjs",
99
100
  "jsonwebtoken": "jsonwebtoken.mjs",
@@ -117,6 +118,7 @@
117
118
  "react-hotkeys-hook": "react-hotkeys-hook.mjs",
118
119
  "react-markdown": "react-markdown.mjs",
119
120
  "react-syntax-highlighter": "react-syntax-highlighter.mjs",
121
+ "react-syntax-highlighter/dist/cjs/create-element.js": "react-syntax-highlighter__dist__cjs__create-element.js.mjs",
120
122
  "react-syntax-highlighter/dist/cjs/styles/prism": "react-syntax-highlighter__dist__cjs__styles__prism.mjs",
121
123
  "react-syntax-highlighter/dist/cjs/styles/prism/index.js": "react-syntax-highlighter__dist__cjs__styles__prism__index.js.mjs",
122
124
  "react-syntax-highlighter/dist/esm/languages/prism/graphql": "react-syntax-highlighter__dist__esm__languages__prism__graphql.mjs",
@@ -0,0 +1,3 @@
1
+ export * from "react-syntax-highlighter/dist/cjs/create-element.js";
2
+ import * as dependency from "react-syntax-highlighter/dist/cjs/create-element.js";
3
+ export default dependency.default;
@@ -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 = "5.0.0-beta.14";
39
+ var version = "5.0.0-beta.16";
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-OFK7U7BX.js";
4
- import "../chunk-I3XDOICA.js";
3
+ } from "../chunk-FQMVEUYE.js";
4
+ import "../chunk-X5Z67IFB.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -117,6 +117,11 @@ export default defineConfig({
117
117
 
118
118
  // just turn this off for all users (for now...)
119
119
  devToolbar: { enabled: false },
120
+ build: {
121
+ // Render several pages at once: pages wait on file reads and graph layouts, and a 640-event
122
+ // catalog built in ~40s rather than ~70s, with the same pages and less memory.
123
+ concurrency: 4,
124
+ },
120
125
 
121
126
  // Unused resource types are valid. Astro otherwise warns on every getCollection()
122
127
  // call for those empty collections ("check your content config file for errors").
@@ -4,6 +4,7 @@ import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
4
4
  import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
5
5
  import { getLanguageForHighlight, getSchemaTypeLabel } from './utils';
6
6
  import { useDarkMode } from './useDarkMode';
7
+ import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
7
8
  import type { SchemaItem } from './types';
8
9
 
9
10
  interface ApiContentViewerProps {
@@ -135,6 +136,7 @@ export default function ApiContentViewer({ message, onCopy, copiedId }: ApiConte
135
136
 
136
137
  <div className="border-t" style={{ borderColor: dividerColor }}>
137
138
  <SyntaxHighlighter
139
+ renderer={renderHighlightedRows}
138
140
  language={getLanguageForHighlight(message.schemaExtension)}
139
141
  style={isDarkMode ? oneDark : oneLight}
140
142
  customStyle={{
@@ -13,6 +13,7 @@ import { MarkdownCodeGroup } from '../MDX/CodeGroup/MarkdownCodeGroup';
13
13
  import { MarkdownColumns, MarkdownColumn } from '../MDX/Columns/MarkdownColumns';
14
14
  import { remarkMarkdownColumns } from '../../remark-plugins/markdown-columns';
15
15
  import { getLanguageForHighlight } from './utils';
16
+ import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
16
17
 
17
18
  interface ExamplesViewerProps {
18
19
  examples: MessageExample[];
@@ -40,6 +41,7 @@ function CodeBlock({ language, code }: { language?: string; code: string }) {
40
41
  const content = code.replace(/\s+$/, '');
41
42
  const highlighter = (
42
43
  <SyntaxHighlighter
44
+ renderer={renderHighlightedRows}
43
45
  language={language || 'text'}
44
46
  style={isDarkMode ? oneDark : oneLight}
45
47
  customStyle={{
@@ -6,6 +6,7 @@ import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
6
6
  import { getLanguageForHighlight } from './utils';
7
7
  import type { SchemaItem } from './types';
8
8
  import { useDarkMode } from './useDarkMode';
9
+ import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
9
10
 
10
11
  interface SchemaCodeModalProps {
11
12
  isOpen: boolean;
@@ -60,6 +61,7 @@ export default function SchemaCodeModal({ isOpen, onOpenChange, message, onCopy,
60
61
  {/* Content */}
61
62
  <div className="flex-1 overflow-auto p-6">
62
63
  <SyntaxHighlighter
64
+ renderer={renderHighlightedRows}
63
65
  language={getLanguageForHighlight(message.schemaExtension)}
64
66
  style={isDarkMode ? oneDark : oneLight}
65
67
  customStyle={{
@@ -9,6 +9,7 @@ import ProtobufSchemaViewer from './ProtobufSchemaViewer';
9
9
  import { getLanguageForHighlight, SCHEMA_CODE_STYLE } from './utils';
10
10
  import type { SchemaItem } from './types';
11
11
  import { useDarkMode } from './useDarkMode';
12
+ import { renderHighlightedRows } from '@utils/syntax-highlighter-renderer';
12
13
 
13
14
  interface SchemaContentViewerProps {
14
15
  message: SchemaItem;
@@ -112,6 +113,7 @@ export default function SchemaContentViewer({
112
113
 
113
114
  <div className="min-h-0 flex-1 overflow-auto">
114
115
  <SyntaxHighlighter
116
+ renderer={renderHighlightedRows}
115
117
  language={getLanguageForHighlight(message.schemaExtension)}
116
118
  style={isDarkMode ? oneDark : oneLight}
117
119
  customStyle={{ ...SCHEMA_CODE_STYLE, height: '100%' }}
@@ -12,3 +12,13 @@ declare module 'react-syntax-highlighter' {
12
12
  }
13
13
 
14
14
  declare module 'react-syntax-highlighter/dist/esm/styles/prism/material-light';
15
+
16
+ declare module 'react-syntax-highlighter/dist/cjs/create-element.js' {
17
+ import type { CSSProperties } from 'react';
18
+
19
+ export function createStyleObject(
20
+ classNames: string[],
21
+ elementStyle?: CSSProperties,
22
+ stylesheet?: { [selector: string]: CSSProperties }
23
+ ): CSSProperties;
24
+ }
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { parse, type DefaultTreeAdapterMap } from 'parse5';
3
+ import { Parser } from 'htmlparser2';
4
4
  import picomatch from 'picomatch';
5
5
 
6
6
  export type LinkValidationSeverity = 'warn' | 'error' | 'ignore';
@@ -42,30 +42,36 @@ const decodeUrlPart = (value: string): string => {
42
42
  }
43
43
  };
44
44
 
45
+ // Elements whose contents browsers don't render as markup (<noscript> when scripts run)
46
+ const INERT_ELEMENTS = new Set(['template', 'noscript']);
47
+
45
48
  // Parse HTML rather than searching markup with a regex: attributes can contain
46
49
  // entities, quoted > characters, or single/unquoted values. Scripts and inert
47
50
  // template contents must not be mistaken for rendered links or anchor targets.
51
+ // A streaming parser, not a document tree: pages can be large (island props),
52
+ // and building a tree of each one made link validation a large part of a build.
48
53
  const readPage = (html: string, source: string): PageLinks => {
49
54
  const page: PageLinks = { source, anchors: new Set(), links: new Set() };
50
- const nodes: DefaultTreeAdapterMap['node'][] = [parse(html)];
51
- while (nodes.length > 0) {
52
- const node = nodes.pop()!;
53
- if ('tagName' in node) {
54
- const attrs = new Map(node.attrs.map((attr) => [attr.name, attr.value]));
55
- const id = attrs.get('id');
56
- if (id) page.anchors.add(id);
57
- if (node.tagName === 'a' && attrs.get('name')) page.anchors.add(attrs.get('name')!);
58
- const href = attrs.get('href');
59
- if (href !== undefined) {
60
- if (node.tagName === 'base' && page.baseHref === undefined) page.baseHref = href;
61
- if (node.tagName === 'a' || node.tagName === 'area') page.links.add(href);
55
+ let inert = 0;
56
+ const parser = new Parser({
57
+ onopentag(tagName, attrs) {
58
+ if (inert === 0) {
59
+ if (attrs.id) page.anchors.add(attrs.id);
60
+ if (tagName === 'a' && attrs.name) page.anchors.add(attrs.name);
61
+ const href = attrs.href;
62
+ if (href !== undefined) {
63
+ // Parsed in document order, so the first <base href> wins
64
+ if (tagName === 'base' && page.baseHref === undefined) page.baseHref = href;
65
+ if (tagName === 'a' || tagName === 'area') page.links.add(href);
66
+ }
62
67
  }
63
- }
64
- // Reverse the stack so the first <base href> wins in document order.
65
- if ('childNodes' in node) {
66
- for (let i = node.childNodes.length - 1; i >= 0; i--) nodes.push(node.childNodes[i]);
67
- }
68
- }
68
+ if (INERT_ELEMENTS.has(tagName)) inert++;
69
+ },
70
+ onclosetag(tagName) {
71
+ if (INERT_ELEMENTS.has(tagName) && inert > 0) inert--;
72
+ },
73
+ });
74
+ parser.end(html);
69
75
  return page;
70
76
  };
71
77
 
@@ -1,7 +1,14 @@
1
1
  import { hideMessageNodes, layoutWithElk } from '@eventcatalog/visualiser/layout';
2
+ import { isSSR } from '@utils/feature';
2
3
 
3
4
  type Graph = { nodes: any[]; edges: any[] };
4
5
 
6
+ // A build renders one route at a time (every message's docs page, then every schema page), so the
7
+ // cache has to outlast a whole route to be reused. A server keeps running as the catalog changes and
8
+ // renders pages as they're asked for, so it keeps the most recent layouts only.
9
+ const MAX_CACHED_LAYOUTS = isSSR() ? 200 : 5000;
10
+ const layouts = new Map<string, ReturnType<typeof layoutWithElk>>();
11
+
5
12
  /**
6
13
  * Lays a node graph out for the visualiser (with ELK, left to right). Builders
7
14
  * create their nodes and edges without positions and lay the finished graph
@@ -9,7 +16,19 @@ type Graph = { nodes: any[]; edges: any[] };
9
16
  * (nodes with children) are sized to fit them, and edges get the route they're
10
17
  * drawn along (`data.route`), with room for their labels.
11
18
  */
12
- export const layoutNodeGraph = async <G extends Graph>(graph: G): Promise<G> => (await layoutWithElk(graph)) as unknown as G;
19
+ export const layoutNodeGraph = async <G extends Graph>(graph: G): Promise<G> => {
20
+ // A build lays the same graph out on several pages (a message's docs, visualiser and schema pages):
21
+ // reuse the layout. Each caller gets its own copy, so it can't change the one kept.
22
+ const key = JSON.stringify(graph);
23
+ let layout = layouts.get(key);
24
+ if (!layout) {
25
+ layout = layoutWithElk(graph);
26
+ layouts.set(key, layout);
27
+ layout.catch(() => layouts.delete(key));
28
+ if (layouts.size > MAX_CACHED_LAYOUTS) layouts.delete(layouts.keys().next().value!);
29
+ }
30
+ return structuredClone(await layout) as unknown as G;
31
+ };
13
32
 
14
33
  /**
15
34
  * Lays out the graphs of a levels page: level 1 (`overview`: domains, systems
@@ -0,0 +1,64 @@
1
+ import { createElement, type CSSProperties, type ReactNode } from 'react';
2
+ import { createStyleObject } from 'react-syntax-highlighter/dist/cjs/create-element.js';
3
+
4
+ type Stylesheet = { [selector: string]: CSSProperties };
5
+ type HighlightedNode = {
6
+ type: 'element' | 'text';
7
+ value?: string | number;
8
+ tagName?: any;
9
+ properties?: { className?: string[]; style?: CSSProperties; [key: string]: unknown };
10
+ children?: HighlightedNode[];
11
+ };
12
+
13
+ const selectorsByStylesheet = new WeakMap<Stylesheet, Set<string>>();
14
+
15
+ /** The class names a theme styles, worked out once per theme */
16
+ const stylesheetSelectors = (stylesheet: Stylesheet) => {
17
+ let selectors = selectorsByStylesheet.get(stylesheet);
18
+ if (!selectors) {
19
+ selectors = new Set(Object.keys(stylesheet).flatMap((selector) => selector.split('.')));
20
+ selectorsByStylesheet.set(stylesheet, selectors);
21
+ }
22
+ return selectors;
23
+ };
24
+
25
+ const renderNode = (node: HighlightedNode, stylesheet: Stylesheet, useInlineStyles: boolean, key: string): ReactNode => {
26
+ if (node.type === 'text') return node.value;
27
+ if (!node.tagName) return undefined;
28
+
29
+ const properties = node.properties ?? {};
30
+ const classNames = properties.className;
31
+ let props;
32
+ if (!useInlineStyles) {
33
+ props = { ...properties, className: classNames?.join(' ') };
34
+ } else {
35
+ // Theme classes become inline styles; any other class names stay
36
+ const selectors = stylesheetSelectors(stylesheet);
37
+ const className =
38
+ classNames && (classNames.includes('token') ? ['token'] : []).concat(classNames.filter((name) => !selectors.has(name)));
39
+ props = {
40
+ ...properties,
41
+ className: className?.join(' ') || undefined,
42
+ style: createStyleObject(classNames ?? [], { ...properties.style }, stylesheet),
43
+ };
44
+ }
45
+
46
+ const children = (node.children ?? []).map((child, i) => renderNode(child, stylesheet, useInlineStyles, `code-segment-1-${i}`));
47
+ return createElement(node.tagName, { key, ...props }, children);
48
+ };
49
+
50
+ /**
51
+ * Renders react-syntax-highlighter's rows as its default renderer does (same elements, styles and keys), but
52
+ * works out the theme's class names once per theme rather than for every token: the default renderer did
53
+ * that for every token, which made highlighting a schema on the server take tens of milliseconds a page.
54
+ * Set `wrapLines`: with a custom renderer, react-syntax-highlighter turns it on when it isn't set.
55
+ */
56
+ export const renderHighlightedRows = ({
57
+ rows,
58
+ stylesheet,
59
+ useInlineStyles,
60
+ }: {
61
+ rows: HighlightedNode[];
62
+ stylesheet: Stylesheet;
63
+ useInlineStyles: boolean;
64
+ }): ReactNode[] => rows.map((node, i) => renderNode(node, stylesheet, useInlineStyles, `code-segment-${i}`));
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "BUSL-1.1",
9
9
  "type": "module",
10
- "version": "5.0.0-beta.14",
10
+ "version": "5.0.0-beta.16",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -47,10 +47,10 @@
47
47
  ],
48
48
  "dependencies": {
49
49
  "@ai-sdk/react": "^4.0.109",
50
- "@astrojs/markdown-remark": "^7.3.1",
51
- "@astrojs/mdx": "^8.0.1",
52
- "@astrojs/node": "^11.1.6",
53
- "@astrojs/react": "^6.0.6",
50
+ "@astrojs/markdown-remark": "^7.3.2",
51
+ "@astrojs/mdx": "^8.0.3",
52
+ "@astrojs/node": "^11.1.7",
53
+ "@astrojs/react": "^7.0.1",
54
54
  "@astrojs/rss": "^4.0.19",
55
55
  "@asyncapi/avro-schema-parser": "3.0.24",
56
56
  "@asyncapi/parser": "^3.6.0",
@@ -81,7 +81,7 @@
81
81
  "@tanstack/react-table": "^8.17.3",
82
82
  "@xyflow/react": "^12.12.0",
83
83
  "ai": "^7.0.106",
84
- "astro": "7.3.3",
84
+ "astro": "7.3.8",
85
85
  "astro-expressive-code": "^0.44.0",
86
86
  "astro-seo": "^1.2.0",
87
87
  "boxen": "^8.0.1",
@@ -99,6 +99,7 @@
99
99
  "gray-matter": "^4.0.3",
100
100
  "hono": "^4.13.7",
101
101
  "html-to-image": "^1.11.11",
102
+ "htmlparser2": "^12.0.0",
102
103
  "js-yaml": "^4.3.2",
103
104
  "jsonpath-plus": "^10.4.0",
104
105
  "jsonwebtoken": "^9.0.2",
@@ -140,8 +141,8 @@
140
141
  "y-protocols": "^1.0.7",
141
142
  "yjs": "^13.6.33",
142
143
  "zod": "^4.3.6",
143
- "@eventcatalog/sdk": "2.30.0-beta.1",
144
144
  "@eventcatalog/linter": "1.2.0-beta.2",
145
+ "@eventcatalog/sdk": "2.30.0-beta.1",
145
146
  "@eventcatalog/visualiser": "^5.0.0-beta.6"
146
147
  },
147
148
  "devDependencies": {