Skip to content

Commit

Permalink
build: simple setup vite for playground (#52)
Browse files Browse the repository at this point in the history
* build: simple setup vite for playground

* build: add preview script to see production build

* chore: remove parcel deps

* build: use vite to bundle react, excalidraw

* refactor: typo fix for "definition" in playground

* build: basic support hmr for test cases

* build: maintain same output build format which parcel uses

Maybe we won't need any adjustments to the vercel for it to work.

* fix: hmr testcase file update not get new definition for button

* chore: some minor adjust in tsconfig

* refactor: use glob pattern for warm-up vite

* feat: transform playground in react

* build: add typecheck for playground

* build: fix typecheck for playground

* refactor: use arrow function for testcases component

* refactor: use arrow function for mermaid component

* refactor: use arrow function for excalidraw component

* refactor: use arrow function for customtest component

* refactor: use arrow function for app component

* refactor: remove context, lifted state up for app

* improve and reuse types

* rename onChangeDefination to onChange

* cleanup Testcases.tsx

* rename syntax to definition to align with testcase

* fix

* refactor: rename mermaid to mermaid digram

* refactor: remove responsability to get mermaid data in excalidraw

* fix: minor fixes

* refactor: rename activeTestcase to activeTestcaseIndex

* refactor: improve readability for testcase error prop

* refactor: separate a single testcase component in own file

* refactor: move error responsability to mermaid diagram

* refactor: better way to handle active testcase file

* fix: force re-render when click in button

* feat: show error when occurs in parseMermaid

* rename the onchange handler to handleOnChange and use explicit types

* Refactor Single Testcase to render a single testcase
Add type attribute to each testcase
Use only activeTestCaseIndex and move to index.tsx to simplify and this also removes the hack to force rerender when render to excalidraw button clicked

* add missing type to class testcase

* fix typo for flowchart testcase

---------

Co-authored-by: Aakansha Doshi <[email protected]>
  • Loading branch information
igorwessel and ad1992 authored May 2, 2024
1 parent 287a699 commit e347696
Show file tree
Hide file tree
Showing 23 changed files with 1,059 additions and 1,684 deletions.
23 changes: 11 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
"description": "Mermaid to Excalidraw Diagrams",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"//": "Set targets.main = false, this instructs Parcel to ignore the main parameters.",
"targets": {
"main": false,
"types": false
},
"files": [
"dist/*"
],
"type": "module",
"scripts": {
"build": "rimraf ./dist && cross-env tsc -b src",
"start": "rimraf .parcel-cache && parcel playground/index.html --open --dist-dir ./public",
"build:playground": "rimraf ./public && parcel build playground/index.html --no-scope-hoist --dist-dir ./public --public-url /",
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx ."
"build": "rimraf -rf ./dist && cross-env tsc -b src",
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .",
"start": "vite playground",
"build:playground": "tsc --noEmit --project ./playground/tsconfig.json && vite build playground",
"preview": "npm run build:playground && vite preview --outDir ./public"
},
"dependencies": {
"@excalidraw/markdown-to-text": "0.1.2",
Expand All @@ -28,21 +24,24 @@
"@babel/core": "7.12.0",
"@excalidraw/eslint-config": "1.0.3",
"@excalidraw/excalidraw": "0.17.1-7381-cdf6d3e",
"@parcel/transformer-sass": "2.9.1",
"@types/mermaid": "9.2.0",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.4",
"@typescript-eslint/eslint-plugin": "5.59.9",
"@typescript-eslint/parser": "5.59.9",
"cross-env": "7.0.3",
"@vitejs/plugin-react-swc": "3.6.0",
"eslint": "8.42.0",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-prettier": "4.2.1",
"parcel": "2.9.1",
"prettier": "2.8.8",
"process": "0.11.10",
"react": "18.2.0",
"react-dom": "18.2.0",
"sass": "1.74.1",
"typescript": "5.2.2",
"rimraf": "5.0.5"
"rimraf": "5.0.5",
"vite": "5.2.8"
},
"resolutions": {
"@babel/preset-env": "7.13.8"
Expand Down
71 changes: 71 additions & 0 deletions playground/CustomTest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { MermaidDiagram } from "./MermaidDiagram.tsx";
import type { ActiveTestCaseIndex, MermaidData } from "./index.tsx";

interface CustomTestProps {
onChange: (
definition: MermaidData["definition"],
activeTestCaseIndex: ActiveTestCaseIndex
) => void;
mermaidData: MermaidData;
activeTestCaseIndex: ActiveTestCaseIndex;
}

const CustomTest = ({
onChange,
mermaidData,
activeTestCaseIndex,
}: CustomTestProps) => {
const isActive = activeTestCaseIndex === "custom";
return (
<>
<form
onSubmit={(e) => {
e.preventDefault();

const formData = new FormData(e.target as HTMLFormElement);

onChange(formData.get("mermaid-input")?.toString() || "", "custom");
}}
>
<textarea
id="mermaid-input"
rows={10}
cols={50}
name="mermaid-input"
onChange={(e) => {
if (!isActive) {
return;
}

onChange(e.target.value, "custom");
}}
style={{ marginTop: "1rem" }}
placeholder="Input Mermaid Syntax"
/>
<br />
<button type="submit" id="render-excalidraw-btn">
{"Render to Excalidraw"}
</button>
</form>

{isActive && (
<>
<MermaidDiagram
definition={mermaidData.definition}
id="custom-diagram"
/>

<details id="parsed-data-details">
<summary>{"Parsed data from parseMermaid"}</summary>
<pre id="custom-parsed-data">
{JSON.stringify(mermaidData.output, null, 2)}
</pre>
{mermaidData.error && <div id="error">{mermaidData.error}</div>}
</details>
</>
)}
</>
);
};

export default CustomTest;
59 changes: 0 additions & 59 deletions playground/ExcalidrawWrapper.ts

This file was deleted.

64 changes: 64 additions & 0 deletions playground/ExcalidrawWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useEffect, useState } from "react";
import {
Excalidraw,
convertToExcalidrawElements,
} from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types/types.js";
import { graphToExcalidraw } from "../src/graphToExcalidraw";
import { DEFAULT_FONT_SIZE } from "../src/constants";
import type { MermaidData } from "./";

interface ExcalidrawWrapperProps {
mermaidDefinition: MermaidData["definition"];
mermaidOutput: MermaidData["output"];
}

const ExcalidrawWrapper = ({
mermaidDefinition,
mermaidOutput,
}: ExcalidrawWrapperProps) => {
const [excalidrawAPI, setExcalidrawAPI] =
useState<ExcalidrawImperativeAPI | null>(null);

useEffect(() => {
if (!excalidrawAPI) {
return;
}

if (mermaidDefinition === "" || mermaidOutput === null) {
excalidrawAPI.resetScene();
return;
}

const { elements, files } = graphToExcalidraw(mermaidOutput, {
fontSize: DEFAULT_FONT_SIZE,
});

excalidrawAPI.updateScene({
elements: convertToExcalidrawElements(elements),
});
excalidrawAPI.scrollToContent(excalidrawAPI.getSceneElements(), {
fitToContent: true,
});

if (files) {
excalidrawAPI.addFiles(Object.values(files));
}
}, [mermaidDefinition, mermaidOutput]);

return (
<div className="excalidraw-wrapper">
<Excalidraw
initialData={{
appState: {
viewBackgroundColor: "#fafafa",
currentItemFontFamily: 1,
},
}}
excalidrawAPI={(api) => setExcalidrawAPI(api)}
/>
</div>
);
};

export default ExcalidrawWrapper;
44 changes: 44 additions & 0 deletions playground/MermaidDiagram.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useState, useTransition, useEffect } from "react";
import mermaid from "mermaid";

