this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

On-demand math formatting

+329 -151
+10
package-lock.json
··· 41 41 "react-router-dom": "6.6.2", 42 42 "string-length": "6.0.0", 43 43 "swiped-events": "~1.2.0", 44 + "temml": "~0.11.9", 44 45 "tinyld": "~1.3.4", 45 46 "toastify-js": "~1.12.0", 46 47 "uid": "~2.0.2", ··· 9399 9400 "version": "1.2.0", 9400 9401 "resolved": "https://registry.npmjs.org/swiped-events/-/swiped-events-1.2.0.tgz", 9401 9402 "integrity": "sha512-KRu67z1hb4sPxMdFIF2kaufYHTcWOb8NVLbIl2g5dPWZkEQ6D3wfSIVJ7iXbicTt9cO3e0vARqgx9fITtTZxQw==" 9403 + }, 9404 + "node_modules/temml": { 9405 + "version": "0.11.9", 9406 + "resolved": "https://registry.npmjs.org/temml/-/temml-0.11.9.tgz", 9407 + "integrity": "sha512-+k+J6u+OGRroUAE07ynDc6jtmRocEYrRIIJvA182OBoY60nrosSA6hBvLPWdKwgXZNJQeUEdX5maJYICkCLjjw==", 9408 + "license": "MIT", 9409 + "engines": { 9410 + "node": ">=18.13.0" 9411 + } 9402 9412 }, 9403 9413 "node_modules/temp-dir": { 9404 9414 "version": "2.0.0",
+1
package.json
··· 53 53 "react-router-dom": "6.6.2", 54 54 "string-length": "6.0.0", 55 55 "swiped-events": "~1.2.0", 56 + "temml": "~0.11.9", 56 57 "tinyld": "~1.3.4", 57 58 "toastify-js": "~1.12.0", 58 59 "uid": "~2.0.2",
+1
src/components/ICONS.jsx
··· 183 183 module: () => import('@iconify-icons/mingcute/user-star-line'), 184 184 rtl: true, 185 185 }, 186 + formula: () => import('@iconify-icons/mingcute/formula-line'), 186 187 };
+48
src/components/status.css
··· 2941 2941 transition-duration: 0.1s; 2942 2942 transition-behavior: allow-discrete; 2943 2943 } 2944 + 2945 + /* MATH */ 2946 + 2947 + .math-block { 2948 + color: var(--text-insignificant-color); 2949 + margin: 8px 0; 2950 + border-top: 1px dashed var(--outline-color); 2951 + padding-top: 8px; 2952 + display: flex; 2953 + align-items: center; 2954 + gap: 4px; 2955 + font-size: 90%; 2956 + } 2957 + .status .inner-content math[display='block'] { 2958 + background-image: 2959 + linear-gradient( 2960 + var(--divider-color) var(--hairline-width), 2961 + transparent var(--hairline-width) 2962 + ), 2963 + linear-gradient( 2964 + to right, 2965 + var(--divider-color) var(--hairline-width), 2966 + transparent var(--hairline-width) 2967 + ); 2968 + background-size: var(--text-size) var(--text-size); 2969 + overflow: auto; 2970 + 2971 + --padding: 8px; 2972 + background-position: center var(--padding); 2973 + &:has(mrow) { 2974 + /* 0.5ex is for mrow from Temml-Local.css */ 2975 + background-position-y: calc(var(--padding) + 0.5ex); 2976 + } 2977 + padding: var(--padding); 2978 + /* mask the padding with gradients */ 2979 + mask-image: 2980 + linear-gradient(to top, transparent, black var(--padding)), 2981 + linear-gradient(to bottom, transparent, black var(--padding)), 2982 + linear-gradient(to left, transparent, black var(--padding)), 2983 + linear-gradient(to right, transparent, black var(--padding)); 2984 + mask-composite: intersect; 2985 + 2986 + animation: appear-smooth 0.3s ease-out; 2987 + *:nth-child(even):not(:has(*)) { 2988 + /* sprinkle a bit more gradual magical feel */ 2989 + animation: appear 1s ease-out; 2990 + } 2991 + }
+87
src/components/status.jsx
··· 1 1 import './status.css'; 2 + import 'temml/dist/Temml-Local.css'; 3 + 2 4 import '@justinribeiro/lite-youtube'; 3 5 4 6 import { msg, plural } from '@lingui/core/macro'; ··· 22 24 useEffect, 23 25 useLayoutEffect, 24 26 useMemo, 27 + useReducer, 25 28 useRef, 26 29 useState, 27 30 } from 'preact/hooks'; ··· 222 225 } 223 226 224 227 const HTTP_REGEX = /^http/i; 228 + 229 + // Follow https://mathstodon.xyz/about 230 + // > You can use LaTeX in toots here! Use \( and \) for inline, and \[ and \] for display mode. 231 + const DELIMITERS_PATTERNS = [ 232 + // '\\$\\$[\\s\\S]*?\\$\\$', // $$...$$ 233 + '\\\\\\[[\\s\\S]*?\\\\\\]', // \[...\] 234 + '\\\\\\([\\s\\S]*?\\\\\\)', // \(...\) 235 + // '\\\\begin\\{(?:equation\\*?|align\\*?|alignat\\*?|gather\\*?|CD)\\}[\\s\\S]*?\\\\end\\{(?:equation\\*?|align\\*?|alignat\\*?|gather\\*?|CD)\\}', // AMS environments 236 + // '\\\\(?:ref|eqref)\\{[^}]*\\}', // \ref{...}, \eqref{...} 237 + ]; 238 + const DELIMITERS_REGEX = new RegExp(DELIMITERS_PATTERNS.join('|'), 'g'); 239 + 240 + const MathBlock = ({ content, contentRef, onRevert }) => { 241 + const { t } = useLingui(); 242 + const [mathRendered, setMathRendered] = useState(false); 243 + const hasLatexContent = useMemo( 244 + () => DELIMITERS_REGEX.test(content), 245 + [content], 246 + ); 247 + 248 + const toggleMathRendering = useCallback( 249 + async (e) => { 250 + e.preventDefault(); 251 + if (mathRendered) { 252 + // Revert to original content by refreshing PostContent 253 + setMathRendered(false); 254 + onRevert(); 255 + } else { 256 + // Render math 257 + try { 258 + // This needs global because the codebase inside temml is calling a function from global.temml 🤦‍♂️ 259 + const temml = 260 + window.temml || (window.temml = (await import('temml'))?.default); 261 + 262 + const oriignalContentRefHTML = contentRef.current.innerHTML; 263 + temml.renderMathInElement(contentRef.current, { 264 + fences: '(', // This should sync with DELIMITERS_REGEX 265 + throwOnError: true, 266 + errorCallback: (err) => { 267 + console.warn('Failed to render LaTeX:', err); 268 + }, 269 + }); 270 + 271 + const hasMath = contentRef.current.querySelector('math.tml-display'); 272 + const htmlChanged = 273 + contentRef.current.innerHTML !== oriignalContentRefHTML; 274 + if (hasMath && htmlChanged) { 275 + setMathRendered(true); 276 + } else { 277 + showToast(t`Unable to format math`); 278 + setMathRendered(false); 279 + } 280 + } catch (e) { 281 + console.error('Failed to LaTeX:', e); 282 + } 283 + } 284 + }, 285 + [mathRendered], 286 + ); 287 + 288 + if (!hasLatexContent) return null; 289 + 290 + return ( 291 + <div class="math-block"> 292 + <Icon icon="formula" size="s" /> <span>{t`Math expressions found.`}</span>{' '} 293 + <button type="button" class="light small" onClick={toggleMathRendering}> 294 + {mathRendered ? t`Show markup` : t`Format math`} 295 + </button> 296 + </div> 297 + ); 298 + }; 299 + 225 300 const PostContent = 226 301 /*memo(*/ 227 302 ({ post, instance, previewMode }) => { ··· 709 784 const mediaContainerRef = useTruncated(); 710 785 711 786 const statusRef = useRef(null); 787 + const [reloadPostContentCount, reloadPostContent] = useReducer( 788 + (c) => c + 1, 789 + 0, 790 + ); 712 791 713 792 const unauthInteractionErrorMessage = t`Sorry, your current logged-in instance can't interact with this post from another instance.`; 714 793 ··· 2201 2280 inert={!!spoilerText && !showSpoiler ? true : undefined} 2202 2281 > 2203 2282 <PostContent 2283 + key={reloadPostContentCount} 2204 2284 post={status} 2205 2285 instance={instance} 2206 2286 previewMode={previewMode} 2207 2287 /> 2208 2288 <QuoteStatuses id={id} instance={instance} level={quoted} /> 2209 2289 </div> 2290 + )} 2291 + {!!content && ( 2292 + <MathBlock 2293 + content={content} 2294 + contentRef={contentRef} 2295 + onRevert={reloadPostContent} 2296 + /> 2210 2297 )} 2211 2298 {!!poll && ( 2212 2299 <Poll
+163 -147
src/locales/en.po
··· 34 34 35 35 #: src/components/account-block.jsx:170 36 36 #: src/components/account-info.jsx:715 37 - #: src/components/status.jsx:590 37 + #: src/components/status.jsx:665 38 38 msgid "Group" 39 39 msgstr "" 40 40 ··· 111 111 #: src/components/compose.jsx:2792 112 112 #: src/components/media-alt-modal.jsx:55 113 113 #: src/components/media-modal.jsx:363 114 - #: src/components/status.jsx:1836 115 - #: src/components/status.jsx:1853 116 - #: src/components/status.jsx:1978 117 - #: src/components/status.jsx:2599 118 - #: src/components/status.jsx:2602 114 + #: src/components/status.jsx:1915 115 + #: src/components/status.jsx:1932 116 + #: src/components/status.jsx:2057 117 + #: src/components/status.jsx:2686 118 + #: src/components/status.jsx:2689 119 119 #: src/pages/account-statuses.jsx:531 120 120 #: src/pages/accounts.jsx:118 121 121 #: src/pages/hashtag.jsx:203 ··· 203 203 msgstr "" 204 204 205 205 #: src/components/account-info.jsx:946 206 - #: src/components/status.jsx:2383 206 + #: src/components/status.jsx:2470 207 207 #: src/pages/catchup.jsx:71 208 208 #: src/pages/catchup.jsx:1448 209 209 #: src/pages/catchup.jsx:2061 ··· 329 329 msgstr "" 330 330 331 331 #: src/components/account-info.jsx:1490 332 - #: src/components/status.jsx:1258 332 + #: src/components/status.jsx:1337 333 333 msgid "Link copied" 334 334 msgstr "" 335 335 336 336 #: src/components/account-info.jsx:1493 337 - #: src/components/status.jsx:1261 337 + #: src/components/status.jsx:1340 338 338 msgid "Unable to copy link" 339 339 msgstr "" 340 340 341 341 #: src/components/account-info.jsx:1499 342 342 #: src/components/shortcuts-settings.jsx:1059 343 - #: src/components/status.jsx:1267 344 - #: src/components/status.jsx:3377 343 + #: src/components/status.jsx:1346 344 + #: src/components/status.jsx:3464 345 345 msgid "Copy" 346 346 msgstr "" 347 347 348 348 #: src/components/account-info.jsx:1514 349 349 #: src/components/shortcuts-settings.jsx:1077 350 - #: src/components/status.jsx:1283 350 + #: src/components/status.jsx:1362 351 351 msgid "Sharing doesn't seem to work." 352 352 msgstr "" 353 353 354 354 #: src/components/account-info.jsx:1520 355 - #: src/components/status.jsx:1289 355 + #: src/components/status.jsx:1368 356 356 msgid "Share…" 357 357 msgstr "" 358 358 ··· 466 466 #: src/components/shortcuts-settings.jsx:230 467 467 #: src/components/shortcuts-settings.jsx:583 468 468 #: src/components/shortcuts-settings.jsx:783 469 - #: src/components/status.jsx:3101 470 - #: src/components/status.jsx:3341 471 - #: src/components/status.jsx:3850 469 + #: src/components/status.jsx:3188 470 + #: src/components/status.jsx:3428 471 + #: src/components/status.jsx:3937 472 472 #: src/pages/accounts.jsx:45 473 473 #: src/pages/catchup.jsx:1584 474 474 #: src/pages/filters.jsx:225 ··· 718 718 msgstr "Attachment #{i} failed" 719 719 720 720 #: src/components/compose.jsx:1221 721 - #: src/components/status.jsx:2166 721 + #: src/components/status.jsx:2245 722 722 #: src/components/timeline.jsx:1023 723 723 msgid "Content warning" 724 724 msgstr "" ··· 728 728 msgstr "Content warning or sensitive media" 729 729 730 730 #: src/components/compose.jsx:1273 731 - #: src/components/status.jsx:96 731 + #: src/components/status.jsx:99 732 732 #: src/pages/settings.jsx:318 733 733 msgid "Public" 734 734 msgstr "" ··· 736 736 #: src/components/compose.jsx:1278 737 737 #: src/components/nav-menu.jsx:349 738 738 #: src/components/shortcuts-settings.jsx:165 739 - #: src/components/status.jsx:97 739 + #: src/components/status.jsx:100 740 740 msgid "Local" 741 741 msgstr "" 742 742 743 743 #: src/components/compose.jsx:1282 744 - #: src/components/status.jsx:98 744 + #: src/components/status.jsx:101 745 745 #: src/pages/settings.jsx:321 746 746 msgid "Unlisted" 747 747 msgstr "" 748 748 749 749 #: src/components/compose.jsx:1285 750 - #: src/components/status.jsx:99 750 + #: src/components/status.jsx:102 751 751 #: src/pages/settings.jsx:324 752 752 msgid "Followers only" 753 753 msgstr "" 754 754 755 755 #: src/components/compose.jsx:1288 756 - #: src/components/status.jsx:100 757 - #: src/components/status.jsx:2042 756 + #: src/components/status.jsx:103 757 + #: src/components/status.jsx:2121 758 758 msgid "Private mention" 759 759 msgstr "" 760 760 ··· 791 791 792 792 #: src/components/compose.jsx:1677 793 793 #: src/components/keyboard-shortcuts-help.jsx:155 794 - #: src/components/status.jsx:1030 795 - #: src/components/status.jsx:1816 796 - #: src/components/status.jsx:1817 797 - #: src/components/status.jsx:2503 794 + #: src/components/status.jsx:1109 795 + #: src/components/status.jsx:1895 796 + #: src/components/status.jsx:1896 797 + #: src/components/status.jsx:2590 798 798 msgid "Reply" 799 799 msgstr "" 800 800 ··· 1016 1016 1017 1017 #: src/components/drafts.jsx:128 1018 1018 #: src/components/list-add-edit.jsx:188 1019 - #: src/components/status.jsx:1433 1019 + #: src/components/status.jsx:1512 1020 1020 #: src/pages/filters.jsx:603 1021 1021 #: src/pages/scheduled-posts.jsx:369 1022 1022 msgid "Delete…" ··· 1225 1225 msgstr "" 1226 1226 1227 1227 #: src/components/keyboard-shortcuts-help.jsx:176 1228 - #: src/components/status.jsx:1038 1229 - #: src/components/status.jsx:2530 1230 - #: src/components/status.jsx:2553 1231 - #: src/components/status.jsx:2554 1228 + #: src/components/status.jsx:1117 1229 + #: src/components/status.jsx:2617 1230 + #: src/components/status.jsx:2640 1231 + #: src/components/status.jsx:2641 1232 1232 msgid "Boost" 1233 1233 msgstr "" 1234 1234 ··· 1237 1237 msgstr "" 1238 1238 1239 1239 #: src/components/keyboard-shortcuts-help.jsx:184 1240 - #: src/components/status.jsx:1101 1241 - #: src/components/status.jsx:2578 1242 - #: src/components/status.jsx:2579 1240 + #: src/components/status.jsx:1180 1241 + #: src/components/status.jsx:2665 1242 + #: src/components/status.jsx:2666 1243 1243 msgid "Bookmark" 1244 1244 msgstr "" 1245 1245 ··· 1304 1304 msgstr "" 1305 1305 1306 1306 #: src/components/media-alt-modal.jsx:67 1307 - #: src/components/status.jsx:1144 1308 - #: src/components/status.jsx:1153 1307 + #: src/components/status.jsx:1223 1308 + #: src/components/status.jsx:1232 1309 1309 #: src/components/translation-block.jsx:239 1310 1310 msgid "Translate" 1311 1311 msgstr "" 1312 1312 1313 1313 #: src/components/media-alt-modal.jsx:78 1314 - #: src/components/status.jsx:1172 1314 + #: src/components/status.jsx:1251 1315 1315 msgid "Speak" 1316 1316 msgstr "" 1317 1317 ··· 1348 1348 msgstr "" 1349 1349 1350 1350 #: src/components/media-post.jsx:133 1351 - #: src/components/status.jsx:3680 1352 - #: src/components/status.jsx:3776 1353 - #: src/components/status.jsx:3854 1351 + #: src/components/status.jsx:3767 1352 + #: src/components/status.jsx:3863 1353 + #: src/components/status.jsx:3941 1354 1354 #: src/components/timeline.jsx:1012 1355 1355 #: src/pages/catchup.jsx:75 1356 1356 #: src/pages/catchup.jsx:1880 ··· 1662 1662 msgstr "" 1663 1663 1664 1664 #: src/components/notification.jsx:451 1665 - #: src/components/status.jsx:1115 1666 - #: src/components/status.jsx:1125 1665 + #: src/components/status.jsx:1194 1666 + #: src/components/status.jsx:1204 1667 1667 msgid "Boosted/Liked by…" 1668 1668 msgstr "" 1669 1669 ··· 1689 1689 msgstr "View #Wrapstodon" 1690 1690 1691 1691 #: src/components/notification.jsx:801 1692 - #: src/components/status.jsx:328 1692 + #: src/components/status.jsx:403 1693 1693 msgid "Read more →" 1694 1694 msgstr "" 1695 1695 ··· 1993 1993 msgstr "" 1994 1994 1995 1995 #: src/components/shortcuts-settings.jsx:379 1996 - #: src/components/status.jsx:1395 1996 + #: src/components/status.jsx:1474 1997 1997 #: src/pages/list.jsx:195 1998 1998 msgid "Edit" 1999 1999 msgstr "" ··· 2192 2192 msgid "Import/export settings from/to instance server (Very experimental)" 2193 2193 msgstr "" 2194 2194 2195 - #: src/components/status.jsx:614 2195 + #: src/components/status.jsx:277 2196 + msgid "Unable to format math" 2197 + msgstr "Unable to format math" 2198 + 2199 + #: src/components/status.jsx:292 2200 + msgid "Math expressions found." 2201 + msgstr "Math expressions found." 2202 + 2203 + #: src/components/status.jsx:294 2204 + msgid "Show markup" 2205 + msgstr "Show markup" 2206 + 2207 + #: src/components/status.jsx:294 2208 + msgid "Format math" 2209 + msgstr "Format math" 2210 + 2211 + #: src/components/status.jsx:689 2196 2212 msgid "<0/> <1>boosted</1>" 2197 - msgstr "" 2213 + msgstr "<0/> <1>boosted</1>" 2198 2214 2199 - #: src/components/status.jsx:713 2215 + #: src/components/status.jsx:792 2200 2216 msgid "Sorry, your current logged-in instance can't interact with this post from another instance." 2201 2217 msgstr "" 2202 2218 2203 2219 #. placeholder {0}: username || acct 2204 - #: src/components/status.jsx:867 2220 + #: src/components/status.jsx:946 2205 2221 msgid "Unliked @{0}'s post" 2206 2222 msgstr "" 2207 2223 2208 2224 #. placeholder {0}: username || acct 2209 - #: src/components/status.jsx:868 2225 + #: src/components/status.jsx:947 2210 2226 msgid "Liked @{0}'s post" 2211 2227 msgstr "Liked @{0}'s post" 2212 2228 2213 2229 #. placeholder {0}: username || acct 2214 - #: src/components/status.jsx:907 2230 + #: src/components/status.jsx:986 2215 2231 msgid "Unbookmarked @{0}'s post" 2216 2232 msgstr "Unbookmarked @{0}'s post" 2217 2233 2218 2234 #. placeholder {0}: username || acct 2219 - #: src/components/status.jsx:908 2235 + #: src/components/status.jsx:987 2220 2236 msgid "Bookmarked @{0}'s post" 2221 2237 msgstr "Bookmarked @{0}'s post" 2222 2238 2223 - #: src/components/status.jsx:1007 2239 + #: src/components/status.jsx:1086 2224 2240 msgid "Some media have no descriptions." 2225 2241 msgstr "" 2226 2242 2227 2243 #. placeholder {0}: rtf.format(-statusMonthsAgo, 'month') 2228 - #: src/components/status.jsx:1014 2244 + #: src/components/status.jsx:1093 2229 2245 msgid "Old post (<0>{0}</0>)" 2230 2246 msgstr "" 2231 2247 2232 - #: src/components/status.jsx:1038 2233 - #: src/components/status.jsx:1078 2234 - #: src/components/status.jsx:2530 2235 - #: src/components/status.jsx:2553 2248 + #: src/components/status.jsx:1117 2249 + #: src/components/status.jsx:1157 2250 + #: src/components/status.jsx:2617 2251 + #: src/components/status.jsx:2640 2236 2252 msgid "Unboost" 2237 2253 msgstr "" 2238 2254 2239 - #: src/components/status.jsx:1054 2240 - #: src/components/status.jsx:2545 2255 + #: src/components/status.jsx:1133 2256 + #: src/components/status.jsx:2632 2241 2257 msgid "Quote" 2242 2258 msgstr "" 2243 2259 2244 2260 #. placeholder {0}: username || acct 2245 - #: src/components/status.jsx:1066 2246 - #: src/components/status.jsx:1532 2261 + #: src/components/status.jsx:1145 2262 + #: src/components/status.jsx:1611 2247 2263 msgid "Unboosted @{0}'s post" 2248 2264 msgstr "Unboosted @{0}'s post" 2249 2265 2250 2266 #. placeholder {0}: username || acct 2251 - #: src/components/status.jsx:1067 2252 - #: src/components/status.jsx:1533 2267 + #: src/components/status.jsx:1146 2268 + #: src/components/status.jsx:1612 2253 2269 msgid "Boosted @{0}'s post" 2254 2270 msgstr "Boosted @{0}'s post" 2255 2271 2256 - #: src/components/status.jsx:1079 2272 + #: src/components/status.jsx:1158 2257 2273 msgid "Boost…" 2258 2274 msgstr "" 2259 2275 2260 - #: src/components/status.jsx:1091 2261 - #: src/components/status.jsx:1826 2262 - #: src/components/status.jsx:2566 2276 + #: src/components/status.jsx:1170 2277 + #: src/components/status.jsx:1905 2278 + #: src/components/status.jsx:2653 2263 2279 msgid "Unlike" 2264 2280 msgstr "" 2265 2281 2266 - #: src/components/status.jsx:1092 2267 - #: src/components/status.jsx:1826 2268 - #: src/components/status.jsx:1827 2269 - #: src/components/status.jsx:2566 2270 - #: src/components/status.jsx:2567 2282 + #: src/components/status.jsx:1171 2283 + #: src/components/status.jsx:1905 2284 + #: src/components/status.jsx:1906 2285 + #: src/components/status.jsx:2653 2286 + #: src/components/status.jsx:2654 2271 2287 msgid "Like" 2272 2288 msgstr "" 2273 2289 2274 - #: src/components/status.jsx:1101 2275 - #: src/components/status.jsx:2578 2290 + #: src/components/status.jsx:1180 2291 + #: src/components/status.jsx:2665 2276 2292 msgid "Unbookmark" 2277 2293 msgstr "" 2278 2294 2279 - #: src/components/status.jsx:1184 2295 + #: src/components/status.jsx:1263 2280 2296 msgid "Post text copied" 2281 2297 msgstr "Post text copied" 2282 2298 2283 - #: src/components/status.jsx:1187 2299 + #: src/components/status.jsx:1266 2284 2300 msgid "Unable to copy post text" 2285 2301 msgstr "Unable to copy post text" 2286 2302 2287 - #: src/components/status.jsx:1193 2303 + #: src/components/status.jsx:1272 2288 2304 msgid "Copy post text" 2289 2305 msgstr "Copy post text" 2290 2306 2291 2307 #. placeholder {0}: username || acct 2292 - #: src/components/status.jsx:1211 2308 + #: src/components/status.jsx:1290 2293 2309 msgid "View post by <0>@{0}</0>" 2294 2310 msgstr "" 2295 2311 2296 - #: src/components/status.jsx:1232 2312 + #: src/components/status.jsx:1311 2297 2313 msgid "Show Edit History" 2298 2314 msgstr "" 2299 2315 2300 - #: src/components/status.jsx:1235 2316 + #: src/components/status.jsx:1314 2301 2317 msgid "Edited: {editedDateText}" 2302 2318 msgstr "" 2303 2319 2304 - #: src/components/status.jsx:1302 2305 - #: src/components/status.jsx:3346 2320 + #: src/components/status.jsx:1381 2321 + #: src/components/status.jsx:3433 2306 2322 msgid "Embed post" 2307 2323 msgstr "" 2308 2324 2309 - #: src/components/status.jsx:1316 2325 + #: src/components/status.jsx:1395 2310 2326 msgid "Conversation unmuted" 2311 2327 msgstr "" 2312 2328 2313 - #: src/components/status.jsx:1316 2329 + #: src/components/status.jsx:1395 2314 2330 msgid "Conversation muted" 2315 2331 msgstr "" 2316 2332 2317 - #: src/components/status.jsx:1322 2333 + #: src/components/status.jsx:1401 2318 2334 msgid "Unable to unmute conversation" 2319 2335 msgstr "" 2320 2336 2321 - #: src/components/status.jsx:1323 2337 + #: src/components/status.jsx:1402 2322 2338 msgid "Unable to mute conversation" 2323 2339 msgstr "" 2324 2340 2325 - #: src/components/status.jsx:1332 2341 + #: src/components/status.jsx:1411 2326 2342 msgid "Unmute conversation" 2327 2343 msgstr "" 2328 2344 2329 - #: src/components/status.jsx:1339 2345 + #: src/components/status.jsx:1418 2330 2346 msgid "Mute conversation" 2331 2347 msgstr "" 2332 2348 2333 - #: src/components/status.jsx:1355 2349 + #: src/components/status.jsx:1434 2334 2350 msgid "Post unpinned from profile" 2335 2351 msgstr "" 2336 2352 2337 - #: src/components/status.jsx:1356 2353 + #: src/components/status.jsx:1435 2338 2354 msgid "Post pinned to profile" 2339 2355 msgstr "" 2340 2356 2341 - #: src/components/status.jsx:1361 2357 + #: src/components/status.jsx:1440 2342 2358 msgid "Unable to unpin post" 2343 2359 msgstr "" 2344 2360 2345 - #: src/components/status.jsx:1361 2361 + #: src/components/status.jsx:1440 2346 2362 msgid "Unable to pin post" 2347 2363 msgstr "" 2348 2364 2349 - #: src/components/status.jsx:1370 2365 + #: src/components/status.jsx:1449 2350 2366 msgid "Unpin from profile" 2351 2367 msgstr "" 2352 2368 2353 - #: src/components/status.jsx:1377 2369 + #: src/components/status.jsx:1456 2354 2370 msgid "Pin to profile" 2355 2371 msgstr "" 2356 2372 2357 - #: src/components/status.jsx:1406 2373 + #: src/components/status.jsx:1485 2358 2374 msgid "Delete this post?" 2359 2375 msgstr "" 2360 2376 2361 - #: src/components/status.jsx:1422 2377 + #: src/components/status.jsx:1501 2362 2378 msgid "Post deleted" 2363 2379 msgstr "" 2364 2380 2365 - #: src/components/status.jsx:1425 2381 + #: src/components/status.jsx:1504 2366 2382 msgid "Unable to delete post" 2367 2383 msgstr "" 2368 2384 2369 - #: src/components/status.jsx:1453 2385 + #: src/components/status.jsx:1532 2370 2386 msgid "Report post…" 2371 2387 msgstr "" 2372 2388 2373 - #: src/components/status.jsx:1827 2374 - #: src/components/status.jsx:1863 2375 - #: src/components/status.jsx:2567 2389 + #: src/components/status.jsx:1906 2390 + #: src/components/status.jsx:1942 2391 + #: src/components/status.jsx:2654 2376 2392 msgid "Liked" 2377 2393 msgstr "" 2378 2394 2379 - #: src/components/status.jsx:1860 2380 - #: src/components/status.jsx:2554 2395 + #: src/components/status.jsx:1939 2396 + #: src/components/status.jsx:2641 2381 2397 msgid "Boosted" 2382 2398 msgstr "" 2383 2399 2384 - #: src/components/status.jsx:1870 2385 - #: src/components/status.jsx:2579 2400 + #: src/components/status.jsx:1949 2401 + #: src/components/status.jsx:2666 2386 2402 msgid "Bookmarked" 2387 2403 msgstr "" 2388 2404 2389 - #: src/components/status.jsx:1874 2405 + #: src/components/status.jsx:1953 2390 2406 msgid "Pinned" 2391 2407 msgstr "" 2392 2408 2393 - #: src/components/status.jsx:1920 2394 - #: src/components/status.jsx:2391 2409 + #: src/components/status.jsx:1999 2410 + #: src/components/status.jsx:2478 2395 2411 msgid "Deleted" 2396 2412 msgstr "" 2397 2413 2398 - #: src/components/status.jsx:1961 2414 + #: src/components/status.jsx:2040 2399 2415 msgid "{repliesCount, plural, one {# reply} other {# replies}}" 2400 2416 msgstr "" 2401 2417 2402 2418 #. placeholder {0}: snapStates.statusThreadNumber[sKey] ? ` ${snapStates.statusThreadNumber[sKey]}/X` : '' 2403 - #: src/components/status.jsx:2051 2419 + #: src/components/status.jsx:2130 2404 2420 msgid "Thread{0}" 2405 2421 msgstr "" 2406 2422 2407 - #: src/components/status.jsx:2129 2408 - #: src/components/status.jsx:2191 2409 - #: src/components/status.jsx:2287 2423 + #: src/components/status.jsx:2208 2424 + #: src/components/status.jsx:2270 2425 + #: src/components/status.jsx:2374 2410 2426 msgid "Show less" 2411 2427 msgstr "" 2412 2428 2413 - #: src/components/status.jsx:2129 2414 - #: src/components/status.jsx:2191 2429 + #: src/components/status.jsx:2208 2430 + #: src/components/status.jsx:2270 2415 2431 msgid "Show content" 2416 2432 msgstr "" 2417 2433 2418 2434 #. placeholder {0}: filterInfo.titlesStr 2419 2435 #. placeholder {0}: filterInfo?.titlesStr 2420 - #: src/components/status.jsx:2283 2436 + #: src/components/status.jsx:2370 2421 2437 #: src/pages/catchup.jsx:1879 2422 2438 msgid "Filtered: {0}" 2423 2439 msgstr "Filtered: {0}" 2424 2440 2425 - #: src/components/status.jsx:2287 2441 + #: src/components/status.jsx:2374 2426 2442 msgid "Show media" 2427 2443 msgstr "" 2428 2444 2429 - #: src/components/status.jsx:2427 2445 + #: src/components/status.jsx:2514 2430 2446 msgid "Edited" 2431 2447 msgstr "" 2432 2448 2433 - #: src/components/status.jsx:2504 2449 + #: src/components/status.jsx:2591 2434 2450 msgid "Comments" 2435 2451 msgstr "" 2436 2452 2437 2453 #. More from [Author] 2438 - #: src/components/status.jsx:2804 2454 + #: src/components/status.jsx:2891 2439 2455 msgid "More from <0/>" 2440 2456 msgstr "More from <0/>" 2441 2457 2442 - #: src/components/status.jsx:3106 2458 + #: src/components/status.jsx:3193 2443 2459 msgid "Edit History" 2444 2460 msgstr "" 2445 2461 2446 - #: src/components/status.jsx:3110 2462 + #: src/components/status.jsx:3197 2447 2463 msgid "Failed to load history" 2448 2464 msgstr "" 2449 2465 2450 - #: src/components/status.jsx:3115 2466 + #: src/components/status.jsx:3202 2451 2467 #: src/pages/annual-report.jsx:45 2452 2468 msgid "Loading…" 2453 2469 msgstr "" 2454 2470 2455 - #: src/components/status.jsx:3351 2471 + #: src/components/status.jsx:3438 2456 2472 msgid "HTML Code" 2457 2473 msgstr "" 2458 2474 2459 - #: src/components/status.jsx:3368 2475 + #: src/components/status.jsx:3455 2460 2476 msgid "HTML code copied" 2461 2477 msgstr "" 2462 2478 2463 - #: src/components/status.jsx:3371 2479 + #: src/components/status.jsx:3458 2464 2480 msgid "Unable to copy HTML code" 2465 2481 msgstr "" 2466 2482 2467 - #: src/components/status.jsx:3383 2483 + #: src/components/status.jsx:3470 2468 2484 msgid "Media attachments:" 2469 2485 msgstr "" 2470 2486 2471 - #: src/components/status.jsx:3405 2487 + #: src/components/status.jsx:3492 2472 2488 msgid "Account Emojis:" 2473 2489 msgstr "" 2474 2490 2475 - #: src/components/status.jsx:3436 2476 - #: src/components/status.jsx:3481 2491 + #: src/components/status.jsx:3523 2492 + #: src/components/status.jsx:3568 2477 2493 msgid "static URL" 2478 2494 msgstr "" 2479 2495 2480 - #: src/components/status.jsx:3450 2496 + #: src/components/status.jsx:3537 2481 2497 msgid "Emojis:" 2482 2498 msgstr "" 2483 2499 2484 - #: src/components/status.jsx:3495 2500 + #: src/components/status.jsx:3582 2485 2501 msgid "Notes:" 2486 2502 msgstr "" 2487 2503 2488 - #: src/components/status.jsx:3499 2504 + #: src/components/status.jsx:3586 2489 2505 msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed." 2490 2506 msgstr "" 2491 2507 2492 - #: src/components/status.jsx:3505 2508 + #: src/components/status.jsx:3592 2493 2509 msgid "Polls are not interactive, becomes a list with vote counts." 2494 2510 msgstr "" 2495 2511 2496 - #: src/components/status.jsx:3510 2512 + #: src/components/status.jsx:3597 2497 2513 msgid "Media attachments can be images, videos, audios or any file types." 2498 2514 msgstr "" 2499 2515 2500 - #: src/components/status.jsx:3516 2516 + #: src/components/status.jsx:3603 2501 2517 msgid "Post could be edited or deleted later." 2502 2518 msgstr "" 2503 2519 2504 - #: src/components/status.jsx:3522 2520 + #: src/components/status.jsx:3609 2505 2521 msgid "Preview" 2506 2522 msgstr "" 2507 2523 2508 - #: src/components/status.jsx:3531 2524 + #: src/components/status.jsx:3618 2509 2525 msgid "Note: This preview is lightly styled." 2510 2526 msgstr "" 2511 2527 2512 2528 #. [Name] [Visibility icon] boosted 2513 - #: src/components/status.jsx:3784 2529 + #: src/components/status.jsx:3871 2514 2530 msgid "<0/> <1/> boosted" 2515 - msgstr "" 2531 + msgstr "<0/> <1/> boosted" 2516 2532 2517 - #: src/components/status.jsx:3886 2533 + #: src/components/status.jsx:3973 2518 2534 msgid "Post hidden by your filters" 2519 2535 msgstr "Post hidden by your filters" 2520 2536 2521 - #: src/components/status.jsx:3887 2537 + #: src/components/status.jsx:3974 2522 2538 msgid "Post removed by author." 2523 2539 msgstr "Post removed by author." 2524 2540 2525 - #: src/components/status.jsx:3888 2541 + #: src/components/status.jsx:3975 2526 2542 msgid "You’re not authorized to view this post." 2527 2543 msgstr "You’re not authorized to view this post." 2528 2544 2529 - #: src/components/status.jsx:3889 2545 + #: src/components/status.jsx:3976 2530 2546 msgid "Post pending author approval." 2531 2547 msgstr "Post pending author approval." 2532 2548 2533 - #: src/components/status.jsx:3890 2534 - #: src/components/status.jsx:3891 2549 + #: src/components/status.jsx:3977 2550 + #: src/components/status.jsx:3978 2535 2551 msgid "Quoting not allowed by the author." 2536 2552 msgstr "Quoting not allowed by the author." 2537 2553
+19 -4
src/pages/sandbox.jsx
··· 51 51 52 52 const shortContent = 'This is a test status with short text content.'; 53 53 const longContent = `<p>This is a test status with long text content. It contains multiple paragraphs and spans several lines to demonstrate how longer content appears.</p> 54 - 54 + 55 55 <p>Second paragraph goes here with more sample text. The Status component will render this appropriately based on the current size setting.</p> 56 - 56 + 57 57 <p>Third paragraph adds even more content to ensure we have a properly long post that might get truncated depending on the view settings.</p>`; 58 58 const linksContent = `<p>This is a test status with links. Check out <a href="https://example.com">this website</a> and <a href="https://google.com">Google</a>. Links should be clickable and properly styled.</p>`; 59 59 const hashtagsContent = `<p>This is a test status with hashtags. <a href="https://example.social/tags/coding" class="hashtag" rel="tag">#coding</a> <a href="https://example.social/tags/webdev" class="hashtag" rel="tag">#webdev</a> <a href="https://example.social/tags/javascript" class="hashtag" rel="tag">#javascript</a> <a href="https://example.social/tags/reactjs" class="hashtag" rel="tag">#reactjs</a> <a href="https://example.social/tags/preact" class="hashtag" rel="tag">#preact</a></p><p>Hashtags should be formatted and clickable.</p>`; 60 60 const mentionsContent = `<p>This is a test status with mentions. Hello <a href="https://example.social/@cheeaun" class="u-url mention">@cheeaun</a> and <a href="https://example.social/@test" class="u-url mention">@test</a>! What do you think about this <a href="https://example.social/@another_user" class="u-url mention">@another_user</a>?</p><p>Mentions should be highlighted and clickable.</p>`; 61 + const mathContent = `<p>This is a test status with mathematical expressions. Here's an inline formula \\( E = mc^2 \\) and a display formula:</p><p>\\[ \\frac{\\left(n!\\right)^2}{2}\\sum _{k=0}^m\\frac{1}{n-k}{n-k \\choose k}^2 \\]</p><p>The MathBlock component should detect and offer to render these LaTeX expressions.</p>`; 61 62 62 63 const base = { 63 64 // Random ID to un-memoize Status ··· 80 81 ? hashtagsContent 81 82 : contentType === 'mentions' 82 83 ? mentionsContent 83 - : shortContent 84 + : contentType === 'math' 85 + ? mathContent 86 + : shortContent 84 87 : '', 85 88 visibility: toggles.visibility || 'public', 86 89 createdAt: new Date().toISOString(), ··· 764 767 class={`sandbox-preview ${toggleState.displayStyle}`} 765 768 onClickCapture={(e) => { 766 769 const isAllowed = e.target.closest( 767 - '.media, .media-caption, .spoiler-button, .spoiler-media-button', 770 + '.media, .media-caption, .spoiler-button, .spoiler-media-button, .math-block button', 768 771 ); 769 772 if (isAllowed) return; 770 773 e.preventDefault(); ··· 987 990 disabled={!toggleState.hasContent} 988 991 /> 989 992 <span>With mentions</span> 993 + </label> 994 + </li> 995 + <li> 996 + <label> 997 + <input 998 + type="radio" 999 + name="contentType" 1000 + checked={toggleState.contentType === 'math'} 1001 + onChange={() => updateToggles({ contentType: 'math' })} 1002 + disabled={!toggleState.hasContent} 1003 + /> 1004 + <span>With math</span> 990 1005 </label> 991 1006 </li> 992 1007 </ul>