mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-01-22 08:36:21 +01:00
Merge remote-tracking branch 'cheeaun/main' into feature/paste-attach
# Conflicts: # src/locales/en.po
This commit is contained in:
commit
6bd3ad0143
50 changed files with 2902 additions and 2708 deletions
1
.github/workflows/main2prod.yml
vendored
1
.github/workflows/main2prod.yml
vendored
|
@ -7,6 +7,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
auto-pull-request:
|
auto-pull-request:
|
||||||
|
if: github.repository == 'cheeaun/phanpy'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: vsoch/pull-request-action@master
|
- uses: vsoch/pull-request-action@master
|
||||||
|
|
9
.github/workflows/prettier-pr.yml
vendored
9
.github/workflows/prettier-pr.yml
vendored
|
@ -14,9 +14,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- uses: creyD/prettier_action@v4.3
|
- run: |
|
||||||
with:
|
echo "Prettier-ing files"
|
||||||
dry: true
|
npx prettier "src/**/*.{js,jsx}" --check
|
||||||
# Don't write anything
|
|
||||||
prettier_options: '--check --config .prettierrc'
|
|
||||||
file_pattern: '.'
|
|
||||||
|
|
|
@ -319,7 +319,7 @@ Costs involved in running and developing this web app:
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15791971/medium/88bdda3090339f16f6083390d32bb434_default.png" alt="" width="16" height="16" /> katullo11 (Italian)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15791971/medium/88bdda3090339f16f6083390d32bb434_default.png" alt="" width="16" height="16" /> katullo11 (Italian)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14677260/medium/e53420d200961f48602324e18c091bdc.png" alt="" width="16" height="16" /> Kytta (German)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14677260/medium/e53420d200961f48602324e18c091bdc.png" alt="" width="16" height="16" /> Kytta (German)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16529521/medium/ae6add93a901b0fefa2d9b1077920d73.png" alt="" width="16" height="16" /> llun (Thai)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16529521/medium/ae6add93a901b0fefa2d9b1077920d73.png" alt="" width="16" height="16" /> llun (Thai)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16291756/medium/e1c4210f15537394cc764b8bc2dffe37.jpg" alt="" width="16" height="16" /> lucasofchirst (Occitan, Portuguese, Portuguese, Brazilian)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16291756/medium/2366972cc86287353708aff1ded3f3c1.jpg" alt="" width="16" height="16" /> lucasofchirst (Occitan, Portuguese, Portuguese, Brazilian)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16537713/medium/825f0bf1a14fc545a76891a52839d86e_default.png" alt="" width="16" height="16" /> marcin.kozinski (Polish)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16537713/medium/825f0bf1a14fc545a76891a52839d86e_default.png" alt="" width="16" height="16" /> marcin.kozinski (Polish)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/13521465/medium/76cb9aa6b753ce900a70478bff7fcea0.png" alt="" width="16" height="16" /> mkljczkk (Polish)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/13521465/medium/76cb9aa6b753ce900a70478bff7fcea0.png" alt="" width="16" height="16" /> mkljczkk (Polish)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/12882812/medium/77744d8db46e9a3e09030e1a02b7a572.jpeg" alt="" width="16" height="16" /> mojosoeun (Korean)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/12882812/medium/77744d8db46e9a3e09030e1a02b7a572.jpeg" alt="" width="16" height="16" /> mojosoeun (Korean)
|
||||||
|
@ -337,12 +337,14 @@ Costs involved in running and developing this web app:
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16539171/medium/0ce95ef6b3b0566136191fbedc1563d0.png" alt="" width="16" height="16" /> SadmL_AI (Russian)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16539171/medium/0ce95ef6b3b0566136191fbedc1563d0.png" alt="" width="16" height="16" /> SadmL_AI (Russian)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/12381015/medium/35e3557fd61d85f9a5b84545d9e3feb4.png" alt="" width="16" height="16" /> shuuji3 (Japanese)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/12381015/medium/35e3557fd61d85f9a5b84545d9e3feb4.png" alt="" width="16" height="16" /> shuuji3 (Japanese)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14565190/medium/79100599131b7776e9803e4b696915a3_default.png" alt="" width="16" height="16" /> Sky_NiniKo (French)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14565190/medium/79100599131b7776e9803e4b696915a3_default.png" alt="" width="16" height="16" /> Sky_NiniKo (French)
|
||||||
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/13143526/medium/2f15fa6d8e1703c7b82bb608b116a30a.png" alt="" width="16" height="16" /> Steffo99 (Italian)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16532441/medium/1a47e8d80c95636e02d2260f6e233ca5.png" alt="" width="16" height="16" /> Su5hicz (Czech)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16532441/medium/1a47e8d80c95636e02d2260f6e233ca5.png" alt="" width="16" height="16" /> Su5hicz (Czech)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16530049/medium/683f3581620c6b4a5c753b416ed695a7.jpeg" alt="" width="16" height="16" /> tferrermo (Spanish)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16530049/medium/683f3581620c6b4a5c753b416ed695a7.jpeg" alt="" width="16" height="16" /> tferrermo (Spanish)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15752199/medium/7e9efd828c4691368d063b19d19eb894.png" alt="" width="16" height="16" /> tkbremnes (Norwegian Bokmal)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15752199/medium/7e9efd828c4691368d063b19d19eb894.png" alt="" width="16" height="16" /> tkbremnes (Norwegian Bokmal)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16527851/medium/649e5a9a8a8cc61ced670d89e9cca082.png" alt="" width="16" height="16" /> tux93 (German)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16527851/medium/649e5a9a8a8cc61ced670d89e9cca082.png" alt="" width="16" height="16" /> tux93 (German)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14427566/medium/ab733b5044c21867fc5a9d1b22cd2c03.png" alt="" width="16" height="16" /> Vac31. (Lithuanian)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/14427566/medium/ab733b5044c21867fc5a9d1b22cd2c03.png" alt="" width="16" height="16" /> Vac31. (Lithuanian)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16026914/medium/e3ca187f354a298ef0c9d02a0ed17be7.jpg" alt="" width="16" height="16" /> valtlai (Finnish)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16026914/medium/e3ca187f354a298ef0c9d02a0ed17be7.jpg" alt="" width="16" height="16" /> valtlai (Finnish)
|
||||||
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16608515/medium/85506c21dce8df07843ca11908ee3951.jpeg" alt="" width="16" height="16" /> vasiriri (Polish)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16563757/medium/af4556c13862d1fd593b51084a159b75_default.png" alt="" width="16" height="16" /> voyagercy (Chinese Traditional)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16563757/medium/af4556c13862d1fd593b51084a159b75_default.png" alt="" width="16" height="16" /> voyagercy (Chinese Traditional)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15982109/medium/9c03062bdc1d3c6d384dbfead97c26ba.jpeg" alt="" width="16" height="16" /> xabi_itzultzaile (Basque)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/15982109/medium/9c03062bdc1d3c6d384dbfead97c26ba.jpeg" alt="" width="16" height="16" /> xabi_itzultzaile (Basque)
|
||||||
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16556017/medium/216e0f7a0c35b079920366939a3aaca7_default.png" alt="" width="16" height="16" /> xen4n (Ukrainian)
|
- <img src="https://crowdin-static.downloads.crowdin.com/avatar/16556017/medium/216e0f7a0c35b079920366939a3aaca7_default.png" alt="" width="16" height="16" /> xen4n (Ukrainian)
|
||||||
|
|
BIN
design/logo-bw-4.png
Normal file
BIN
design/logo-bw-4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
12
design/logo-bw-4.svg
Normal file
12
design/logo-bw-4.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd" viewBox="0 0 64 64">
|
||||||
|
<path fill="none" d="M0 0h63.99v63.99H0z"/>
|
||||||
|
<clipPath id="a">
|
||||||
|
<path d="M0 0h63.99v63.99H0z"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#a)">
|
||||||
|
<path d="M0 0h64.25v63.99H0z"/>
|
||||||
|
<path fill="#fff" d="M37.77 11.47c14.64 3.75 19.04 16.56 15.9 31.3a12.55 12.55 0 0 1-6.36 8.7c-3.2 1.71-8.07 2.53-15.34.55l-9.64-2.4c-10.68-2.63-13.95-10.89-12.3-17.8 3.62-15.2 15.54-23.48 27.74-20.35Z"/>
|
||||||
|
<path d="M36.76 15.43c12.29 3.15 15.55 14.11 12.9 26.5-.94 4.43-4.93 9.36-16.66 6.13l-9.68-2.41c-7.85-1.93-10.53-7.8-9.32-12.88 3.02-12.64 12.61-19.94 22.76-17.34Z"/>
|
||||||
|
<path fill="#fff" d="M27.47 25c-1.46-.7-7.23 3.2-7.66 8.92-.18 2.39 4.55 3.23 5.07-.17.72-4.74 3.71-8.22 2.6-8.76Zm10.75 2c-2.09.32-.39 5.9-.6 10.72-.12 2.8 4.39 3.47 4.7 2.01 1.1-5.07-2.06-13.05-4.1-12.73Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 954 B |
BIN
design/logo-wb-4.png
Normal file
BIN
design/logo-wb-4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
12
design/logo-wb-4.svg
Normal file
12
design/logo-wb-4.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" clip-rule="evenodd" viewBox="0 0 64 64">
|
||||||
|
<path fill="none" d="M0 0h63.99v63.99H0z"/>
|
||||||
|
<clipPath id="a">
|
||||||
|
<path d="M0 0h63.99v63.99H0z"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#a)">
|
||||||
|
<path fill="#fff" d="M0 0h64.25v63.99H0z"/>
|
||||||
|
<path d="M37.77 11.47c14.64 3.75 19.04 16.56 15.9 31.3a12.55 12.55 0 0 1-6.36 8.7c-3.2 1.71-8.07 2.53-15.34.55l-9.64-2.4c-10.68-2.63-13.95-10.89-12.3-17.8 3.62-15.2 15.54-23.48 27.74-20.35Z"/>
|
||||||
|
<path fill="#fff" d="M36.76 15.43c12.29 3.15 15.55 14.11 12.9 26.5-.94 4.43-4.93 9.36-16.66 6.13l-9.68-2.41c-7.85-1.93-10.53-7.8-9.32-12.88 3.02-12.64 12.61-19.94 22.76-17.34Z"/>
|
||||||
|
<path d="M27.47 25c-1.46-.7-7.23 3.2-7.66 8.92-.18 2.39 4.55 3.23 5.07-.17.72-4.74 3.71-8.22 2.6-8.76Zm10.75 2c-2.09.32-.39 5.9-.6 10.72-.12 2.8 4.39 3.47 4.7 2.01 1.1-5.07-2.06-13.05-4.1-12.73Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 954 B |
Binary file not shown.
56
package-lock.json
generated
56
package-lock.json
generated
|
@ -11,7 +11,7 @@
|
||||||
"@formatjs/intl-localematcher": "~0.5.4",
|
"@formatjs/intl-localematcher": "~0.5.4",
|
||||||
"@formatjs/intl-segmenter": "~11.5.7",
|
"@formatjs/intl-segmenter": "~11.5.7",
|
||||||
"@formkit/auto-animate": "~0.8.2",
|
"@formkit/auto-animate": "~0.8.2",
|
||||||
"@github/text-expander-element": "~2.7.1",
|
"@github/text-expander-element": "~2.7.2",
|
||||||
"@iconify-icons/mingcute": "~1.2.9",
|
"@iconify-icons/mingcute": "~1.2.9",
|
||||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||||
"@lingui/detect-locale": "~4.11.4",
|
"@lingui/detect-locale": "~4.11.4",
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
"moize": "~6.1.6",
|
"moize": "~6.1.6",
|
||||||
"p-retry": "~6.2.0",
|
"p-retry": "~6.2.0",
|
||||||
"p-throttle": "~6.2.0",
|
"p-throttle": "~6.2.0",
|
||||||
"preact": "~10.24.0",
|
"preact": "~10.24.2",
|
||||||
"punycode": "~2.3.1",
|
"punycode": "~2.3.1",
|
||||||
"react-hotkeys-hook": "~4.5.1",
|
"react-hotkeys-hook": "~4.5.1",
|
||||||
"react-intersection-observer": "~9.13.1",
|
"react-intersection-observer": "~9.13.1",
|
||||||
|
@ -56,9 +56,9 @@
|
||||||
"babel-plugin-macros": "~3.1.0",
|
"babel-plugin-macros": "~3.1.0",
|
||||||
"postcss": "~8.4.47",
|
"postcss": "~8.4.47",
|
||||||
"postcss-dark-theme-class": "~1.3.0",
|
"postcss-dark-theme-class": "~1.3.0",
|
||||||
"postcss-preset-env": "~10.0.3",
|
"postcss-preset-env": "~10.0.6",
|
||||||
"twitter-text": "~3.1.0",
|
"twitter-text": "~3.1.0",
|
||||||
"vite": "~5.4.7",
|
"vite": "~5.4.8",
|
||||||
"vite-plugin-generate-file": "~0.2.0",
|
"vite-plugin-generate-file": "~0.2.0",
|
||||||
"vite-plugin-html-config": "~2.0.2",
|
"vite-plugin-html-config": "~2.0.2",
|
||||||
"vite-plugin-pwa": "~0.20.5",
|
"vite-plugin-pwa": "~0.20.5",
|
||||||
|
@ -2349,9 +2349,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-light-dark-function": {
|
"node_modules/@csstools/postcss-light-dark-function": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-2.0.4.tgz",
|
||||||
"integrity": "sha512-QAWWDJtJ7ywzhaMe09QwhjhuwB0XN04fW1MFwoEJMcYyiQub4a57mVFV+ngQEekUhsqe/EtKVCzyOx4q3xshag==",
|
"integrity": "sha512-yHUt5DZ61Irvp72notmAl3Zt4Me50EWToWNocazyIFTVYFwwo/EucmV3hWi9zJehu3rOSvMclL7DzvRDfbak/A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -3282,12 +3282,12 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@github/text-expander-element": {
|
"node_modules/@github/text-expander-element": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.7.2.tgz",
|
||||||
"integrity": "sha512-CWxfYxJRkeWVCUhJveproLs6pHsPrWtK8TsjL8ByYVcSCs8CJmNzF8b7ZawrUgfai0F2jb4aIdw2FoBTykj9XA==",
|
"integrity": "sha512-eTIOUQKoBxe+e0yHKHQHoo4x61Erb7m0lhi2vMRHZS7TwI6OCGSj/3YydAr3obbQbZjevF9wPihLf1wADu3A9g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@github/combobox-nav": "^2.0.2",
|
"@github/combobox-nav": "^2.0.2",
|
||||||
"dom-input-range": "^1.1.6"
|
"dom-input-range": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ianvs/prettier-plugin-sort-imports": {
|
"node_modules/@ianvs/prettier-plugin-sort-imports": {
|
||||||
|
@ -5870,9 +5870,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dom-input-range": {
|
"node_modules/dom-input-range": {
|
||||||
"version": "1.1.6",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-input-range/-/dom-input-range-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/dom-input-range/-/dom-input-range-1.2.0.tgz",
|
||||||
"integrity": "sha512-4o/SkTpscD0n81BeErrrtmE58lG8vTks++92vk//ld0NmkQTb4AVJ2rexh2yor6rtBf5IMte26u+fF3EgCppPQ==",
|
"integrity": "sha512-8HVA5Oy5Vt872S7IXsjjp6/5Hqsm5YZLhurxwwQXp80T9qVsj8/mEUH3sQlFujLLUoWfxiaThHHuJ3/q1MHVuA==",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"demos"
|
"demos"
|
||||||
]
|
]
|
||||||
|
@ -8512,9 +8512,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-custom-media": {
|
"node_modules/postcss-custom-media": {
|
||||||
"version": "11.0.1",
|
"version": "11.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-11.0.2.tgz",
|
||||||
"integrity": "sha512-vfBliYVgEEJUFXCRPQ7jYt1wlD322u+/5GT0tZqMVYFInkpDHfjhU3nk2quTRW4uFc/umOOqLlxvrEOZRvloMw==",
|
"integrity": "sha512-IDtxB1VgPayRLjNBMjuf827sn1j2m9EGnhIxpx2coVerbWJF+twt590+PKvdDc4K8QNFqFJh+W/SOiHpasVXsg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -8945,9 +8945,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-preset-env": {
|
"node_modules/postcss-preset-env": {
|
||||||
"version": "10.0.3",
|
"version": "10.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.0.6.tgz",
|
||||||
"integrity": "sha512-1nrZ4IeBXEEj53IMoRKE+k/Ub6nQb3gFjaxTeyUNG5zv3JQclFDY5GKKhAi3nsa1lnPMWgzQX+/1y6wUt2+I7Q==",
|
"integrity": "sha512-qixfM2wbvKJhUjJELLB8lV2UCsyrMdSXqiXHiNKMgAbNturstc80j/8MsthJeOpxYEekrCrFzcaoOJm8JRSdBg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -8972,7 +8972,7 @@
|
||||||
"@csstools/postcss-ic-unit": "^4.0.0",
|
"@csstools/postcss-ic-unit": "^4.0.0",
|
||||||
"@csstools/postcss-initial": "^2.0.0",
|
"@csstools/postcss-initial": "^2.0.0",
|
||||||
"@csstools/postcss-is-pseudo-class": "^5.0.0",
|
"@csstools/postcss-is-pseudo-class": "^5.0.0",
|
||||||
"@csstools/postcss-light-dark-function": "^2.0.2",
|
"@csstools/postcss-light-dark-function": "^2.0.4",
|
||||||
"@csstools/postcss-logical-float-and-clear": "^3.0.0",
|
"@csstools/postcss-logical-float-and-clear": "^3.0.0",
|
||||||
"@csstools/postcss-logical-overflow": "^2.0.0",
|
"@csstools/postcss-logical-overflow": "^2.0.0",
|
||||||
"@csstools/postcss-logical-overscroll-behavior": "^2.0.0",
|
"@csstools/postcss-logical-overscroll-behavior": "^2.0.0",
|
||||||
|
@ -9001,7 +9001,7 @@
|
||||||
"postcss-color-functional-notation": "^7.0.2",
|
"postcss-color-functional-notation": "^7.0.2",
|
||||||
"postcss-color-hex-alpha": "^10.0.0",
|
"postcss-color-hex-alpha": "^10.0.0",
|
||||||
"postcss-color-rebeccapurple": "^10.0.0",
|
"postcss-color-rebeccapurple": "^10.0.0",
|
||||||
"postcss-custom-media": "^11.0.1",
|
"postcss-custom-media": "^11.0.2",
|
||||||
"postcss-custom-properties": "^14.0.1",
|
"postcss-custom-properties": "^14.0.1",
|
||||||
"postcss-custom-selectors": "^8.0.1",
|
"postcss-custom-selectors": "^8.0.1",
|
||||||
"postcss-dir-pseudo-class": "^9.0.0",
|
"postcss-dir-pseudo-class": "^9.0.0",
|
||||||
|
@ -9110,9 +9110,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/preact": {
|
"node_modules/preact": {
|
||||||
"version": "10.24.0",
|
"version": "10.24.2",
|
||||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz",
|
||||||
"integrity": "sha512-aK8Cf+jkfyuZ0ZZRG9FbYqwmEiGQ4y/PUO4SuTWoyWL244nZZh7bd5h2APd4rSNDYTBNghg1L+5iJN3Skxtbsw==",
|
"integrity": "sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/preact"
|
"url": "https://opencollective.com/preact"
|
||||||
|
@ -10536,9 +10536,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.7",
|
"version": "5.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
|
||||||
"integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==",
|
"integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"@formatjs/intl-localematcher": "~0.5.4",
|
"@formatjs/intl-localematcher": "~0.5.4",
|
||||||
"@formatjs/intl-segmenter": "~11.5.7",
|
"@formatjs/intl-segmenter": "~11.5.7",
|
||||||
"@formkit/auto-animate": "~0.8.2",
|
"@formkit/auto-animate": "~0.8.2",
|
||||||
"@github/text-expander-element": "~2.7.1",
|
"@github/text-expander-element": "~2.7.2",
|
||||||
"@iconify-icons/mingcute": "~1.2.9",
|
"@iconify-icons/mingcute": "~1.2.9",
|
||||||
"@justinribeiro/lite-youtube": "~1.5.0",
|
"@justinribeiro/lite-youtube": "~1.5.0",
|
||||||
"@lingui/detect-locale": "~4.11.4",
|
"@lingui/detect-locale": "~4.11.4",
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
"moize": "~6.1.6",
|
"moize": "~6.1.6",
|
||||||
"p-retry": "~6.2.0",
|
"p-retry": "~6.2.0",
|
||||||
"p-throttle": "~6.2.0",
|
"p-throttle": "~6.2.0",
|
||||||
"preact": "~10.24.0",
|
"preact": "~10.24.2",
|
||||||
"punycode": "~2.3.1",
|
"punycode": "~2.3.1",
|
||||||
"react-hotkeys-hook": "~4.5.1",
|
"react-hotkeys-hook": "~4.5.1",
|
||||||
"react-intersection-observer": "~9.13.1",
|
"react-intersection-observer": "~9.13.1",
|
||||||
|
@ -64,9 +64,9 @@
|
||||||
"babel-plugin-macros": "~3.1.0",
|
"babel-plugin-macros": "~3.1.0",
|
||||||
"postcss": "~8.4.47",
|
"postcss": "~8.4.47",
|
||||||
"postcss-dark-theme-class": "~1.3.0",
|
"postcss-dark-theme-class": "~1.3.0",
|
||||||
"postcss-preset-env": "~10.0.3",
|
"postcss-preset-env": "~10.0.6",
|
||||||
"twitter-text": "~3.1.0",
|
"twitter-text": "~3.1.0",
|
||||||
"vite": "~5.4.7",
|
"vite": "~5.4.8",
|
||||||
"vite-plugin-generate-file": "~0.2.0",
|
"vite-plugin-generate-file": "~0.2.0",
|
||||||
"vite-plugin-html-config": "~2.0.2",
|
"vite-plugin-html-config": "~2.0.2",
|
||||||
"vite-plugin-pwa": "~0.20.5",
|
"vite-plugin-pwa": "~0.20.5",
|
||||||
|
|
|
@ -1722,7 +1722,7 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
|
||||||
0 8px 16px -8px var(--drop-shadow-color);
|
0 8px 16px -8px var(--drop-shadow-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@supports (animation-timeline: scroll()) {
|
@supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {
|
||||||
.sheet header {
|
.sheet header {
|
||||||
animation: header-border 1s linear both;
|
animation: header-border 1s linear both;
|
||||||
animation-timeline: --sheet-scroll;
|
animation-timeline: --sheet-scroll;
|
||||||
|
@ -2363,7 +2363,7 @@ body > .szh-menu-container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (animation-timeline: scroll()) {
|
@supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {
|
||||||
.header-account {
|
.header-account {
|
||||||
animation: peekaboo-header 1s linear both;
|
animation: peekaboo-header 1s linear both;
|
||||||
animation-timeline: scroll();
|
animation-timeline: scroll();
|
||||||
|
|
|
@ -105,11 +105,13 @@ function AccountBlock({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Avatar
|
<div class="avatar-container">
|
||||||
url={useAvatarStatic ? avatarStatic : avatar || avatarStatic}
|
<Avatar
|
||||||
size={avatarSize}
|
url={useAvatarStatic ? avatarStatic : avatar || avatarStatic}
|
||||||
squircle={bot}
|
size={avatarSize}
|
||||||
/>
|
squircle={bot}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<span class="account-block-content">
|
<span class="account-block-content">
|
||||||
{!hideDisplayName && (
|
{!hideDisplayName && (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -217,13 +217,13 @@
|
||||||
background-image: none;
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
& + header .avatar + * {
|
& + header .avatar-container + * {
|
||||||
transition: opacity 0.3s ease-in-out;
|
transition: opacity 0.3s ease-in-out;
|
||||||
opacity: 0 !important;
|
opacity: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&,
|
&,
|
||||||
& + header .avatar {
|
& + header .avatar-container {
|
||||||
transition: filter 0.3s ease-in-out;
|
transition: filter 0.3s ease-in-out;
|
||||||
filter: none !important;
|
filter: none !important;
|
||||||
}
|
}
|
||||||
|
@ -250,16 +250,21 @@
|
||||||
-8px 0 24px var(--header-color-3, --bg-color),
|
-8px 0 24px var(--header-color-3, --bg-color),
|
||||||
8px 0 24px var(--header-color-4, --bg-color);
|
8px 0 24px var(--header-color-4, --bg-color);
|
||||||
animation: fade-in 0.3s both ease-in-out 0.1s;
|
animation: fade-in 0.3s both ease-in-out 0.1s;
|
||||||
}
|
|
||||||
.account-container header .avatar {
|
.avatar-container {
|
||||||
/* box-shadow: -8px 0 24px var(--header-color-3, --bg-color),
|
filter: drop-shadow(-2px 0 4px var(--header-color-3, --bg-color))
|
||||||
|
drop-shadow(2px 0 4px var(--header-color-4, --bg-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
/* box-shadow: -8px 0 24px var(--header-color-3, --bg-color),
|
||||||
8px 0 24px var(--header-color-4, --bg-color); */
|
8px 0 24px var(--header-color-4, --bg-color); */
|
||||||
overflow: initial;
|
/* overflow: initial; */
|
||||||
filter: drop-shadow(-2px 0 4px var(--header-color-3, --bg-color))
|
|
||||||
drop-shadow(2px 0 4px var(--header-color-4, --bg-color));
|
&:not(.has-alpha) img {
|
||||||
}
|
border-radius: inherit;
|
||||||
.account-container header .avatar:not(.has-alpha) img {
|
}
|
||||||
border-radius: inherit;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.account-container main > *:first-child {
|
.account-container main > *:first-child {
|
||||||
|
@ -585,7 +590,7 @@
|
||||||
margin-top: calc(-1 * var(--banner-overlap));
|
margin-top: calc(-1 * var(--banner-overlap));
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (animation-timeline: scroll()) {
|
@supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {
|
||||||
.header-banner:not(.header-is-avatar):not(:hover):not(:active) {
|
.header-banner:not(.header-is-avatar):not(:hover):not(:active) {
|
||||||
animation: bye-banner 1s linear both;
|
animation: bye-banner 1s linear both;
|
||||||
animation-timeline: view();
|
animation-timeline: view();
|
||||||
|
@ -754,12 +759,16 @@
|
||||||
letter-spacing: -0.5px;
|
letter-spacing: -0.5px;
|
||||||
mix-blend-mode: multiply;
|
mix-blend-mode: multiply;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
|
||||||
.timeline-start .account-container header .account-block .avatar {
|
.avatar-container {
|
||||||
width: 112px !important;
|
filter: drop-shadow(-8px 0 8px var(--header-color-3, --bg-color))
|
||||||
height: 112px !important;
|
drop-shadow(8px 0 8px var(--header-color-4, --bg-color));
|
||||||
filter: drop-shadow(-8px 0 8px var(--header-color-3, --bg-color))
|
}
|
||||||
drop-shadow(8px 0 8px var(--header-color-4, --bg-color));
|
|
||||||
|
.avatar {
|
||||||
|
width: 112px !important;
|
||||||
|
height: 112px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,12 @@ const ctx = canvas.getContext('2d', {
|
||||||
});
|
});
|
||||||
ctx.imageSmoothingEnabled = false;
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
|
||||||
|
const MISSING_IMAGE_PATH_REGEX = /missing\.png$/;
|
||||||
|
|
||||||
function Avatar({ url, size, alt = '', squircle, ...props }) {
|
function Avatar({ url, size, alt = '', squircle, ...props }) {
|
||||||
size = SIZES[size] || size || SIZES.m;
|
size = SIZES[size] || size || SIZES.m;
|
||||||
const avatarRef = useRef();
|
const avatarRef = useRef();
|
||||||
const isMissing = /missing\.png$/.test(url);
|
const isMissing = MISSING_IMAGE_PATH_REGEX.test(url);
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
ref={avatarRef}
|
ref={avatarRef}
|
||||||
|
@ -48,6 +50,7 @@ function Avatar({ url, size, alt = '', squircle, ...props }) {
|
||||||
alt={alt}
|
alt={alt}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
|
fetchPriority="low"
|
||||||
crossOrigin={
|
crossOrigin={
|
||||||
alphaCache[url] === undefined && !isMissing
|
alphaCache[url] === undefined && !isMissing
|
||||||
? 'anonymous'
|
? 'anonymous'
|
||||||
|
|
|
@ -13,6 +13,7 @@ export default function CustomEmoji({ staticUrl, alt, url }) {
|
||||||
height="16"
|
height="16"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
|
fetchPriority="low"
|
||||||
/>
|
/>
|
||||||
</picture>
|
</picture>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,29 +1,45 @@
|
||||||
import { memo } from 'preact/compat';
|
import { memo } from 'preact/compat';
|
||||||
|
|
||||||
|
import mem from '../utils/mem';
|
||||||
|
|
||||||
import CustomEmoji from './custom-emoji';
|
import CustomEmoji from './custom-emoji';
|
||||||
|
|
||||||
|
const shortcodesRegexp = mem((shortcodes) => {
|
||||||
|
return new RegExp(`:(${shortcodes.join('|')}):`, 'g');
|
||||||
|
});
|
||||||
|
|
||||||
function EmojiText({ text, emojis }) {
|
function EmojiText({ text, emojis }) {
|
||||||
if (!text) return '';
|
if (!text) return '';
|
||||||
if (!emojis?.length) return text;
|
if (!emojis?.length) return text;
|
||||||
if (text.indexOf(':') === -1) return text;
|
if (text.indexOf(':') === -1) return text;
|
||||||
const regex = new RegExp(
|
// const regex = new RegExp(
|
||||||
`:(${emojis.map((e) => e.shortcode).join('|')}):`,
|
// `:(${emojis.map((e) => e.shortcode).join('|')}):`,
|
||||||
'g',
|
// 'g',
|
||||||
);
|
// );
|
||||||
const elements = text.split(regex).map((word) => {
|
const regex = shortcodesRegexp(emojis.map((e) => e.shortcode));
|
||||||
|
const elements = text.split(regex).map((word, i) => {
|
||||||
const emoji = emojis.find((e) => e.shortcode === word);
|
const emoji = emojis.find((e) => e.shortcode === word);
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
const { url, staticUrl } = emoji;
|
const { url, staticUrl } = emoji;
|
||||||
return <CustomEmoji staticUrl={staticUrl} alt={word} url={url} />;
|
return (
|
||||||
|
<CustomEmoji
|
||||||
|
staticUrl={staticUrl}
|
||||||
|
alt={word}
|
||||||
|
url={url}
|
||||||
|
key={word + '-' + i} // Handle >= 2 same shortcodes
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return word;
|
return word;
|
||||||
});
|
});
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(
|
export default mem(EmojiText);
|
||||||
EmojiText,
|
|
||||||
(oldProps, newProps) =>
|
// export default memo(
|
||||||
oldProps.text === newProps.text &&
|
// EmojiText,
|
||||||
oldProps.emojis?.length === newProps.emojis?.length,
|
// (oldProps, newProps) =>
|
||||||
);
|
// oldProps.text === newProps.text &&
|
||||||
|
// oldProps.emojis?.length === newProps.emojis?.length,
|
||||||
|
// );
|
||||||
|
|
|
@ -21,6 +21,11 @@ const nameCollator = mem((locale) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ACCT_REGEX = /([^@]+)(@.+)/i;
|
||||||
|
const SHORTCODES_REGEX = /(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/g;
|
||||||
|
const SPACES_REGEX = /\s+/g;
|
||||||
|
const NON_ALPHA_NUMERIC_REGEX = /[^a-z0-9@\.]/gi;
|
||||||
|
|
||||||
function NameText({
|
function NameText({
|
||||||
account,
|
account,
|
||||||
instance,
|
instance,
|
||||||
|
@ -42,17 +47,17 @@ function NameText({
|
||||||
bot,
|
bot,
|
||||||
username,
|
username,
|
||||||
} = account;
|
} = account;
|
||||||
const [_, acct1, acct2] = acct.match(/([^@]+)(@.+)/i) || [, acct];
|
const [_, acct1, acct2] = acct.match(ACCT_REGEX) || [, acct];
|
||||||
|
|
||||||
if (!instance) instance = api().instance;
|
if (!instance) instance = api().instance;
|
||||||
|
|
||||||
const trimmedUsername = username.toLowerCase().trim();
|
const trimmedUsername = username.toLowerCase().trim();
|
||||||
const trimmedDisplayName = (displayName || '').toLowerCase().trim();
|
const trimmedDisplayName = (displayName || '').toLowerCase().trim();
|
||||||
const shortenedDisplayName = trimmedDisplayName
|
const shortenedDisplayName = trimmedDisplayName
|
||||||
.replace(/(\:(\w|\+|\-)+\:)(?=|[\!\.\?]|$)/g, '') // Remove shortcodes, regex from https://regex101.com/r/iE9uV0/1
|
.replace(SHORTCODES_REGEX, '') // Remove shortcodes, regex from https://regex101.com/r/iE9uV0/1
|
||||||
.replace(/\s+/g, ''); // E.g. "My name" === "myname"
|
.replace(SPACES_REGEX, ''); // E.g. "My name" === "myname"
|
||||||
const shortenedAlphaNumericDisplayName = shortenedDisplayName.replace(
|
const shortenedAlphaNumericDisplayName = shortenedDisplayName.replace(
|
||||||
/[^a-z0-9@\.]/gi,
|
NON_ALPHA_NUMERIC_REGEX,
|
||||||
'',
|
'',
|
||||||
); // Remove non-alphanumeric characters
|
); // Remove non-alphanumeric characters
|
||||||
|
|
||||||
|
@ -130,9 +135,11 @@ function NameText({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(NameText, (oldProps, newProps) => {
|
export default mem(NameText);
|
||||||
// Only care about account.id, the other props usually don't change
|
|
||||||
const { account } = oldProps;
|
// export default memo(NameText, (oldProps, newProps) => {
|
||||||
const { account: newAccount } = newProps;
|
// // Only care about account.id, the other props usually don't change
|
||||||
return account?.acct === newAccount?.acct;
|
// const { account } = oldProps;
|
||||||
});
|
// const { account: newAccount } = newProps;
|
||||||
|
// return account?.acct === newAccount?.acct;
|
||||||
|
// });
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Fragment } from 'preact';
|
||||||
import { memo } from 'preact/compat';
|
import { memo } from 'preact/compat';
|
||||||
|
|
||||||
import { api } from '../utils/api';
|
import { api } from '../utils/api';
|
||||||
|
import { isFiltered } from '../utils/filters';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import states, { statusKey } from '../utils/states';
|
import states, { statusKey } from '../utils/states';
|
||||||
import { getCurrentAccountID } from '../utils/store-utils';
|
import { getCurrentAccountID } from '../utils/store-utils';
|
||||||
|
@ -447,9 +448,19 @@ function Notification({
|
||||||
|
|
||||||
console.debug('RENDER Notification', notification.id);
|
console.debug('RENDER Notification', notification.id);
|
||||||
|
|
||||||
const sameCount =
|
const diffCount =
|
||||||
notificationsCount > 0 && notificationsCount <= sampleAccounts?.length;
|
notificationsCount > 0 && notificationsCount > sampleAccounts?.length;
|
||||||
const expandAccounts = sameCount ? 'local' : 'remote';
|
const expandAccounts = diffCount ? 'remote' : 'local';
|
||||||
|
|
||||||
|
// If there's a status and filter action is 'hide', then the notification is hidden
|
||||||
|
// TODO: Handle 'warn' action one day
|
||||||
|
if (!!status?.filtered) {
|
||||||
|
const isOwnPost = status?.account?.id === currentAccount;
|
||||||
|
const filterInfo = isFiltered(status.filtered, 'notifications');
|
||||||
|
if (!isSelf && !isOwnPost && filterInfo?.action === 'hide') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1601,7 +1601,7 @@ body:has(#modal-container .carousel) .status .media img:hover {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
@supports (animation-timeline: scroll()) {
|
@supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {
|
||||||
animation: media-carousel-slide 1s linear both;
|
animation: media-carousel-slide 1s linear both;
|
||||||
animation-timeline: --media-carousel;
|
animation-timeline: --media-carousel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
useCallback,
|
useCallback,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useLayoutEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
|
@ -124,11 +125,31 @@ function getPostText(status) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PostContent = memo(
|
const HTTP_REGEX = /^http/i;
|
||||||
|
const PostContent =
|
||||||
|
/*memo(*/
|
||||||
({ post, instance, previewMode }) => {
|
({ post, instance, previewMode }) => {
|
||||||
const { content, emojis, language, mentions, url } = post;
|
const { content, emojis, language, mentions, url } = post;
|
||||||
|
|
||||||
|
const divRef = useRef();
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (!divRef.current) return;
|
||||||
|
const dom = enhanceContent(content, {
|
||||||
|
emojis,
|
||||||
|
returnDOM: true,
|
||||||
|
});
|
||||||
|
// Remove target="_blank" from links
|
||||||
|
for (const a of dom.querySelectorAll('a.u-url[target="_blank"]')) {
|
||||||
|
if (!HTTP_REGEX.test(a.innerText.trim())) {
|
||||||
|
a.removeAttribute('target');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
divRef.current.replaceChildren(dom.cloneNode(true));
|
||||||
|
}, [content, emojis.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={divRef}
|
||||||
lang={language}
|
lang={language}
|
||||||
dir="auto"
|
dir="auto"
|
||||||
class="inner-content"
|
class="inner-content"
|
||||||
|
@ -138,28 +159,28 @@ const PostContent = memo(
|
||||||
previewMode,
|
previewMode,
|
||||||
statusURL: url,
|
statusURL: url,
|
||||||
})}
|
})}
|
||||||
dangerouslySetInnerHTML={{
|
// dangerouslySetInnerHTML={{
|
||||||
__html: enhanceContent(content, {
|
// __html: enhanceContent(content, {
|
||||||
emojis,
|
// emojis,
|
||||||
postEnhanceDOM: (dom) => {
|
// postEnhanceDOM: (dom) => {
|
||||||
// Remove target="_blank" from links
|
// // Remove target="_blank" from links
|
||||||
dom.querySelectorAll('a.u-url[target="_blank"]').forEach((a) => {
|
// dom.querySelectorAll('a.u-url[target="_blank"]').forEach((a) => {
|
||||||
if (!/http/i.test(a.innerText.trim())) {
|
// if (!/http/i.test(a.innerText.trim())) {
|
||||||
a.removeAttribute('target');
|
// a.removeAttribute('target');
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
}}
|
// }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
}; /*,
|
||||||
(oldProps, newProps) => {
|
(oldProps, newProps) => {
|
||||||
const { post: oldPost } = oldProps;
|
const { post: oldPost } = oldProps;
|
||||||
const { post: newPost } = newProps;
|
const { post: newPost } = newProps;
|
||||||
return oldPost.content === newPost.content;
|
return oldPost.content === newPost.content;
|
||||||
},
|
},
|
||||||
);
|
);*/
|
||||||
|
|
||||||
const SIZE_CLASS = {
|
const SIZE_CLASS = {
|
||||||
s: 'small',
|
s: 'small',
|
||||||
|
@ -189,6 +210,25 @@ const detectLang = pmem(async (text) => {
|
||||||
|
|
||||||
const readMoreText = msg`Read more →`;
|
const readMoreText = msg`Read more →`;
|
||||||
|
|
||||||
|
// All this work just to make sure this only lazy-run once
|
||||||
|
// Because first run is slow due to intl-localematcher
|
||||||
|
const DIFFERENT_LANG_CHECK = {};
|
||||||
|
const checkDifferentLanguage = (
|
||||||
|
language,
|
||||||
|
contentTranslationHideLanguages = [],
|
||||||
|
) => {
|
||||||
|
if (!language) return false;
|
||||||
|
const targetLanguage = getTranslateTargetLanguage(true);
|
||||||
|
const different =
|
||||||
|
language !== targetLanguage &&
|
||||||
|
!localeMatch([language], [targetLanguage]) &&
|
||||||
|
!contentTranslationHideLanguages.find(
|
||||||
|
(l) => language === l || localeMatch([language], [l]),
|
||||||
|
);
|
||||||
|
DIFFERENT_LANG_CHECK[language + contentTranslationHideLanguages] = true;
|
||||||
|
return different;
|
||||||
|
};
|
||||||
|
|
||||||
function Status({
|
function Status({
|
||||||
statusID,
|
statusID,
|
||||||
status,
|
status,
|
||||||
|
@ -513,9 +553,9 @@ function Status({
|
||||||
const isSizeLarge = size === 'l';
|
const isSizeLarge = size === 'l';
|
||||||
|
|
||||||
const [forceTranslate, setForceTranslate] = useState(_forceTranslate);
|
const [forceTranslate, setForceTranslate] = useState(_forceTranslate);
|
||||||
const targetLanguage = getTranslateTargetLanguage(true);
|
// const targetLanguage = getTranslateTargetLanguage(true);
|
||||||
const contentTranslationHideLanguages =
|
// const contentTranslationHideLanguages =
|
||||||
snapStates.settings.contentTranslationHideLanguages || [];
|
// snapStates.settings.contentTranslationHideLanguages || [];
|
||||||
const { contentTranslation, contentTranslationAutoInline } =
|
const { contentTranslation, contentTranslationAutoInline } =
|
||||||
snapStates.settings;
|
snapStates.settings;
|
||||||
if (!contentTranslation) enableTranslate = false;
|
if (!contentTranslation) enableTranslate = false;
|
||||||
|
@ -760,13 +800,37 @@ function Status({
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const differentLanguage =
|
// const differentLanguage =
|
||||||
!!language &&
|
// !!language &&
|
||||||
language !== targetLanguage &&
|
// language !== targetLanguage &&
|
||||||
!localeMatch([language], [targetLanguage]) &&
|
// !localeMatch([language], [targetLanguage]) &&
|
||||||
!contentTranslationHideLanguages.find(
|
// !contentTranslationHideLanguages.find(
|
||||||
(l) => language === l || localeMatch([language], [l]),
|
// (l) => language === l || localeMatch([language], [l]),
|
||||||
);
|
// );
|
||||||
|
const contentTranslationHideLanguages =
|
||||||
|
snapStates.settings.contentTranslationHideLanguages || [];
|
||||||
|
const [differentLanguage, setDifferentLanguage] = useState(
|
||||||
|
DIFFERENT_LANG_CHECK[language + contentTranslationHideLanguages]
|
||||||
|
? checkDifferentLanguage(language, contentTranslationHideLanguages)
|
||||||
|
: false,
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
!language ||
|
||||||
|
differentLanguage ||
|
||||||
|
DIFFERENT_LANG_CHECK[language + contentTranslationHideLanguages]
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let timeout = setTimeout(() => {
|
||||||
|
const different = checkDifferentLanguage(
|
||||||
|
language,
|
||||||
|
contentTranslationHideLanguages,
|
||||||
|
);
|
||||||
|
if (different) setDifferentLanguage(different);
|
||||||
|
}, 1);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, [language, differentLanguage, contentTranslationHideLanguages]);
|
||||||
|
|
||||||
const reblogIterator = useRef();
|
const reblogIterator = useRef();
|
||||||
const favouriteIterator = useRef();
|
const favouriteIterator = useRef();
|
||||||
|
@ -1228,6 +1292,9 @@ function Status({
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
itemProps={{
|
||||||
|
className: 'danger',
|
||||||
|
}}
|
||||||
menuItemClassName="danger"
|
menuItemClassName="danger"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// const yes = confirm('Delete this post?');
|
// const yes = confirm('Delete this post?');
|
||||||
|
@ -2721,6 +2788,8 @@ function Card({ card, selfReferential, selfAuthor, instance }) {
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
fetchPriority="low"
|
||||||
alt={imageDescription || ''}
|
alt={imageDescription || ''}
|
||||||
onError={(e) => {
|
onError={(e) => {
|
||||||
try {
|
try {
|
||||||
|
@ -3061,7 +3130,7 @@ function generateHTMLCode(post, instance, level = 0) {
|
||||||
: '');
|
: '');
|
||||||
|
|
||||||
const htmlCode = `
|
const htmlCode = `
|
||||||
<blockquote lang="${language}" cite="${url}">
|
<blockquote lang="${language}" cite="${url}" data-source="fediverse">
|
||||||
${
|
${
|
||||||
spoilerText
|
spoilerText
|
||||||
? `
|
? `
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
"code": "fa-IR",
|
"code": "fa-IR",
|
||||||
"nativeName": "فارسی",
|
"nativeName": "فارسی",
|
||||||
"name": "Persian",
|
"name": "Persian",
|
||||||
"completion": 77
|
"completion": 78
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "fi-FI",
|
"code": "fi-FI",
|
||||||
|
@ -99,13 +99,13 @@
|
||||||
"code": "lt-LT",
|
"code": "lt-LT",
|
||||||
"nativeName": "lietuvių",
|
"nativeName": "lietuvių",
|
||||||
"name": "Lithuanian",
|
"name": "Lithuanian",
|
||||||
"completion": 80
|
"completion": 97
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "nb-NO",
|
"code": "nb-NO",
|
||||||
"nativeName": "norsk bokmål",
|
"nativeName": "norsk bokmål",
|
||||||
"name": "Norwegian Bokmål",
|
"name": "Norwegian Bokmål",
|
||||||
"completion": 4
|
"completion": 31
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"code": "nl-NL",
|
"code": "nl-NL",
|
||||||
|
|
446
src/locales/ca-ES.po
generated
446
src/locales/ca-ES.po
generated
File diff suppressed because it is too large
Load diff
310
src/locales/eo-UY.po
generated
310
src/locales/eo-UY.po
generated
|
@ -8,7 +8,7 @@ msgstr ""
|
||||||
"Language: eo\n"
|
"Language: eo\n"
|
||||||
"Project-Id-Version: phanpy\n"
|
"Project-Id-Version: phanpy\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"PO-Revision-Date: 2024-09-22 19:29\n"
|
"PO-Revision-Date: 2024-10-06 13:22\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: Esperanto\n"
|
"Language-Team: Esperanto\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
@ -18,40 +18,40 @@ msgstr ""
|
||||||
"X-Crowdin-File: /main/src/locales/en.po\n"
|
"X-Crowdin-File: /main/src/locales/en.po\n"
|
||||||
"X-Crowdin-File-ID: 18\n"
|
"X-Crowdin-File-ID: 18\n"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:133
|
#: src/components/account-block.jsx:135
|
||||||
msgid "Locked"
|
msgid "Locked"
|
||||||
msgstr "Ŝlosita"
|
msgstr "Ŝlosita"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:139
|
#: src/components/account-block.jsx:141
|
||||||
msgid "Posts: {0}"
|
msgid "Posts: {0}"
|
||||||
msgstr "Afiŝoj: {0}"
|
msgstr "Afiŝoj: {0}"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:144
|
#: src/components/account-block.jsx:146
|
||||||
msgid "Last posted: {0}"
|
msgid "Last posted: {0}"
|
||||||
msgstr "Laste afiŝita: {0}"
|
msgstr "Laste afiŝita: {0}"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:159
|
#: src/components/account-block.jsx:161
|
||||||
#: src/components/account-info.jsx:634
|
#: src/components/account-info.jsx:634
|
||||||
msgid "Automated"
|
msgid "Automated"
|
||||||
msgstr "Aŭtomatigita"
|
msgstr "Aŭtomatigita"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:166
|
#: src/components/account-block.jsx:168
|
||||||
#: src/components/account-info.jsx:639
|
#: src/components/account-info.jsx:639
|
||||||
#: src/components/status.jsx:440
|
#: src/components/status.jsx:480
|
||||||
#: src/pages/catchup.jsx:1471
|
#: src/pages/catchup.jsx:1471
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Grupo"
|
msgstr "Grupo"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:176
|
#: src/components/account-block.jsx:178
|
||||||
msgid "Mutual"
|
msgid "Mutual"
|
||||||
msgstr "Reciproka"
|
msgstr "Reciproka"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:180
|
#: src/components/account-block.jsx:182
|
||||||
#: src/components/account-info.jsx:1677
|
#: src/components/account-info.jsx:1677
|
||||||
msgid "Requested"
|
msgid "Requested"
|
||||||
msgstr "Petita"
|
msgstr "Petita"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:184
|
#: src/components/account-block.jsx:186
|
||||||
#: src/components/account-info.jsx:416
|
#: src/components/account-info.jsx:416
|
||||||
#: src/components/account-info.jsx:742
|
#: src/components/account-info.jsx:742
|
||||||
#: src/components/account-info.jsx:756
|
#: src/components/account-info.jsx:756
|
||||||
|
@ -63,21 +63,21 @@ msgstr "Petita"
|
||||||
msgid "Following"
|
msgid "Following"
|
||||||
msgstr "Sekvatoj"
|
msgstr "Sekvatoj"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:188
|
#: src/components/account-block.jsx:190
|
||||||
#: src/components/account-info.jsx:1059
|
#: src/components/account-info.jsx:1059
|
||||||
msgid "Follows you"
|
msgid "Follows you"
|
||||||
msgstr "Sekvas vin"
|
msgstr "Sekvas vin"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:196
|
#: src/components/account-block.jsx:198
|
||||||
msgid "{followersCount, plural, one {# follower} other {# followers}}"
|
msgid "{followersCount, plural, one {# follower} other {# followers}}"
|
||||||
msgstr "{followersCount, plural, one {# sekvanto} other {# sekvantoj}}"
|
msgstr "{followersCount, plural, one {# sekvanto} other {# sekvantoj}}"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:205
|
#: src/components/account-block.jsx:207
|
||||||
#: src/components/account-info.jsx:680
|
#: src/components/account-info.jsx:680
|
||||||
msgid "Verified"
|
msgid "Verified"
|
||||||
msgstr "Kontrolita"
|
msgstr "Kontrolita"
|
||||||
|
|
||||||
#: src/components/account-block.jsx:220
|
#: src/components/account-block.jsx:222
|
||||||
#: src/components/account-info.jsx:777
|
#: src/components/account-info.jsx:777
|
||||||
msgid "Joined <0>{0}</0>"
|
msgid "Joined <0>{0}</0>"
|
||||||
msgstr "Aliĝis <0>{0}</0>"
|
msgstr "Aliĝis <0>{0}</0>"
|
||||||
|
@ -113,11 +113,11 @@ msgstr "Afiŝoj"
|
||||||
#: src/components/compose.jsx:2463
|
#: src/components/compose.jsx:2463
|
||||||
#: src/components/media-alt-modal.jsx:45
|
#: src/components/media-alt-modal.jsx:45
|
||||||
#: src/components/media-modal.jsx:283
|
#: src/components/media-modal.jsx:283
|
||||||
#: src/components/status.jsx:1636
|
#: src/components/status.jsx:1700
|
||||||
#: src/components/status.jsx:1653
|
#: src/components/status.jsx:1717
|
||||||
#: src/components/status.jsx:1777
|
#: src/components/status.jsx:1841
|
||||||
#: src/components/status.jsx:2375
|
#: src/components/status.jsx:2439
|
||||||
#: src/components/status.jsx:2378
|
#: src/components/status.jsx:2442
|
||||||
#: src/pages/account-statuses.jsx:528
|
#: src/pages/account-statuses.jsx:528
|
||||||
#: src/pages/accounts.jsx:109
|
#: src/pages/accounts.jsx:109
|
||||||
#: src/pages/hashtag.jsx:199
|
#: src/pages/hashtag.jsx:199
|
||||||
|
@ -186,7 +186,7 @@ msgid "Original"
|
||||||
msgstr "Originala"
|
msgstr "Originala"
|
||||||
|
|
||||||
#: src/components/account-info.jsx:859
|
#: src/components/account-info.jsx:859
|
||||||
#: src/components/status.jsx:2166
|
#: src/components/status.jsx:2230
|
||||||
#: src/pages/catchup.jsx:71
|
#: src/pages/catchup.jsx:71
|
||||||
#: src/pages/catchup.jsx:1445
|
#: src/pages/catchup.jsx:1445
|
||||||
#: src/pages/catchup.jsx:2056
|
#: src/pages/catchup.jsx:2056
|
||||||
|
@ -279,33 +279,33 @@ msgstr "Ŝalti diskonigojn"
|
||||||
#: src/components/account-info.jsx:1260
|
#: src/components/account-info.jsx:1260
|
||||||
#: src/components/account-info.jsx:1861
|
#: src/components/account-info.jsx:1861
|
||||||
msgid "Add/Remove from Lists"
|
msgid "Add/Remove from Lists"
|
||||||
msgstr "Aldoni / Forigi el listoj"
|
msgstr "Aldoni/Forigi el Listoj"
|
||||||
|
|
||||||
#: src/components/account-info.jsx:1299
|
#: src/components/account-info.jsx:1299
|
||||||
#: src/components/status.jsx:1079
|
#: src/components/status.jsx:1143
|
||||||
msgid "Link copied"
|
msgid "Link copied"
|
||||||
msgstr "Ligilo kopiita"
|
msgstr "Ligilo kopiita"
|
||||||
|
|
||||||
#: src/components/account-info.jsx:1302
|
#: src/components/account-info.jsx:1302
|
||||||
#: src/components/status.jsx:1082
|
#: src/components/status.jsx:1146
|
||||||
msgid "Unable to copy link"
|
msgid "Unable to copy link"
|
||||||
msgstr "Ne eblas kopii la ligilon"
|
msgstr "Ne eblas kopii la ligilon"
|
||||||
|
|
||||||
#: src/components/account-info.jsx:1308
|
#: src/components/account-info.jsx:1308
|
||||||
#: src/components/shortcuts-settings.jsx:1056
|
#: src/components/shortcuts-settings.jsx:1056
|
||||||
#: src/components/status.jsx:1088
|
#: src/components/status.jsx:1152
|
||||||
#: src/components/status.jsx:3150
|
#: src/components/status.jsx:3214
|
||||||
msgid "Copy"
|
msgid "Copy"
|
||||||
msgstr "Kopii"
|
msgstr "Kopii"
|
||||||
|
|
||||||
#: src/components/account-info.jsx:1323
|
#: src/components/account-info.jsx:1323
|
||||||
#: src/components/shortcuts-settings.jsx:1074
|
#: src/components/shortcuts-settings.jsx:1074
|
||||||
#: src/components/status.jsx:1104
|
#: src/components/status.jsx:1168
|
||||||
msgid "Sharing doesn't seem to work."
|
msgid "Sharing doesn't seem to work."
|
||||||
msgstr "Kunhavigo ŝajnas ne funkcii."
|
msgstr "Kunhavigo ŝajnas ne funkcii."
|
||||||
|
|
||||||
#: src/components/account-info.jsx:1329
|
#: src/components/account-info.jsx:1329
|
||||||
#: src/components/status.jsx:1110
|
#: src/components/status.jsx:1174
|
||||||
msgid "Share…"
|
msgid "Share…"
|
||||||
msgstr "Diskonigi…"
|
msgstr "Diskonigi…"
|
||||||
|
|
||||||
|
@ -422,9 +422,9 @@ msgstr "Sekvi"
|
||||||
#: src/components/shortcuts-settings.jsx:227
|
#: src/components/shortcuts-settings.jsx:227
|
||||||
#: src/components/shortcuts-settings.jsx:580
|
#: src/components/shortcuts-settings.jsx:580
|
||||||
#: src/components/shortcuts-settings.jsx:780
|
#: src/components/shortcuts-settings.jsx:780
|
||||||
#: src/components/status.jsx:2875
|
#: src/components/status.jsx:2939
|
||||||
#: src/components/status.jsx:3114
|
#: src/components/status.jsx:3178
|
||||||
#: src/components/status.jsx:3612
|
#: src/components/status.jsx:3676
|
||||||
#: src/pages/accounts.jsx:36
|
#: src/pages/accounts.jsx:36
|
||||||
#: src/pages/catchup.jsx:1581
|
#: src/pages/catchup.jsx:1581
|
||||||
#: src/pages/filters.jsx:224
|
#: src/pages/filters.jsx:224
|
||||||
|
@ -610,7 +610,7 @@ msgid "Attachment #{i} failed"
|
||||||
msgstr "Eraro aldonante #{i}"
|
msgstr "Eraro aldonante #{i}"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1118
|
#: src/components/compose.jsx:1118
|
||||||
#: src/components/status.jsx:1962
|
#: src/components/status.jsx:2026
|
||||||
#: src/components/timeline.jsx:984
|
#: src/components/timeline.jsx:984
|
||||||
msgid "Content warning"
|
msgid "Content warning"
|
||||||
msgstr "Enhavaverto"
|
msgstr "Enhavaverto"
|
||||||
|
@ -620,7 +620,7 @@ msgid "Content warning or sensitive media"
|
||||||
msgstr "Enhavaverto aŭ sentema plurmedio"
|
msgstr "Enhavaverto aŭ sentema plurmedio"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1170
|
#: src/components/compose.jsx:1170
|
||||||
#: src/components/status.jsx:92
|
#: src/components/status.jsx:93
|
||||||
#: src/pages/settings.jsx:297
|
#: src/pages/settings.jsx:297
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr "Publika"
|
msgstr "Publika"
|
||||||
|
@ -628,25 +628,25 @@ msgstr "Publika"
|
||||||
#: src/components/compose.jsx:1175
|
#: src/components/compose.jsx:1175
|
||||||
#: src/components/nav-menu.jsx:386
|
#: src/components/nav-menu.jsx:386
|
||||||
#: src/components/shortcuts-settings.jsx:162
|
#: src/components/shortcuts-settings.jsx:162
|
||||||
#: src/components/status.jsx:93
|
#: src/components/status.jsx:94
|
||||||
msgid "Local"
|
msgid "Local"
|
||||||
msgstr "Loka"
|
msgstr "Loka"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1179
|
#: src/components/compose.jsx:1179
|
||||||
#: src/components/status.jsx:94
|
#: src/components/status.jsx:95
|
||||||
#: src/pages/settings.jsx:300
|
#: src/pages/settings.jsx:300
|
||||||
msgid "Unlisted"
|
msgid "Unlisted"
|
||||||
msgstr "Nelistigita"
|
msgstr "Nelistigita"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1182
|
#: src/components/compose.jsx:1182
|
||||||
#: src/components/status.jsx:95
|
#: src/components/status.jsx:96
|
||||||
#: src/pages/settings.jsx:303
|
#: src/pages/settings.jsx:303
|
||||||
msgid "Followers only"
|
msgid "Followers only"
|
||||||
msgstr "Nur sekvantoj"
|
msgstr "Nur sekvantoj"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1185
|
#: src/components/compose.jsx:1185
|
||||||
#: src/components/status.jsx:96
|
#: src/components/status.jsx:97
|
||||||
#: src/components/status.jsx:1840
|
#: src/components/status.jsx:1904
|
||||||
msgid "Private mention"
|
msgid "Private mention"
|
||||||
msgstr "Privata mencio"
|
msgstr "Privata mencio"
|
||||||
|
|
||||||
|
@ -676,10 +676,10 @@ msgstr "Aldoni propran emoĝion"
|
||||||
|
|
||||||
#: src/components/compose.jsx:1479
|
#: src/components/compose.jsx:1479
|
||||||
#: src/components/keyboard-shortcuts-help.jsx:143
|
#: src/components/keyboard-shortcuts-help.jsx:143
|
||||||
#: src/components/status.jsx:831
|
#: src/components/status.jsx:895
|
||||||
#: src/components/status.jsx:1616
|
#: src/components/status.jsx:1680
|
||||||
#: src/components/status.jsx:1617
|
#: src/components/status.jsx:1681
|
||||||
#: src/components/status.jsx:2271
|
#: src/components/status.jsx:2335
|
||||||
msgid "Reply"
|
msgid "Reply"
|
||||||
msgstr "Respondi"
|
msgstr "Respondi"
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ msgstr "Eraro dum forigo de malneto! Bonvolu provi denove."
|
||||||
|
|
||||||
#: src/components/drafts.jsx:127
|
#: src/components/drafts.jsx:127
|
||||||
#: src/components/list-add-edit.jsx:183
|
#: src/components/list-add-edit.jsx:183
|
||||||
#: src/components/status.jsx:1251
|
#: src/components/status.jsx:1315
|
||||||
#: src/pages/filters.jsx:587
|
#: src/pages/filters.jsx:587
|
||||||
msgid "Delete…"
|
msgid "Delete…"
|
||||||
msgstr "Forigi…"
|
msgstr "Forigi…"
|
||||||
|
@ -1094,10 +1094,10 @@ msgid "<0>l</0> or <1>f</1>"
|
||||||
msgstr "<0>l</0> aŭ <1>f</1>"
|
msgstr "<0>l</0> aŭ <1>f</1>"
|
||||||
|
|
||||||
#: src/components/keyboard-shortcuts-help.jsx:164
|
#: src/components/keyboard-shortcuts-help.jsx:164
|
||||||
#: src/components/status.jsx:839
|
#: src/components/status.jsx:903
|
||||||
#: src/components/status.jsx:2297
|
#: src/components/status.jsx:2361
|
||||||
#: src/components/status.jsx:2329
|
#: src/components/status.jsx:2393
|
||||||
#: src/components/status.jsx:2330
|
#: src/components/status.jsx:2394
|
||||||
msgid "Boost"
|
msgid "Boost"
|
||||||
msgstr "Diskonigi"
|
msgstr "Diskonigi"
|
||||||
|
|
||||||
|
@ -1106,9 +1106,9 @@ msgid "<0>Shift</0> + <1>b</1>"
|
||||||
msgstr "<0>Ŝovo</0> + <1>b</1>"
|
msgstr "<0>Ŝovo</0> + <1>b</1>"
|
||||||
|
|
||||||
#: src/components/keyboard-shortcuts-help.jsx:172
|
#: src/components/keyboard-shortcuts-help.jsx:172
|
||||||
#: src/components/status.jsx:924
|
#: src/components/status.jsx:988
|
||||||
#: src/components/status.jsx:2354
|
#: src/components/status.jsx:2418
|
||||||
#: src/components/status.jsx:2355
|
#: src/components/status.jsx:2419
|
||||||
msgid "Bookmark"
|
msgid "Bookmark"
|
||||||
msgstr "Legosigni"
|
msgstr "Legosigni"
|
||||||
|
|
||||||
|
@ -1167,15 +1167,15 @@ msgid "Media description"
|
||||||
msgstr "Priskribo de plurmedio"
|
msgstr "Priskribo de plurmedio"
|
||||||
|
|
||||||
#: src/components/media-alt-modal.jsx:57
|
#: src/components/media-alt-modal.jsx:57
|
||||||
#: src/components/status.jsx:968
|
#: src/components/status.jsx:1032
|
||||||
#: src/components/status.jsx:995
|
#: src/components/status.jsx:1059
|
||||||
#: src/components/translation-block.jsx:195
|
#: src/components/translation-block.jsx:195
|
||||||
msgid "Translate"
|
msgid "Translate"
|
||||||
msgstr "Traduki"
|
msgstr "Traduki"
|
||||||
|
|
||||||
#: src/components/media-alt-modal.jsx:68
|
#: src/components/media-alt-modal.jsx:68
|
||||||
#: src/components/status.jsx:982
|
#: src/components/status.jsx:1046
|
||||||
#: src/components/status.jsx:1009
|
#: src/components/status.jsx:1073
|
||||||
msgid "Speak"
|
msgid "Speak"
|
||||||
msgstr "Paroli"
|
msgstr "Paroli"
|
||||||
|
|
||||||
|
@ -1212,9 +1212,9 @@ msgid "Filtered: {filterTitleStr}"
|
||||||
msgstr "Filtrila: {filterTitleStr}"
|
msgstr "Filtrila: {filterTitleStr}"
|
||||||
|
|
||||||
#: src/components/media-post.jsx:133
|
#: src/components/media-post.jsx:133
|
||||||
#: src/components/status.jsx:3442
|
#: src/components/status.jsx:3506
|
||||||
#: src/components/status.jsx:3538
|
#: src/components/status.jsx:3602
|
||||||
#: src/components/status.jsx:3616
|
#: src/components/status.jsx:3680
|
||||||
#: src/components/timeline.jsx:973
|
#: src/components/timeline.jsx:973
|
||||||
#: src/pages/catchup.jsx:75
|
#: src/pages/catchup.jsx:75
|
||||||
#: src/pages/catchup.jsx:1876
|
#: src/pages/catchup.jsx:1876
|
||||||
|
@ -1411,7 +1411,7 @@ msgstr "{account} petis sekvi vin."
|
||||||
|
|
||||||
#: src/components/notification.jsx:150
|
#: src/components/notification.jsx:150
|
||||||
msgid "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} liked your reply.} other {{account} liked your post.}}} other {{account} liked {postsCount} of your posts.}}} other {{postType, select, reply {<0><1>{0}</1> people</0> liked your reply.} other {<2><3>{1}</3> people</2> liked your post.}}}}"
|
msgid "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} liked your reply.} other {{account} liked your post.}}} other {{account} liked {postsCount} of your posts.}}} other {{postType, select, reply {<0><1>{0}</1> people</0> liked your reply.} other {<2><3>{1}</3> people</2> liked your post.}}}}"
|
||||||
msgstr "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} stelumis vian respondon.} other {{account} stelumis vian afiŝon.}}} other {{account} stelumis {postsCount} de viaj afiŝoj.}}} other {{postType, select, reply {<0><1>{0}</1> homoj</0> stelumis vian respondon.} other {<2><3>{1}</3> homoj</2> stelumis vian afiŝon.}}}}"
|
msgstr "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} ŝatis vian respondon.} other {{account} ŝatis vian afiŝon.}}} other {{account} ŝatis {postsCount} de viaj afiŝoj.}}} other {{postType, select, reply {<0><1>{0}</1> homoj</0> ŝatis vian respondon.} other {<2><3>{1}</3> homoj</2> ŝatis vian afiŝon.}}}}"
|
||||||
|
|
||||||
#: src/components/notification.jsx:192
|
#: src/components/notification.jsx:192
|
||||||
msgid "A poll you have voted in or created has ended."
|
msgid "A poll you have voted in or created has ended."
|
||||||
|
@ -1431,7 +1431,7 @@ msgstr "Afiŝo, kun kiu vi interagis, estis redaktita."
|
||||||
|
|
||||||
#: src/components/notification.jsx:203
|
#: src/components/notification.jsx:203
|
||||||
msgid "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} boosted & liked your reply.} other {{account} boosted & liked your post.}}} other {{account} boosted & liked {postsCount} of your posts.}}} other {{postType, select, reply {<0><1>{0}</1> people</0> boosted & liked your reply.} other {<2><3>{1}</3> people</2> boosted & liked your post.}}}}"
|
msgid "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} boosted & liked your reply.} other {{account} boosted & liked your post.}}} other {{account} boosted & liked {postsCount} of your posts.}}} other {{postType, select, reply {<0><1>{0}</1> people</0> boosted & liked your reply.} other {<2><3>{1}</3> people</2> boosted & liked your post.}}}}"
|
||||||
msgstr "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} diskonigis kaj stelumis vian respondon.} other {{account} diskonigis kaj stelumis vian afiŝon.}}} other {{account} diskonigis kaj stelumis {postsCount} de viaj afiŝoj.}}} other {{postType, select, reply {<0><1>{0}</1> homoj</0> diskonigis kaj stelumis vian respondon.} other {<2><3>{1}</3> homoj</2> diskonigis kaj stelumis vian afiŝon.}}}}"
|
msgstr "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{account} diskonigis kaj ŝatis vian respondon.} other {{account} diskonigis kaj ŝatis vian afiŝon.}}} other {{account} diskonigis kaj ŝatis {postsCount} de viaj afiŝoj.}}} other {{postType, select, reply {<0><1>{0}</1> homoj</0> diskonigis kaj ŝatis vian respondon.} other {<2><3>{1}</3> homoj</2> diskonigis kaj ŝatis vian afiŝon.}}}}"
|
||||||
|
|
||||||
#: src/components/notification.jsx:245
|
#: src/components/notification.jsx:245
|
||||||
msgid "{account} signed up."
|
msgid "{account} signed up."
|
||||||
|
@ -1494,8 +1494,8 @@ msgid "[Unknown notification type: {type}]"
|
||||||
msgstr "[Nekonata tipo de sciigo: {type}]"
|
msgstr "[Nekonata tipo de sciigo: {type}]"
|
||||||
|
|
||||||
#: src/components/notification.jsx:433
|
#: src/components/notification.jsx:433
|
||||||
#: src/components/status.jsx:938
|
#: src/components/status.jsx:1002
|
||||||
#: src/components/status.jsx:948
|
#: src/components/status.jsx:1012
|
||||||
msgid "Boosted/Liked by…"
|
msgid "Boosted/Liked by…"
|
||||||
msgstr "Diskonigita/Ŝatita de…"
|
msgstr "Diskonigita/Ŝatita de…"
|
||||||
|
|
||||||
|
@ -1517,7 +1517,7 @@ msgid "Learn more <0/>"
|
||||||
msgstr "Lerni pli <0/>"
|
msgstr "Lerni pli <0/>"
|
||||||
|
|
||||||
#: src/components/notification.jsx:745
|
#: src/components/notification.jsx:745
|
||||||
#: src/components/status.jsx:190
|
#: src/components/status.jsx:211
|
||||||
msgid "Read more →"
|
msgid "Read more →"
|
||||||
msgstr "Legi pli →"
|
msgstr "Legi pli →"
|
||||||
|
|
||||||
|
@ -1810,7 +1810,7 @@ msgid "Move down"
|
||||||
msgstr "Moviĝi malsupren"
|
msgstr "Moviĝi malsupren"
|
||||||
|
|
||||||
#: src/components/shortcuts-settings.jsx:376
|
#: src/components/shortcuts-settings.jsx:376
|
||||||
#: src/components/status.jsx:1216
|
#: src/components/status.jsx:1280
|
||||||
#: src/pages/list.jsx:170
|
#: src/pages/list.jsx:170
|
||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr "Redakti"
|
msgstr "Redakti"
|
||||||
|
@ -2008,297 +2008,297 @@ msgstr "Ne estas plu ŝparvojoj por importi"
|
||||||
msgid "Import/export settings from/to instance server (Very experimental)"
|
msgid "Import/export settings from/to instance server (Very experimental)"
|
||||||
msgstr "Importi/eksporti agordojn de/al nodservilo (Tre eksperimenta)"
|
msgstr "Importi/eksporti agordojn de/al nodservilo (Tre eksperimenta)"
|
||||||
|
|
||||||
#: src/components/status.jsx:464
|
#: src/components/status.jsx:504
|
||||||
msgid "<0/> <1>boosted</1>"
|
msgid "<0/> <1>boosted</1>"
|
||||||
msgstr "<0/> <1>diskonigita</1>"
|
msgstr "<0/> <1>diskonigita</1>"
|
||||||
|
|
||||||
#: src/components/status.jsx:563
|
#: src/components/status.jsx:603
|
||||||
msgid "Sorry, your current logged-in instance can't interact with this post from another instance."
|
msgid "Sorry, your current logged-in instance can't interact with this post from another instance."
|
||||||
msgstr "Pardonu, la nodo en kiu vi estas ensalutinta ne permesas vin interagi kun ĉi tiu afiŝo de alia nodo."
|
msgstr "Pardonu, la nodo en kiu vi estas ensalutinta ne permesas vin interagi kun ĉi tiu afiŝo de alia nodo."
|
||||||
|
|
||||||
#: src/components/status.jsx:716
|
#: src/components/status.jsx:756
|
||||||
msgid "Unliked @{0}'s post"
|
msgid "Unliked @{0}'s post"
|
||||||
msgstr "Ne plu ŝatis la afiŝon de {0}"
|
msgstr "Ne plu ŝatis la afiŝon de {0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:717
|
#: src/components/status.jsx:757
|
||||||
msgid "Liked @{0}'s post"
|
msgid "Liked @{0}'s post"
|
||||||
msgstr "Ŝatis la afiŝon de {0}"
|
msgstr "Ŝatis la afiŝon de {0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:756
|
#: src/components/status.jsx:796
|
||||||
msgid "Unbookmarked @{0}'s post"
|
msgid "Unbookmarked @{0}'s post"
|
||||||
msgstr "Ne plu legosignis la afiŝon de @{0}"
|
msgstr "Ne plu legosignis la afiŝon de @{0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:757
|
#: src/components/status.jsx:797
|
||||||
msgid "Bookmarked @{0}'s post"
|
msgid "Bookmarked @{0}'s post"
|
||||||
msgstr "Legosignis la afiŝon de @{0}"
|
msgstr "Legosignis la afiŝon de @{0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:839
|
#: src/components/status.jsx:903
|
||||||
#: src/components/status.jsx:901
|
#: src/components/status.jsx:965
|
||||||
#: src/components/status.jsx:2297
|
#: src/components/status.jsx:2361
|
||||||
#: src/components/status.jsx:2329
|
#: src/components/status.jsx:2393
|
||||||
msgid "Unboost"
|
msgid "Unboost"
|
||||||
msgstr "Ne plu diskonigi"
|
msgstr "Ne plu diskonigi"
|
||||||
|
|
||||||
#: src/components/status.jsx:855
|
#: src/components/status.jsx:919
|
||||||
#: src/components/status.jsx:2312
|
#: src/components/status.jsx:2376
|
||||||
msgid "Quote"
|
msgid "Quote"
|
||||||
msgstr "Citaĵo"
|
msgstr "Citaĵo"
|
||||||
|
|
||||||
#: src/components/status.jsx:863
|
#: src/components/status.jsx:927
|
||||||
#: src/components/status.jsx:2321
|
#: src/components/status.jsx:2385
|
||||||
msgid "Some media have no descriptions."
|
msgid "Some media have no descriptions."
|
||||||
msgstr "Iuj plurmedioj ne havas priskribojn."
|
msgstr "Iuj plurmedioj ne havas priskribojn."
|
||||||
|
|
||||||
#: src/components/status.jsx:870
|
#: src/components/status.jsx:934
|
||||||
msgid "Old post (<0>{0}</0>)"
|
msgid "Old post (<0>{0}</0>)"
|
||||||
msgstr "Malnova afiŝo (<0>{0}</0>)"
|
msgstr "Malnova afiŝo (<0>{0}</0>)"
|
||||||
|
|
||||||
#: src/components/status.jsx:889
|
#: src/components/status.jsx:953
|
||||||
#: src/components/status.jsx:1341
|
#: src/components/status.jsx:1405
|
||||||
msgid "Unboosted @{0}'s post"
|
msgid "Unboosted @{0}'s post"
|
||||||
msgstr "Ne plu diskonigita la afiŝon de @{0}"
|
msgstr "Ne plu diskonigita la afiŝon de @{0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:890
|
#: src/components/status.jsx:954
|
||||||
#: src/components/status.jsx:1342
|
#: src/components/status.jsx:1406
|
||||||
msgid "Boosted @{0}'s post"
|
msgid "Boosted @{0}'s post"
|
||||||
msgstr "Diskonigita la afiŝon de @{0}"
|
msgstr "Diskonigita la afiŝon de @{0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:902
|
#: src/components/status.jsx:966
|
||||||
msgid "Boost…"
|
msgid "Boost…"
|
||||||
msgstr "Diskonigi…"
|
msgstr "Diskonigi…"
|
||||||
|
|
||||||
#: src/components/status.jsx:914
|
#: src/components/status.jsx:978
|
||||||
#: src/components/status.jsx:1626
|
#: src/components/status.jsx:1690
|
||||||
#: src/components/status.jsx:2342
|
#: src/components/status.jsx:2406
|
||||||
msgid "Unlike"
|
msgid "Unlike"
|
||||||
msgstr "Ne plu ŝati"
|
msgstr "Ne plu ŝati"
|
||||||
|
|
||||||
#: src/components/status.jsx:915
|
#: src/components/status.jsx:979
|
||||||
#: src/components/status.jsx:1626
|
#: src/components/status.jsx:1690
|
||||||
#: src/components/status.jsx:1627
|
#: src/components/status.jsx:1691
|
||||||
#: src/components/status.jsx:2342
|
#: src/components/status.jsx:2406
|
||||||
#: src/components/status.jsx:2343
|
#: src/components/status.jsx:2407
|
||||||
msgid "Like"
|
msgid "Like"
|
||||||
msgstr "Ŝatata"
|
msgstr "Ŝatata"
|
||||||
|
|
||||||
#: src/components/status.jsx:924
|
#: src/components/status.jsx:988
|
||||||
#: src/components/status.jsx:2354
|
#: src/components/status.jsx:2418
|
||||||
msgid "Unbookmark"
|
msgid "Unbookmark"
|
||||||
msgstr "Ne plu legosignis"
|
msgstr "Ne plu legosignis"
|
||||||
|
|
||||||
#: src/components/status.jsx:1032
|
#: src/components/status.jsx:1096
|
||||||
msgid "View post by <0>@{0}</0>"
|
msgid "View post by <0>@{0}</0>"
|
||||||
msgstr "Vidi afiŝon de <0>@{0}</0>"
|
msgstr "Vidi afiŝon de <0>@{0}</0>"
|
||||||
|
|
||||||
#: src/components/status.jsx:1053
|
#: src/components/status.jsx:1117
|
||||||
msgid "Show Edit History"
|
msgid "Show Edit History"
|
||||||
msgstr "Montri redaktan historion"
|
msgstr "Montri redaktan historion"
|
||||||
|
|
||||||
#: src/components/status.jsx:1056
|
#: src/components/status.jsx:1120
|
||||||
msgid "Edited: {editedDateText}"
|
msgid "Edited: {editedDateText}"
|
||||||
msgstr "Redaktita: {editedDateText}"
|
msgstr "Redaktita: {editedDateText}"
|
||||||
|
|
||||||
#: src/components/status.jsx:1123
|
#: src/components/status.jsx:1187
|
||||||
#: src/components/status.jsx:3119
|
#: src/components/status.jsx:3183
|
||||||
msgid "Embed post"
|
msgid "Embed post"
|
||||||
msgstr "Enkorpigi afiŝon"
|
msgstr "Enkorpigi afiŝon"
|
||||||
|
|
||||||
#: src/components/status.jsx:1137
|
#: src/components/status.jsx:1201
|
||||||
msgid "Conversation unmuted"
|
msgid "Conversation unmuted"
|
||||||
msgstr "Konversacion nesilentigita"
|
msgstr "Konversacion nesilentigita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1137
|
#: src/components/status.jsx:1201
|
||||||
msgid "Conversation muted"
|
msgid "Conversation muted"
|
||||||
msgstr "Konversacion silentigita"
|
msgstr "Konversacion silentigita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1143
|
#: src/components/status.jsx:1207
|
||||||
msgid "Unable to unmute conversation"
|
msgid "Unable to unmute conversation"
|
||||||
msgstr "Ne eblas nesilentigi konversacion"
|
msgstr "Ne eblas nesilentigi konversacion"
|
||||||
|
|
||||||
#: src/components/status.jsx:1144
|
#: src/components/status.jsx:1208
|
||||||
msgid "Unable to mute conversation"
|
msgid "Unable to mute conversation"
|
||||||
msgstr "Ne eblas silentigi konversacion"
|
msgstr "Ne eblas silentigi konversacion"
|
||||||
|
|
||||||
#: src/components/status.jsx:1153
|
#: src/components/status.jsx:1217
|
||||||
msgid "Unmute conversation"
|
msgid "Unmute conversation"
|
||||||
msgstr "Nesilentigi konversacion"
|
msgstr "Nesilentigi konversacion"
|
||||||
|
|
||||||
#: src/components/status.jsx:1160
|
#: src/components/status.jsx:1224
|
||||||
msgid "Mute conversation"
|
msgid "Mute conversation"
|
||||||
msgstr "Silentigi konversacion"
|
msgstr "Silentigi konversacion"
|
||||||
|
|
||||||
#: src/components/status.jsx:1176
|
#: src/components/status.jsx:1240
|
||||||
msgid "Post unpinned from profile"
|
msgid "Post unpinned from profile"
|
||||||
msgstr "Afiŝo depinglinta de profilo"
|
msgstr "Afiŝo depinglinta de profilo"
|
||||||
|
|
||||||
#: src/components/status.jsx:1177
|
#: src/components/status.jsx:1241
|
||||||
msgid "Post pinned to profile"
|
msgid "Post pinned to profile"
|
||||||
msgstr "Afiŝo alpinglita al profilo"
|
msgstr "Afiŝo alpinglita al profilo"
|
||||||
|
|
||||||
#: src/components/status.jsx:1182
|
#: src/components/status.jsx:1246
|
||||||
msgid "Unable to unpin post"
|
msgid "Unable to unpin post"
|
||||||
msgstr "Ne eblas depingli afiŝon"
|
msgstr "Ne eblas depingli afiŝon"
|
||||||
|
|
||||||
#: src/components/status.jsx:1182
|
#: src/components/status.jsx:1246
|
||||||
msgid "Unable to pin post"
|
msgid "Unable to pin post"
|
||||||
msgstr "Ne eblas alpingli afiŝon"
|
msgstr "Ne eblas alpingli afiŝon"
|
||||||
|
|
||||||
#: src/components/status.jsx:1191
|
#: src/components/status.jsx:1255
|
||||||
msgid "Unpin from profile"
|
msgid "Unpin from profile"
|
||||||
msgstr "Depingli de profilo"
|
msgstr "Depingli de profilo"
|
||||||
|
|
||||||
#: src/components/status.jsx:1198
|
#: src/components/status.jsx:1262
|
||||||
msgid "Pin to profile"
|
msgid "Pin to profile"
|
||||||
msgstr "Alpingli al la profilo"
|
msgstr "Alpingli al la profilo"
|
||||||
|
|
||||||
#: src/components/status.jsx:1227
|
#: src/components/status.jsx:1291
|
||||||
msgid "Delete this post?"
|
msgid "Delete this post?"
|
||||||
msgstr "Ĉu forigi ĉi tiun afiŝon?"
|
msgstr "Ĉu forigi ĉi tiun afiŝon?"
|
||||||
|
|
||||||
#: src/components/status.jsx:1240
|
#: src/components/status.jsx:1304
|
||||||
msgid "Post deleted"
|
msgid "Post deleted"
|
||||||
msgstr "Afiŝo forigita"
|
msgstr "Afiŝo forigita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1243
|
#: src/components/status.jsx:1307
|
||||||
msgid "Unable to delete post"
|
msgid "Unable to delete post"
|
||||||
msgstr "Ne eblas forigi afiŝon"
|
msgstr "Ne eblas forigi afiŝon"
|
||||||
|
|
||||||
#: src/components/status.jsx:1271
|
#: src/components/status.jsx:1335
|
||||||
msgid "Report post…"
|
msgid "Report post…"
|
||||||
msgstr "Raporti afiŝon…"
|
msgstr "Raporti afiŝon…"
|
||||||
|
|
||||||
#: src/components/status.jsx:1627
|
#: src/components/status.jsx:1691
|
||||||
#: src/components/status.jsx:1663
|
#: src/components/status.jsx:1727
|
||||||
#: src/components/status.jsx:2343
|
#: src/components/status.jsx:2407
|
||||||
msgid "Liked"
|
msgid "Liked"
|
||||||
msgstr "Ŝatita"
|
msgstr "Ŝatita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1660
|
#: src/components/status.jsx:1724
|
||||||
#: src/components/status.jsx:2330
|
#: src/components/status.jsx:2394
|
||||||
msgid "Boosted"
|
msgid "Boosted"
|
||||||
msgstr "Diskonigita"
|
msgstr "Diskonigita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1670
|
#: src/components/status.jsx:1734
|
||||||
#: src/components/status.jsx:2355
|
#: src/components/status.jsx:2419
|
||||||
msgid "Bookmarked"
|
msgid "Bookmarked"
|
||||||
msgstr "Legosignita"
|
msgstr "Legosignita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1674
|
#: src/components/status.jsx:1738
|
||||||
msgid "Pinned"
|
msgid "Pinned"
|
||||||
msgstr "Alpinglita"
|
msgstr "Alpinglita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1719
|
#: src/components/status.jsx:1783
|
||||||
#: src/components/status.jsx:2174
|
#: src/components/status.jsx:2238
|
||||||
msgid "Deleted"
|
msgid "Deleted"
|
||||||
msgstr "Forigita"
|
msgstr "Forigita"
|
||||||
|
|
||||||
#: src/components/status.jsx:1760
|
#: src/components/status.jsx:1824
|
||||||
msgid "{repliesCount, plural, one {# reply} other {# replies}}"
|
msgid "{repliesCount, plural, one {# reply} other {# replies}}"
|
||||||
msgstr "{repliesCount, plural, one {# respondo} other {# respondoj}}"
|
msgstr "{repliesCount, plural, one {# respondo} other {# respondoj}}"
|
||||||
|
|
||||||
#: src/components/status.jsx:1849
|
#: src/components/status.jsx:1913
|
||||||
msgid "Thread{0}"
|
msgid "Thread{0}"
|
||||||
msgstr "Fadeno{0}"
|
msgstr "Fadeno{0}"
|
||||||
|
|
||||||
#: src/components/status.jsx:1925
|
#: src/components/status.jsx:1989
|
||||||
#: src/components/status.jsx:1987
|
#: src/components/status.jsx:2051
|
||||||
#: src/components/status.jsx:2072
|
#: src/components/status.jsx:2136
|
||||||
msgid "Show less"
|
msgid "Show less"
|
||||||
msgstr "Montri malpli"
|
msgstr "Montri malpli"
|
||||||
|
|
||||||
#: src/components/status.jsx:1925
|
#: src/components/status.jsx:1989
|
||||||
#: src/components/status.jsx:1987
|
#: src/components/status.jsx:2051
|
||||||
msgid "Show content"
|
msgid "Show content"
|
||||||
msgstr "Montri enhavon"
|
msgstr "Montri enhavon"
|
||||||
|
|
||||||
#: src/components/status.jsx:2072
|
#: src/components/status.jsx:2136
|
||||||
msgid "Show media"
|
msgid "Show media"
|
||||||
msgstr "Montri plurmedion"
|
msgstr "Montri plurmedion"
|
||||||
|
|
||||||
#: src/components/status.jsx:2195
|
#: src/components/status.jsx:2259
|
||||||
msgid "Edited"
|
msgid "Edited"
|
||||||
msgstr "Redaktita"
|
msgstr "Redaktita"
|
||||||
|
|
||||||
#: src/components/status.jsx:2272
|
#: src/components/status.jsx:2336
|
||||||
msgid "Comments"
|
msgid "Comments"
|
||||||
msgstr "Komentoj"
|
msgstr "Komentoj"
|
||||||
|
|
||||||
#. More from [Author]
|
#. More from [Author]
|
||||||
#: src/components/status.jsx:2581
|
#: src/components/status.jsx:2645
|
||||||
msgid "More from <0/>"
|
msgid "More from <0/>"
|
||||||
msgstr "Pli de <0/>"
|
msgstr "Pli de <0/>"
|
||||||
|
|
||||||
#: src/components/status.jsx:2880
|
#: src/components/status.jsx:2944
|
||||||
msgid "Edit History"
|
msgid "Edit History"
|
||||||
msgstr "Redaktan historion"
|
msgstr "Redaktan historion"
|
||||||
|
|
||||||
#: src/components/status.jsx:2884
|
#: src/components/status.jsx:2948
|
||||||
msgid "Failed to load history"
|
msgid "Failed to load history"
|
||||||
msgstr "Malsukcesis ŝargi historion"
|
msgstr "Malsukcesis ŝargi historion"
|
||||||
|
|
||||||
#: src/components/status.jsx:2889
|
#: src/components/status.jsx:2953
|
||||||
msgid "Loading…"
|
msgid "Loading…"
|
||||||
msgstr "Ŝargante…"
|
msgstr "Ŝargante…"
|
||||||
|
|
||||||
#: src/components/status.jsx:3124
|
#: src/components/status.jsx:3188
|
||||||
msgid "HTML Code"
|
msgid "HTML Code"
|
||||||
msgstr "HTML-kodo"
|
msgstr "HTML-kodo"
|
||||||
|
|
||||||
#: src/components/status.jsx:3141
|
#: src/components/status.jsx:3205
|
||||||
msgid "HTML code copied"
|
msgid "HTML code copied"
|
||||||
msgstr "HTML-kodo kopiita"
|
msgstr "HTML-kodo kopiita"
|
||||||
|
|
||||||
#: src/components/status.jsx:3144
|
#: src/components/status.jsx:3208
|
||||||
msgid "Unable to copy HTML code"
|
msgid "Unable to copy HTML code"
|
||||||
msgstr "Ne eblas kopii HTML-kodon"
|
msgstr "Ne eblas kopii HTML-kodon"
|
||||||
|
|
||||||
#: src/components/status.jsx:3156
|
#: src/components/status.jsx:3220
|
||||||
msgid "Media attachments:"
|
msgid "Media attachments:"
|
||||||
msgstr "Plurmediaj aldonaĵoj:"
|
msgstr "Plurmediaj aldonaĵoj:"
|
||||||
|
|
||||||
#: src/components/status.jsx:3178
|
#: src/components/status.jsx:3242
|
||||||
msgid "Account Emojis:"
|
msgid "Account Emojis:"
|
||||||
msgstr "Emoĝioj de la konto:"
|
msgstr "Emoĝioj de la konto:"
|
||||||
|
|
||||||
#: src/components/status.jsx:3209
|
#: src/components/status.jsx:3273
|
||||||
#: src/components/status.jsx:3254
|
#: src/components/status.jsx:3318
|
||||||
msgid "static URL"
|
msgid "static URL"
|
||||||
msgstr "statika URL"
|
msgstr "statika URL"
|
||||||
|
|
||||||
#: src/components/status.jsx:3223
|
#: src/components/status.jsx:3287
|
||||||
msgid "Emojis:"
|
msgid "Emojis:"
|
||||||
msgstr "Emoĝioj:"
|
msgstr "Emoĝioj:"
|
||||||
|
|
||||||
#: src/components/status.jsx:3268
|
#: src/components/status.jsx:3332
|
||||||
msgid "Notes:"
|
msgid "Notes:"
|
||||||
msgstr "Notoj:"
|
msgstr "Notoj:"
|
||||||
|
|
||||||
#: src/components/status.jsx:3272
|
#: src/components/status.jsx:3336
|
||||||
msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed."
|
msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed."
|
||||||
msgstr "Ĉi tio estas senmova, ne stilita kaj senskriba. Vi eble bezonos apliki viajn proprajn stilojn kaj redakti laŭbezone."
|
msgstr "Ĉi tio estas senmova, ne stilita kaj senskriba. Vi eble bezonos apliki viajn proprajn stilojn kaj redakti laŭbezone."
|
||||||
|
|
||||||
#: src/components/status.jsx:3278
|
#: src/components/status.jsx:3342
|
||||||
msgid "Polls are not interactive, becomes a list with vote counts."
|
msgid "Polls are not interactive, becomes a list with vote counts."
|
||||||
msgstr "Balotenketoj ne estas interagaj kaj estos konvertitaj al listo kun balotkalkuloj."
|
msgstr "Balotenketoj ne estas interagaj kaj estos konvertitaj al listo kun balotkalkuloj."
|
||||||
|
|
||||||
#: src/components/status.jsx:3283
|
#: src/components/status.jsx:3347
|
||||||
msgid "Media attachments can be images, videos, audios or any file types."
|
msgid "Media attachments can be images, videos, audios or any file types."
|
||||||
msgstr "Plurmediaj aldonaĵoj povas esti bildoj, filmetoj, sonaĵoj aŭ ajnaj dosiertipoj."
|
msgstr "Plurmediaj aldonaĵoj povas esti bildoj, filmetoj, sonaĵoj aŭ ajnaj dosiertipoj."
|
||||||
|
|
||||||
#: src/components/status.jsx:3289
|
#: src/components/status.jsx:3353
|
||||||
msgid "Post could be edited or deleted later."
|
msgid "Post could be edited or deleted later."
|
||||||
msgstr "Afiŝo povus esti redaktita aŭ forigita poste."
|
msgstr "Afiŝo povus esti redaktita aŭ forigita poste."
|
||||||
|
|
||||||
#: src/components/status.jsx:3295
|
#: src/components/status.jsx:3359
|
||||||
msgid "Preview"
|
msgid "Preview"
|
||||||
msgstr "Antaŭrigardo"
|
msgstr "Antaŭrigardo"
|
||||||
|
|
||||||
#: src/components/status.jsx:3304
|
#: src/components/status.jsx:3368
|
||||||
msgid "Note: This preview is lightly styled."
|
msgid "Note: This preview is lightly styled."
|
||||||
msgstr "Noto: Ĉi tiu antaŭmontro estas malpeze stilita."
|
msgstr "Noto: Ĉi tiu antaŭmontro estas malpeze stilita."
|
||||||
|
|
||||||
#. [Name] [Visibility icon] boosted
|
#. [Name] [Visibility icon] boosted
|
||||||
#: src/components/status.jsx:3546
|
#: src/components/status.jsx:3610
|
||||||
msgid "<0/> <1/> boosted"
|
msgid "<0/> <1/> boosted"
|
||||||
msgstr "<0/> <1/> diskonigita"
|
msgstr "<0/> <1/> diskonigita"
|
||||||
|
|
||||||
|
@ -2705,7 +2705,7 @@ msgstr "Nenio"
|
||||||
|
|
||||||
#: src/pages/catchup.jsx:1503
|
#: src/pages/catchup.jsx:1503
|
||||||
msgid "Show all authors"
|
msgid "Show all authors"
|
||||||
msgstr "Montru ĉiujn aŭtorojn"
|
msgstr "Montri ĉiujn aŭtorojn"
|
||||||
|
|
||||||
#: src/pages/catchup.jsx:1554
|
#: src/pages/catchup.jsx:1554
|
||||||
msgid "You don't have to read everything."
|
msgid "You don't have to read everything."
|
||||||
|
@ -2931,7 +2931,7 @@ msgstr "Neniu ankoraŭ afiŝis ion kun ĉi tiu kradvorto."
|
||||||
|
|
||||||
#: src/pages/hashtag.jsx:182
|
#: src/pages/hashtag.jsx:182
|
||||||
msgid "Unable to load posts with this tag"
|
msgid "Unable to load posts with this tag"
|
||||||
msgstr "Ne eblas ŝargi afiŝojn kun tiu ĉi kradvorto"
|
msgstr "Ne eblas ŝarĝi afiŝojn kun ĉi tiu kradvorto"
|
||||||
|
|
||||||
#: src/pages/hashtag.jsx:208
|
#: src/pages/hashtag.jsx:208
|
||||||
msgid "Unfollow #{hashtag}?"
|
msgid "Unfollow #{hashtag}?"
|
||||||
|
|
420
src/locales/es-ES.po
generated
420
src/locales/es-ES.po
generated
File diff suppressed because it is too large
Load diff
454
src/locales/eu-ES.po
generated
454
src/locales/eu-ES.po
generated
File diff suppressed because it is too large
Load diff
802
src/locales/fa-IR.po
generated
802
src/locales/fa-IR.po
generated
File diff suppressed because it is too large
Load diff
456
src/locales/it-IT.po
generated
456
src/locales/it-IT.po
generated
File diff suppressed because it is too large
Load diff
780
src/locales/lt-LT.po
generated
780
src/locales/lt-LT.po
generated
File diff suppressed because it is too large
Load diff
926
src/locales/nb-NO.po
generated
926
src/locales/nb-NO.po
generated
File diff suppressed because it is too large
Load diff
454
src/locales/pl-PL.po
generated
454
src/locales/pl-PL.po
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,7 @@
|
||||||
#settings-container {
|
#settings-container {
|
||||||
background-color: var(--bg-faded-color);
|
background-color: var(--bg-faded-color);
|
||||||
|
/* Prevent immediate text size change affecting max width */
|
||||||
|
max-width: calc(40 * var(--current-text-size) - 50px - 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings-container main h3 {
|
#settings-container main h3 {
|
||||||
|
|
|
@ -63,7 +63,14 @@ function Settings({ onClose }) {
|
||||||
// }, []);
|
// }, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="settings-container" class="sheet" tabIndex="-1">
|
<div
|
||||||
|
id="settings-container"
|
||||||
|
class="sheet"
|
||||||
|
tabIndex="-1"
|
||||||
|
style={{
|
||||||
|
'--current-text-size': `${currentTextSize}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
{!!onClose && (
|
{!!onClose && (
|
||||||
<button type="button" class="sheet-close" onClick={onClose}>
|
<button type="button" class="sheet-close" onClick={onClose}>
|
||||||
<Icon icon="x" alt={t`Close`} />
|
<Icon icon="x" alt={t`Close`} />
|
||||||
|
|
|
@ -44,6 +44,8 @@ import useTitle from '../utils/useTitle';
|
||||||
|
|
||||||
import getInstanceStatusURL from './../utils/get-instance-status-url';
|
import getInstanceStatusURL from './../utils/get-instance-status-url';
|
||||||
|
|
||||||
|
const { PHANPY_DEFAULT_INSTANCE: DEFAULT_INSTANCE } = import.meta.env;
|
||||||
|
|
||||||
const LIMIT = 40;
|
const LIMIT = 40;
|
||||||
const SUBCOMMENTS_OPEN_ALL_LIMIT = 10;
|
const SUBCOMMENTS_OPEN_ALL_LIMIT = 10;
|
||||||
const MAX_WEIGHT = 5;
|
const MAX_WEIGHT = 5;
|
||||||
|
@ -788,7 +790,14 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
||||||
not possible.
|
not possible.
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
<Link to="/login" class="button">
|
<Link
|
||||||
|
to={
|
||||||
|
DEFAULT_INSTANCE
|
||||||
|
? `/login?instance=${DEFAULT_INSTANCE}&submit=1`
|
||||||
|
: '/login'
|
||||||
|
}
|
||||||
|
class="button"
|
||||||
|
>
|
||||||
<Trans>Log in</Trans>
|
<Trans>Log in</Trans>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@ function emojifyText(text, emojis = []) {
|
||||||
const { shortcode, staticUrl, url } = emoji;
|
const { shortcode, staticUrl, url } = emoji;
|
||||||
text = text.replace(
|
text = text.replace(
|
||||||
new RegExp(`:${shortcode}:`, 'g'),
|
new RegExp(`:${shortcode}:`, 'g'),
|
||||||
`<picture><source srcset="${staticUrl}" media="(prefers-reduced-motion: reduce)"></source><img class="shortcode-emoji emoji" src="${url}" alt=":${shortcode}:" width="16" height="16" loading="lazy" decoding="async" /></picture>`,
|
`<picture><source srcset="${staticUrl}" media="(prefers-reduced-motion: reduce)"></source><img class="shortcode-emoji emoji" src="${url}" alt=":${shortcode}:" width="16" height="16" loading="lazy" decoding="async" fetchPriority="low" /></picture>`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// console.log(text, emojis);
|
// console.log(text, emojis);
|
||||||
|
|
|
@ -4,53 +4,85 @@ import mem from './mem';
|
||||||
const fauxDiv = document.createElement('div');
|
const fauxDiv = document.createElement('div');
|
||||||
const whitelistLinkClasses = ['u-url', 'mention', 'hashtag'];
|
const whitelistLinkClasses = ['u-url', 'mention', 'hashtag'];
|
||||||
|
|
||||||
|
const HTML_CHARS_REGEX = /[&<>]/g;
|
||||||
|
function escapeHTML(html) {
|
||||||
|
return html.replace(
|
||||||
|
HTML_CHARS_REGEX,
|
||||||
|
(c) =>
|
||||||
|
({
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
}[c]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LINK_REGEX = /<a/i;
|
||||||
|
const HTTP_LINK_REGEX = /^https?:\/\//i;
|
||||||
|
const MENTION_REGEX = /^@[^@]+(@[^@]+)?$/;
|
||||||
|
const HASHTAG_REGEX = /^#[^#]+$/;
|
||||||
|
const CODE_BLOCK_REGEX = /^```[^]+```$/;
|
||||||
|
const CODE_BLOCK_START_REGEX = /^```/;
|
||||||
|
const CODE_BLOCK_END_REGEX = /```$/;
|
||||||
|
const INLINE_CODE_REGEX = /`[^`]+`/;
|
||||||
|
const TWITTER_DOMAIN_REGEX = /(twitter|x)\.com/i;
|
||||||
|
const TWITTER_MENTION_REGEX = /@[a-zA-Z0-9_]+@(twitter|x)\.com/;
|
||||||
|
const TWITTER_MENTION_CAPTURE_REGEX = /(@([a-zA-Z0-9_]+)@(twitter|x)\.com)/;
|
||||||
|
|
||||||
|
function createDOM(html, isDocumentFragment) {
|
||||||
|
const tpl = document.createElement('template');
|
||||||
|
tpl.innerHTML = html;
|
||||||
|
return isDocumentFragment ? tpl.content : tpl;
|
||||||
|
}
|
||||||
|
|
||||||
function _enhanceContent(content, opts = {}) {
|
function _enhanceContent(content, opts = {}) {
|
||||||
const { emojis, postEnhanceDOM = () => {} } = opts;
|
const { emojis, returnDOM, postEnhanceDOM = () => {} } = opts;
|
||||||
let enhancedContent = content;
|
let enhancedContent = content;
|
||||||
const dom = document.createElement('div');
|
// const dom = document.createElement('div');
|
||||||
dom.innerHTML = enhancedContent;
|
// dom.innerHTML = enhancedContent;
|
||||||
const hasLink = /<a/i.test(enhancedContent);
|
const dom = createDOM(enhancedContent, returnDOM);
|
||||||
|
const hasLink = LINK_REGEX.test(enhancedContent);
|
||||||
const hasCodeBlock = enhancedContent.includes('```');
|
const hasCodeBlock = enhancedContent.includes('```');
|
||||||
|
|
||||||
if (hasLink) {
|
if (hasLink) {
|
||||||
// Add target="_blank" to all links with no target="_blank"
|
// Add target="_blank" to all links with no target="_blank"
|
||||||
// E.g. `note` in `account`
|
// E.g. `note` in `account`
|
||||||
const noTargetBlankLinks = dom.querySelectorAll('a:not([target="_blank"])');
|
const noTargetBlankLinks = dom.querySelectorAll('a:not([target="_blank"])');
|
||||||
noTargetBlankLinks.forEach((link) => {
|
for (const link of noTargetBlankLinks) {
|
||||||
link.setAttribute('target', '_blank');
|
link.setAttribute('target', '_blank');
|
||||||
});
|
}
|
||||||
|
|
||||||
// Remove all classes except `u-url`, `mention`, `hashtag`
|
// Remove all classes except `u-url`, `mention`, `hashtag`
|
||||||
const links = dom.querySelectorAll('a[class]');
|
const links = dom.querySelectorAll('a[class]');
|
||||||
links.forEach((link) => {
|
for (const link of links) {
|
||||||
link.classList.forEach((c) => {
|
for (const c of link.classList) {
|
||||||
if (!whitelistLinkClasses.includes(c)) {
|
if (!whitelistLinkClasses.includes(c)) {
|
||||||
link.classList.remove(c);
|
link.classList.remove(c);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 'has-url-text' to all links that contains a url
|
// Add 'has-url-text' to all links that contains a url
|
||||||
if (hasLink) {
|
if (hasLink) {
|
||||||
const links = dom.querySelectorAll('a[href]');
|
const links = dom.querySelectorAll('a[href]');
|
||||||
links.forEach((link) => {
|
for (const link of links) {
|
||||||
if (/^https?:\/\//i.test(link.textContent.trim())) {
|
if (HTTP_LINK_REGEX.test(link.textContent.trim())) {
|
||||||
link.classList.add('has-url-text');
|
link.classList.add('has-url-text');
|
||||||
shortenLink(link);
|
shortenLink(link);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spanify un-spanned mentions
|
// Spanify un-spanned mentions
|
||||||
if (hasLink) {
|
if (hasLink) {
|
||||||
const links = dom.querySelectorAll('a[href]');
|
const links = dom.querySelectorAll('a[href]');
|
||||||
const usernames = [];
|
const usernames = [];
|
||||||
links.forEach((link) => {
|
for (const link of links) {
|
||||||
const text = link.innerText.trim();
|
const text = link.innerText.trim();
|
||||||
const hasChildren = link.querySelector('*');
|
const hasChildren = link.querySelector('*');
|
||||||
// If text looks like @username@domain, then it's a mention
|
// If text looks like @username@domain, then it's a mention
|
||||||
if (/^@[^@]+(@[^@]+)?$/g.test(text)) {
|
if (MENTION_REGEX.test(text)) {
|
||||||
// Only show @username
|
// Only show @username
|
||||||
const [_, username, domain] = text.split('@');
|
const [_, username, domain] = text.split('@');
|
||||||
if (!hasChildren) {
|
if (!hasChildren) {
|
||||||
|
@ -67,11 +99,11 @@ function _enhanceContent(content, opts = {}) {
|
||||||
link.classList.add('mention');
|
link.classList.add('mention');
|
||||||
}
|
}
|
||||||
// If text looks like #hashtag, then it's a hashtag
|
// If text looks like #hashtag, then it's a hashtag
|
||||||
if (/^#[^#]+$/g.test(text)) {
|
if (HASHTAG_REGEX.test(text)) {
|
||||||
if (!hasChildren) link.innerHTML = `#<span>${text.slice(1)}</span>`;
|
if (!hasChildren) link.innerHTML = `#<span>${text.slice(1)}</span>`;
|
||||||
link.classList.add('mention', 'hashtag');
|
link.classList.add('mention', 'hashtag');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMOJIS
|
// EMOJIS
|
||||||
|
@ -80,18 +112,14 @@ function _enhanceContent(content, opts = {}) {
|
||||||
let textNodes;
|
let textNodes;
|
||||||
if (enhancedContent.includes(':')) {
|
if (enhancedContent.includes(':')) {
|
||||||
textNodes = extractTextNodes(dom);
|
textNodes = extractTextNodes(dom);
|
||||||
textNodes.forEach((node) => {
|
for (const node of textNodes) {
|
||||||
let html = node.nodeValue
|
let html = escapeHTML(node.nodeValue);
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
if (emojis) {
|
if (emojis) {
|
||||||
html = emojifyText(html, emojis);
|
html = emojifyText(html, emojis);
|
||||||
}
|
}
|
||||||
fauxDiv.innerHTML = html;
|
fauxDiv.innerHTML = html;
|
||||||
// const nodes = [...fauxDiv.childNodes];
|
|
||||||
node.replaceWith(...fauxDiv.childNodes);
|
node.replaceWith(...fauxDiv.childNodes);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CODE BLOCKS
|
// CODE BLOCKS
|
||||||
|
@ -99,31 +127,35 @@ function _enhanceContent(content, opts = {}) {
|
||||||
// Convert ```code``` to <pre><code>code</code></pre>
|
// Convert ```code``` to <pre><code>code</code></pre>
|
||||||
if (hasCodeBlock) {
|
if (hasCodeBlock) {
|
||||||
const blocks = [...dom.querySelectorAll('p')].filter((p) =>
|
const blocks = [...dom.querySelectorAll('p')].filter((p) =>
|
||||||
/^```[^]+```$/g.test(p.innerText.trim()),
|
CODE_BLOCK_REGEX.test(p.innerText.trim()),
|
||||||
);
|
);
|
||||||
blocks.forEach((block) => {
|
for (const block of blocks) {
|
||||||
const pre = document.createElement('pre');
|
const pre = document.createElement('pre');
|
||||||
// Replace <br /> with newlines
|
// Replace <br /> with newlines
|
||||||
block.querySelectorAll('br').forEach((br) => br.replaceWith('\n'));
|
for (const br of block.querySelectorAll('br')) {
|
||||||
|
br.replaceWith('\n');
|
||||||
|
}
|
||||||
pre.innerHTML = `<code>${block.innerHTML.trim()}</code>`;
|
pre.innerHTML = `<code>${block.innerHTML.trim()}</code>`;
|
||||||
block.replaceWith(pre);
|
block.replaceWith(pre);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert multi-paragraph code blocks to <pre><code>code</code></pre>
|
// Convert multi-paragraph code blocks to <pre><code>code</code></pre>
|
||||||
if (hasCodeBlock) {
|
if (hasCodeBlock) {
|
||||||
const paragraphs = [...dom.querySelectorAll('p')];
|
const paragraphs = [...dom.querySelectorAll('p')];
|
||||||
// Filter out paragraphs with ``` in beginning only
|
// Filter out paragraphs with ``` in beginning only
|
||||||
const codeBlocks = paragraphs.filter((p) => /^```/g.test(p.innerText));
|
const codeBlocks = paragraphs.filter((p) =>
|
||||||
|
CODE_BLOCK_START_REGEX.test(p.innerText),
|
||||||
|
);
|
||||||
// For each codeBlocks, get all paragraphs until the last paragraph with ``` at the end only
|
// For each codeBlocks, get all paragraphs until the last paragraph with ``` at the end only
|
||||||
codeBlocks.forEach((block) => {
|
for (const block of codeBlocks) {
|
||||||
const nextParagraphs = [block];
|
const nextParagraphs = [block];
|
||||||
let hasCodeBlock = false;
|
let hasCodeBlock = false;
|
||||||
let currentBlock = block;
|
let currentBlock = block;
|
||||||
while (currentBlock.nextElementSibling) {
|
while (currentBlock.nextElementSibling) {
|
||||||
const next = currentBlock.nextElementSibling;
|
const next = currentBlock.nextElementSibling;
|
||||||
if (next && next.tagName === 'P') {
|
if (next && next.tagName === 'P') {
|
||||||
if (/```$/g.test(next.innerText)) {
|
if (CODE_BLOCK_END_REGEX.test(next.innerText)) {
|
||||||
nextParagraphs.push(next);
|
nextParagraphs.push(next);
|
||||||
hasCodeBlock = true;
|
hasCodeBlock = true;
|
||||||
break;
|
break;
|
||||||
|
@ -137,16 +169,20 @@ function _enhanceContent(content, opts = {}) {
|
||||||
}
|
}
|
||||||
if (hasCodeBlock) {
|
if (hasCodeBlock) {
|
||||||
const pre = document.createElement('pre');
|
const pre = document.createElement('pre');
|
||||||
nextParagraphs.forEach((p) => {
|
for (const p of nextParagraphs) {
|
||||||
// Replace <br /> with newlines
|
// Replace <br /> with newlines
|
||||||
p.querySelectorAll('br').forEach((br) => br.replaceWith('\n'));
|
for (const br of p.querySelectorAll('br')) {
|
||||||
});
|
br.replaceWith('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
const codeText = nextParagraphs.map((p) => p.innerHTML).join('\n\n');
|
const codeText = nextParagraphs.map((p) => p.innerHTML).join('\n\n');
|
||||||
pre.innerHTML = `<code tabindex="0">${codeText}</code>`;
|
pre.innerHTML = `<code tabindex="0">${codeText}</code>`;
|
||||||
block.replaceWith(pre);
|
block.replaceWith(pre);
|
||||||
nextParagraphs.forEach((p) => p.remove());
|
for (const p of nextParagraphs) {
|
||||||
|
p.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// INLINE CODE
|
// INLINE CODE
|
||||||
|
@ -154,42 +190,36 @@ function _enhanceContent(content, opts = {}) {
|
||||||
// Convert `code` to <code>code</code>
|
// Convert `code` to <code>code</code>
|
||||||
if (enhancedContent.includes('`')) {
|
if (enhancedContent.includes('`')) {
|
||||||
textNodes = extractTextNodes(dom);
|
textNodes = extractTextNodes(dom);
|
||||||
textNodes.forEach((node) => {
|
for (const node of textNodes) {
|
||||||
let html = node.nodeValue
|
let html = escapeHTML(node.nodeValue);
|
||||||
.replace(/&/g, '&')
|
if (INLINE_CODE_REGEX.test(html)) {
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
if (/`[^`]+`/g.test(html)) {
|
|
||||||
html = html.replaceAll(/(`[^]+?`)/g, '<code>$1</code>');
|
html = html.replaceAll(/(`[^]+?`)/g, '<code>$1</code>');
|
||||||
}
|
}
|
||||||
fauxDiv.innerHTML = html;
|
fauxDiv.innerHTML = html;
|
||||||
// const nodes = [...fauxDiv.childNodes];
|
// const nodes = [...fauxDiv.childNodes];
|
||||||
node.replaceWith(...fauxDiv.childNodes);
|
node.replaceWith(...fauxDiv.childNodes);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TWITTER USERNAMES
|
// TWITTER USERNAMES
|
||||||
// =================
|
// =================
|
||||||
// Convert @username@twitter.com to <a href="https://twitter.com/username">@username@twitter.com</a>
|
// Convert @username@twitter.com to <a href="https://twitter.com/username">@username@twitter.com</a>
|
||||||
if (/twitter\.com/i.test(enhancedContent)) {
|
if (TWITTER_DOMAIN_REGEX.test(enhancedContent)) {
|
||||||
textNodes = extractTextNodes(dom, {
|
textNodes = extractTextNodes(dom, {
|
||||||
rejectFilter: ['A'],
|
rejectFilter: ['A'],
|
||||||
});
|
});
|
||||||
textNodes.forEach((node) => {
|
for (const node of textNodes) {
|
||||||
let html = node.nodeValue
|
let html = escapeHTML(node.nodeValue);
|
||||||
.replace(/&/g, '&')
|
if (TWITTER_MENTION_REGEX.test(html)) {
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
if (/@[a-zA-Z0-9_]+@twitter\.com/g.test(html)) {
|
|
||||||
html = html.replaceAll(
|
html = html.replaceAll(
|
||||||
/(@([a-zA-Z0-9_]+)@twitter\.com)/g,
|
TWITTER_MENTION_CAPTURE_REGEX,
|
||||||
'<a href="https://twitter.com/$2" rel="nofollow noopener noreferrer" target="_blank">$1</a>',
|
'<a href="https://twitter.com/$2" rel="nofollow noopener noreferrer" target="_blank">$1</a>',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fauxDiv.innerHTML = html;
|
fauxDiv.innerHTML = html;
|
||||||
// const nodes = [...fauxDiv.childNodes];
|
// const nodes = [...fauxDiv.childNodes];
|
||||||
node.replaceWith(...fauxDiv.childNodes);
|
node.replaceWith(...fauxDiv.childNodes);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HASHTAG STUFFING
|
// HASHTAG STUFFING
|
||||||
|
@ -235,22 +265,24 @@ function _enhanceContent(content, opts = {}) {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (hashtagStuffedParagraphs?.length) {
|
if (hashtagStuffedParagraphs?.length) {
|
||||||
hashtagStuffedParagraphs.forEach((p) => {
|
for (const p of hashtagStuffedParagraphs) {
|
||||||
p.classList.add('hashtag-stuffing');
|
p.classList.add('hashtag-stuffing');
|
||||||
p.title = p.innerText;
|
p.title = p.innerText;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD ASPECT RATIO TO ALL IMAGES
|
// ADD ASPECT RATIO TO ALL IMAGES
|
||||||
if (enhancedContent.includes('<img')) {
|
if (enhancedContent.includes('<img')) {
|
||||||
dom.querySelectorAll('img').forEach((img) => {
|
const imgs = dom.querySelectorAll('img');
|
||||||
|
for (let i = 0; i < imgs.length; i++) {
|
||||||
|
const img = imgs[i];
|
||||||
const width = img.getAttribute('width') || img.naturalWidth;
|
const width = img.getAttribute('width') || img.naturalWidth;
|
||||||
const height = img.getAttribute('height') || img.naturalHeight;
|
const height = img.getAttribute('height') || img.naturalHeight;
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
img.style.setProperty('--original-aspect-ratio', `${width}/${height}`);
|
img.style.setProperty('--original-aspect-ratio', `${width}/${height}`);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (postEnhanceDOM) {
|
if (postEnhanceDOM) {
|
||||||
|
@ -258,9 +290,7 @@ function _enhanceContent(content, opts = {}) {
|
||||||
// postEnhanceDOM(dom); // mutate dom
|
// postEnhanceDOM(dom); // mutate dom
|
||||||
}
|
}
|
||||||
|
|
||||||
enhancedContent = dom.innerHTML;
|
return returnDOM ? dom : dom.innerHTML;
|
||||||
|
|
||||||
return enhancedContent;
|
|
||||||
}
|
}
|
||||||
const enhanceContent = mem(_enhanceContent);
|
const enhanceContent = mem(_enhanceContent);
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,9 @@ import moize from 'moize';
|
||||||
window._moize = moize;
|
window._moize = moize;
|
||||||
|
|
||||||
export default function mem(fn, opts = {}) {
|
export default function mem(fn, opts = {}) {
|
||||||
return moize(fn, { ...opts, maxSize: 50, isDeepEqual: true });
|
return moize(fn, {
|
||||||
|
...opts,
|
||||||
|
maxSize: 30,
|
||||||
|
isDeepEqual: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue