Dualcoding

pull/1/head
Antonio De Lucreziis 2 years ago
parent 6c877eccf0
commit 8719ba3279

@ -7,9 +7,21 @@
<title>PHC | Problemi</title>
<link rel="stylesheet" href="/styles/main.scss" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,600;1,400;1,600&family=Lato:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="./node_modules/katex/dist/katex.css" />
<link rel="stylesheet" href="./styles/main.scss" />
</head>
<body>
<script type="module" src="/src/main.jsx"></script>
<script type="module" src="./src/main.jsx"></script>
</body>
</html>

@ -3,13 +3,20 @@
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --clearScreen false",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@preact/signals": "^1.1.2",
"katex": "^0.16.3",
"preact": "^10.11.2",
"rehype-katex": "^6.0.2",
"rehype-stringify": "^9.0.3",
"remark-math": "^5.1.1",
"remark-parse": "^10.0.1",
"remark-rehype": "^10.1.0",
"unified": "^10.1.2",
"url-pattern": "^1.0.3"
},
"devDependencies": {

@ -3,15 +3,29 @@ lockfileVersion: 5.4
specifiers:
'@preact/preset-vite': ^2.4.0
'@preact/signals': ^1.1.2
katex: ^0.16.3
preact: ^10.11.2
rehype-katex: ^6.0.2
rehype-stringify: ^9.0.3
remark-math: ^5.1.1
remark-parse: ^10.0.1
remark-rehype: ^10.1.0
sass: ^1.55.0
typescript: ^4.6.4
unified: ^10.1.2
url-pattern: ^1.0.3
vite: ^3.2.0
dependencies:
'@preact/signals': 1.1.2_preact@10.11.2
katex: 0.16.3
preact: 10.11.2
rehype-katex: 6.0.2
rehype-stringify: 9.0.3
remark-math: 5.1.1
remark-parse: 10.0.1
remark-rehype: 10.1.0
unified: 10.1.2
url-pattern: 1.0.3
devDependencies:
@ -400,6 +414,40 @@ packages:
picomatch: 2.3.1
dev: true
/@types/debug/4.1.7:
resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==}
dependencies:
'@types/ms': 0.7.31
dev: false
/@types/hast/2.3.4:
resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==}
dependencies:
'@types/unist': 2.0.6
dev: false
/@types/katex/0.11.1:
resolution: {integrity: sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==}
dev: false
/@types/mdast/3.0.10:
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==}
dependencies:
'@types/unist': 2.0.6
dev: false
/@types/ms/0.7.31:
resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
dev: false
/@types/parse5/6.0.3:
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
dev: false
/@types/unist/2.0.6:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: false
/ansi-styles/3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
@ -423,6 +471,10 @@ packages:
'@babel/core': 7.19.6
dev: true
/bail/2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
dev: false
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
@ -450,6 +502,10 @@ packages:
resolution: {integrity: sha512-lfXQ73oB9c8DP5Suxaszm+Ta2sr/4tf8+381GkIm1MLj/YdLf+rEDyDSRCzeltuyTVGm+/s18gdZ0q+Wmp8VsQ==}
dev: true
/ccount/2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
dev: false
/chalk/2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
@ -459,6 +515,18 @@ packages:
supports-color: 5.5.0
dev: true
/character-entities-html4/2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
dev: false
/character-entities-legacy/3.0.0:
resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
dev: false
/character-entities/2.0.2:
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
dev: false
/chokidar/3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@ -484,6 +552,15 @@ packages:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true
/comma-separated-tokens/2.0.2:
resolution: {integrity: sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==}
dev: false
/commander/8.3.0:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
dev: false
/convert-source-map/1.9.0:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
dev: true
@ -498,7 +575,22 @@ packages:
optional: true
dependencies:
ms: 2.1.2
dev: true
/decode-named-character-reference/1.0.2:
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
dependencies:
character-entities: 2.0.2
dev: false
/dequal/2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
dev: false
/diff/5.1.0:
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
engines: {node: '>=0.3.1'}
dev: false
/electron-to-chromium/1.4.284:
resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==}
@ -728,6 +820,10 @@ packages:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
/extend/3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
dev: false
/fill-range/7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@ -776,6 +872,73 @@ packages:
function-bind: 1.1.1
dev: true
/hast-util-from-parse5/7.1.0:
resolution: {integrity: sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ==}
dependencies:
'@types/hast': 2.3.4
'@types/parse5': 6.0.3
'@types/unist': 2.0.6
hastscript: 7.1.0
property-information: 6.1.1
vfile: 5.3.5
vfile-location: 4.0.1
web-namespaces: 2.0.1
dev: false
/hast-util-is-element/2.1.2:
resolution: {integrity: sha512-thjnlGAnwP8ef/GSO1Q8BfVk2gundnc2peGQqEg2kUt/IqesiGg/5mSwN2fE7nLzy61pg88NG6xV+UrGOrx9EA==}
dependencies:
'@types/hast': 2.3.4
'@types/unist': 2.0.6
dev: false
/hast-util-parse-selector/3.1.0:
resolution: {integrity: sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg==}
dependencies:
'@types/hast': 2.3.4
dev: false
/hast-util-to-html/8.0.3:
resolution: {integrity: sha512-/D/E5ymdPYhHpPkuTHOUkSatxr4w1ZKrZsG0Zv/3C2SRVT0JFJG53VS45AMrBtYk0wp5A7ksEhiC8QaOZM95+A==}
dependencies:
'@types/hast': 2.3.4
ccount: 2.0.1
comma-separated-tokens: 2.0.2
hast-util-is-element: 2.1.2
hast-util-whitespace: 2.0.0
html-void-elements: 2.0.1
property-information: 6.1.1
space-separated-tokens: 2.0.1
stringify-entities: 4.0.3
unist-util-is: 5.1.1
dev: false
/hast-util-to-text/3.1.1:
resolution: {integrity: sha512-7S3mOBxACy8syL45hCn3J7rHqYaXkxRfsX6LXEU5Shz4nt4GxdjtMUtG+T6G/ZLUHd7kslFAf14kAN71bz30xA==}
dependencies:
'@types/hast': 2.3.4
hast-util-is-element: 2.1.2
unist-util-find-after: 4.0.0
dev: false
/hast-util-whitespace/2.0.0:
resolution: {integrity: sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==}
dev: false
/hastscript/7.1.0:
resolution: {integrity: sha512-uBjaTTLN0MkCZxY/R2fWUOcu7FRtUVzKRO5P/RAfgsu3yFiMB1JWCO4AjeVkgHxAira1f2UecHK5WfS9QurlWA==}
dependencies:
'@types/hast': 2.3.4
comma-separated-tokens: 2.0.2
hast-util-parse-selector: 3.1.0
property-information: 6.1.1
space-separated-tokens: 2.0.1
dev: false
/html-void-elements/2.0.1:
resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
dev: false
/immutable/4.1.0:
resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==}
dev: true
@ -787,6 +950,11 @@ packages:
binary-extensions: 2.2.0
dev: true
/is-buffer/2.0.5:
resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
engines: {node: '>=4'}
dev: false
/is-core-module/2.11.0:
resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
dependencies:
@ -810,6 +978,11 @@ packages:
engines: {node: '>=0.12.0'}
dev: true
/is-plain-obj/4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
dev: false
/js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
@ -826,13 +999,300 @@ packages:
hasBin: true
dev: true
/katex/0.13.24:
resolution: {integrity: sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==}
hasBin: true
dependencies:
commander: 8.3.0
dev: false
/katex/0.15.6:
resolution: {integrity: sha512-UpzJy4yrnqnhXvRPhjEuLA4lcPn6eRngixW7Q3TJErjg3Aw2PuLFBzTkdUb89UtumxjhHTqL3a5GDGETMSwgJA==}
hasBin: true
dependencies:
commander: 8.3.0
dev: false
/katex/0.16.3:
resolution: {integrity: sha512-3EykQddareoRmbtNiNEDgl3IGjryyrp2eg/25fHDEnlHymIDi33bptkMv6K4EOC2LZCybLW/ZkEo6Le+EM9pmA==}
hasBin: true
dependencies:
commander: 8.3.0
dev: false
/kleur/4.1.5:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}
dev: false
/kolorist/1.6.0:
resolution: {integrity: sha512-dLkz37Ab97HWMx9KTes3Tbi3D1ln9fCAy2zr2YVExJasDRPGRaKcoE4fycWNtnCAJfjFqe0cnY+f8KT2JePEXQ==}
dev: true
/longest-streak/3.0.1:
resolution: {integrity: sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg==}
dev: false
/mdast-util-definitions/5.1.1:
resolution: {integrity: sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==}
dependencies:
'@types/mdast': 3.0.10
'@types/unist': 2.0.6
unist-util-visit: 4.1.1
dev: false
/mdast-util-from-markdown/1.2.0:
resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==}
dependencies:
'@types/mdast': 3.0.10
'@types/unist': 2.0.6
decode-named-character-reference: 1.0.2
mdast-util-to-string: 3.1.0
micromark: 3.1.0
micromark-util-decode-numeric-character-reference: 1.0.0
micromark-util-decode-string: 1.0.2
micromark-util-normalize-identifier: 1.0.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
unist-util-stringify-position: 3.0.2
uvu: 0.5.6
transitivePeerDependencies:
- supports-color
dev: false
/mdast-util-math/2.0.1:
resolution: {integrity: sha512-ZZtjyRwobsiVg4bY0Q5CzAZztpbjRIA7ZlMMb0PNkwTXOnJTUoHvzBhVG95LIuek5Mlj1l2P+jBvWviqW7G+0A==}
dependencies:
'@types/mdast': 3.0.10
longest-streak: 3.0.1
mdast-util-to-markdown: 1.3.0
dev: false
/mdast-util-to-hast/12.2.4:
resolution: {integrity: sha512-a21xoxSef1l8VhHxS1Dnyioz6grrJkoaCUgGzMD/7dWHvboYX3VW53esRUfB5tgTyz4Yos1n25SPcj35dJqmAg==}
dependencies:
'@types/hast': 2.3.4
'@types/mdast': 3.0.10
mdast-util-definitions: 5.1.1
micromark-util-sanitize-uri: 1.1.0
trim-lines: 3.0.1
unist-builder: 3.0.0
unist-util-generated: 2.0.0
unist-util-position: 4.0.3
unist-util-visit: 4.1.1
dev: false
/mdast-util-to-markdown/1.3.0:
resolution: {integrity: sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==}
dependencies:
'@types/mdast': 3.0.10
'@types/unist': 2.0.6
longest-streak: 3.0.1
mdast-util-to-string: 3.1.0
micromark-util-decode-string: 1.0.2
unist-util-visit: 4.1.1
zwitch: 2.0.2
dev: false
/mdast-util-to-string/3.1.0:
resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==}
dev: false
/micromark-core-commonmark/1.0.6:
resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==}
dependencies:
decode-named-character-reference: 1.0.2
micromark-factory-destination: 1.0.0
micromark-factory-label: 1.0.2
micromark-factory-space: 1.0.0
micromark-factory-title: 1.0.2
micromark-factory-whitespace: 1.0.0
micromark-util-character: 1.1.0
micromark-util-chunked: 1.0.0
micromark-util-classify-character: 1.0.0
micromark-util-html-tag-name: 1.1.0
micromark-util-normalize-identifier: 1.0.0
micromark-util-resolve-all: 1.0.0
micromark-util-subtokenize: 1.0.2
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
dev: false
/micromark-extension-math/2.0.2:
resolution: {integrity: sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA==}
dependencies:
'@types/katex': 0.11.1
katex: 0.13.24
micromark-factory-space: 1.0.0
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
dev: false
/micromark-factory-destination/1.0.0:
resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==}
dependencies:
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
dev: false
/micromark-factory-label/1.0.2:
resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==}
dependencies:
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
dev: false
/micromark-factory-space/1.0.0:
resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==}
dependencies:
micromark-util-character: 1.1.0
micromark-util-types: 1.0.2
dev: false
/micromark-factory-title/1.0.2:
resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==}
dependencies:
micromark-factory-space: 1.0.0
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
dev: false
/micromark-factory-whitespace/1.0.0:
resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==}
dependencies:
micromark-factory-space: 1.0.0
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
dev: false
/micromark-util-character/1.1.0:
resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==}
dependencies:
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
dev: false
/micromark-util-chunked/1.0.0:
resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==}
dependencies:
micromark-util-symbol: 1.0.1
dev: false
/micromark-util-classify-character/1.0.0:
resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==}
dependencies:
micromark-util-character: 1.1.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
dev: false
/micromark-util-combine-extensions/1.0.0:
resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==}
dependencies:
micromark-util-chunked: 1.0.0
micromark-util-types: 1.0.2
dev: false
/micromark-util-decode-numeric-character-reference/1.0.0:
resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==}
dependencies:
micromark-util-symbol: 1.0.1
dev: false
/micromark-util-decode-string/1.0.2:
resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==}
dependencies:
decode-named-character-reference: 1.0.2
micromark-util-character: 1.1.0
micromark-util-decode-numeric-character-reference: 1.0.0
micromark-util-symbol: 1.0.1
dev: false
/micromark-util-encode/1.0.1:
resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==}
dev: false
/micromark-util-html-tag-name/1.1.0:
resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==}
dev: false
/micromark-util-normalize-identifier/1.0.0:
resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==}
dependencies:
micromark-util-symbol: 1.0.1
dev: false
/micromark-util-resolve-all/1.0.0:
resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==}
dependencies:
micromark-util-types: 1.0.2
dev: false
/micromark-util-sanitize-uri/1.1.0:
resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==}
dependencies:
micromark-util-character: 1.1.0
micromark-util-encode: 1.0.1
micromark-util-symbol: 1.0.1
dev: false
/micromark-util-subtokenize/1.0.2:
resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==}
dependencies:
micromark-util-chunked: 1.0.0
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
dev: false
/micromark-util-symbol/1.0.1:
resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==}
dev: false
/micromark-util-types/1.0.2:
resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==}
dev: false
/micromark/3.1.0:
resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==}
dependencies:
'@types/debug': 4.1.7
debug: 4.3.4
decode-named-character-reference: 1.0.2
micromark-core-commonmark: 1.0.6
micromark-factory-space: 1.0.0
micromark-util-character: 1.1.0
micromark-util-chunked: 1.0.0
micromark-util-combine-extensions: 1.0.0
micromark-util-decode-numeric-character-reference: 1.0.0
micromark-util-encode: 1.0.1
micromark-util-normalize-identifier: 1.0.0
micromark-util-resolve-all: 1.0.0
micromark-util-sanitize-uri: 1.1.0
micromark-util-subtokenize: 1.0.2
micromark-util-symbol: 1.0.1
micromark-util-types: 1.0.2
uvu: 0.5.6
transitivePeerDependencies:
- supports-color
dev: false
/mri/1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
dev: false
/ms/2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/nanoid/3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
@ -849,6 +1309,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/parse5/6.0.1:
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
dev: false
/path-parse/1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
@ -874,6 +1338,10 @@ packages:
/preact/10.11.2:
resolution: {integrity: sha512-skAwGDFmgxhq1DCBHke/9e12ewkhc7WYwjuhHB8HHS8zkdtITXLRmUMTeol2ldxvLwYtwbFeifZ9uDDWuyL4Iw==}
/property-information/6.1.1:
resolution: {integrity: sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==}
dev: false
/readdirp/3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
@ -881,6 +1349,64 @@ packages:
picomatch: 2.3.1
dev: true
/rehype-katex/6.0.2:
resolution: {integrity: sha512-C4gDAlS1+l0hJqctyiU64f9CvT00S03qV1T6HiMzbSuLBgWUtcqydWHY9OpKrm0SpkK16FNd62CDKyWLwV2ppg==}
dependencies:
'@types/hast': 2.3.4
'@types/katex': 0.11.1
hast-util-to-text: 3.1.1
katex: 0.15.6
rehype-parse: 8.0.4
unified: 10.1.2
unist-util-remove-position: 4.0.1
unist-util-visit: 4.1.1
dev: false
/rehype-parse/8.0.4:
resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==}
dependencies:
'@types/hast': 2.3.4
hast-util-from-parse5: 7.1.0
parse5: 6.0.1
unified: 10.1.2
dev: false
/rehype-stringify/9.0.3:
resolution: {integrity: sha512-kWiZ1bgyWlgOxpqD5HnxShKAdXtb2IUljn3hQAhySeak6IOQPPt6DeGnsIh4ixm7yKJWzm8TXFuC/lPfcWHJqw==}
dependencies:
'@types/hast': 2.3.4
hast-util-to-html: 8.0.3
unified: 10.1.2
dev: false
/remark-math/5.1.1:
resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==}
dependencies:
'@types/mdast': 3.0.10
mdast-util-math: 2.0.1
micromark-extension-math: 2.0.2
unified: 10.1.2
dev: false
/remark-parse/10.0.1:
resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==}
dependencies:
'@types/mdast': 3.0.10
mdast-util-from-markdown: 1.2.0
unified: 10.1.2
transitivePeerDependencies:
- supports-color
dev: false
/remark-rehype/10.1.0:
resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
dependencies:
'@types/hast': 2.3.4
'@types/mdast': 3.0.10
mdast-util-to-hast: 12.2.4
unified: 10.1.2
dev: false
/resolve/1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true
@ -898,6 +1424,13 @@ packages:
fsevents: 2.3.2
dev: true
/sade/1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
dependencies:
mri: 1.2.0
dev: false
/sass/1.55.0:
resolution: {integrity: sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==}
engines: {node: '>=12.0.0'}
@ -918,6 +1451,17 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/space-separated-tokens/2.0.1:
resolution: {integrity: sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==}
dev: false
/stringify-entities/4.0.3:
resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==}
dependencies:
character-entities-html4: 2.1.0
character-entities-legacy: 3.0.0
dev: false
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@ -942,12 +1486,87 @@ packages:
is-number: 7.0.0
dev: true
/trim-lines/3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
dev: false
/trough/2.1.0:
resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==}
dev: false
/typescript/4.8.4:
resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
engines: {node: '>=4.2.0'}
hasBin: true
dev: true
/unified/10.1.2:
resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
dependencies:
'@types/unist': 2.0.6
bail: 2.0.2
extend: 3.0.2
is-buffer: 2.0.5
is-plain-obj: 4.1.0
trough: 2.1.0
vfile: 5.3.5
dev: false
/unist-builder/3.0.0:
resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==}
dependencies:
'@types/unist': 2.0.6
dev: false
/unist-util-find-after/4.0.0:
resolution: {integrity: sha512-gfpsxKQde7atVF30n5Gff2fQhAc4/HTOV4CvkXpTg9wRfQhZWdXitpyXHWB6YcYgnsxLx+4gGHeVjCTAAp9sjw==}
dependencies:
'@types/unist': 2.0.6
unist-util-is: 5.1.1
dev: false
/unist-util-generated/2.0.0:
resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==}
dev: false
/unist-util-is/5.1.1:
resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==}
dev: false
/unist-util-position/4.0.3:
resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==}
dependencies:
'@types/unist': 2.0.6
dev: false
/unist-util-remove-position/4.0.1:
resolution: {integrity: sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ==}
dependencies:
'@types/unist': 2.0.6
unist-util-visit: 4.1.1
dev: false
/unist-util-stringify-position/3.0.2:
resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==}
dependencies:
'@types/unist': 2.0.6
dev: false
/unist-util-visit-parents/5.1.1:
resolution: {integrity: sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==}
dependencies:
'@types/unist': 2.0.6
unist-util-is: 5.1.1
dev: false
/unist-util-visit/4.1.1:
resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==}
dependencies:
'@types/unist': 2.0.6
unist-util-is: 5.1.1
unist-util-visit-parents: 5.1.1
dev: false
/update-browserslist-db/1.0.10_browserslist@4.21.4:
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
hasBin: true
@ -964,6 +1583,40 @@ packages:
engines: {node: '>=0.12.0'}
dev: false
/uvu/0.5.6:
resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
engines: {node: '>=8'}
hasBin: true
dependencies:
dequal: 2.0.3
diff: 5.1.0
kleur: 4.1.5
sade: 1.8.1
dev: false
/vfile-location/4.0.1:
resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==}
dependencies:
'@types/unist': 2.0.6
vfile: 5.3.5
dev: false
/vfile-message/3.1.2:
resolution: {integrity: sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==}
dependencies:
'@types/unist': 2.0.6
unist-util-stringify-position: 3.0.2
dev: false
/vfile/5.3.5:
resolution: {integrity: sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==}
dependencies:
'@types/unist': 2.0.6
is-buffer: 2.0.5
unist-util-stringify-position: 3.0.2
vfile-message: 3.1.2
dev: false
/vite/3.2.1_sass@1.55.0:
resolution: {integrity: sha512-ADtMkfHuWq4tskJsri2n2FZkORO8ZyhI+zIz7zTrDAgDEtct1jdxOg3YsZBfHhKjmMoWLOSCr+64qrEDGo/DbQ==}
engines: {node: ^14.18.0 || >=16.0.0}
@ -994,3 +1647,11 @@ packages:
optionalDependencies:
fsevents: 2.3.2
dev: true
/web-namespaces/2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
dev: false
/zwitch/2.0.2:
resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==}
dev: false

