diff --git a/.dockerignore b/.dockerignore index 18710c85..24175c1d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,8 @@ +# Docs +README.md +LICENSE +TODO.txt + # Git .git .gitignore diff --git a/README.md b/README.md index 6d5c9db4..9e089614 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ This readme file is used mostly to document project dependencies - react-tooltip - @uiw/react-codemirror - @uiw/codemirror-themes + - @lezer/lr
@@ -45,6 +46,7 @@ This readme file is used mostly to document project dependencies - jest - ts-jest - @types/jest + - @lezer/generator
diff --git a/rsconcept/frontend/.eslintignore b/rsconcept/frontend/.eslintignore new file mode 100644 index 00000000..bb693464 --- /dev/null +++ b/rsconcept/frontend/.eslintignore @@ -0,0 +1 @@ +**/parser.ts \ No newline at end of file diff --git a/rsconcept/frontend/package-lock.json b/rsconcept/frontend/package-lock.json index b22721e1..920083c2 100644 --- a/rsconcept/frontend/package-lock.json +++ b/rsconcept/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "1.0.0", "dependencies": { + "@lezer/lr": "^1.3.9", "@uiw/codemirror-themes": "^4.21.9", "@uiw/react-codemirror": "^4.21.9", "axios": "^1.4.0", @@ -26,6 +27,7 @@ "reagraph": "^4.11.1" }, "devDependencies": { + "@lezer/generator": "^1.4.0", "@types/jest": "^29.5.3", "@types/node": "^20.4.5", "@types/react": "^18.2.15", @@ -3681,6 +3683,19 @@ "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.3.tgz", "integrity": "sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==" }, + "node_modules/@lezer/generator": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-1.4.0.tgz", + "integrity": "sha512-X/gB7vr7rEhtPQtgGxK61pMFOt60iXUBvANMq7DNO06PxrY6ZAmEEZIfSX8kfaVO/EVd9xARAsvguYDoShcMWA==", + "dev": true, + "dependencies": { + "@lezer/common": "^1.0.2", + "@lezer/lr": "^1.3.0" + }, + "bin": { + "lezer-generator": "dist/lezer-generator.cjs" + } + }, "node_modules/@lezer/highlight": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz", diff --git a/rsconcept/frontend/package.json b/rsconcept/frontend/package.json index 72777ced..5a8d3fed 100644 --- a/rsconcept/frontend/package.json +++ b/rsconcept/frontend/package.json @@ -4,6 +4,7 @@ "version": "1.0.0", "type": "module", "scripts": { + "prepare": "lezer-generator src/components/RSInput/rslang/rslangFull.grammar -o src/components/RSInput/rslang/parser.ts", "test": "jest", "dev": "vite", "build": "tsc && vite build", @@ -11,6 +12,7 @@ "preview": "vite preview" }, "dependencies": { + "@lezer/lr": "^1.3.9", "@uiw/codemirror-themes": "^4.21.9", "@uiw/react-codemirror": "^4.21.9", "axios": "^1.4.0", @@ -29,6 +31,7 @@ "reagraph": "^4.11.1" }, "devDependencies": { + "@lezer/generator": "^1.4.0", "@types/jest": "^29.5.3", "@types/node": "^20.4.5", "@types/react": "^18.2.15", diff --git a/rsconcept/frontend/public/DejaVu.ttf b/rsconcept/frontend/public/DejaVu.ttf index 27cff476..c1180728 100644 Binary files a/rsconcept/frontend/public/DejaVu.ttf and b/rsconcept/frontend/public/DejaVu.ttf differ diff --git a/rsconcept/frontend/src/components/Common/ConceptDataTable.tsx b/rsconcept/frontend/src/components/Common/ConceptDataTable.tsx index ea619cfe..34906066 100644 --- a/rsconcept/frontend/src/components/Common/ConceptDataTable.tsx +++ b/rsconcept/frontend/src/components/Common/ConceptDataTable.tsx @@ -38,12 +38,21 @@ createTheme('customDark', { } }, 'dark'); +createTheme('customLight', { + divider: { + default: '#d1d5db' + }, + striped: { + default: '#f0f2f7' + }, +}, 'light'); + function ConceptDataTable({ theme, ...props }: TableProps) { const { darkMode } = useConceptTheme(); return ( - theme={ theme ?? (darkMode ? 'customDark' : '')} + theme={ theme ?? (darkMode ? 'customDark' : 'customLight')} {...props} /> ); diff --git a/rsconcept/frontend/src/components/Common/ConceptSelect.tsx b/rsconcept/frontend/src/components/Common/ConceptSelect.tsx index 18679458..eb9bd45a 100644 --- a/rsconcept/frontend/src/components/Common/ConceptSelect.tsx +++ b/rsconcept/frontend/src/components/Common/ConceptSelect.tsx @@ -9,7 +9,7 @@ extends Omit>, 'noDataLabel'> { function ConceptSelect({ className, ...props }: ConceptSelectProps) { return ( { setFilterText(event.target.value); }} - /> - - - + width: '65px', + maxWidth: '65px', + conditionalCellStyles: [ + { + when: (cst: IConstituenta) => cst.id <= 0, + classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] + } + ] + }, + { + name: 'Описание', + id: 'description', + selector: (cst: IConstituenta) => getCstDescription(cst), + minWidth: '350px', + wrap: true, + conditionalCellStyles: [ + { + when: (cst: IConstituenta) => cst.id <= 0, + classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] + } + ] + }, + { + name: 'Выражение', + id: 'expression', + selector: (cst: IConstituenta) => cst.definition?.formal ?? '', + minWidth: '200px', + hide: 1600, + grow: 2, + wrap: true, + conditionalCellStyles: [ + { + when: (cst: IConstituenta) => cst.id <= 0, + classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] + } + ] + } + ], []); + + const maxHeight = useMemo( + () => { + const siblingHeight = `${baseHeight} - ${LOCAL_NAVIGATION_H}` + return (noNavigation ? + `calc(min(100vh - 5.2rem, ${siblingHeight}))` + : `calc(min(100vh - 8.7rem, ${siblingHeight}))`); + }, [noNavigation, baseHeight]); + + return (<> +
+ + setFilterText(event.target.value)} + /> + +
+
-

