zudoku 0.21.14 → 0.22.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 (43) hide show
  1. package/dist/config/loader.js +3 -1
  2. package/dist/config/loader.js.map +1 -1
  3. package/dist/lib/components/Markdown.js +1 -1
  4. package/dist/lib/components/Markdown.js.map +1 -1
  5. package/dist/lib/components/ReactMarkdown.d.ts +29 -0
  6. package/dist/lib/components/ReactMarkdown.js +182 -0
  7. package/dist/lib/components/ReactMarkdown.js.map +1 -0
  8. package/dist/lib/plugins/search-inkeep/index.d.ts +22 -3
  9. package/dist/lib/plugins/search-inkeep/index.js +27 -5
  10. package/dist/lib/plugins/search-inkeep/index.js.map +1 -1
  11. package/dist/lib/plugins/search-inkeep/inkeep.d.ts +3 -4
  12. package/dist/lib/plugins/search-inkeep/inkeep.js.map +1 -1
  13. package/lib/{Markdown-CdkU5HcM.js → Markdown-CRsmPPfY.js} +13083 -13095
  14. package/lib/Markdown-CRsmPPfY.js.map +1 -0
  15. package/lib/{MdxPage-ChziqNPp.js → MdxPage-Wp8QU0-q.js} +2 -2
  16. package/lib/{MdxPage-ChziqNPp.js.map → MdxPage-Wp8QU0-q.js.map} +1 -1
  17. package/lib/{OperationList-CQKkyrZH.js → OperationList-u8xHU9-b.js} +3 -3
  18. package/lib/{OperationList-CQKkyrZH.js.map → OperationList-u8xHU9-b.js.map} +1 -1
  19. package/lib/{SlotletProvider-D77pO-fA.js → SlotletProvider-BgvYIPQe.js} +2 -2
  20. package/lib/{SlotletProvider-D77pO-fA.js.map → SlotletProvider-BgvYIPQe.js.map} +1 -1
  21. package/lib/{index-DjB6H4GT.js → index-CmdLGbbk.js} +2 -2
  22. package/lib/{index-DjB6H4GT.js.map → index-CmdLGbbk.js.map} +1 -1
  23. package/lib/zudoku.components.js +2 -2
  24. package/lib/zudoku.plugin-api-catalog.js +1 -1
  25. package/lib/zudoku.plugin-api-keys.js +1 -1
  26. package/lib/zudoku.plugin-custom-pages.js +1 -1
  27. package/lib/zudoku.plugin-markdown.js +1 -1
  28. package/lib/zudoku.plugin-openapi.js +1 -1
  29. package/lib/zudoku.plugin-search-inkeep.js +44 -23
  30. package/lib/zudoku.plugin-search-inkeep.js.map +1 -1
  31. package/package.json +9 -3
  32. package/src/lib/components/Markdown.tsx +1 -1
  33. package/src/lib/components/ReactMarkdown.license.txt +21 -0
  34. package/src/lib/components/ReactMarkdown.tsx +264 -0
  35. package/src/lib/plugins/search-inkeep/index.tsx +59 -23
  36. package/src/lib/plugins/search-inkeep/inkeep.ts +3 -9
  37. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.d.ts +0 -2
  38. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.js +0 -3
  39. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.js.map +0 -1
  40. package/lib/InkeepCustomTrigger-CE5-K5ex.js +0 -6
  41. package/lib/InkeepCustomTrigger-CE5-K5ex.js.map +0 -1
  42. package/lib/Markdown-CdkU5HcM.js.map +0 -1
  43. package/src/lib/plugins/search-inkeep/InkeepCustomTrigger.tsx +0 -3
