diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e124309e..19c2c453 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -66,6 +66,7 @@ module.exports = { 'unicorn/consistent-function-scoping': 'warn', 'unicorn/no-array-callback-reference': 'warn', 'unicorn/no-array-method-this-argument': 'warn', + 'unicorn/no-for-loop': 'off', 'sonarjs/no-duplicate-string': ['warn', { threshold: 5 }], diff --git a/api/edge-ssr.js b/api/edge-ssr.js new file mode 100644 index 00000000..c810ed9b --- /dev/null +++ b/api/edge-ssr.js @@ -0,0 +1,32 @@ +import { renderPage } from 'vike/server' + +export const config = { + runtime: 'edge' +} +export default async function handler(request) { + const { url, cookies } = request + + const pageContext = await renderPage({ urlOriginal: url, cookies }) + + const { httpResponse, errorWhileRendering, is404 } = pageContext + + if (errorWhileRendering && !is404) { + console.error(errorWhileRendering) + return new Response('', { status: 500 }) + } + + if (!httpResponse) { + return new Response() + } + + const { body, statusCode, headers: headersArray } = httpResponse + + const headers = headersArray.reduce((acc, [name, value]) => { + acc[name] = value + return acc + }, {}) + + headers['Cache-Control'] = 's-maxage=1, stale-while-revalidate' + + return new Response(body, { status: statusCode, headers }) +} diff --git a/api/ssr.mjs b/api/ssr.mjs deleted file mode 100644 index 0d471d1f..00000000 --- a/api/ssr.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import { renderPage } from 'vike/server' - -export default async function handler(req, res) { - const { url, cookies } = req - - const pageContext = await renderPage({ urlOriginal: url, cookies }) - - const { httpResponse, errorWhileRendering, is404 } = pageContext - - if (errorWhileRendering && !is404) { - console.error(errorWhileRendering) - res.statusCode = 500 - res.end() - return - } - - if (!httpResponse) { - res.statusCode = 200 - res.end() - return - } - - const { body, statusCode, contentType } = httpResponse - res.statusCode = statusCode - res.setHeader('Content-Type', contentType) - res.end(body) -} diff --git a/package-lock.json b/package-lock.json index 809a2792..573e7d43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "i18next": "22.4.15", "i18next-icu": "2.3.0", "intl-messageformat": "10.5.3", - "just-throttle": "4.2.0", "mailgun.js": "8.2.1" }, "devDependencies": { @@ -76,7 +75,6 @@ "bootstrap": "5.3.2", "clsx": "2.0.0", "cross-env": "7.0.3", - "debounce": "1.2.1", "eslint": "8.53.0", "eslint-config-stylelint": "20.0.0", "eslint-import-resolver-typescript": "3.6.1", @@ -90,7 +88,6 @@ "fast-deep-equal": "3.1.3", "graphql": "16.6.0", "graphql-tag": "2.12.6", - "html-to-json-parser": "1.1.0", "husky": "8.0.3", "hygen": "6.2.11", "i18next-http-backend": "2.2.0", @@ -100,11 +97,6 @@ "lint-staged": "15.0.2", "loglevel": "1.8.1", "loglevel-plugin-prefix": "0.8.4", - "markdown-it": "13.0.1", - "markdown-it-container": "3.0.0", - "markdown-it-implicit-figures": "0.11.0", - "markdown-it-mark": "3.0.1", - "markdown-it-replace-link": "1.2.0", "nanostores": "0.7.4", "prettier": "3.0.3", "prettier-eslint": "16.1.2", @@ -123,6 +115,7 @@ "stylelint-order": "6.0.3", "stylelint-scss": "5.3.0", "swiper": "9.4.1", + "throttle-debounce": "5.0.0", "typescript": "5.2.2", "typograf": "7.1.0", "uniqolor": "1.1.0", @@ -5102,6 +5095,15 @@ "throttle-debounce": "^3.0.1" } }, + "node_modules/@remirror/core-helpers/node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/@remirror/types": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@remirror/types/-/types-1.0.1.tgz", @@ -8287,78 +8289,6 @@ "node": ">=6.0.0" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "optional": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "optional": true - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "optional": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "optional": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -8412,9 +8342,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.579", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.579.tgz", - "integrity": "sha512-bJKvA+awBIzYR0xRced7PrQuRIwGQPpo6ZLP62GAShahU9fWpsNN2IP6BSP1BLDDSbxvBVRGAMWlvVVq3npmLA==", + "version": "1.4.581", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.581.tgz", + "integrity": "sha512-6uhqWBIapTJUxgPTCHH9sqdbxIMPt7oXl0VcAL1kOtlU6aECdcMncCrX5Z7sHQ/invtrC9jUQUef7+HhO8vVFw==", "dev": true }, "node_modules/emittery": { @@ -8466,6 +8396,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "dev": true, + "peer": true, "engines": { "node": ">=0.12" }, @@ -8558,9 +8489,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, "node_modules/es-set-tostringtag": { @@ -9101,9 +9032,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.0.tgz", - "integrity": "sha512-/XZLH5CUXGK3laz3xYFNza8ZxLCq8ZNW6MsVw5z3d5hc2AwZzi0fPiySFZHQTdVDOHGs2cGv91aqzWmgBdq2gQ==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.1.tgz", + "integrity": "sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -9111,6 +9042,7 @@ "eslint-plugin-es-x": "^7.1.0", "get-tsconfig": "^4.7.0", "ignore": "^5.2.4", + "is-builtin-module": "^3.2.1", "is-core-module": "^2.12.1", "minimatch": "^3.1.2", "resolve": "^1.22.2", @@ -9794,9 +9726,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -9804,7 +9736,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -10649,48 +10581,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/html-to-json-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/html-to-json-parser/-/html-to-json-parser-1.1.0.tgz", - "integrity": "sha512-j6JiUBhIQkC+guahmh0VKwQRrnsROpUaRWAQyRlu5tp6atQg9ljeU70eBtpHSJwNALFNo//VOozvif7AQlfOtA==", - "dev": true, - "dependencies": { - "xmldom": "^0.6.0" - } - }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "optional": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/http-proxy-agent": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", @@ -13946,11 +13836,6 @@ "node": ">=4.0" } }, - "node_modules/just-throttle": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/just-throttle/-/just-throttle-4.2.0.tgz", - "integrity": "sha512-/iAZv1953JcExpvsywaPKjSzfTiCLqeguUTE6+VmK15mOcwxBx7/FHrVvS4WEErMR03TRazH8kcBSHqMagYIYg==" - }, "node_modules/kebab-case": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz", @@ -14070,6 +13955,7 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, + "peer": true, "dependencies": { "uc.micro": "^1.0.1" } @@ -14985,10 +14871,11 @@ } }, "node_modules/markdown-it": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", - "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", "dev": true, + "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "~3.0.1", @@ -15000,37 +14887,6 @@ "markdown-it": "bin/markdown-it.js" } }, - "node_modules/markdown-it-container": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz", - "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==", - "dev": true - }, - "node_modules/markdown-it-implicit-figures": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/markdown-it-implicit-figures/-/markdown-it-implicit-figures-0.11.0.tgz", - "integrity": "sha512-ed32u3O8pTEM3TKgeBTMKw8ce86L8u5L41CuLvGee3yevYOq+1BoxjI84m/f7RcUaATcKgXTgZwieadvOH4afg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-it-mark": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/markdown-it-mark/-/markdown-it-mark-3.0.1.tgz", - "integrity": "sha512-HyxjAu6BRsdt6Xcv6TKVQnkz/E70TdGXEFHRYBGLncRE9lBFwDNLVtFojKxjJWgJ+5XxUwLaHXy+2sGBbDn+4A==", - "dev": true - }, - "node_modules/markdown-it-replace-link": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/markdown-it-replace-link/-/markdown-it-replace-link-1.2.0.tgz", - "integrity": "sha512-tIsShJvQOYwTHjIPhE1SWo12HjOtpEqSQfVoApm3fuIkVcZrSE7zK3iW8kXcaJYasf8Ddf+VbH5fNXCzfejOrQ==", - "dev": true, - "optionalDependencies": { - "dom-serializer": "^2.0.0", - "htmlparser2": "^8.0.1" - } - }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -15051,7 +14907,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true + "dev": true, + "peer": true }, "node_modules/meow": { "version": "10.1.5", @@ -18252,12 +18109,12 @@ "dev": true }, "node_modules/throttle-debounce": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", - "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz", + "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.22" } }, "node_modules/through": { @@ -18574,7 +18431,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -19699,15 +19557,6 @@ } } }, - "node_modules/xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/y-prosemirror": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-1.2.1.tgz", diff --git a/package.json b/package.json index 6abc61e1..2f5c90e0 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "i18next": "22.4.15", "i18next-icu": "2.3.0", "intl-messageformat": "10.5.3", - "just-throttle": "4.2.0", "mailgun.js": "8.2.1" }, "devDependencies": { @@ -97,7 +96,6 @@ "bootstrap": "5.3.2", "clsx": "2.0.0", "cross-env": "7.0.3", - "debounce": "1.2.1", "eslint": "8.53.0", "eslint-config-stylelint": "20.0.0", "eslint-import-resolver-typescript": "3.6.1", @@ -111,7 +109,6 @@ "fast-deep-equal": "3.1.3", "graphql": "16.6.0", "graphql-tag": "2.12.6", - "html-to-json-parser": "1.1.0", "husky": "8.0.3", "hygen": "6.2.11", "i18next-http-backend": "2.2.0", @@ -121,11 +118,6 @@ "lint-staged": "15.0.2", "loglevel": "1.8.1", "loglevel-plugin-prefix": "0.8.4", - "markdown-it": "13.0.1", - "markdown-it-container": "3.0.0", - "markdown-it-implicit-figures": "0.11.0", - "markdown-it-mark": "3.0.1", - "markdown-it-replace-link": "1.2.0", "nanostores": "0.7.4", "prettier": "3.0.3", "prettier-eslint": "16.1.2", @@ -144,6 +136,7 @@ "stylelint-order": "6.0.3", "stylelint-scss": "5.3.0", "swiper": "9.4.1", + "throttle-debounce": "5.0.0", "typescript": "5.2.2", "typograf": "7.1.0", "uniqolor": "1.1.0", diff --git a/src/components/Article/Article.module.scss b/src/components/Article/Article.module.scss index d2bc419d..1f863c1d 100644 --- a/src/components/Article/Article.module.scss +++ b/src/components/Article/Article.module.scss @@ -69,6 +69,7 @@ img { &[data-float='left'], &[data-float='right'] { @include font-size(2.2rem); + line-height: 1.4; @include media-breakpoint-up(sm) { @@ -417,7 +418,7 @@ img { } .shoutStatsItemViews { - color: rgb(0 0 0 / 0.4); + color: rgb(0 0 0 / 40%); cursor: default; font-weight: normal; margin-left: auto; @@ -460,7 +461,8 @@ img { .shoutStatsItemAdditionalDataItem { font-weight: normal; display: inline-block; - //margin-left: 2rem; + + // margin-left: 2rem; margin-right: 0; margin-bottom: 0; cursor: default; diff --git a/src/components/Article/AudioPlayer/PlayerPlaylist.tsx b/src/components/Article/AudioPlayer/PlayerPlaylist.tsx index 7ce74f36..7f456f8b 100644 --- a/src/components/Article/AudioPlayer/PlayerPlaylist.tsx +++ b/src/components/Article/AudioPlayer/PlayerPlaylist.tsx @@ -6,7 +6,6 @@ import { Popover } from '../../_shared/Popover' import { Icon } from '../../_shared/Icon' import styles from './AudioPlayer.module.scss' import { GrowingTextarea } from '../../_shared/GrowingTextarea' -import MD from '../MD' import { MediaItem } from '../../../pages/types' import SimplifiedEditor from '../../Editor/SimplifiedEditor' @@ -146,12 +145,12 @@ export const PlayerPlaylist = (props: Props) => {
- +
- +
diff --git a/src/components/Article/Comment/Comment.module.scss b/src/components/Article/Comment/Comment.module.scss index e16db64f..168ae67c 100644 --- a/src/components/Article/Comment/Comment.module.scss +++ b/src/components/Article/Comment/Comment.module.scss @@ -4,7 +4,7 @@ transition: background-color 0.3s; position: relative; list-style: none; - background: rgb(0 0 0 / 0.1); + background: rgb(0 0 0 / 10%); @include media-breakpoint-down(sm) { padding-right: 0; diff --git a/src/components/Article/Comment/Comment.tsx b/src/components/Article/Comment/Comment.tsx index dc43c7ee..4bb7bc2f 100644 --- a/src/components/Article/Comment/Comment.tsx +++ b/src/components/Article/Comment/Comment.tsx @@ -2,7 +2,6 @@ import { Show, createMemo, createSignal, For, lazy, Suspense } from 'solid-js' import { clsx } from 'clsx' import { getPagePath } from '@nanostores/router' -import MD from '../MD' import { Userpic } from '../../Author/Userpic' import { CommentRatingControl } from '../CommentRatingControl' import { CommentDate } from '../CommentDate' @@ -171,7 +170,7 @@ export const Comment = (props: Props) => {
- }> + }> {t('Loading')}

}> { description={m.body} /> - +
)} @@ -327,11 +326,7 @@ export const FullArticle = (props: Props) => {
-
- }> - - -
+
diff --git a/src/components/Article/MD.tsx b/src/components/Article/MD.tsx deleted file mode 100644 index 4dd6cd9c..00000000 --- a/src/components/Article/MD.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import MD from 'markdown-it' -import mdfig from 'markdown-it-implicit-figures' -import mdmark from 'markdown-it-mark' -import mdcustom from 'markdown-it-container' -import mdlinks from 'markdown-it-replace-link' -import { createMemo } from 'solid-js' - -const mit = MD({ - html: true, - linkify: true, - typographer: true -}) -mit.use(mdmark) -mit.use(mdcustom) -mit.use(mdfig, { - dataType: false, //
- figcaption: true //
alternative text
-}) -mit.use(mdlinks) - -export default (props: { body: string }) => { - const body = createMemo(() => (props.body.startsWith('<') ? props.body : mit.render(props.body))) - return
-} diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index 74b49154..5c9683f1 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -64,7 +64,7 @@ export const AuthorBadge = (props: Props) => { return isSubscribing() ? t('subscribing...') : t('Subscribe') }) - const unsubscribeValue = () => { + const unsubscribeValue = createMemo(() => { if (props.iconButtons) { return } @@ -75,7 +75,7 @@ export const AuthorBadge = (props: Props) => { {t('Unfollow')} ) - } + }) return (
diff --git a/src/components/Author/AuthorCard/AuthorCard.tsx b/src/components/Author/AuthorCard/AuthorCard.tsx index 432bc5ef..62c7856b 100644 --- a/src/components/Author/AuthorCard/AuthorCard.tsx +++ b/src/components/Author/AuthorCard/AuthorCard.tsx @@ -97,20 +97,22 @@ export const AuthorCard = (props: Props) => { } }) - const followButtonText = () => { + const followButtonText = createMemo(() => { if (isSubscribing()) { return t('subscribing...') - } else if (subscribed()) { + } + + if (subscribed()) { return ( <> {t('Following')} {t('Unfollow')} ) - } else { - return t('Follow') } - } + + return t('Follow') + }) return (
diff --git a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx index cae2606c..eca9335a 100644 --- a/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx +++ b/src/components/Editor/EditorFloatingMenu/EditorFloatingMenu.tsx @@ -1,9 +1,8 @@ import { createEffect, createSignal, Show } from 'solid-js' -import type { Editor, JSONContent } from '@tiptap/core' +import type { Editor } from '@tiptap/core' import { Icon } from '../../_shared/Icon' import { InlineForm } from '../InlineForm' import styles from './EditorFloatingMenu.module.scss' -import HTMLParser from 'html-to-json-parser' import { useLocalize } from '../../../context/localize' import { Modal } from '../../Nav/Modal' import { Menu } from './Menu' @@ -20,10 +19,17 @@ type FloatingMenuProps = { } const embedData = async (data) => { - const result = (await HTMLParser(data, false)) as JSONContent - if ('type' in result && result.type === 'iframe') { - return result.attributes + const element = document.createRange().createContextualFragment(data) + const { attributes } = element.firstChild as HTMLIFrameElement + + const result: { src: string } = { src: '' } + + for (let i = 0; i < attributes.length; i++) { + const attribute = attributes[i] + result[attribute.name] = attribute.value } + + return result } export const EditorFloatingMenu = (props: FloatingMenuProps) => { @@ -39,8 +45,8 @@ export const EditorFloatingMenu = (props: FloatingMenuProps) => { } const validateEmbed = async (value) => { - const iframeData = (await HTMLParser(value, false)) as JSONContent - if (iframeData.type !== 'iframe') { + const element = document.createRange().createContextualFragment(value) + if (element.firstChild?.nodeName !== 'IFRAME') { return t('Error') } } diff --git a/src/components/Nav/Header/Header.tsx b/src/components/Nav/Header/Header.tsx index 7dbe5026..088441a6 100644 --- a/src/components/Nav/Header/Header.tsx +++ b/src/components/Nav/Header/Header.tsx @@ -24,6 +24,7 @@ import { apiClient } from '../../../utils/apiClient' import { RANDOM_TOPICS_COUNT } from '../../Views/Home' import { Link } from './Link' import { Subscribe } from '../../_shared/Subscribe' +import { ShowOnlyOnClient } from '../../_shared/ShowOnlyOnClient' type Props = { title?: string @@ -527,8 +528,9 @@ export const Header = (props: Props) => {
- - + + +
) diff --git a/src/components/NotificationsPanel/NotificationsPanel.tsx b/src/components/NotificationsPanel/NotificationsPanel.tsx index 2618895f..30619e70 100644 --- a/src/components/NotificationsPanel/NotificationsPanel.tsx +++ b/src/components/NotificationsPanel/NotificationsPanel.tsx @@ -9,7 +9,7 @@ import { PAGE_SIZE, useNotifications } from '../../context/notifications' import { NotificationView } from './NotificationView' import { EmptyMessage } from './EmptyMessage' import { Button } from '../_shared/Button' -import throttle from 'just-throttle' +import { throttle } from 'throttle-debounce' import { useSession } from '../../context/session' type Props = { @@ -132,7 +132,7 @@ export const NotificationsPanel = (props: Props) => { setIsLoading(false) } } - const handleScrollThrottled = throttle(handleScroll, 50) + const handleScrollThrottled = throttle(50, handleScroll) onMount(() => { scrollContainerRef.current.addEventListener('scroll', handleScrollThrottled) diff --git a/src/components/TableOfContents/TableOfContents.tsx b/src/components/TableOfContents/TableOfContents.tsx index 1efcdd4e..d35601e9 100644 --- a/src/components/TableOfContents/TableOfContents.tsx +++ b/src/components/TableOfContents/TableOfContents.tsx @@ -2,11 +2,10 @@ import { For, Show, createSignal, createEffect, on, onMount, onCleanup } from 's import { clsx } from 'clsx' import { DEFAULT_HEADER_OFFSET } from '../../stores/router' import { useLocalize } from '../../context/localize' -import debounce from 'debounce' import { Icon } from '../_shared/Icon' import styles from './TableOfContents.module.scss' import { isDesktop } from '../../utils/media-query' -import throttle from 'just-throttle' +import { throttle, debounce } from 'throttle-debounce' interface Props { variant: 'article' | 'editor' @@ -49,12 +48,12 @@ export const TableOfContents = (props: Props) => { setAreHeadingsLoaded(true) } - const debouncedUpdateHeadings = debounce(updateHeadings, 500) + const debouncedUpdateHeadings = debounce(500, updateHeadings) - const updateActiveHeader = throttle(() => { + const updateActiveHeader = throttle(50, () => { const newActiveIndex = headings().findLastIndex((heading) => isInViewport(heading)) setActiveHeaderIndex(newActiveIndex) - }, 50) + }) createEffect( on( diff --git a/src/components/_shared/SocialNetworkInput/SocialNetworkInput.module.scss b/src/components/_shared/SocialNetworkInput/SocialNetworkInput.module.scss index 65401cdf..29728c4a 100644 --- a/src/components/_shared/SocialNetworkInput/SocialNetworkInput.module.scss +++ b/src/components/_shared/SocialNetworkInput/SocialNetworkInput.module.scss @@ -40,8 +40,10 @@ width: 54px; height: 54px; padding: 16px; + &:hover { background: var(--background-color-invert); + img { filter: invert(1); } diff --git a/src/components/_shared/SolidSwiper/ArticleCardSwiper.tsx b/src/components/_shared/SolidSwiper/ArticleCardSwiper.tsx index bbfec7a1..8020c91b 100644 --- a/src/components/_shared/SolidSwiper/ArticleCardSwiper.tsx +++ b/src/components/_shared/SolidSwiper/ArticleCardSwiper.tsx @@ -1,6 +1,6 @@ -import { createSignal, For, Show } from 'solid-js' +import { For, onMount, Show } from 'solid-js' import { Icon } from '../Icon' -import { register } from 'swiper/element/bundle' + import SwiperCore, { Manipulation, Navigation, Pagination } from 'swiper' import { SwiperRef } from './swiper' import { clsx } from 'clsx' @@ -13,19 +13,13 @@ type Props = { title?: string } -register() - -SwiperCore.use([Pagination, Navigation, Manipulation]) - export const ArticleCardSwiper = (props: Props) => { - const [slideIndex, setSlideIndex] = createSignal(0) - const mainSwipeRef: { current: SwiperRef } = { current: null } - - const handleSlideChange = () => { - setSlideIndex(mainSwipeRef.current.swiper.activeIndex) - } - + onMount(async () => { + const { register } = await import('swiper/element/bundle') + register() + SwiperCore.use([Pagination, Navigation, Manipulation]) + }) return (
@@ -38,7 +32,6 @@ export const ArticleCardSwiper = (props: Props) => { ref={(el) => (mainSwipeRef.current = el)} centered-slides={true} observer={true} - onSlideChange={handleSlideChange} space-between={20} breakpoints={{ 576: { spaceBetween: 20, slidesPerView: 1.5 }, diff --git a/src/components/_shared/SolidSwiper/ImageSwiper.tsx b/src/components/_shared/SolidSwiper/ImageSwiper.tsx index 8b3a497c..d22c5196 100644 --- a/src/components/_shared/SolidSwiper/ImageSwiper.tsx +++ b/src/components/_shared/SolidSwiper/ImageSwiper.tsx @@ -1,9 +1,8 @@ -import { createEffect, createSignal, For, Show, on } from 'solid-js' +import { createEffect, createSignal, For, Show, on, onMount } from 'solid-js' import { MediaItem, UploadedFile } from '../../../pages/types' import { Icon } from '../Icon' import { Popover } from '../Popover' import { useLocalize } from '../../../context/localize' -import { register } from 'swiper/element/bundle' import { DropArea } from '../DropArea' import { createFileUploader } from '@solid-primitives/upload' import SwiperCore, { Manipulation, Navigation, Pagination } from 'swiper' @@ -28,10 +27,6 @@ type Props = { onImageChange?: (index: number, value: MediaItem) => void } -register() - -SwiperCore.use([Pagination, Navigation, Manipulation]) - export const ImageSwiper = (props: Props) => { const { t } = useLocalize() const [loading, setLoading] = createSignal(false) @@ -139,6 +134,12 @@ export const ImageSwiper = (props: Props) => { handleSlideDescriptionChange(slideIndex(), 'body', slideBody()) } + onMount(async () => { + const { register } = await import('swiper/element/bundle') + register() + SwiperCore.use([Pagination, Navigation, Manipulation]) + }) + return (
diff --git a/src/components/_shared/SolidSwiper/Swiper.module.scss b/src/components/_shared/SolidSwiper/Swiper.module.scss index 648ca264..e953b565 100644 --- a/src/components/_shared/SolidSwiper/Swiper.module.scss +++ b/src/components/_shared/SolidSwiper/Swiper.module.scss @@ -38,8 +38,8 @@ } .container { - margin: auto; // max-width: 800px; + margin: auto; position: relative; padding: 24px 0; display: flex; @@ -177,12 +177,12 @@ } &.prev { - background-image: linear-gradient(to right, #000, rgb(0 0 0 / 0)); + background-image: linear-gradient(to right, #000, rgb(0 0 0 / 0%)); left: 0; } &.next { - background-image: linear-gradient(to left, #000, rgb(0 0 0 / 0)); + background-image: linear-gradient(to left, #000, rgb(0 0 0 / 0%)); justify-content: end; right: 0; } @@ -239,11 +239,11 @@ height: auto; &.prev { - left: -var(--navigation-reserve); + left: calc(0px - var(--navigation-reserve)); } &.next { - right: -var(--navigation-reserve); + right: calc(0px - var(--navigation-reserve)); } } diff --git a/src/pages/profile/profileSettings.page.tsx b/src/pages/profile/profileSettings.page.tsx index 9eef5ad6..484307d5 100644 --- a/src/pages/profile/profileSettings.page.tsx +++ b/src/pages/profile/profileSettings.page.tsx @@ -11,7 +11,6 @@ import { useSession } from '../../context/session' import FloatingPanel from '../../components/_shared/FloatingPanel/FloatingPanel' import { useSnackbar } from '../../context/snackbar' import { useLocalize } from '../../context/localize' -import { Userpic } from '../../components/Author/Userpic' import { createStore } from 'solid-js/store' import { clone } from '../../utils/clone' import SimplifiedEditor from '../../components/Editor/SimplifiedEditor' diff --git a/vercel.json b/vercel.json index 3cd1f85e..6a76165f 100644 --- a/vercel.json +++ b/vercel.json @@ -2,7 +2,7 @@ "rewrites": [ { "source": "/((?!assets/).*)", - "destination": "/api/ssr.mjs" + "destination": "/api/edge-ssr.js" } ] }