@ -37,7 +37,10 @@ export const Router = ({ pages }) => {
const { Page, params } = route
const queryPart = routerUrl.value.slice(routerUrl.value.indexOf('?') + 1)
const queryPart =
routerUrl.value.indexOf('?') === -1
? ''
: routerUrl.value.slice(routerUrl.value.indexOf('?') + 1)
console.log(queryPart)
const queryParams =

@ -0,0 +1,28 @@
import { useEffect, useRef } from 'preact/hooks'
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkMath from 'remark-math'
import remarkRehype from 'remark-rehype'
import rehypeKatex from 'rehype-katex'
import rehypeStringify from 'rehype-stringify'
export const Markdown = ({ source }) => {
const elementRef = useRef()
useEffect(async () => {
const renderedHtml = await unified()
.use(remarkParse)
.use(remarkMath)
.use(remarkRehype)
.use(rehypeKatex, { throwOnError: false, errorColor: '#c60' })
.use(rehypeStringify)
.process(source)
if (elementRef.current) {
elementRef.current.innerHTML = renderedHtml
}
}, [source])
return <div class="markdown" ref={elementRef}></div>
}

@ -0,0 +1,16 @@
import { Markdown } from './Markdown.jsx'
export const Problem = ({ title, content }) => {
return (
<div class="problem">
<div class="problem-header">
<div class="problem-title">
<Markdown source={title} />
</div>
</div>
<div class="problem-content">
<Markdown source={content} />
</div>
</div>
)
}

@ -1,9 +1,11 @@
import { render } from 'preact'
import { Router } from './Router.jsx'
import { HomePage } from './pages/Home.jsx'
import { LoginPage } from './pages/Login.jsx'
import { ProblemPage } from './pages/Problem.jsx'
import { Router } from './Router.jsx'
import { NewSolutionPage } from './pages/NewSolution.jsx'
render(
<Router
@ -11,6 +13,7 @@ render(
'/': HomePage,
'/login': LoginPage,
'/problem/:id': ProblemPage,
'/problem/:id/new-solution': NewSolutionPage,
}}
/>,
document.body

@ -1,20 +1,28 @@
import { computed, useSignal } from '@preact/signals'
import { Markdown } from '../components/Markdown.jsx'
import { Link } from '../Router.jsx'
export const HomePage = () => {
return (
<>
<p>
Home Page or <Link page="/login">go to the login page</Link>.
</p>
<p>
<Link
page="/problem/:id"
params={{ id: 'uSiR6CDdyd1h3cm0' }}
query={{ q: 'example', foo: 'bar' }}
>
Some random problem
</Link>
</p>
</>
<main class="home">
<div class="logo">PHC / Problemi</div>
<div class="board">
{Array.from({ length: 20 }).map(({} = {}, i) => (
<div class="problem" style={{ '--size': ((7 * i) % 4) + 2 }}>
<div class="problem-header">
<div class="problem-title">Problema {i + 1}</div>
</div>
<div class="problem-content">
{Array.from({ length: ((7 * i) % 4) + 1 }).map(({} = {}) => (
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nemo
minima doloremque nihil ducimus qui reiciendis. Provident, odit?
</p>
))}
</div>
</div>
))}
</div>
</main>
)
}

@ -0,0 +1,61 @@
import { useEffect, useRef, useState } from 'preact/hooks'
import { Markdown } from '../components/Markdown.jsx'
export const NewSolutionPage = ({ params: { id } }) => {
const [source, setSource] = useState('')
const editorRef = useRef()
const sendSolution = async () => {
const res = await fetch(`/api/problem/${id}/new-solution`, {
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
source,
}),
})
console.log(await res.json())
}
useEffect(() => {
if (editorRef.current) {
editorRef.current.style.height = 'auto'
editorRef.current.style.height = editorRef.current.scrollHeight + 'px'
}
}, [source])
return (
<main class="new-solution">
<div class="logo">PHC / Problemi</div>
<div class="subtitle">Nuova soluzione per il problema #{id}</div>
<div class="solution-editor">
<div class="editor">
<h1>Editor</h1>
<textarea
onInput={e => setSource(e.target.value)}
value={source}
cols="60"
ref={editorRef}
placeholder="Scrivi una nuova soluzione..."
></textarea>
</div>
<div class="preview">
<h1>Preview</h1>
<div class="preview-content">
{source.length ? (
<Markdown source={source} />
) : (
<div class="placeholder">Scrivi una nuova soluzione...</div>
)}
</div>
</div>
</div>
<div class="submit-solution">
<button onClick={sendSolution}>Invia Soluzione</button>
</div>
</main>
)
}