interface MermaidProps {
id: string;
definition: string;
}

export const MermaidDiagram = ({ definition, id }: MermaidProps) => {
const [svg, setSvg] = useState("");
const [error, setError] = useState<string | null>(null);
const [, startTransition] = useTransition();

useEffect(() => {
const render = async (id: string, definition: string) => {
try {
setError(null);

const { svg } = await mermaid.render(
`mermaid-diagram-${id}`,
definition
);
startTransition(() => {
setSvg(svg);
});
} catch (err) {
setError(String(err));
}
};

render(id, definition);
}, [definition, id]);

return (
<>
<div
style={{ width: "50%" }}
className="mermaid"
dangerouslySetInnerHTML={{ __html: svg }}
/>
{error && <div id="error">{error}</div>}
</>
);
};
39 changes: 39 additions & 0 deletions playground/SingleTestCase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { MermaidDiagram } from "./MermaidDiagram";

export interface TestCase {
type: "class" | "flowchart" | "sequence" | "unsupported";
name: string;
definition: string;
}

export interface SingleTestCaseProps {
testcase: TestCase;
onChange: (activeTestcaseIndex: number) => void;
index: number;
activeTestcaseIndex?: number;
}

const SingleTestCase = ({ testcase, onChange, index }: SingleTestCaseProps) => {
const { name, definition, type } = testcase;
return (
<>
<h2 style={{ marginTop: "50px", color: "#f06595" }}>{name}</h2>
<pre>{definition}</pre>
<button
onClick={() => {
onChange(index);
}}
>
{"Render to Excalidraw"}
</button>

<MermaidDiagram
key={definition}
definition={definition}
id={`${type}-${index}`}
/>
</>
);
};

export default SingleTestCase;
Loading

0 comments on commit e347696

Please sign in to comment.