Merge branch 'pen-plotter' of inno-js/multy-stub into master
This commit is contained in:
commit
9eafc74de9
477
package-lock.json
generated
477
package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"bcrypt": "^5.1.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
@ -19,6 +20,7 @@
|
||||
"express": "^4.18.2",
|
||||
"express-jwt": "^8.4.1",
|
||||
"express-session": "^1.17.3",
|
||||
"jsdom": "^22.1.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongodb": "^3.6.8",
|
||||
"mysql": "^2.18.1",
|
||||
@ -269,6 +271,31 @@
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||
"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
|
||||
"dependencies": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/connect": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
||||
@ -282,6 +309,33 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "^4.17.33",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express-serve-static-core": {
|
||||
"version": "4.17.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz",
|
||||
"integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*",
|
||||
"@types/send": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-errors": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
|
||||
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
@ -296,11 +350,50 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mime": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz",
|
||||
"integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw=="
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz",
|
||||
"integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw=="
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
|
||||
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
|
||||
},
|
||||
"node_modules/@types/send": {
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
|
||||
"dependencies": {
|
||||
"@types/mime": "^1",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/serve-static": {
|
||||
"version": "1.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
||||
"integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==",
|
||||
"dependencies": {
|
||||
"@types/http-errors": "*",
|
||||
"@types/mime": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/abab": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
@ -965,6 +1058,61 @@
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
|
||||
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz",
|
||||
"integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==",
|
||||
"dependencies": {
|
||||
"rrweb-cssom": "^0.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
|
||||
"integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
|
||||
"dependencies": {
|
||||
"abab": "^2.0.6",
|
||||
"whatwg-mimetype": "^3.0.0",
|
||||
"whatwg-url": "^12.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/tr46": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
||||
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/whatwg-url": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz",
|
||||
"integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==",
|
||||
"dependencies": {
|
||||
"tr46": "^4.1.1",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@ -973,6 +1121,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
|
||||
},
|
||||
"node_modules/deep-is": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
@ -1053,6 +1206,25 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/domexception": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
|
||||
"integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
|
||||
"dependencies": {
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/domexception/node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
||||
@ -1144,6 +1316,17 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
|
||||
@ -1969,20 +2152,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@ -2237,6 +2406,17 @@
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
|
||||
},
|
||||
"node_modules/html-encoding-sniffer": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
|
||||
"dependencies": {
|
||||
"whatwg-encoding": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
@ -2252,6 +2432,40 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
|
||||
"dependencies": {
|
||||
"@tootallnate/once": "2",
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
@ -2547,6 +2761,11 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
|
||||
},
|
||||
"node_modules/is-regex": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||
@ -2677,6 +2896,98 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "22.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
|
||||
"integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==",
|
||||
"dependencies": {
|
||||
"abab": "^2.0.6",
|
||||
"cssstyle": "^3.0.0",
|
||||
"data-urls": "^4.0.0",
|
||||
"decimal.js": "^10.4.3",
|
||||
"domexception": "^4.0.0",
|
||||
"form-data": "^4.0.0",
|
||||
"html-encoding-sniffer": "^3.0.0",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"nwsapi": "^2.2.4",
|
||||
"parse5": "^7.1.2",
|
||||
"rrweb-cssom": "^0.6.0",
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^4.1.2",
|
||||
"w3c-xmlserializer": "^4.0.0",
|
||||
"webidl-conversions": "^7.0.0",
|
||||
"whatwg-encoding": "^2.0.0",
|
||||
"whatwg-mimetype": "^3.0.0",
|
||||
"whatwg-url": "^12.0.1",
|
||||
"ws": "^8.13.0",
|
||||
"xml-name-validator": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"canvas": "^2.5.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"canvas": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/tr46": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
|
||||
"integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/whatwg-url": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz",
|
||||
"integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==",
|
||||
"dependencies": {
|
||||
"tr46": "^4.1.1",
|
||||
"webidl-conversions": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
@ -3228,6 +3539,11 @@
|
||||
"set-blocking": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nwsapi": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
|
||||
"integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ=="
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@ -3442,6 +3758,17 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
|
||||
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
|
||||
"dependencies": {
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
@ -3554,6 +3881,11 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
||||
},
|
||||
"node_modules/pstree.remy": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||
@ -3564,7 +3896,6 @@
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -3583,6 +3914,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@ -3689,6 +4025,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.3",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.3.tgz",
|
||||
@ -3738,6 +4079,11 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rrweb-cssom": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
|
||||
"integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw=="
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
@ -3843,6 +4189,17 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/saxes": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
||||
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
|
||||
"dependencies": {
|
||||
"xmlchars": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.22.7"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
@ -4260,6 +4617,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.1.15",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
|
||||
@ -4334,6 +4696,20 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
|
||||
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.33",
|
||||
"punycode": "^2.1.1",
|
||||
"universalify": "^0.2.0",
|
||||
"url-parse": "^1.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
@ -4489,6 +4865,14 @@
|
||||
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
@ -4506,6 +4890,15 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||
"dependencies": {
|
||||
"querystringify": "^2.1.1",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@ -4535,6 +4928,17 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||
"integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
|
||||
"dependencies": {
|
||||
"xml-name-validator": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/wait-on": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.0.1.tgz",
|
||||
@ -4558,6 +4962,36 @@
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
||||
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
|
||||
"dependencies": {
|
||||
"iconv-lite": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
|
||||
"integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
@ -4649,6 +5083,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
||||
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlchars": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -24,6 +24,7 @@
|
||||
"license": "MIT",
|
||||
"homepage": "https://bitbucket.org/online-mentor/multi-stub#readme",
|
||||
"dependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"bcrypt": "^5.1.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"cookie-parser": "^1.4.5",
|
||||
@ -34,6 +35,7 @@
|
||||
"express": "^4.18.2",
|
||||
"express-jwt": "^8.4.1",
|
||||
"express-session": "^1.17.3",
|
||||
"jsdom": "^22.1.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongodb": "^3.6.8",
|
||||
"mysql": "^2.18.1",
|
||||
|
@ -43,9 +43,9 @@ app.use(require('./root'))
|
||||
app.use('/lobsters', require('./routers/lobsters'))
|
||||
app.use('/example', require('./routers/example'))
|
||||
// app.use('/coder', require('./routers/coder'))
|
||||
app.use('/stc-21-03', require('./routers/stc-21-03'))
|
||||
app.use('/stc-21', require('./routers/stc'))
|
||||
app.use('/stc-22-24', require('./routers/stc-22-24'))
|
||||
//app.use('/stc-21-03', require('./routers/stc-21-03'))
|
||||
//app.use('/stc-21', require('./routers/stc'))
|
||||
//app.use('/stc-22-24', require('./routers/stc-22-24'))
|
||||
// app.use('/bushou-api', require('./routers/bushou'))
|
||||
|
||||
// app.use('/uryndyklar-api', require('./routers/uryndyklar'))
|
||||
@ -55,9 +55,9 @@ app.use('/stc-22-24', require('./routers/stc-22-24'))
|
||||
// app.use('/task-boss', require('./routers/task-boss'))
|
||||
// app.use('/car-wash', require('./routers/car-wash'))
|
||||
app.use('/zoom-bar', require('./routers/zoom-bar'))
|
||||
app.use('/basket', require('./routers/basket'))
|
||||
app.use('/easy-project', require('./routers/easy-project'))
|
||||
app.use('/sugarbun', require('./routers/sugarbun'))
|
||||
//app.use('/basket', require('./routers/basket'))
|
||||
//app.use('/easy-project', require('./routers/easy-project'))
|
||||
//app.use('/sugarbun', require('./routers/sugarbun'))
|
||||
app.use('/epja-2023-2', require('./routers/epja-2023-2'))
|
||||
require('./routers/hub-video')
|
||||
|
||||
|
@ -3,5 +3,6 @@ const router = express.Router()
|
||||
|
||||
|
||||
router.use('/example', require('./example/index'))
|
||||
router.use('/pen-plotter', require('./pen-plotter/index'))
|
||||
|
||||
module.exports = router
|
||||
|
3
server/routers/epja-2023-2/pen-plotter/.gitignore
vendored
Normal file
3
server/routers/epja-2023-2/pen-plotter/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
static/
|
||||
profiles/
|
35
server/routers/epja-2023-2/pen-plotter/index.js
Normal file
35
server/routers/epja-2023-2/pen-plotter/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const BASE_PATH = __dirname;
|
||||
const STATIC_PATH = `${BASE_PATH}/static`;
|
||||
// Serve static files
|
||||
router.use(express.static(path.join(__dirname, './assets/')))
|
||||
// Add the required directories
|
||||
router.use((req, res, next) => {
|
||||
const directories = ['/static', '/profiles']
|
||||
directories.forEach((dir) => {
|
||||
if (!fs.existsSync(BASE_PATH + dir)) {
|
||||
fs.mkdirSync(BASE_PATH + dir)
|
||||
}
|
||||
})
|
||||
next()
|
||||
})
|
||||
// Serve Static generated SVGs
|
||||
router.get('/static/:name', async (req, res, next) => {
|
||||
const fileName = req.params.name
|
||||
const filePath = `${STATIC_PATH}/${fileName}`
|
||||
|
||||
const file = await fs.readFileSync(filePath)
|
||||
res.setHeader('Content-Type', 'image/svg+xml')
|
||||
res.send(file)
|
||||
})
|
||||
router.use('/api', require('./routes/api').default)
|
||||
|
||||
router.get('/info', (req, res) => {
|
||||
res.send('Pen-Plotter backend')
|
||||
})
|
||||
|
||||
module.exports = router
|
9
server/routers/epja-2023-2/pen-plotter/paths.js
Normal file
9
server/routers/epja-2023-2/pen-plotter/paths.js
Normal file
@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.STATIC_PATH = exports.PROFILES_PATH = exports.BASE_PATH = void 0;
|
||||
const BASE_PATH = __dirname;
|
||||
exports.BASE_PATH = BASE_PATH;
|
||||
const PROFILES_PATH = `${BASE_PATH}/profiles`;
|
||||
exports.PROFILES_PATH = PROFILES_PATH;
|
||||
const STATIC_PATH = `${BASE_PATH}/static`;
|
||||
exports.STATIC_PATH = STATIC_PATH;
|
10
server/routers/epja-2023-2/pen-plotter/routes/api.js
Normal file
10
server/routers/epja-2023-2/pen-plotter/routes/api.js
Normal file
@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const router = express_1.default.Router();
|
||||
router.use("/users", require("./sub-routes/users").default);
|
||||
router.use("/svg", require("./sub-routes/svg").default);
|
||||
exports.default = router;
|
111
server/routers/epja-2023-2/pen-plotter/routes/sub-routes/svg.js
Normal file
111
server/routers/epja-2023-2/pen-plotter/routes/sub-routes/svg.js
Normal file
@ -0,0 +1,111 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const svg_1 = require("../../utilities/svg");
|
||||
const user_1 = require("../../utilities/user");
|
||||
const paths_1 = require("../../paths");
|
||||
const router = express_1.default.Router();
|
||||
router.post("/characters", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
const { name, username, svg } = req.body;
|
||||
// Validate input
|
||||
if (!name || !username || !svg) {
|
||||
return res.status(400).json({ error: "Missing name, username, or SVG" });
|
||||
}
|
||||
// Check if the user exists
|
||||
if (!(yield (0, user_1.userExists)(username))) {
|
||||
return res.status(400).json({ error: "User does not exist" });
|
||||
}
|
||||
// Create character directory if it doesn't exist
|
||||
const characterName = (0, svg_1.validateName)(name);
|
||||
const userDir = `${paths_1.PROFILES_PATH}/${username}`;
|
||||
yield (0, svg_1.createCharacterDirectory)(userDir, characterName);
|
||||
// Generate a unique filename for the SVG
|
||||
const svgPath = yield (0, svg_1.generateUniqueSVGPath)(`${userDir}/${characterName}`);
|
||||
// Extract the SVG content from the data URL
|
||||
const svgContent = decodeURIComponent(svg.split(",")[1]);
|
||||
// Write the SVG content to a file
|
||||
yield (0, svg_1.writeSVGToFile)(svgPath, svgContent);
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Something went wrong!" });
|
||||
}
|
||||
}));
|
||||
router.post("/number-entries", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const { char, username } = req.body;
|
||||
try {
|
||||
if (!char || !username) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ error: "Missing characterName or username" });
|
||||
}
|
||||
const validCharName = (0, svg_1.validateName)(char);
|
||||
const characterDir = `${paths_1.PROFILES_PATH}/${username}/${validCharName}`;
|
||||
const numberOfEntries = yield (0, svg_1.numberOfFiles)(characterDir);
|
||||
res.json({ numberOfEntries: numberOfEntries });
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Something went wrong!" });
|
||||
}
|
||||
}));
|
||||
router.post("/handwriting", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const { username, text, scaleFactor, defects } = req.body;
|
||||
if (!text) {
|
||||
return res.status(400).json({ error: "Missing text" });
|
||||
}
|
||||
try {
|
||||
// Split by lines
|
||||
const lines = text.split("\n");
|
||||
let totalMissing = []; // Expected to be one dim array
|
||||
let totalPaths = []; // Expected to be two dim array
|
||||
for (let line of lines) {
|
||||
const { paths, missing } = yield (0, svg_1.svgLinePathNames)(username, line);
|
||||
totalMissing.push(...missing);
|
||||
totalPaths.push(paths);
|
||||
}
|
||||
// If there is missing char
|
||||
if (totalMissing.length > 0) {
|
||||
// Remove duplicates
|
||||
totalMissing = [...new Set(totalMissing)];
|
||||
return res
|
||||
.status(404)
|
||||
.json({ error: `Missing character/s ${totalMissing.join(",")}` });
|
||||
}
|
||||
// Generate a larger
|
||||
const path = yield (0, svg_1.generateSvg)(totalPaths, scaleFactor || 1, defects);
|
||||
// Read the SVG files
|
||||
return res.json({ svgLink: path });
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Unable to create the handwriting" });
|
||||
}
|
||||
}));
|
||||
router.post("/print", (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
var _a;
|
||||
try {
|
||||
const printingStatus = yield (0, svg_1.printSVG)(`${paths_1.STATIC_PATH}/generated.svg`);
|
||||
res.status(printingStatus.success ? 200 : 500).json({
|
||||
error: (_a = printingStatus.message.split("\n")[1]) !== null && _a !== void 0 ? _a : "Something went wrong",
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
return res.status(500).json({ error: e });
|
||||
}
|
||||
}));
|
||||
exports.default = router;
|
@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const paths_1 = require("../../paths");
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const router = express_1.default.Router();
|
||||
router.get("/", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
// Get all the users from the profiles directory
|
||||
const users = yield fs_1.default.promises.readdir(paths_1.PROFILES_PATH);
|
||||
// For each user, read the meta.json file and add the createdAt property
|
||||
let response = [];
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
// Get the last modification time
|
||||
const timestamp = yield fs_1.default.statSync(`${paths_1.PROFILES_PATH}/${users[i]}`).mtime;
|
||||
response.push({ name: users[i], createdAt: timestamp.toISOString() });
|
||||
}
|
||||
res.json(response);
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Unable to read the directory" });
|
||||
}
|
||||
}));
|
||||
router.post("/", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const { name } = req.body;
|
||||
if (!name) {
|
||||
return res.status(400).json({ error: "Missing name" });
|
||||
}
|
||||
try {
|
||||
yield fs_1.default.promises.mkdir(`${paths_1.PROFILES_PATH}/${name}`);
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Unable to create the directory" });
|
||||
}
|
||||
}));
|
||||
router.delete("/", (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const { name } = req.body;
|
||||
try {
|
||||
yield fs_1.default.promises.rm(`${paths_1.PROFILES_PATH}/${name}`, {
|
||||
recursive: true,
|
||||
});
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Unable to delete the directory" });
|
||||
}
|
||||
}));
|
||||
exports.default = router;
|
556
server/routers/epja-2023-2/pen-plotter/utilities/svg.js
Normal file
556
server/routers/epja-2023-2/pen-plotter/utilities/svg.js
Normal file
@ -0,0 +1,556 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeSVGToFile = exports.generateUniqueSVGPath = exports.createCharacterDirectory = exports.validateName = exports.numberOfFiles = exports.svgLinePathNames = exports.generateSvg = exports.printSVG = void 0;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const paths_1 = require("../paths");
|
||||
const jsdom_1 = __importDefault(require("jsdom"));
|
||||
/**
|
||||
* Returns the number of files in a directory.
|
||||
* @param dir - The directory path.
|
||||
* @returns A promise that resolves to the number of files in the directory.
|
||||
*/
|
||||
const numberOfFiles = (dir) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
const files = yield fs_1.default.promises.readdir(dir);
|
||||
return files.length;
|
||||
}
|
||||
catch (err) {
|
||||
// File is not found
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
exports.numberOfFiles = numberOfFiles;
|
||||
/**
|
||||
* Returns a string with a valid name based on the input string.
|
||||
* Replaces invalid characters with their corresponding names or "lower-" / "upper-" prefix.
|
||||
* @param name - The input string to be validated.
|
||||
* @returns A string with a valid name.
|
||||
*/
|
||||
const validateName = (name) => {
|
||||
const map = {
|
||||
"?": "questionMark",
|
||||
"*": "asterisk",
|
||||
"/": "slash",
|
||||
"\\": "backslash",
|
||||
":": "colon",
|
||||
"|": "pipe",
|
||||
"<": "lessThan",
|
||||
">": "greaterThan",
|
||||
'"': "doubleQuote",
|
||||
"'": "singleQuote",
|
||||
"@": "at",
|
||||
"#": "hash",
|
||||
$: "dollar",
|
||||
"%": "percent",
|
||||
"^": "caret",
|
||||
"&": "ampersand",
|
||||
"(": "leftParenthesis",
|
||||
")": "rightParenthesis",
|
||||
"-": "hyphen",
|
||||
_: "underscore",
|
||||
"=": "equal",
|
||||
"+": "plus",
|
||||
"{": "leftCurlyBrace",
|
||||
"}": "rightCurlyBrace",
|
||||
"[": "leftSquareBracket",
|
||||
"]": "rightSquareBracket",
|
||||
",": "comma",
|
||||
".": "period",
|
||||
"!": "exclamationMark",
|
||||
"~": "tilde",
|
||||
"`": "graveAccent",
|
||||
};
|
||||
const numbers = {
|
||||
"0": "zero",
|
||||
"1": "one",
|
||||
"2": "two",
|
||||
"3": "three",
|
||||
"4": "four",
|
||||
"5": "five",
|
||||
"6": "six",
|
||||
"7": "seven",
|
||||
"8": "eight",
|
||||
"9": "nine",
|
||||
};
|
||||
if (name in map)
|
||||
return map[name];
|
||||
if (name in numbers)
|
||||
return numbers[name];
|
||||
// distingush between upper and lower case
|
||||
if (isUpperCase(name))
|
||||
return `upper-${name}`;
|
||||
return `lower-${name}`;
|
||||
};
|
||||
exports.validateName = validateName;
|
||||
const isUpperCase = (char) => {
|
||||
return char === char.toUpperCase();
|
||||
};
|
||||
/**
|
||||
* Returns a random entity path for a given user and character name.
|
||||
* @param userName - The name of the user.
|
||||
* @param charName - The title of the character.
|
||||
* @returns A promise that resolves to a string representing the path to the random entity or empty.
|
||||
*/
|
||||
const getRandomEntityPath = (userName, charName) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
const basePath = `${paths_1.PROFILES_PATH}/${userName}/${charName}`;
|
||||
const characters = yield fs_1.default.promises.readdir(basePath);
|
||||
const randomIndex = Math.floor(Math.random() * characters.length);
|
||||
return `${basePath}/${characters[randomIndex]}`;
|
||||
}
|
||||
catch (err) {
|
||||
console.error("Could not get random entity path");
|
||||
return "";
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Checks if a given character path contains any special characters.
|
||||
* Special characters include: questionMark, asterisk, slash, backslash, colon, pipe, lessThan, greaterThan,
|
||||
* doubleQuote, singleQuote, at, hash, dollar, percent, caret, ampersand, leftParenthesis, rightParenthesis,
|
||||
* hyphen, underscore, equal, plus, leftCurlyBrace, rightCurlyBrace, leftSquareBracket, rightSquareBracket,
|
||||
* comma, period, exclamationMark, tilde, graveAccent.
|
||||
*
|
||||
* @param charPath - The character path to check.
|
||||
* @returns True if the character path contains any special characters, false otherwise.
|
||||
*/
|
||||
const isSpecialChar = (charPath) => {
|
||||
const specialLocatedTop = [
|
||||
"singleQuote",
|
||||
"doubleQuote",
|
||||
"graveAccent",
|
||||
"asterisk",
|
||||
"caret",
|
||||
];
|
||||
const specialLocatedMiddle = [
|
||||
"colon",
|
||||
"lessThan",
|
||||
"greaterThan",
|
||||
"leftParenthesis",
|
||||
"rightParenthesis",
|
||||
"hyphen",
|
||||
"equal",
|
||||
"plus",
|
||||
"leftCurlyBrace",
|
||||
"rightCurlyBrace",
|
||||
"leftSquareBracket",
|
||||
"rightSquareBracket",
|
||||
"exclamationMark",
|
||||
"tilde",
|
||||
];
|
||||
const specialLocatedBottom = ["underscore", "comma", "period"];
|
||||
let isSpecial = false;
|
||||
let position = "bottom";
|
||||
for (const special of specialLocatedTop) {
|
||||
if (charPath.includes(special)) {
|
||||
isSpecial = true;
|
||||
position = "top";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isSpecial) {
|
||||
for (const special of specialLocatedMiddle) {
|
||||
if (charPath.includes(special)) {
|
||||
isSpecial = true;
|
||||
position = "middle";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isSpecial) {
|
||||
for (const special of specialLocatedBottom) {
|
||||
if (charPath.includes(special)) {
|
||||
isSpecial = true;
|
||||
position = "bottom";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { isSpecial, position };
|
||||
};
|
||||
/**
|
||||
* Determines if the given character path should extend below the baseline.
|
||||
* @param charPath The character path to check.
|
||||
* @returns A boolean indicating whether the character path should extend below the baseline.
|
||||
*/
|
||||
const extendBelowBaseline = (charPath) => {
|
||||
const extendBelowBaseline = [
|
||||
"lower-q",
|
||||
"lower-y",
|
||||
"lower-g",
|
||||
"lower-p",
|
||||
"lower-j",
|
||||
];
|
||||
let extend = false;
|
||||
for (const char of extendBelowBaseline) {
|
||||
if (charPath.includes(char)) {
|
||||
extend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return extend;
|
||||
};
|
||||
/**
|
||||
* Returns an object containing an array of SVG paths for each word in the input text and an array of missing characters.
|
||||
* @param userName - The name of the user.
|
||||
* @param text - The input text to generate SVG paths for.
|
||||
* @returns An object containing an array of SVG paths for each word in the input text and an array of missing characters.
|
||||
*/
|
||||
const svgLinePathNames = (userName, text) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
let paths = [];
|
||||
let missing = [];
|
||||
const words = text.split(" ");
|
||||
for (const word of words) {
|
||||
let wordPath = [];
|
||||
const chars = word.trim().split("");
|
||||
for (const c of chars) {
|
||||
const cName = validateName(c);
|
||||
const path = yield getRandomEntityPath(userName, cName);
|
||||
if (path === "") {
|
||||
missing.push(c);
|
||||
}
|
||||
else {
|
||||
wordPath.push(path);
|
||||
}
|
||||
}
|
||||
paths.push(wordPath);
|
||||
}
|
||||
return {
|
||||
missing,
|
||||
paths,
|
||||
};
|
||||
});
|
||||
exports.svgLinePathNames = svgLinePathNames;
|
||||
/**
|
||||
* Parses an SVG string and returns the SVG element and its paths.
|
||||
* @param svg - The SVG string to parse.
|
||||
* @returns An object containing the SVG element and its paths.
|
||||
*/
|
||||
const parseSVG = (svg) => {
|
||||
const dom = new jsdom_1.default.JSDOM(svg);
|
||||
const svgElement = dom.window.document.querySelector("svg");
|
||||
const svgPaths = svgElement === null || svgElement === void 0 ? void 0 : svgElement.querySelectorAll("path");
|
||||
return {
|
||||
parent: svgElement,
|
||||
paths: svgPaths,
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Returns a random number between the given minimum and maximum values, with an optional percentage range.
|
||||
* @param min The minimum value for the random number.
|
||||
* @param max The maximum value for the random number.
|
||||
* @param percentage The percentage range for the random number. Defaults to 25%.
|
||||
* @returns A random number between the given minimum and maximum values.
|
||||
*/
|
||||
const getRandomNumber = (min, max, percentage = 25, scale = 1) => {
|
||||
const howRandom = Math.round((max - min) * (percentage / 100));
|
||||
const randomNumber = Math.floor(Math.random() * (howRandom + 1));
|
||||
// const randomSign = Math.random() < 0.5 ? -1 : 1;
|
||||
return Math.round(min + randomNumber) * scale;
|
||||
};
|
||||
// Get standard values for the characters
|
||||
const getStandardValues = (isSpecial, position) => {
|
||||
// Standard values for the characters
|
||||
const standard = {
|
||||
char_width: 20,
|
||||
space_width: 10,
|
||||
special_char_located_top_width: 5,
|
||||
special_char_located_middle_width: 15,
|
||||
special_char_located_top_max_width: 10,
|
||||
special_char_located_middle_max_width: 20,
|
||||
special_char_located_bottom_width: 5,
|
||||
special_char_located_bottom_max_width: 15,
|
||||
special_char_height_top: 10,
|
||||
special_char_height_middle: 20,
|
||||
special_char_height_bottom: 30,
|
||||
max_char_width: 30,
|
||||
max_char_height: 30,
|
||||
};
|
||||
const standerdWidth = isSpecial
|
||||
? position === "top"
|
||||
? standard.special_char_located_top_width
|
||||
: position === "middle"
|
||||
? standard.special_char_located_middle_width
|
||||
: standard.special_char_located_bottom_width
|
||||
: standard.char_width;
|
||||
const standerdMaxWidth = isSpecial
|
||||
? position === "top"
|
||||
? standard.special_char_located_top_max_width
|
||||
: position === "middle"
|
||||
? standard.special_char_located_middle_max_width
|
||||
: standard.special_char_located_bottom_max_width
|
||||
: standard.max_char_width;
|
||||
const standerdHeight = isSpecial
|
||||
? position === "top"
|
||||
? standard.special_char_height_top
|
||||
: position === "middle"
|
||||
? standard.special_char_height_middle
|
||||
: standard.special_char_height_bottom
|
||||
: standard.max_char_height;
|
||||
const standerdMaxHeight = isSpecial
|
||||
? position === "top"
|
||||
? standard.special_char_height_top
|
||||
: position === "middle"
|
||||
? standard.special_char_height_middle
|
||||
: standard.special_char_height_bottom
|
||||
: standard.max_char_height;
|
||||
return { standerdWidth, standerdMaxWidth, standerdHeight, standerdMaxHeight };
|
||||
};
|
||||
// Get Random Defects
|
||||
const getRandomDefects = (defects, scaleFactor, charPath = "") => {
|
||||
const { baseline, kerning, letterSize, lineSpacing, indent } = defects;
|
||||
const { isSpecial, position } = isSpecialChar(charPath);
|
||||
const { standerdWidth, standerdMaxWidth, standerdHeight, standerdMaxHeight } = getStandardValues(isSpecial, position);
|
||||
const indentRandom = getRandomNumber(0, 80, indent, scaleFactor);
|
||||
const lineSpacingRandom = getRandomNumber(0, 30, lineSpacing, scaleFactor);
|
||||
const kerningDeffects = getRandomNumber(0, 10, kerning, scaleFactor);
|
||||
const baselineOffset = getRandomNumber(0, 10, baseline, scaleFactor);
|
||||
const letterSizeWidthRandom = getRandomNumber(standerdWidth, standerdMaxWidth, letterSize, scaleFactor);
|
||||
const letterSizeRandomHeight = getRandomNumber(standerdHeight, standerdMaxHeight, letterSize, scaleFactor);
|
||||
return {
|
||||
indentRandom,
|
||||
lineSpacingRandom,
|
||||
kerningDeffects,
|
||||
baselineOffset,
|
||||
letterSizeWidthRandom,
|
||||
letterSizeRandomHeight,
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Assembles a word by processing each character and generating SVG elements.
|
||||
*
|
||||
* @param {AssembleWord} options - The options for assembling the word.
|
||||
* @param {string} options.word - The word to assemble.
|
||||
* @param {number} options.offsetX - The initial X offset.
|
||||
* @param {number} options.offsetY - The initial Y offset.
|
||||
* @param {number} options.scaleFactor - The scale factor for the word.
|
||||
* @param {number} options.indentRandom - The random indentation for the word.
|
||||
* @param {Defects} options.defects - The defects for the word.
|
||||
*
|
||||
* @returns {Object} - The assembled word elements, the height of the word, and the updated X offset.
|
||||
*/
|
||||
const assembleWord = ({ word, offsetX, offsetY, scaleFactor, indentRandom, defects, }) => {
|
||||
const space_width = 10 * scaleFactor;
|
||||
let wordElements = [];
|
||||
let wordHeight = 0;
|
||||
if (word.length === 0) {
|
||||
offsetX += space_width;
|
||||
}
|
||||
else {
|
||||
offsetX += indentRandom;
|
||||
for (let j = 0; j < word.length; j++) {
|
||||
const char = word[j];
|
||||
const { kerningDeffects, baselineOffset } = getRandomDefects(defects, scaleFactor);
|
||||
const { isSpecial, position } = isSpecialChar(char);
|
||||
const { letterSizeWidthRandom, letterSizeRandomHeight } = getRandomDefects(defects, scaleFactor, char);
|
||||
// You need to load the SVG content from the file
|
||||
const svgFileContent = fs_1.default.readFileSync(char, "utf-8");
|
||||
// Get the width and height of the SVG and its paths children
|
||||
const { parent } = parseSVG(svgFileContent);
|
||||
const width = parent === null || parent === void 0 ? void 0 : parent.getAttribute("width");
|
||||
const height = parent === null || parent === void 0 ? void 0 : parent.getAttribute("height");
|
||||
// Scale down the width to the standerd width while keeping the aspect ratio
|
||||
const widthScale = letterSizeWidthRandom / Number(width);
|
||||
const heightScale = letterSizeRandomHeight / Number(height);
|
||||
const scale = Math.min(widthScale, heightScale);
|
||||
// Calculate the scaled width and height
|
||||
const scaledHeight = Number(height) * scale * scaleFactor;
|
||||
const scaledWidth = Number(width) * scale * scaleFactor;
|
||||
// Change the width and height of the SVG
|
||||
parent === null || parent === void 0 ? void 0 : parent.setAttribute("width", String(scaledWidth));
|
||||
parent === null || parent === void 0 ? void 0 : parent.setAttribute("height", String(scaledHeight));
|
||||
// Add viewBox attribute to scale the paths inside the SVG
|
||||
parent === null || parent === void 0 ? void 0 : parent.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
||||
// Change the position of the SVG
|
||||
parent === null || parent === void 0 ? void 0 : parent.setAttribute("x", offsetX.toString());
|
||||
parent === null || parent === void 0 ? void 0 : parent.setAttribute("y", String(offsetY + baselineOffset));
|
||||
// Add the SVG content to the SVG content variable
|
||||
offsetX += scaledWidth + kerningDeffects;
|
||||
wordElements.push({
|
||||
element: parent,
|
||||
isSpecial,
|
||||
position,
|
||||
extendBelowBaseline: extendBelowBaseline(char),
|
||||
});
|
||||
wordHeight = Math.max(wordHeight, scaledHeight + baselineOffset);
|
||||
}
|
||||
// Align the line elements to the bottom of the line
|
||||
let extended = false;
|
||||
wordElements.forEach((e) => {
|
||||
const { element, isSpecial, position, extendBelowBaseline } = e;
|
||||
const elementHeight = parseInt(element.getAttribute("height"));
|
||||
const lineYOffset = wordHeight - elementHeight;
|
||||
if (isSpecial) {
|
||||
if (position === "top") {
|
||||
element.setAttribute("y", String(offsetY));
|
||||
}
|
||||
else if (position === "middle") {
|
||||
element.setAttribute("y", String(offsetY + lineYOffset / 2));
|
||||
}
|
||||
else {
|
||||
element.setAttribute("y", String(offsetY + lineYOffset));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (extendBelowBaseline) {
|
||||
element.setAttribute("y", String(offsetY + lineYOffset + wordHeight / 2));
|
||||
extended = true;
|
||||
}
|
||||
else {
|
||||
element.setAttribute("y", String(offsetY + lineYOffset));
|
||||
}
|
||||
}
|
||||
});
|
||||
// Fix the line height
|
||||
if (extended)
|
||||
wordHeight += wordHeight / 2;
|
||||
// Add a space between words
|
||||
offsetX += space_width * scaleFactor;
|
||||
}
|
||||
return { wordElements, wordHeight, offsetX };
|
||||
};
|
||||
/**
|
||||
* Assembles a line of text into SVG elements.
|
||||
*
|
||||
* @param {AssembleLine} options - The options for assembling the line.
|
||||
* @param {number} options.defects - The number of defects in the line.
|
||||
* @param {number} options.scaleFactor - The scale factor for the line.
|
||||
* @param {string[]} options.line - The words in the line.
|
||||
* @param {number} options.offsetY - The vertical offset of the line.
|
||||
* @returns {Object} - The assembled line content and updated vertical offset.
|
||||
*/
|
||||
const assembleLine = ({ defects, scaleFactor, line, offsetY, }) => {
|
||||
const { indentRandom, lineSpacingRandom } = getRandomDefects(defects, scaleFactor);
|
||||
let lineContent = "";
|
||||
// Add a line container for each line of text
|
||||
let lineHeight = 0;
|
||||
let offsetX = indentRandom;
|
||||
let lineElements = [];
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
const word = line[i];
|
||||
const { wordElements, wordHeight, offsetX: newOffsetX, } = assembleWord({
|
||||
word,
|
||||
offsetX,
|
||||
offsetY,
|
||||
scaleFactor,
|
||||
indentRandom,
|
||||
defects,
|
||||
});
|
||||
// Update the offset
|
||||
offsetX = newOffsetX;
|
||||
lineHeight = Math.max(lineHeight, wordHeight);
|
||||
lineElements = lineElements.concat(wordElements);
|
||||
}
|
||||
// Update the offset
|
||||
offsetY += lineHeight + lineSpacingRandom;
|
||||
// Append the line elements to the SVG content
|
||||
lineElements.forEach((e) => {
|
||||
lineContent += e.element.outerHTML;
|
||||
});
|
||||
return { lineContent, offsetY, offsetX };
|
||||
};
|
||||
/**
|
||||
* Writes the SVG content to a file and returns the server file path.
|
||||
* @param svgContent - The SVG content to be written to the file.
|
||||
* @returns The server file path of the generated SVG file.
|
||||
*/
|
||||
const writeSVG = (svgContent, totalHeight, totalWidth) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
// wrap the SVG content in an SVG document
|
||||
const outputFile = `<svg width="${totalWidth}" height="${totalHeight}" xmlns="http://www.w3.org/2000/svg">${svgContent}</svg>`; // Change this to your desired SVG content
|
||||
// Write the SVG content to a file
|
||||
const svgFilePath = `${paths_1.STATIC_PATH}/generated.svg`; // Change this to your desired file path
|
||||
fs_1.default.writeFileSync(svgFilePath, outputFile);
|
||||
// Return the SVG file path
|
||||
const basePath = `${process.env.BASE_URL || "http://localhost"}`;
|
||||
const port = process.env.PORT || "5000";
|
||||
// Date.now() is used to prevent caching (cache busting)
|
||||
const serverFilePath = `${basePath}:${port}/static/generated.svg?v=${Date.now()}`;
|
||||
return serverFilePath;
|
||||
});
|
||||
/**
|
||||
* Generates an SVG file based on the provided paths, scale factor, and defects.
|
||||
* @param paths - A 3D array of file paths representing the characters to be included in the SVG.
|
||||
* @param scaleFactor - The scale factor to apply to the SVG. Default is 1.
|
||||
* @param defects - An object containing defect values for line spacing, kerning, letter size, and baseline offset.
|
||||
* @returns A Promise that resolves to the file path of the generated SVG.
|
||||
*/
|
||||
const generateSvg = (paths, scaleFactor = 1, defects) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
let svgContent = "";
|
||||
let offsetY = 0;
|
||||
let totalHeight = 0;
|
||||
let totalWidth = 0;
|
||||
// Iterate over the lines, words and chars creating the SVG content
|
||||
paths.forEach((line) => {
|
||||
const { lineContent, offsetY: newOffsetY, offsetX, } = assembleLine({
|
||||
defects,
|
||||
scaleFactor,
|
||||
line,
|
||||
offsetY,
|
||||
});
|
||||
svgContent += lineContent;
|
||||
offsetY = newOffsetY;
|
||||
totalHeight = Math.max(totalHeight, offsetY);
|
||||
totalWidth = Math.max(totalWidth, offsetX);
|
||||
});
|
||||
// Write the SVG content to a file
|
||||
const serverFilePath = yield writeSVG(svgContent, totalHeight, totalWidth);
|
||||
return serverFilePath;
|
||||
});
|
||||
exports.generateSvg = generateSvg;
|
||||
/**
|
||||
* Renders an SVG file to a connected plotter.
|
||||
* @param inputPath - The path to the input SVG file.
|
||||
* @param outputPath - Optional. The path to the output SVG file.
|
||||
* @returns An error if one occurs during the rendering process.
|
||||
*/
|
||||
const printSVG = (inputPath) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
// Execute the following command : axicli inputPath usin os.system
|
||||
const { execSync } = require("child_process");
|
||||
try {
|
||||
const command = `axicli ${inputPath}`;
|
||||
const result = execSync(command, { encoding: "utf-8" });
|
||||
// Process the result and return an object
|
||||
return {
|
||||
success: true,
|
||||
message: `success: ${result}`,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
const errorMessage = error;
|
||||
return {
|
||||
success: false,
|
||||
message: `error: ${errorMessage.message}`,
|
||||
};
|
||||
}
|
||||
});
|
||||
exports.printSVG = printSVG;
|
||||
// Function to create the character directory
|
||||
const createCharacterDirectory = (userPath, charTitle) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const characters = yield fs_1.default.promises.readdir(userPath);
|
||||
if (!characters.includes(charTitle)) {
|
||||
yield fs_1.default.promises.mkdir(`${userPath}/${charTitle}`);
|
||||
}
|
||||
});
|
||||
exports.createCharacterDirectory = createCharacterDirectory;
|
||||
// Function to generate a unique SVG filename
|
||||
const generateUniqueSVGPath = (characterDir) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const characterLength = yield numberOfFiles(characterDir);
|
||||
return `${characterDir}/${characterLength + 1}.svg`;
|
||||
});
|
||||
exports.generateUniqueSVGPath = generateUniqueSVGPath;
|
||||
// Function to write SVG content to a file
|
||||
const writeSVGToFile = (svgPath, svgContent) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
yield fs_1.default.promises.writeFile(svgPath, svgContent);
|
||||
});
|
||||
exports.writeSVGToFile = writeSVGToFile;
|
23
server/routers/epja-2023-2/pen-plotter/utilities/user.js
Normal file
23
server/routers/epja-2023-2/pen-plotter/utilities/user.js
Normal file
@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.userExists = void 0;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const paths_1 = require("../paths");
|
||||
// Function to check if the user exists
|
||||
const userExists = (userName) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const users = yield fs_1.default.promises.readdir(paths_1.PROFILES_PATH);
|
||||
return users.includes(userName);
|
||||
});
|
||||
exports.userExists = userExists;
|
Loading…
Reference in New Issue
Block a user