Skip to content

Commit

Permalink
feat: support mermaid
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed Jan 13, 2025
1 parent ec258ff commit 0dc1b2e
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 50 deletions.
Binary file modified bun.lockb
Binary file not shown.
8 changes: 4 additions & 4 deletions nodedevpkg/vue-vite-presets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
},
"dependencies": {
"@innoai-tech/lodash": "^0.2.5",
"@innoai-tech/purebundle": "^0.5.1",
"@innoai-tech/vuecomponentcompleter": "^0.2.1",
"@innoai-tech/purebundle": "^0.5.2",
"@innoai-tech/vuecomponentcompleter": "^0.2.2",
"@mapbox/rehype-prism": "^0.9.0",
"@mdx-js/rollup": "^3.1.0",
"@swc/core": "^1.10.1",
"@swc/core": "^1.10.7",
"@vitejs/plugin-vue": "^5.2.1",
"hastscript": "^9.0.0",
"unist-util-visit": "^5.0.0",
"vite": "^6.0.3",
"vite": "^6.0.7",
"vite-plugin-pages": "^0.32.4",
"vite-tsconfig-paths": "^5.1.4"
},
Expand Down
4 changes: 3 additions & 1 deletion nodepkg/typedef/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"devDependencies": {
"reflect-metadata": "^0.2.2"
},
"peerDependencies": {},
"peerDependencies": {
"@innoai-tech/lodash": "*"
},
"exports": {
".": {
"bun": "./src/index.ts",
Expand Down
2 changes: 1 addition & 1 deletion nodepkg/vueuikit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/utils": "^1.4.2",
"@floating-ui/dom": "^1.6.12",
"@floating-ui/dom": "^1.6.13",
"@innoai-tech/lodash": "^0.2.5",
"@innoai-tech/vuekit": "workspace:^",
"@material/material-color-utilities": "^0.3.0",
Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"type": "module",
"private": true,
"packageManager": "[email protected].38",
"packageManager": "[email protected].43",
"workspaces": [
"nodepkg/*",
"nodedevpkg/*"
Expand All @@ -29,7 +29,8 @@
"rxjs": "^7.8.1"
},
"devDependencies": {
"@happy-dom/global-registrator": "^15.11.7",
"mermaid": "^11.4.1",
"@happy-dom/global-registrator": "^16.5.3",
"@innoai-tech/config": "^0.5.7",
"@innoai-tech/devconfig": "^0.5.0",
"@innoai-tech/monobundle": "^0.14.6",
Expand All @@ -39,17 +40,17 @@
"@vue/test-utils": "^2.4.6",
"bun-types": "latest",
"copy-to-clipboard": "^3.3.3",
"core-js": "^3.39.0",
"core-js": "^3.40.0",
"normalize.css": "^8.0.1",
"prettier": "^3.4.2",
"turbo": "^2.3.3",
"typescript": "^5.7.2",
"vite": "^6.0.3",
"typescript": "^5.7.3",
"vite": "^6.0.7",
"vue": "^3.5.13"
},
"resolutions": {
"vite": "^6.0.3",
"vue": "^3.5.13",
"rollup": "^4.20.0"
"rollup": "^4.30.1",
"vite": "^6.0.7",
"vue": "^3.5.13"
}
}
4 changes: 1 addition & 3 deletions webapp/openapi-playground/mod/openapi/DatabaseErView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ const DatabaseErTableColumnOfView = component$<{
);

return () => {

return (
<DatabaseErTableColumnOf
onClick={() => {
Expand Down Expand Up @@ -316,12 +315,11 @@ export const DatabaseDescription = styled<{
}
});


const DialogContainer = styled("div")({
display: "flex",
containerStyle: "sys.surface",
width: "90vw",
roundedLeft: "sm",
roundedBottom: "sm",
px: 16,
py: 36,
top: 0,
Expand Down
60 changes: 60 additions & 0 deletions webapp/openapi-playground/mod/openapi/MermaidView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { styled } from "@innoai-tech/vueuikit";
import type { VNodeChild } from "vue";
import { component$, observableRef, rx, subscribeOnMountedUntilUnmount } from "@innoai-tech/vuekit";
// @ts-ignore
import mermaid from "mermaid";
import { EMPTY, from, switchMap } from "rxjs";

export const PreWithMermaid = styled<{
$default?: VNodeChild
}, "pre">("pre", ({}, { slots }) => {
return (Root) => {
const children = slots.default?.();
const child = children?.[0];

if (child && (child as any).props.className === "language-mermaid") {
return <Mermaid code={(child as any).children} />;
}

return (
<Root>
{children}
</Root>
);
};
})({});


const Mermaid = component$<{
code: string
}>((props, {}) => {
const $el = observableRef(null);

mermaid.initialize({});

rx(
$el,
switchMap((el) => {
if (el) {
return from(mermaid.run({ nodes: [el] }));
}
return EMPTY;
}),
subscribeOnMountedUntilUnmount()
);

return () => {
return (
<MermaidContainer ref={$el} class={"mermaid"}>
{props.code}
</MermaidContainer>
);
};
});

const MermaidContainer = styled("div")({
"& > svg": {
minWidth: "80%"
}
});

129 changes: 96 additions & 33 deletions webapp/openapi-playground/mod/openapi/OperationView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { component$, render, rx, t } from "@innoai-tech/vuekit";
import { component$, ImmerBehaviorSubject, render, rx, t } from "@innoai-tech/vuekit";
import { OpenAPIProvider } from "./OpenAPIProvider.tsx";
import { filter, switchMap } from "rxjs";
import { Box, styled } from "@innoai-tech/vueuikit";
import { ResponseView } from "./ResponseView.tsx";
import { RequestBuilder } from "./RequestBuilder.tsx";
import { Markdown } from "@innoai-tech/vuemarkdown";
import { DatabaseErContainer } from "./DatabaseErView.tsx";
import { PreWithMermaid } from "./MermaidView.tsx";
import { Dialog, Icon, IconButton } from "@innoai-tech/vuematerial";
import { mdiHelp } from "@mdi/js";
import { MarkdownContainer } from "./SchemaView.tsx";

export const OperationView = component$({
operationId: t.string()
Expand All @@ -22,43 +26,73 @@ export const OperationView = component$({
filter((op): op is NonNullable<typeof op> => !!op)
);

const $heading = rx(
const open$ = ImmerBehaviorSubject.seed(false);

const $descInDialog = rx(
opExists$,
render((op) => {
return (
<OperationHeading sx={{
containerStyle: ({
"get": "sys.primary-container",
"post": "sys.success-container",
"put": "sys.warning-container",
"delete": "sys.error-container"
} as const)[op.method] ?? "sys.secondary-container"
return op.description ? (
<Markdown
text={op.description}
components={{
"pre": PreWithMermaid
}}
/>
) : null;
})
);

}}>
<div data-operation-method>
{op.method}
</div>
<div data-operation-desc>
<div data-operation-path>
{op.path}
</div>
<div data-operation-summary>
{op.summary} {op.operationId != op.summary ? op.operationId : ""}
</div>
</div>
</OperationHeading>
const $dialog = rx(
open$,
render((open) => {
return (
<Dialog
isOpen={open}
onClose={() => {
open$.next(false);
}}
>
<DialogContainer>
<Box sx={{
px: 24,
py: 12,
width: "100%"
}}>
<MarkdownContainer>
{$descInDialog}
</MarkdownContainer>
</Box>
</DialogContainer>
</Dialog>
);
})
);

const $desc = rx(
const DialogContainer = styled("div")({
display: "flex",
containerStyle: "sys.surface",
width: "90vw",
roundedBottom: "sm",
px: 16,
py: 36,
top: 0,
position: "absolute",
overflow: "auto"
});

const $descBtn = rx(
opExists$,
render((op) => {
return (
<Box sx={{ px: 24 }}>
<Markdown text={op.description ?? ""} />
</Box>
);
return op.description ? (
<IconButton
onClick={() => {
open$.next(true);
}}
>
<Icon path={mdiHelp} />
{$dialog}
</IconButton>
) : null;
})
);

Expand All @@ -82,6 +116,36 @@ export const OperationView = component$({
})
);

const $heading = rx(
opExists$,
render((op) => {
return (
<OperationHeading sx={{
containerStyle: ({
"get": "sys.primary-container",
"post": "sys.success-container",
"put": "sys.warning-container",
"delete": "sys.error-container"
} as const)[op.method] ?? "sys.secondary-container"
}}>
<div data-operation-method>
{op.method}
</div>
<div data-operation-desc>
<div data-operation-path>
{op.path}
</div>
<div data-operation-summary>
{op.summary} {op.operationId != op.summary ? op.operationId : ""}
</div>
</div>
<Box sx={{ flex: 1 }} />
{$descBtn}
</OperationHeading>
);
})
);

return rx(
op$,
render((op) => {
Expand All @@ -92,20 +156,18 @@ export const OperationView = component$({
return (
<OperationContainer key={op.operationId}>
{$heading}
{$desc}
<OperationMain>
<DatabaseErContainer
op={op}
/>
</OperationMain>
</OperationContainer>
)
);
}

return (
<OperationContainer key={op.operationId}>
{$heading}
{$desc}
<OperationMain>
<Box sx={{
flex: 1,
Expand All @@ -120,6 +182,7 @@ export const OperationView = component$({
);
});


const OperationContainer = styled("div")({
height: "100%",
display: "flex",
Expand All @@ -137,7 +200,7 @@ const OperationMain = styled("div")({
});


const OperationHeading = styled("div")({
const OperationHeading = styled("summary")({
display: "flex",
alignItems: "center",
width: "100%",
Expand Down

0 comments on commit 0dc1b2e

Please sign in to comment.