commit
3f3bd798e6
|
@ -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 }],
|
||||
|
||||
|
|
32
api/edge-ssr.js
Normal file
32
api/edge-ssr.js
Normal file
|
@ -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 })
|
||||
}
|
27
api/ssr.mjs
27
api/ssr.mjs
|
@ -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)
|
||||
}
|
227
package-lock.json
generated
227
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) => {
|
|||
<div class={styles.descriptionBlock}>
|
||||
<Show when={mi.body}>
|
||||
<div class={styles.description}>
|
||||
<MD body={mi.body} />
|
||||
<div innerHTML={mi.body} />
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={mi.lyrics}>
|
||||
<div class={styles.lyrics}>
|
||||
<MD body={mi.lyrics} />
|
||||
<div innerHTML={mi.lyrics} />
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) => {
|
|||
</div>
|
||||
</Show>
|
||||
<div class={styles.commentBody}>
|
||||
<Show when={editMode()} fallback={<MD body={body()} />}>
|
||||
<Show when={editMode()} fallback={<div innerHTML={body()} />}>
|
||||
<Suspense fallback={<p>{t('Loading')}</p>}>
|
||||
<SimplifiedEditor
|
||||
initialContent={comment().body}
|
||||
|
|
|
@ -2,7 +2,6 @@ import { createEffect, For, createMemo, onMount, Show, createSignal, onCleanup }
|
|||
import { Title } from '@solidjs/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { getPagePath } from '@nanostores/router'
|
||||
import MD from './MD'
|
||||
import type { Author, Shout } from '../../graphql/types.gen'
|
||||
import { useSession } from '../../context/session'
|
||||
import { useLocalize } from '../../context/localize'
|
||||
|
@ -318,7 +317,7 @@ export const FullArticle = (props: Props) => {
|
|||
description={m.body}
|
||||
/>
|
||||
<Show when={m?.body}>
|
||||
<MD body={m.body} />
|
||||
<div innerHTML={m.body} />
|
||||
</Show>
|
||||
</div>
|
||||
)}
|
||||
|
@ -327,11 +326,7 @@ export const FullArticle = (props: Props) => {
|
|||
</Show>
|
||||
|
||||
<Show when={body()}>
|
||||
<div id="shoutBody" class={styles.shoutBody}>
|
||||
<Show when={!body().startsWith('<')} fallback={<div innerHTML={body()} />}>
|
||||
<MD body={body()} />
|
||||
</Show>
|
||||
</div>
|
||||
<div id="shoutBody" class={styles.shoutBody} innerHTML={body()} />
|
||||
</Show>
|
||||
</article>
|
||||
|
||||
|
|
|
@ -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, // <figure data-type="image">
|
||||
figcaption: true // <figcaption>alternative text</figcaption>
|
||||
})
|
||||
mit.use(mdlinks)
|
||||
|
||||
export default (props: { body: string }) => {
|
||||
const body = createMemo(() => (props.body.startsWith('<') ? props.body : mit.render(props.body)))
|
||||
return <div innerHTML={body()} />
|
||||
}
|
|
@ -64,7 +64,7 @@ export const AuthorBadge = (props: Props) => {
|
|||
return isSubscribing() ? t('subscribing...') : t('Subscribe')
|
||||
})
|
||||
|
||||
const unsubscribeValue = () => {
|
||||
const unsubscribeValue = createMemo(() => {
|
||||
if (props.iconButtons) {
|
||||
return <Icon name="author-unsubscribe" class={stylesButton.icon} />
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ export const AuthorBadge = (props: Props) => {
|
|||
<span class={styles.actionButtonLabelHovered}>{t('Unfollow')}</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.AuthorBadge, { [styles.nameOnly]: props.nameOnly })}>
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
<span class={stylesButton.buttonSubscribeLabel}>{t('Following')}</span>
|
||||
<span class={stylesButton.buttonSubscribeLabelHovered}>{t('Unfollow')}</span>
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
return t('Follow')
|
||||
}
|
||||
}
|
||||
|
||||
return t('Follow')
|
||||
})
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.author, 'row')}>
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
|||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<Snackbar />
|
||||
<ShowOnlyOnClient>
|
||||
<Snackbar />
|
||||
</ShowOnlyOnClient>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -40,8 +40,10 @@
|
|||
width: 54px;
|
||||
height: 54px;
|
||||
padding: 16px;
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-invert);
|
||||
|
||||
img {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<div class={clsx(styles.Swiper, styles.articleMode, styles.ArticleCardSwiper)}>
|
||||
<Show when={props.title}>
|
||||
|
@ -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 },
|
||||
|
|
|
@ -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 (
|
||||
<div class={clsx(styles.Swiper, props.editorMode ? styles.editorMode : styles.articleMode)}>
|
||||
<div class={styles.container}>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"rewrites": [
|
||||
{
|
||||
"source": "/((?!assets/).*)",
|
||||
"destination": "/api/ssr.mjs"
|
||||
"destination": "/api/edge-ssr.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user