@@ -16,7 +16,7 @@ var J = (e, t, r, s) => ({
16
16
  import { a as He, H as me } from "./index.esm-Bm8pj-bc.js";
17
17
  import { d as jt, R as wt, N as ae, u as St, L as ge } from "./index-Yn8c3UWE.js";
18
18
  import { u as Nt } from "./state-tsXBLONe.js";
19
- import { E as Ue, S as O, a as Et, R as Ct } from "./SlotletProvider-D77pO-fA.js";
19
+ import { E as Ue, S as O, a as Et, R as Ct } from "./SlotletProvider-BgvYIPQe.js";
20
20
  import { j as a } from "./jsx-runtime-B6kdoens.js";
21
21
  import { Button as Pt } from "./ui/Button.js";
22
22
  import { Callout as kt } from "./ui/Callout.js";
@@ -32,7 +32,7 @@ import { C as je } from "./ClientOnly-E7hGysn1.js";
32
32
  import { ChevronRightIcon as Xt, ExternalLinkIcon as Jt, CircleXIcon as Gt, SearchIcon as er, MoonStarIcon as tr, SunIcon as rr, MenuIcon as ar, PanelLeftIcon as sr } from "lucide-react";
33
33
  import { Drawer as et, DrawerTrigger as tt, DrawerContent as rt, DrawerTitle as at } from "./ui/Drawer.js";
34
34
  import { c as R } from "./cn-BmFQLtkS.js";
35
- import { u as we, a as nr, V as ir } from "./Markdown-CdkU5HcM.js";
35
+ import { u as we, a as nr, V as ir } from "./Markdown-CRsmPPfY.js";
36
36
  import { c as or, a as lr } from "./index-BuAyrJe3.js";
37
37
  import { A as cr, M as ur, u as dr } from "./AnchorLink-BR0MvI7n.js";
38
38
  import * as oe from "@radix-ui/react-collapsible";
@@ -2,7 +2,7 @@ import { j as e } from "./jsx-runtime-B6kdoens.js";
2
2
  import { s as n } from "./index-LNp6rxyU.js";
3
3
  import { Fragment as x } from "react";
4
4
  import { Head as f, Link as h } from "./zudoku.components.js";
5
- import { M as u } from "./Markdown-CdkU5HcM.js";
5
+ import { M as u } from "./Markdown-CRsmPPfY.js";
6
6
  import { u as j } from "./useExposedProps-CTPtylCV.js";
7
7
  const b = ({
8
8
  items: l,
@@ -1,6 +1,6 @@
1
1
  import { j as e } from "./jsx-runtime-B6kdoens.js";
2
2
  import { RotateCwIcon as g, TrashIcon as f, EyeOffIcon as j, EyeIcon as v, CheckIcon as w, CopyIcon as b, FileKey2Icon as K } from "lucide-react";
3
- import { D as k, S as m, R as N } from "./SlotletProvider-D77pO-fA.js";
3
+ import { D as k, S as m, R as N } from "./SlotletProvider-BgvYIPQe.js";
4
4
  import { i as c } from "./invariant-Caa8-XvF.js";
5
5
  import { u as d, S as I, a as S, b as A, c as C, d as E, e as x } from "./Select-O9ZM3ZgX.js";
6
6
  import { a as P } from "./index.esm-C5mr_sKO.js";
@@ -1,6 +1,6 @@
1
1
  import { j as o } from "./jsx-runtime-B6kdoens.js";
2
2
  import a from "react";
3
- import { P as n } from "./Markdown-CdkU5HcM.js";
3
+ import { P as n } from "./Markdown-CRsmPPfY.js";
4
4
  import { c } from "./cn-BmFQLtkS.js";
5
5
  import { u as p } from "./useExposedProps-CTPtylCV.js";
6
6
  const u = ({
@@ -74,7 +74,7 @@ const C = (n) => ({
74
74
  const h = {
75
75
  path: r,
76
76
  lazy: async () => {
77
- const { MdxPage: l } = await import("./MdxPage-ChziqNPp.js"), { default: p, ...g } = await a();
77
+ const { MdxPage: l } = await import("./MdxPage-Wp8QU0-q.js"), { default: p, ...g } = await a();
78
78
  return {
79
79
  element: /* @__PURE__ */ P.jsx(
80
80
  l,
@@ -1,5 +1,5 @@
1
1
  import "./jsx-runtime-B6kdoens.js";
2
- import { o as a } from "./index-DjB6H4GT.js";
2
+ import { o as a } from "./index-CmdLGbbk.js";
3
3
  import "./utils-DcpDOncX.js";
4
4
  import "lucide-react";
5
5
  import "./hook-hEqe7fPB.js";
@@ -1,7 +1,7 @@
1
1
  import { j as n } from "./jsx-runtime-B6kdoens.js";
2
- import { lazy as a } from "react";
3
- import { C as i } from "./ClientOnly-E7hGysn1.js";
4
- const o = {
2
+ import { useRef as a, useMemo as p, useEffect as c } from "react";
3
+ import { C as u } from "./ClientOnly-E7hGysn1.js";
4
+ const d = {
5
5
  theme: {
6
6
  components: {
7
7
  AIChatPageWrapper: {
@@ -19,29 +19,50 @@ const o = {
19
19
  }
20
20
  }
21
21
  }
22
- }, p = {}, c = a(() => import("./InkeepCustomTrigger-CE5-K5ex.js")), l = ({
23
- prefilledQuery: e,
24
- isOpen: r,
25
- onClose: t,
26
- settings: s
27
- }) => /* @__PURE__ */ n.jsx(
28
- c,
29
- {
30
- isOpen: r,
31
- onClose: t,
32
- baseSettings: { ...o, ...s },
33
- aiChatSettings: p,
34
- searchSettings: {
35
- prefilledQuery: e || void 0
22
+ }, m = {}, g = ({
23
+ prefilledQuery: t,
24
+ isOpen: e,
25
+ onClose: r,
26
+ settings: i
27
+ }) => {
28
+ const s = a(null), o = p(
29
+ () => ({
30
+ componentType: "CustomTrigger",
31
+ targetElement: s.current,
32
+ properties: {
33
+ isOpen: e,
34
+ onClose: r,
35
+ onOpen: void 0,
36
+ baseSettings: { ...d, ...i },
37
+ searchSettings: {
38
+ prefilledQuery: t || void 0
39
+ },
40
+ aiChatSettings: m
41
+ }
42
+ }),
43
+ [e, r, t, i, s]
44
+ );
45
+ return c(() => {
46
+ Inkeep().embed(o).render({
47
+ ...o,
48
+ isOpen: e
49
+ });
50
+ }), /* @__PURE__ */ n.jsx("div", { ref: s });
51
+ }, j = (t) => ({
52
+ getHead: () => /* @__PURE__ */ n.jsx(
53
+ "script",
54
+ {
55
+ type: "module",
56
+ src: "https://unpkg.com/@inkeep/uikit-js@0.3.19/dist/embed.js",
57
+ defer: !0
36
58
  }
37
- }
38
- ), d = (e) => ({
59
+ ),
39
60
  renderSearch: ({
40
- isOpen: r,
41
- onClose: t
42
- }) => /* @__PURE__ */ n.jsx(i, { children: /* @__PURE__ */ n.jsx(l, { isOpen: r, onClose: t, settings: e }) })
61
+ isOpen: e,
62
+ onClose: r
63
+ }) => /* @__PURE__ */ n.jsx(u, { children: /* @__PURE__ */ n.jsx(g, { isOpen: e, onClose: r, settings: t }) })
43
64
  });
44
65
  export {
45
- d as inkeepSearchPlugin
66
+ j as inkeepSearchPlugin
46
67
  };
47
68
  //# sourceMappingURL=zudoku.plugin-search-inkeep.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-search-inkeep.js","sources":["../src/lib/plugins/search-inkeep/inkeep.ts","../src/lib/plugins/search-inkeep/index.tsx"],"sourcesContent":["import {\n InkeepAIChatSettings,\n InkeepModalSettings,\n InkeepSearchSettings,\n} from \"@inkeep/widgets\";\n\nconst baseSettings = {\n theme: {\n components: {\n AIChatPageWrapper: {\n defaultProps: {\n size: \"shrink-vertically\",\n variant: \"no-shadow\",\n },\n },\n SearchBarTrigger: {\n defaultProps: {\n size: \"expand\",\n variant: \"subtle\", // Choose from 'emphasized' or 'subtle'\n },\n },\n },\n },\n} as const;\n\nconst modalSettings: InkeepModalSettings = {};\n\nconst searchSettings: InkeepSearchSettings = {};\n\nconst aiChatSettings: InkeepAIChatSettings = {};\n\nexport { aiChatSettings, baseSettings, modalSettings, searchSettings };\n","import type { InkeepWidgetBaseSettings } from \"@inkeep/widgets\";\nimport { lazy } from \"react\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { aiChatSettings, baseSettings } from \"./inkeep.js\";\n\ntype PickedPluginInkeepBaseSettings =\n | \"apiKey\"\n | \"integrationId\"\n | \"organizationId\"\n | \"primaryBrandColor\"\n | \"organizationDisplayName\";\n\ntype PluginInkeepBaseSettings = Pick<\n InkeepWidgetBaseSettings,\n PickedPluginInkeepBaseSettings\n>;\n\nconst Inkeep = lazy(() => import(\"./InkeepCustomTrigger.js\"));\n\nconst InkeepSearch = ({\n prefilledQuery,\n isOpen,\n onClose,\n settings,\n}: {\n isOpen: boolean;\n onClose: () => void;\n prefilledQuery?: string | null;\n settings: PluginInkeepBaseSettings;\n}) => {\n return (\n <Inkeep\n isOpen={isOpen}\n onClose={onClose}\n baseSettings={{ ...baseSettings, ...settings }}\n aiChatSettings={aiChatSettings}\n searchSettings={{\n prefilledQuery: prefilledQuery || undefined,\n }}\n />\n );\n};\n\nexport const inkeepSearchPlugin = (\n settings: PluginInkeepBaseSettings,\n): ZudokuPlugin => {\n return {\n renderSearch: ({\n isOpen,\n onClose,\n }: {\n isOpen: boolean;\n onClose: () => void;\n }) => {\n return (\n <ClientOnly>\n <InkeepSearch isOpen={isOpen} onClose={onClose} settings={settings} />\n </ClientOnly>\n );\n },\n };\n};\n"],"names":["baseSettings","aiChatSettings","Inkeep","lazy","InkeepSearch","prefilledQuery","isOpen","onClose","settings","jsx","inkeepSearchPlugin","ClientOnly"],"mappings":";;;AAMA,MAAMA,IAAe;AAAA,EACnB,OAAO;AAAA,IACL,YAAY;AAAA,MACV,mBAAmB;AAAA,QACjB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,kBAAkB;AAAA,QAChB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,GAMMC,IAAuC,CAAC,GCXxCC,IAASC,EAAK,MAAM,OAAO,mCAA0B,CAAC,GAEtDC,IAAe,CAAC;AAAA,EACpB,gBAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AACF,MAOIC,gBAAAA,EAAA;AAAA,EAACP;AAAA,EAAA;AAAA,IACC,QAAAI;AAAA,IACA,SAAAC;AAAA,IACA,cAAc,EAAE,GAAGP,GAAc,GAAGQ,EAAS;AAAA,IAC7C,gBAAAP;AAAA,IACA,gBAAgB;AAAA,MACd,gBAAgBI,KAAkB;AAAA,IACpC;AAAA,EAAA;AAAA,GAKOK,IAAqB,CAChCF,OAEO;AAAA,EACL,cAAc,CAAC;AAAA,IACb,QAAAF;AAAA,IACA,SAAAC;AAAA,EAAA,4BAMGI,GACC,EAAA,UAAAF,gBAAAA,EAAAA,IAACL,KAAa,QAAAE,GAAgB,SAAAC,GAAkB,UAAAC,EAAoB,CAAA,EACtE,CAAA;AAEJ;"}
1
+ {"version":3,"file":"zudoku.plugin-search-inkeep.js","sources":["../src/lib/plugins/search-inkeep/inkeep.ts","../src/lib/plugins/search-inkeep/index.tsx"],"sourcesContent":["const baseSettings = {\n theme: {\n components: {\n AIChatPageWrapper: {\n defaultProps: {\n size: \"shrink-vertically\",\n variant: \"no-shadow\",\n },\n },\n SearchBarTrigger: {\n defaultProps: {\n size: \"expand\",\n variant: \"subtle\", // Choose from 'emphasized' or 'subtle'\n },\n },\n },\n },\n} as const;\n\nconst modalSettings = {};\n\nconst searchSettings = {};\n\nconst aiChatSettings = {};\n\nexport { aiChatSettings, baseSettings, modalSettings, searchSettings };\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { aiChatSettings, baseSettings } from \"./inkeep.js\";\n\ninterface PluginInkeepBaseSettings {\n apiKey?: string;\n integrationId: string;\n organizationId: string;\n organizationDisplayName?: string;\n primaryBrandColor: string;\n}\n\ninterface InkeepEmbedConfig {\n componentType: string;\n targetElement: HTMLElement;\n properties: unknown;\n}\n\ninterface InkeepWidget {\n render: (config: InkeepEmbedConfig & { isOpen: boolean }) => void;\n}\n\ndeclare global {\n let Inkeep: () => {\n embed: (config: InkeepEmbedConfig) => InkeepWidget;\n };\n}\n\nconst InkeepSearch = ({\n prefilledQuery,\n isOpen,\n onClose,\n settings,\n}: {\n isOpen: boolean;\n onClose: () => void;\n prefilledQuery?: string | null;\n settings: PluginInkeepBaseSettings;\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n\n const config: InkeepEmbedConfig = useMemo(\n () => ({\n componentType: \"CustomTrigger\",\n targetElement: ref.current!,\n properties: {\n isOpen,\n onClose,\n onOpen: undefined,\n baseSettings: { ...baseSettings, ...settings },\n searchSettings: {\n prefilledQuery: prefilledQuery || undefined,\n },\n aiChatSettings,\n },\n }),\n [isOpen, onClose, prefilledQuery, settings, ref],\n );\n\n useEffect(() => {\n const inkeepWidget = Inkeep().embed(config);\n inkeepWidget.render({\n ...config,\n isOpen,\n });\n });\n\n return <div ref={ref} />;\n};\n\nexport const inkeepSearchPlugin = (\n settings: PluginInkeepBaseSettings,\n): ZudokuPlugin => {\n return {\n getHead: () => {\n return (\n <script\n type=\"module\"\n src=\"https://unpkg.com/@inkeep/uikit-js@0.3.19/dist/embed.js\"\n defer\n ></script>\n );\n },\n renderSearch: ({\n isOpen,\n onClose,\n }: {\n isOpen: boolean;\n onClose: () => void;\n }) => {\n return (\n <ClientOnly>\n <InkeepSearch isOpen={isOpen} onClose={onClose} settings={settings} />\n </ClientOnly>\n );\n },\n };\n};\n"],"names":["baseSettings","aiChatSettings","InkeepSearch","prefilledQuery","isOpen","onClose","settings","ref","useRef","config","useMemo","useEffect","jsx","inkeepSearchPlugin","ClientOnly"],"mappings":";;;AAAA,MAAMA,IAAe;AAAA,EACnB,OAAO;AAAA,IACL,YAAY;AAAA,MACV,mBAAmB;AAAA,QACjB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,kBAAkB;AAAA,QAChB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,GAMMC,IAAiB,CAAC,GCMlBC,IAAe,CAAC;AAAA,EACpB,gBAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AACF,MAKM;AACE,QAAAC,IAAMC,EAAuB,IAAI,GAEjCC,IAA4BC;AAAA,IAChC,OAAO;AAAA,MACL,eAAe;AAAA,MACf,eAAeH,EAAI;AAAA,MACnB,YAAY;AAAA,QACV,QAAAH;AAAA,QACA,SAAAC;AAAA,QACA,QAAQ;AAAA,QACR,cAAc,EAAE,GAAGL,GAAc,GAAGM,EAAS;AAAA,QAC7C,gBAAgB;AAAA,UACd,gBAAgBH,KAAkB;AAAA,QACpC;AAAA,QACA,gBAAAF;AAAA,MACF;AAAA,IAAA;AAAA,IAEF,CAACG,GAAQC,GAASF,GAAgBG,GAAUC,CAAG;AAAA,EAAA;AAGjD,SAAAI,EAAU,MAAM;AAEd,IADqB,OAAA,EAAS,MAAMF,CAAM,EAC7B,OAAO;AAAA,MAClB,GAAGA;AAAA,MACH,QAAAL;AAAA,IAAA,CACD;AAAA,EAAA,CACF,GAEMQ,gBAAAA,MAAC,SAAI,KAAAL,EAAU,CAAA;AACxB,GAEaM,IAAqB,CAChCP,OAEO;AAAA,EACL,SAAS,MAELM,gBAAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,KAAI;AAAA,MACJ,OAAK;AAAA,IAAA;AAAA,EAAA;AAAA,EAIX,cAAc,CAAC;AAAA,IACb,QAAAR;AAAA,IACA,SAAAC;AAAA,EAAA,4BAMGS,GACC,EAAA,UAAAF,gBAAAA,EAAAA,IAACV,KAAa,QAAAE,GAAgB,SAAAC,GAAkB,UAAAC,EAAoB,CAAA,EACtE,CAAA;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.21.14",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
5
  "homepage": "https://zudoku.dev",
6
6
  "repository": {
@@ -160,6 +160,7 @@
160
160
  "class-variance-authority": "0.7.0",
161
161
  "clsx": "2.1.1",
162
162
  "cmdk": "1.0.4",
163
+ "devlop": "^1.1.0",
163
164
  "embla-carousel-react": "8.3.1",
164
165
  "estree-util-value-to-estree": "3.2.1",
165
166
  "express": "4.21.1",
@@ -168,7 +169,9 @@
168
169
  "graphql-type-json": "0.3.2",
169
170
  "graphql-yoga": "5.7.0",
170
171
  "gray-matter": "4.0.3",
172
+ "hast-util-to-jsx-runtime": "^2.3.2",
171
173
  "hast-util-to-string": "3.0.1",
174
+ "html-url-attributes": "^3.0.1",
172
175
  "http-terminator": "3.2.0",
173
176
  "loglevel": "1.9.2",
174
177
  "lru-cache": "11.0.1",
@@ -185,7 +188,6 @@
185
188
  "react-error-boundary": "4.1.2",
186
189
  "react-hook-form": "7.53.0",
187
190
  "react-is": "18.3.1",
188
- "react-markdown": "9.0.1",
189
191
  "react-router-dom": "6.27.0",
190
192
  "rehype-raw": "7.0.0",
191
193
  "rehype-slug": "6.0.0",
@@ -195,6 +197,8 @@
195
197
  "remark-frontmatter": "5.0.0",
196
198
  "remark-gfm": "4.0.0",
197
199
  "remark-mdx-frontmatter": "5.0.0",
200
+ "remark-parse": "^11.0.0",
201
+ "remark-rehype": "^11.1.1",
198
202
  "rollup": "4.24.0",
199
203
  "semver": "7.6.3",
200
204
  "sitemap": "8.0.0",
@@ -204,6 +208,7 @@
204
208
  "tailwindcss": "3.4.13",
205
209
  "tsx": "^4.19.2",
206
210
  "ulidx": "2.4.1",
211
+ "unified": "^11.0.5",
207
212
  "unist-util-visit": "5.0.0",
208
213
  "urql": "4.1.0",
209
214
  "vaul": "1.1.1",
@@ -221,6 +226,7 @@
221
226
  "@types/estree": "1.0.6",
222
227
  "@types/express": "5.0.0",
223
228
  "@types/har-format": "1.2.15",
229
+ "@types/hast": "^3.0.4",
224
230
  "@types/json-schema": "7.0.15",
225
231
  "@types/mdast": "4.0.4",
226
232
  "@types/mdx": "2.0.13",
@@ -228,6 +234,7 @@
228
234
  "@types/object-hash": "3.0.6",
229
235
  "@types/react-is": "18.3.0",
230
236
  "@types/semver": "7.5.8",
237
+ "@types/unist": "^3.0.3",
231
238
  "@types/yargs": "17.0.33",
232
239
  "@vitest/coverage-v8": "2.1.8",
233
240
  "mdast-util-mdx": "3.0.0",
@@ -243,7 +250,6 @@
243
250
  },
244
251
  "optionalDependencies": {
245
252
  "@clerk/clerk-js": "5.11.0",
246
- "@inkeep/widgets": "^0.2.289",
247
253
  "@sentry/react": "^8.45.1"
248
254
  },
249
255
  "scripts": {
@@ -1,8 +1,8 @@
1
- import ReactMarkdown from "react-markdown";
2
1
  import rehypeRaw from "rehype-raw";
3
2
  import remarkGfm from "remark-gfm";
4
3
  import { visit } from "unist-util-visit";
5
4
  import { MdxComponents } from "../util/MdxComponents.js";
5
+ import { ReactMarkdown } from "./ReactMarkdown.js";
6
6
 
7
7
  // same as in packages/dev-portal/framework/vite.ts
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Espen Hovlandsdal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,264 @@
1
+ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
2
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
3
+
4
+ /**
5
+ * This is a fork of `react-markdown` converted to typescript.
6
+ * The reason we fork it is because react-markdown is comptaible with
7
+ * unified 11, but references the unified 10 and related packages causing
8
+ * type errors and a bunch of extra imports
9
+ *
10
+ * Source: https://github.com/remarkjs/react-markdown/blob/main/index.js
11
+ */
12
+
13
+ import { unreachable } from "devlop";
14
+ import type { Element, ElementContent, Nodes, Parents } from "hast";
15
+ import {
16
+ Components as JsxRuntimeComponents,
17
+ toJsxRuntime,
18
+ } from "hast-util-to-jsx-runtime";
19
+ import { urlAttributes } from "html-url-attributes";
20
+ import { ReactElement } from "react";
21
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
+ import remarkParse from "remark-parse";
23
+ import remarkRehype, { Options as RemarkRehypeOptions } from "remark-rehype";
24
+ import { PluggableList, unified } from "unified";
25
+ import { visit } from "unist-util-visit";
26
+ import { VFile } from "vfile";
27
+
28
+ const changelog =
29
+ "https://github.com/remarkjs/react-markdown/blob/main/changelog.md";
30
+
31
+ const emptyPlugins: PluggableList = [];
32
+ const emptyRemarkRehypeOptions: Readonly<RemarkRehypeOptions> = {
33
+ allowDangerousHtml: true,
34
+ };
35
+ const safeProtocol = /^(https?|ircs?|mailto|xmpp)$/i;
36
+
37
+ interface Deprecation {
38
+ from: string;
39
+ id: string;
40
+ to?: keyof Options;
41
+ }
42
+
43
+ interface AllowElement {
44
+ (
45
+ element: Readonly<Element>,
46
+ index: number,
47
+ parent: Readonly<Parents> | undefined,
48
+ ): boolean | null | undefined;
49
+ }
50
+
51
+ interface UrlTransform {
52
+ (
53
+ url: string,
54
+ key: string,
55
+ node: Readonly<Element>,
56
+ ): string | null | undefined;
57
+ }
58
+
59
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
60
+ interface Components extends Partial<JsxRuntimeComponents> {}
61
+
62
+ interface Options {
63
+ allowElement?: AllowElement | null;
64
+ allowedElements?: ReadonlyArray<string> | null;
65
+ children?: string | null;
66
+ className?: string | null;
67
+ components?: Components | null;
68
+ disallowedElements?: ReadonlyArray<string> | null;
69
+ rehypePlugins?: PluggableList | null;
70
+ remarkPlugins?: PluggableList | null;
71
+ remarkRehypeOptions?: Readonly<RemarkRehypeOptions> | null;
72
+ skipHtml?: boolean | null;
73
+ unwrapDisallowed?: boolean | null;
74
+ urlTransform?: UrlTransform | null;
75
+ }
76
+
77
+ const deprecations: ReadonlyArray<Readonly<Deprecation>> = [
78
+ { from: "astPlugins", id: "remove-buggy-html-in-markdown-parser" },
79
+ { from: "allowDangerousHtml", id: "remove-buggy-html-in-markdown-parser" },
80
+ {
81
+ from: "allowNode",
82
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
83
+ to: "allowElement",
84
+ },
85
+ {
86
+ from: "allowedTypes",
87
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
88
+ to: "allowedElements",
89
+ },
90
+ {
91
+ from: "disallowedTypes",
92
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
93
+ to: "disallowedElements",
94
+ },
95
+ { from: "escapeHtml", id: "remove-buggy-html-in-markdown-parser" },
96
+ { from: "includeElementIndex", id: "#remove-includeelementindex" },
97
+ {
98
+ from: "includeNodeIndex",
99
+ id: "change-includenodeindex-to-includeelementindex",
100
+ },
101
+ { from: "linkTarget", id: "remove-linktarget" },
102
+ {
103
+ from: "plugins",
104
+ id: "change-plugins-to-remarkplugins",
105
+ to: "remarkPlugins",
106
+ },
107
+ { from: "rawSourcePos", id: "#remove-rawsourcepos" },
108
+ { from: "renderers", id: "change-renderers-to-components", to: "components" },
109
+ { from: "source", id: "change-source-to-children", to: "children" },
110
+ { from: "sourcePos", id: "#remove-sourcepos" },
111
+ { from: "transformImageUri", id: "#add-urltransform", to: "urlTransform" },
112
+ { from: "transformLinkUri", id: "#add-urltransform", to: "urlTransform" },
113
+ ];
114
+
115
+ export function ReactMarkdown(options: Readonly<Options>): ReactElement {
116
+ const allowedElements = options.allowedElements;
117
+ const allowElement = options.allowElement;
118
+ const children = options.children || "";
119
+ const className = options.className;
120
+ const components = options.components;
121
+ const disallowedElements = options.disallowedElements;
122
+ const rehypePlugins = options.rehypePlugins || emptyPlugins;
123
+ const remarkPlugins = options.remarkPlugins || emptyPlugins;
124
+ const remarkRehypeOptions = options.remarkRehypeOptions
125
+ ? { ...options.remarkRehypeOptions, ...emptyRemarkRehypeOptions }
126
+ : emptyRemarkRehypeOptions;
127
+ const skipHtml = options.skipHtml;
128
+ const unwrapDisallowed = options.unwrapDisallowed;
129
+ const urlTransform = options.urlTransform || defaultUrlTransform;
130
+
131
+ const processor = unified()
132
+ .use(remarkParse)
133
+ .use(remarkPlugins)
134
+ .use(remarkRehype, remarkRehypeOptions)
135
+ .use(rehypePlugins);
136
+
137
+ const file = new VFile();
138
+
139
+ if (typeof children === "string") {
140
+ file.value = children;
141
+ } else {
142
+ unreachable(
143
+ `Unexpected value '${children}' for 'children' prop, expected 'string'`,
144
+ );
145
+ }
146
+
147
+ if (allowedElements && disallowedElements) {
148
+ unreachable(
149
+ "Unexpected combined `allowedElements` and `disallowedElements`, expected one or the other",
150
+ );
151
+ }
152
+
153
+ for (const deprecation of deprecations) {
154
+ if (Object.prototype.hasOwnProperty.call(options, deprecation.from)) {
155
+ unreachable(
156
+ `Unexpected '${deprecation.from}' prop, ` +
157
+ (deprecation.to ? `use '${deprecation.to}' instead` : "remove it") +
158
+ ` (see <${changelog}#${deprecation.id}> for more info)`,
159
+ );
160
+ }
161
+ }
162
+
163
+ const mdastTree = processor.parse(file);
164
+ let hastTree: Nodes = processor.runSync(mdastTree, file);
165
+
166
+ if (className) {
167
+ hastTree = {
168
+ type: "element",
169
+ tagName: "div",
170
+ properties: { className },
171
+ children:
172
+ hastTree.type === "root"
173
+ ? (hastTree.children as ElementContent[])
174
+ : [hastTree],
175
+ };
176
+ }
177
+
178
+ // Nodes type is slightly off, different versions of `hast` have different types
179
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
180
+ // @ts-ignore
181
+ visit(hastTree, transform);
182
+
183
+ return toJsxRuntime(hastTree, {
184
+ Fragment,
185
+ components,
186
+ ignoreInvalidStyle: true,
187
+ jsx,
188
+ jsxs,
189
+ passKeys: true,
190
+ passNode: true,
191
+ });
192
+
193
+ function transform(
194
+ node: Nodes,
195
+ index: number | null,
196
+ parent: Parents | undefined,
197
+ ): number | void {
198
+ if (node.type === "raw" && parent && typeof index === "number") {
199
+ if (skipHtml) {
200
+ parent.children.splice(index, 1);
201
+ } else {
202
+ parent.children[index] = { type: "text", value: node.value };
203
+ }
204
+ return index;
205
+ }
206
+
207
+ if (node.type === "element") {
208
+ for (const key in urlAttributes) {
209
+ if (
210
+ Object.prototype.hasOwnProperty.call(urlAttributes, key) &&
211
+ Object.prototype.hasOwnProperty.call(node.properties, key)
212
+ ) {
213
+ const value = node.properties[key];
214
+ const test = urlAttributes[key];
215
+ if (
216
+ test === null ||
217
+ test === undefined ||
218
+ test.includes(node.tagName)
219
+ ) {
220
+ node.properties[key] = urlTransform(String(value || ""), key, node);
221
+ }
222
+ }
223
+ }
224
+
225
+ let remove = allowedElements
226
+ ? !allowedElements.includes(node.tagName)
227
+ : disallowedElements
228
+ ? disallowedElements.includes(node.tagName)
229
+ : false;
230
+
231
+ if (!remove && allowElement && typeof index === "number") {
232
+ remove = !allowElement(node, index, parent);
233
+ }
234
+
235
+ if (remove && parent && typeof index === "number") {
236
+ if (unwrapDisallowed && node.children) {
237
+ parent.children.splice(index, 1, ...node.children);
238
+ } else {
239
+ parent.children.splice(index, 1);
240
+ }
241
+ return index;
242
+ }
243
+ }
244
+ }
245
+ }
246
+
247
+ function defaultUrlTransform(value: string): string {
248
+ const colon = value.indexOf(":");
249
+ const questionMark = value.indexOf("?");
250
+ const numberSign = value.indexOf("#");
251
+ const slash = value.indexOf("/");
252
+
253
+ if (
254
+ colon < 0 ||
255
+ (slash > -1 && colon > slash) ||
256
+ (questionMark > -1 && colon > questionMark) ||
257
+ (numberSign > -1 && colon > numberSign) ||
258
+ safeProtocol.test(value.slice(0, colon))
259
+ ) {
260
+ return value;
261
+ }
262
+
263
+ return "";
264
+ }
@@ -1,22 +1,31 @@
1
- import type { InkeepWidgetBaseSettings } from "@inkeep/widgets";
2
- import { lazy } from "react";
1
+ import { useEffect, useMemo, useRef } from "react";
3
2
  import { ClientOnly } from "../../components/ClientOnly.js";
4
3
  import type { ZudokuPlugin } from "../../core/plugins.js";
5
4
  import { aiChatSettings, baseSettings } from "./inkeep.js";
6
5
 
7
- type PickedPluginInkeepBaseSettings =
8
- | "apiKey"
9
- | "integrationId"
10
- | "organizationId"
11
- | "primaryBrandColor"
12
- | "organizationDisplayName";
6
+ interface PluginInkeepBaseSettings {
7
+ apiKey?: string;
8
+ integrationId: string;
9
+ organizationId: string;
10
+ organizationDisplayName?: string;
11
+ primaryBrandColor: string;
12
+ }
13
13
 
14
- type PluginInkeepBaseSettings = Pick<
15
- InkeepWidgetBaseSettings,
16
- PickedPluginInkeepBaseSettings
17
- >;
14
+ interface InkeepEmbedConfig {
15
+ componentType: string;
16
+ targetElement: HTMLElement;
17
+ properties: unknown;
18
+ }
18
19
 
19
- const Inkeep = lazy(() => import("./InkeepCustomTrigger.js"));
20
+ interface InkeepWidget {
21
+ render: (config: InkeepEmbedConfig & { isOpen: boolean }) => void;
22
+ }
23
+
24
+ declare global {
25
+ let Inkeep: () => {
26
+ embed: (config: InkeepEmbedConfig) => InkeepWidget;
27
+ };
28
+ }
20
29
 
21
30
  const InkeepSearch = ({
22
31
  prefilledQuery,
@@ -29,23 +38,50 @@ const InkeepSearch = ({
29
38
  prefilledQuery?: string | null;
30
39
  settings: PluginInkeepBaseSettings;
31
40
  }) => {
32
- return (
33
- <Inkeep
34
- isOpen={isOpen}
35
- onClose={onClose}
36
- baseSettings={{ ...baseSettings, ...settings }}
37
- aiChatSettings={aiChatSettings}
38
- searchSettings={{
39
- prefilledQuery: prefilledQuery || undefined,
40
- }}
41
- />
41
+ const ref = useRef<HTMLDivElement>(null);
42
+
43
+ const config: InkeepEmbedConfig = useMemo(
44
+ () => ({
45
+ componentType: "CustomTrigger",
46
+ targetElement: ref.current!,
47
+ properties: {
48
+ isOpen,
49
+ onClose,
50
+ onOpen: undefined,
51
+ baseSettings: { ...baseSettings, ...settings },
52
+ searchSettings: {
53
+ prefilledQuery: prefilledQuery || undefined,
54
+ },
55
+ aiChatSettings,
56
+ },
57
+ }),
58
+ [isOpen, onClose, prefilledQuery, settings, ref],
42
59
  );
60
+
61
+ useEffect(() => {
62
+ const inkeepWidget = Inkeep().embed(config);
63
+ inkeepWidget.render({
64
+ ...config,
65
+ isOpen,
66
+ });
67
+ });
68
+
69
+ return <div ref={ref} />;
43
70
  };
44
71
 
45
72
  export const inkeepSearchPlugin = (
46
73
  settings: PluginInkeepBaseSettings,
47
74
  ): ZudokuPlugin => {
48
75
  return {
76
+ getHead: () => {
77
+ return (
78
+ <script
79
+ type="module"
80
+ src="https://unpkg.com/@inkeep/uikit-js@0.3.19/dist/embed.js"
81
+ defer
82
+ ></script>
83
+ );
84
+ },
49
85
  renderSearch: ({
50
86
  isOpen,
51
87
  onClose,
@@ -1,9 +1,3 @@
1
- import {
2
- InkeepAIChatSettings,
3
- InkeepModalSettings,
4
- InkeepSearchSettings,
5
- } from "@inkeep/widgets";
6
-
7
1
  const baseSettings = {
8
2
  theme: {
9
3
  components: {
@@ -23,10 +17,10 @@ const baseSettings = {
23
17
  },
24
18
  } as const;
25
19
 
26
- const modalSettings: InkeepModalSettings = {};
20
+ const modalSettings = {};
27
21
 
28
- const searchSettings: InkeepSearchSettings = {};
22
+ const searchSettings = {};
29
23
 
30
- const aiChatSettings: InkeepAIChatSettings = {};
24
+ const aiChatSettings = {};
31
25
 
32
26
  export { aiChatSettings, baseSettings, modalSettings, searchSettings };