Switch to monaco-editor from codemirror (#403)

* switch to monaco-editor

* fix styles
This commit is contained in:
1ilit 2025-04-12 20:50:47 +04:00 committed by GitHub
parent 00e97653cb
commit adf647483c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 259 additions and 325 deletions

302
package-lock.json generated
View File

@ -8,14 +8,10 @@
"name": "client-vite",
"version": "0.0.0",
"dependencies": {
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.6.3",
"@dbml/core": "^3.9.7-alpha.0",
"@douyinfe/semi-ui": "^2.77.1",
"@lexical/react": "^0.12.5",
"@uiw/codemirror-theme-github": "^4.21.25",
"@uiw/codemirror-theme-vscode": "^4.21.25",
"@uiw/react-codemirror": "^4.21.25",
"@monaco-editor/react": "^4.7.0",
"@vercel/analytics": "^1.2.2",
"@vercel/speed-insights": "^1.2.0",
"axios": "^1.8.2",
@ -378,115 +374,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@codemirror/autocomplete": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz",
"integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0"
},
"peerDependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0"
}
},
"node_modules/@codemirror/commands": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.4.0.tgz",
"integrity": "sha512-HB3utD5GxCvEhSyj5EuG9KpuQQhFpxalh3lwrspyL/GeSNDe4c6JDxVzL12SJ+7gUknHjZzmq7OPCb9QPgiRmQ==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.1.0"
}
},
"node_modules/@codemirror/lang-json": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@lezer/json": "^1.0.0"
}
},
"node_modules/@codemirror/lang-sql": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.6.3.tgz",
"integrity": "sha512-fo5i3OD/7TmmqMtKycC4OaqfPsRxk0sKOb35g8cOtyUyyI2hfP2qXkDc7Asb6h7BiJK+MU/DYVPnQm6iNB5ZTw==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@codemirror/language": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz",
"integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
"@lezer/common": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"node_modules/@codemirror/lint": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz",
"integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/search": {
"version": "6.5.6",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
},
"node_modules/@codemirror/theme-one-dark": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.26.3",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
"integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
"dependencies": {
"@codemirror/state": "^6.4.0",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"node_modules/@dbml/core": {
"version": "3.9.7-alpha.0",
"resolved": "https://registry.npmjs.org/@dbml/core/-/core-3.9.7-alpha.0.tgz",
@ -1516,37 +1403,6 @@
"yjs": ">=13.5.22"
}
},
"node_modules/@lezer/common": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
},
"node_modules/@lezer/highlight": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/json": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/lr": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz",
"integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@mdx-js/mdx": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz",
@ -1583,6 +1439,29 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/@monaco-editor/loader": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
"integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
"license": "MIT",
"dependencies": {
"state-local": "^1.0.6"
}
},
"node_modules/@monaco-editor/react": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
"integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
"license": "MIT",
"dependencies": {
"@monaco-editor/loader": "^1.5.0"
},
"peerDependencies": {
"monaco-editor": ">= 0.25.0 < 1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -2643,97 +2522,6 @@
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"license": "MIT"
},
"node_modules/@uiw/codemirror-extensions-basic-setup": {
"version": "4.21.25",
"resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.25.tgz",
"integrity": "sha512-eeUKlmEE8aSoSgelS8OR2elcPGntpRo669XinAqPCLa0eKorT2B0d3ts+AE+njAeGk744tiyAEbHb2n+6OQmJw==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
},
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@codemirror/autocomplete": ">=6.0.0",
"@codemirror/commands": ">=6.0.0",
"@codemirror/language": ">=6.0.0",
"@codemirror/lint": ">=6.0.0",
"@codemirror/search": ">=6.0.0",
"@codemirror/state": ">=6.0.0",
"@codemirror/view": ">=6.0.0"
}
},
"node_modules/@uiw/codemirror-theme-github": {
"version": "4.21.25",
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.21.25.tgz",
"integrity": "sha512-RDS9s/Lbi1uIvupIXNiREFMryZjd7X4xRMKzmf6NfZuXWVdDATTA1b5smzxXldJgl8bY4QoOevczRncFTVRfGA==",
"dependencies": {
"@uiw/codemirror-themes": "4.21.25"
},
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
}
},
"node_modules/@uiw/codemirror-theme-vscode": {
"version": "4.21.25",
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.21.25.tgz",
"integrity": "sha512-1gubCz7kHE5XH3H1IUTSrnyK/G3dQRmOIgPFsefE9e+TizhBJnkbKSDSfRfpm5l7jl1G7v/as0HQvN3cYg/Rkg==",
"dependencies": {
"@uiw/codemirror-themes": "4.21.25"
},
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
}
},
"node_modules/@uiw/codemirror-themes": {
"version": "4.21.25",
"resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.21.25.tgz",
"integrity": "sha512-C3t/voELxQj0eaVhrlgzaOnSALNf8bOcRbL5xN9r2+RkdsbFOmvNl3VVhlxEB7PSGc1jUZwVO4wQsB2AP178ag==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
},
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@codemirror/language": ">=6.0.0",
"@codemirror/state": ">=6.0.0",
"@codemirror/view": ">=6.0.0"
}
},
"node_modules/@uiw/react-codemirror": {
"version": "4.21.25",
"resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.25.tgz",
"integrity": "sha512-mBrCoiffQ+hbTqV1JoixFEcH7BHXkS3PjTyNH7dE8Gzf3GSBRazhtSM5HrAFIiQ5FIRGFs8Gznc4UAdhtevMmw==",
"dependencies": {
"@babel/runtime": "^7.18.6",
"@codemirror/commands": "^6.1.0",
"@codemirror/state": "^6.1.1",
"@codemirror/theme-one-dark": "^6.0.0",
"@uiw/codemirror-extensions-basic-setup": "4.21.25",
"codemirror": "^6.0.0"
},
"funding": {
"url": "https://jaywcjlove.github.io/#/sponsor"
},
"peerDependencies": {
"@babel/runtime": ">=7.11.0",
"@codemirror/state": ">=6.0.0",
"@codemirror/theme-one-dark": ">=6.0.0",
"@codemirror/view": ">=6.0.0",
"codemirror": ">=6.0.0",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@ -3280,20 +3068,6 @@
"node": ">=6"
}
},
"node_modules/codemirror": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"node_modules/collapse-white-space": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
@ -3373,11 +3147,6 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -6775,6 +6544,13 @@
"node": "*"
}
},
"node_modules/monaco-editor": {
"version": "0.52.2",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
"integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
"license": "MIT",
"peer": true
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -7960,6 +7736,12 @@
"node": ">=0.1.14"
}
},
"node_modules/state-local": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
"license": "MIT"
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@ -8072,11 +7854,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/style-mod": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
},
"node_modules/style-to-js": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz",
@ -8607,11 +8384,6 @@
"node": ">=0.10.0"
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -10,14 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.6.3",
"@dbml/core": "^3.9.7-alpha.0",
"@douyinfe/semi-ui": "^2.77.1",
"@lexical/react": "^0.12.5",
"@uiw/codemirror-theme-github": "^4.21.25",
"@uiw/codemirror-theme-vscode": "^4.21.25",
"@uiw/react-codemirror": "^4.21.25",
"@monaco-editor/react": "^4.7.0",
"@vercel/analytics": "^1.2.2",
"@vercel/speed-insights": "^1.2.0",
"axios": "^1.8.2",