@ -12,6 +12,11 @@ body {
height: 100%;
min-height: 100%;
margin: 0;
font-family: 'Lato', sans-serif;
font-size: 20px;
line-height: 1;
}
// Typography
@ -20,6 +25,10 @@ p {
margin: 0;
}
p + p {
margin-top: 0.5rem;
}
$base-font-size: 16px;
$heading-scale: 1.25;
@ -62,3 +71,173 @@ $device-s-width: 640px;
@media screen and (max-width: $device-s-width), (pointer: coarse) {
// ...
}
//
// Components
//
.text-body {
font-family: 'EB Garamond', serif;
font-weight: 400;
font-size: 21px;
line-height: 1.41;
b,
strong {
font-weight: 600;
}
}
//
// Structure
//
body {
display: flex;
flex-direction: column;
align-items: center;
background: #f8f8f8;
main {
padding: 1rem;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
}
.logo {
// font-size: 42px;
// font-family: 'EB Garamond';
// font-weight: 600;
font-size: 38px;
font-family: 'Lato';
font-weight: 300;
}
main.home {
padding-top: 2rem;
gap: 2rem;
}
main.new-solution {
padding-top: 2rem;
gap: 2rem;
.solution-editor {
display: grid;
width: 100%;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
.editor,
.preview {
width: 100%;
max-width: 70ch;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.editor {
justify-self: end;
textarea {
font-family: 'DM Mono', monospace;
font-size: 18px;
border: none;
outline: gray;
width: 100%;
padding: 1rem;
box-shadow: -2px 4px 8px 1px #00000020, -1px 1px 1px 0px #00000010;
border-radius: 0.25rem;
background: #ffffff;
resize: none;
overflow-y: hidden;
min-height: 10rem;
}
}
.preview {
justify-self: start;
.placeholder {
color: #444;
}
.preview-content {
@extend .text-body;
width: 100%;
padding: 1rem;
box-shadow: -2px 4px 8px 1px #00000020, -1px 1px 1px 0px #00000010;
border-radius: 0.25rem;
background: #ffffff;
}
}
}
}
.board {
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(50ch, 1fr));
grid-auto-rows: 3rem;
gap: 1rem;
}
//
// Components
//
.problem {
padding: 1rem;
// border: 1px solid #ddd;
box-shadow: -2px 4px 8px 1px #00000020, -1px 1px 1px 0px #00000010;
border-radius: 0.25rem;
background: #ffffff;
grid-row: span var(--size);
overflow-y: auto;
display: grid;
grid-template-rows: auto 1fr;
gap: 0.5rem;
.problem-header {
display: grid;
grid-template-columns: auto;
.problem-title {
font-size: 24px;
font-weight: 700;
}
}
.problem-content {
@extend .text-body;
}
}
.math-inline {
font-size: 95%;
}

@ -1,18 +1,22 @@
import polka from 'polka'
import send from '@polka/send-type'
import express from 'express'
// import serveStatic from 'serve-static'
import bodyParser from 'body-parser'
import { LoggingMiddleware, PingRouter, StatusRouter } from './server/helpers.js'
import { loggingMiddleware, PingRouter, StatusRouter } from './server/helpers.js'
const app = polka()
const app = express()
app.use(bodyParser.json())
app.use(LoggingMiddleware)
app.use(loggingMiddleware)
app.use('/api', StatusRouter)
app.use('/api', PingRouter)
app.use('/api/status', new StatusRouter())
app.use('/api/ping', new PingRouter())
app.all('*', (req, res) => {
res.status(404)
res.end('Not found')
})
app.listen(4000, () => {
console.log(`Started server on port 4000...`)

@ -5,16 +5,18 @@
"main": "index.js",
"type": "module",
"scripts": {
"start": "node ./main.js"
"start:frontend": "cd frontend && npm run dev",
"start:server": "node ./main.js",
"start": "concurrently npm:start:server npm:start:frontend"
},
"keywords": [],
"author": "",
"license": "ISC",
"license": "MIT",
"dependencies": {
"@polka/send-type": "^0.5.2",
"body-parser": "^1.20.1",
"chalk": "^5.1.2",
"polka": "^0.5.2",
"serve-static": "^1.15.0"
"express": "^4.18.2"
},
"devDependencies": {
"concurrently": "^7.5.0",
"npm-run-all": "^4.1.5"
}
}

File diff suppressed because it is too large Load Diff

@ -1,26 +1,34 @@
import polka from 'polka'
import send from '@polka/send-type'
import { Router } from 'express'
import chalk from 'chalk'
import { toLocalISO } from '../utils/util.js'
export const StatusRouter = polka()
export class StatusRouter extends Router {
constructor() {
super()
StatusRouter.get('/status', (req, res) => {
send(res, 200, { status: 'ok' })
})
export const PingRouter = polka()
this.get('/', (req, res) => {
res.json({ status: 'ok' })
})
}
}
PingRouter.post('/ping', (req, res) => {
if (req.body?.message === 'ping') {
send(res, 200, 'pong')
} else {
send(res, 400, 'Invalid request')
export class PingRouter extends Router {
constructor() {
super()
this.post('/', (req, res) => {
if (req.body?.message === 'ping') {
res.json('pong')
} else {
res.status(400)
res.json('Invalid request')
}
})
}
})
}
export const LoggingMiddleware = (req, res, next) => {
export const loggingMiddleware = (req, res, next) => {
next()
const coloredStatusCode = [

Loading…
Cancel
Save