Список конституент пуст

-

Измените параметры фильтра

- } + conditionalRowStyles={conditionalRowStyles} + noDataComponent={ + +

Список конституент пуст

+

Измените параметры фильтра

+
+ } striped highlightOnHover @@ -173,7 +187,7 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons dense />
-); + ); } export default ViewSideConstituents; diff --git a/rsconcept/frontend/src/utils/print-lezer-tree.ts b/rsconcept/frontend/src/utils/print-lezer-tree.ts new file mode 100644 index 00000000..c47b5801 --- /dev/null +++ b/rsconcept/frontend/src/utils/print-lezer-tree.ts @@ -0,0 +1,60 @@ +import { NodeType, Tree, TreeCursor } from "@lezer/common" + +export type CursorNode = { + type: NodeType + from: number + to: number + isLeaf: boolean +} + +function cursorNode({ type, from, to }: TreeCursor, isLeaf = false): CursorNode { + return { type, from, to, isLeaf } +} + +type TreeTraversalOptions = { + beforeEnter?: (cursor: TreeCursor) => void + onEnter: (node: CursorNode) => false | void + onLeave?: (node: CursorNode) => false | void +} + +export function traverseTree(tree: Tree, { beforeEnter, onEnter, onLeave, }: TreeTraversalOptions) { + const cursor = tree.cursor(); + for (;;) { + let node = cursorNode(cursor) + let leave = false + const enter = !node.type.isAnonymous + if (enter && beforeEnter) beforeEnter(cursor) + node.isLeaf = !cursor.firstChild() + if (enter) { + leave = true + if (onEnter(node) === false) return + } + if (!node.isLeaf) continue + for (;;) { + node = cursorNode(cursor, node.isLeaf) + if (leave && onLeave) if (onLeave(node) === false) return; + leave = cursor.type.isAnonymous + node.isLeaf = false + if (cursor.nextSibling()) break; + if (!cursor.parent()) return; + leave = true + } + } +} + +export function printTree(tree: Tree): string { + const state = { + output: "", + prefixes: [] as string[] + } + traverseTree(tree, { + onEnter: node => { + state.output += "["; + state.output += node.type.name; + }, + onLeave: () => { + state.output += "]"; + }, + }) + return state.output; +} diff --git a/rsconcept/frontend/tsconfig.node.json b/rsconcept/frontend/tsconfig.node.json index 42872c59..364bc0ea 100644 --- a/rsconcept/frontend/tsconfig.node.json +++ b/rsconcept/frontend/tsconfig.node.json @@ -6,5 +6,5 @@ "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, - "include": ["vite.config.ts"] + "include": ["vite.config.ts", "package.json"] } diff --git a/rsconcept/frontend/vite.config.ts b/rsconcept/frontend/vite.config.ts index aa93ddaa..8cc2b4a1 100644 --- a/rsconcept/frontend/vite.config.ts +++ b/rsconcept/frontend/vite.config.ts @@ -1,10 +1,33 @@ import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; +import { dependencies } from './package.json' + +const exclVendors = ['react', 'react-router-dom', 'react-dom'] +function renderChunks(deps: Record) { + const chunks = {} + Object.keys(deps).forEach((key) => { + if (exclVendors.includes(key)) return + chunks[key] = [key] + }) + return chunks +} + // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], server: { port: 3000 + }, + build: { + chunkSizeWarningLimit: 4000, // KB + sourcemap: false, + rollupOptions: { + output: { + manualChunks: { + ...renderChunks(dependencies), + }, + }, + }, } }) diff --git a/updateProd.sh b/updateProd.sh new file mode 100644 index 00000000..e7a4693e --- /dev/null +++ b/updateProd.sh @@ -0,0 +1,3 @@ +git pull +docker compose -f "docker-compose-prod.yml" up --build -d +docker image prune -f \ No newline at end of file