View File

@ -0,0 +1,47 @@
import { Editor } from "@monaco-editor/react";
import { useDiagram, useSettings } from "../../hooks";
import { Button, Toast } from "@douyinfe/semi-ui";
import { useTranslation } from "react-i18next";
import { IconCopy } from "@douyinfe/semi-icons";
import { setUpDBML } from "./setUpDBML";
import "./styles.css";
export default function CodeEditor({ showCopyButton, ...props }) {
const { settings } = useSettings();
const { database } = useDiagram();
const { t } = useTranslation();
const copyCode = () => {
navigator.clipboard
.writeText(props.value)
.then(() => Toast.success(t("copied_to_clipboard")))
.catch((e) => {
console.log(e);
});
};
const handleEditorMount = (editor, monaco) => {
setUpDBML(monaco, database);
setTimeout(() => {
editor.getAction("editor.action.formatDocument").run();
}, 300);
};
return (
<div className="relative">
<Editor
{...props}
theme={settings.mode === "light" ? "vs" : "vs-dark"}
onMount={handleEditorMount}
/>
{showCopyButton && (
<Button
className="absolute right-6 bottom-2 z-10"
icon={<IconCopy />}
onClick={copyCode}
/>
)}
</div>
);
}

View File

@ -0,0 +1,152 @@
import { dbToTypes } from "../../data/datatypes";
export function setUpDBML(monaco, database) {
monaco.languages.register({ id: "dbml" });
console.log(Object.keys(dbToTypes[database]));
monaco.languages.setMonarchTokensProvider("dbml", {
defaultToken: "",
tokenPostfix: ".dbml",
ignoreCase: true,
keywords: [
"table",
"tablegroup",
"project",
"enum",
"ref",
"as",
"indexes",
"index",
"note",
"delete",
"update",
"pk",
"increment",
"not",
"null",
"unique",
"default",
],
typeKeywords: Object.keys(dbToTypes[database]),
operators: [
"=",
">",
"<",
"!",
"~",
"?",
":",
"==",
"<=",
">=",
"!=",
"&&",
"||",
"++",
"--",
"+",
"-",
"*",
"/",
"&",
"|",
"^",
],
symbols: /[=><!~?:&|+\-*/^%]+/,
escapes:
/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
tokenizer: {
root: [
[
/[a-zA-Z_$][\w$]*/,
{
cases: {
"@keywords": "keyword",
"@typeKeywords": "type",
"@default": "identifier",
},
},
],
{ include: "@whitespace" },
[/[{}()[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[
/@symbols/,
{
cases: {
"@operators": "operator",
"@default": "",
},
},
],
[/\d*\.\d+([eE][-+]?\d+)?/, "number.float"],
[/0[xX][0-9a-fA-F]+/, "number.hex"],
[/\d+/, "number"],
[/[;,.]/, "delimiter"],
[/"([^"\\]|\\.)*$/, "string.invalid"],
[/'([^'\\]|\\.)*$/, "string.invalid"],
[/"/, { token: "string.quote", bracket: "@open", next: "@dqstring" }],
[/'/, { token: "string.quote", bracket: "@open", next: "@sqstring" }],
],
dqstring: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
sqstring: [
[/[^\\']+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/'/, { token: "string.quote", bracket: "@close", next: "@pop" }],
],
comment: [
[/[^\\/*]+/, "comment"],
[/\/\*/, "comment", "@push"],
["\\*/", "comment", "@pop"],
[/[\\/*]/, "comment"],
],
whitespace: [
[/[ \t\r\n]+/, "white"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*$/, "comment"],
],
},
});
monaco.languages.setLanguageConfiguration("dbml", {
comments: {
lineComment: "//",
blockComment: ["/*", "*/"],
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
],
autoClosingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
],
surroundingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
],
});
}

View File

@ -0,0 +1,4 @@
.monaco-editor,
.monaco-editor > .overflow-guard {
border-radius: 6px;
}

View File

@ -1,52 +0,0 @@
import { useState } from "react";
import { sql } from "@codemirror/lang-sql";
import { json } from "@codemirror/lang-json";
import { vscodeDark } from "@uiw/codemirror-theme-vscode";
import { githubLight } from "@uiw/codemirror-theme-github";
import { useSettings } from "../../../hooks";
import { useTranslation } from "react-i18next";
import CodeMirror from "@uiw/react-codemirror";
const languageExtension = {
sql: [sql()],
json: [json()],
};
export default function Code({ value, language }) {
const { t } = useTranslation();
const { settings } = useSettings();
const [copied, setCopied] = useState(false);
const copyCode = () => {
navigator.clipboard
.writeText(value)
.then(() => {
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 2000);
})
.catch((e) => {
console.log(e);
});
};
return (
<div className="relative">
<CodeMirror
value={value}
height="360px"
extensions={languageExtension[language]}
editable={false}
theme={settings.mode === "dark" ? vscodeDark : githubLight}
/>
<button
onClick={copyCode}
className={`absolute right-4 top-2 px-2 py-1 rounded-sm ${settings.mode === "dark" ? "bg-zinc-700" : "bg-zinc-200"}`}
>
<i className={`bi bi-clipboard${copied ? "-check" : ""} me-2`} />
{t("copy")}
</button>
</div>
);
}

View File

@ -34,12 +34,19 @@ import ImportSource from "./ImportSource";
import SetTableWidth from "./SetTableWidth";
import Language from "./Language";
import Share from "./Share";
import Code from "./Code";
import CodeEditor from "../../CodeEditor";
import { useTranslation } from "react-i18next";
import { importSQL } from "../../../utils/importSQL";
import { databases } from "../../../data/databases";
import { isRtl } from "../../../i18n/utils/rtl";
const extensionToLanguage = {
md: "markdown",
sql: "sql",
dbml: "dbml",
json: "json",
};
export default function Modal({
modal,
setModal,
@ -52,7 +59,8 @@ export default function Modal({
importFrom,
}) {
const { t, i18n } = useTranslation();
const { tables, setTables, setRelationships, database, setDatabase } = useDiagram();
const { tables, setTables, setRelationships, database, setDatabase } =
useDiagram();
const { setNotes } = useNotes();
const { setAreas } = useAreas();
const { setTypes } = useTypes();
@ -307,7 +315,13 @@ export default function Modal({
{modal === MODAL.IMG ? (
<Image src={exportData.data} alt="Diagram" height={280} />
) : (
<Code value={exportData.data} language={exportData.extension} />
<CodeEditor
height={360}
value={exportData.data}
language={extensionToLanguage[exportData.extension]}
options={{ readOnly: true }}
showCopyButton={true}
/>
)}
<div className="text-sm font-semibold mt-2">{t("filename")}:</div>
<Input

View File

@ -34,6 +34,7 @@ export const getModalWidth = (modal) => {
switch (modal) {
case MODAL.LANGUAGE:
case MODAL.OPEN:
case MODAL.CODE:
case MODAL.NEW:
return 740;
default: