diff --git a/package-lock.json b/package-lock.json index 5d05c56..4478a70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "jumble-imwald", - "version": "10.14.0", + "version": "10.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jumble-imwald", - "version": "10.14.0", + "version": "10.15", "license": "MIT", "dependencies": { + "@asciidoctor/core": "^3.0.4", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", @@ -42,7 +43,6 @@ "@tiptap/starter-kit": "^2.12.0", "@tiptap/suggestion": "^2.12.0", "@webbtc/webln-types": "^3.0.0", - "asciidoctor": "^2.2.8", "blossom-client-sdk": "^4.1.0", "blurhash": "^2.0.5", "class-variance-authority": "^0.7.1", @@ -59,7 +59,7 @@ "highlight.js": "^11.9.0", "i18next": "^24.2.0", "i18next-browser-languagedetector": "^8.0.4", - "katex": "^0.16.9", + "katex": "^0.16.25", "lru-cache": "^11.0.2", "lucide-react": "^0.469.0", "next-themes": "^0.4.6", @@ -74,7 +74,9 @@ "react-katex": "^3.0.1", "react-markdown": "^10.1.0", "react-simple-pull-to-refresh": "^1.3.3", + "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", + "remark-math": "^6.0.0", "sonner": "^2.0.5", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", @@ -127,39 +129,72 @@ "node": ">=6.0.0" } }, - "node_modules/@asciidoctor/cli": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@asciidoctor/cli/-/cli-3.5.0.tgz", - "integrity": "sha512-/VMHXcZBnZ9vgWfmqk9Hu0x0gMjPLup0YGq/xA8qCQuk11kUIZNMVQwgSsIUzOEwJqIUD7CgncJdtfwv1Ndxuw==", + "node_modules/@asciidoctor/core": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-3.0.4.tgz", + "integrity": "sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==", "license": "MIT", "dependencies": { - "yargs": "16.2.0" - }, - "bin": { - "asciidoctor": "bin/asciidoctor", - "asciidoctorjs": "bin/asciidoctor" + "@asciidoctor/opal-runtime": "3.0.1", + "unxhr": "1.2.0" }, "engines": { - "node": ">=8.11", - "npm": ">=5.0.0" + "node": ">=16", + "npm": ">=8" + } + }, + "node_modules/@asciidoctor/opal-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@asciidoctor/opal-runtime/-/opal-runtime-3.0.1.tgz", + "integrity": "sha512-iW7ACahOG0zZft4A/4CqDcc7JX+fWRNjV5tFAVkNCzwZD+EnFolPaUOPYt8jzadc0+Bgd80cQTtRMQnaaV1kkg==", + "license": "MIT", + "dependencies": { + "glob": "8.1.0", + "unxhr": "1.2.0" }, - "peerDependencies": { - "@asciidoctor/core": "^2.0.0-rc.1" + "engines": { + "node": ">=16" } }, - "node_modules/@asciidoctor/core": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", - "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", + "node_modules/@asciidoctor/opal-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { - "asciidoctor-opal-runtime": "0.3.3", - "unxhr": "1.0.1" + "balanced-match": "^1.0.0" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@asciidoctor/opal-runtime/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8.11", - "npm": ">=5.0.0", - "yarn": ">=1.1.0" + "node": ">=10" } }, "node_modules/@babel/code-frame": { @@ -4807,6 +4842,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, "node_modules/@types/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", @@ -5281,56 +5322,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/asciidoctor": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/asciidoctor/-/asciidoctor-2.2.8.tgz", - "integrity": "sha512-G+sDYWnNo+QHRkIvN5k7ASbvrd2bHuNXHlZ83+PjVFYtl0//as5iebq+Bdf3aSwXrkM7akcEJPUpdTjjP0MgYw==", - "license": "MIT", - "dependencies": { - "@asciidoctor/cli": "3.5.0", - "@asciidoctor/core": "2.2.8" - }, - "bin": { - "asciidoctor": "bin/asciidoctor", - "asciidoctorjs": "bin/asciidoctor" - }, - "engines": { - "node": ">=8.11", - "npm": ">=5.0.0", - "yarn": ">=1.1.0" - } - }, - "node_modules/asciidoctor-opal-runtime": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", - "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", - "license": "MIT", - "dependencies": { - "glob": "7.1.3", - "unxhr": "1.0.1" - }, - "engines": { - "node": ">=8.11" - } - }, - "node_modules/asciidoctor-opal-runtime/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -5504,6 +5495,7 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -5774,75 +5766,6 @@ "url": "https://polar.sh/cva" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -6317,7 +6240,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -6876,6 +6800,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "engines": { "node": ">=6" } @@ -7355,15 +7280,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", @@ -7610,6 +7526,101 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-from-dom": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", + "integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==", + "license": "ISC", + "dependencies": { + "@types/hast": "^3.0.0", + "hastscript": "^9.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html-isomorphic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-dom": "^5.0.0", + "hast-util-from-html": "^2.0.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", @@ -7636,6 +7647,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -7648,6 +7675,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/highlight.js": { "version": "11.11.1", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", @@ -8751,6 +8795,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", @@ -9067,6 +9130,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -9437,6 +9519,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9737,6 +9820,30 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9750,6 +9857,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10584,6 +10692,25 @@ "node": ">=6" } }, + "node_modules/rehype-katex": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", + "integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/katex": "^0.16.0", + "hast-util-from-html-isomorphic": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "katex": "^0.16.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-gfm": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", @@ -10601,6 +10728,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -10646,15 +10789,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -11823,6 +11957,20 @@ "node": ">=8" } }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", @@ -11847,6 +11995,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -11896,9 +12058,9 @@ } }, "node_modules/unxhr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", - "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", + "integrity": "sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==", "license": "MIT", "engines": { "node": ">=8.11" @@ -12033,6 +12195,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vfile-message": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", @@ -12195,6 +12371,16 @@ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -12757,15 +12943,6 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -12783,74 +12960,6 @@ "node": ">= 14" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yet-another-react-lightbox": { "version": "3.21.7", "resolved": "https://registry.npmjs.org/yet-another-react-lightbox/-/yet-another-react-lightbox-3.21.7.tgz", diff --git a/package.json b/package.json index bd19b6d..4d0609f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "preview": "vite preview" }, "dependencies": { + "@asciidoctor/core": "^3.0.4", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", @@ -65,8 +66,10 @@ "emoji-picker-react": "^4.12.2", "flexsearch": "^0.7.43", "franc-min": "^6.2.0", + "highlight.js": "^11.9.0", "i18next": "^24.2.0", "i18next-browser-languagedetector": "^8.0.4", + "katex": "^0.16.25", "lru-cache": "^11.0.2", "lucide-react": "^0.469.0", "next-themes": "^0.4.6", @@ -78,20 +81,19 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^15.2.0", + "react-katex": "^3.0.1", "react-markdown": "^10.1.0", "react-simple-pull-to-refresh": "^1.3.3", + "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", + "remark-math": "^6.0.0", "sonner": "^2.0.5", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "tippy.js": "^6.3.7", "vaul": "^1.1.2", "yet-another-react-lightbox": "^3.21.7", - "zod": "^3.24.1", - "asciidoctor": "^2.2.8", - "katex": "^0.16.9", - "react-katex": "^3.0.1", - "highlight.js": "^11.9.0" + "zod": "^3.24.1" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/src/components/Note/Article/index.tsx b/src/components/Note/Article/index.tsx new file mode 100644 index 0000000..a381085 --- /dev/null +++ b/src/components/Note/Article/index.tsx @@ -0,0 +1,212 @@ +import { useSecondaryPage } from '@/PageManager' +import ImageWithLightbox from '@/components/ImageWithLightbox' +import ImageGallery from '@/components/ImageGallery' +import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata' +import { toNoteList } from '@/lib/link' +import { ExternalLink } from 'lucide-react' +import { Event, kinds } from 'nostr-tools' +import { useMemo } from 'react' +import Markdown from 'react-markdown' +import remarkGfm from 'remark-gfm' +import remarkMath from 'remark-math' +import rehypeKatex from 'rehype-katex' +import NostrNode from '../LongFormArticle/NostrNode' +import { remarkNostr } from '../LongFormArticle/remarkNostr' +import { Components } from '../LongFormArticle/types' +import { useEventFieldParser } from '@/hooks/useContentParser' +import WebPreview from '../../WebPreview' +import 'katex/dist/katex.min.css' + +export default function Article({ + event, + className +}: { + event: Event + className?: string +}) { + const { push } = useSecondaryPage() + const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event]) + + // Use the comprehensive content parser + const { parsedContent, isLoading, error } = useEventFieldParser(event, 'content', { + enableMath: true, + enableSyntaxHighlighting: true + }) + + const components = useMemo( + () => + ({ + nostr: ({ rawText, bech32Id }) => , + a: ({ href, children, ...props }) => { + if (href?.startsWith('nostr:')) { + return + } + return ( + + {children} + + + ) + }, + p: (props) => { + // Check if paragraph contains only an image + if (props.children && typeof props.children === 'string' && props.children.match(/^!\[.*\]\(.*\)$/)) { + return
+ } + return

+ }, + div: (props) =>

, + code: (props) => , + img: (props) => ( + + ) + }) as Components, + [event.pubkey] + ) + + if (isLoading) { + return ( +
+
Loading content...
+
+ ) + } + + if (error) { + return ( +
+
Error loading content: {error.message}
+
+ ) + } + + if (!parsedContent) { + return ( +
+
No content available
+
+ ) + } + + return ( +
+ {/* Article metadata */} +

{metadata.title}

+ {metadata.summary && ( +
+

{metadata.summary}

+
+ )} + {metadata.image && ( + + )} + + + {/* Render content based on markup type */} + {parsedContent.markupType === 'asciidoc' ? ( + // AsciiDoc content (already processed to HTML) +
+ ) : ( + // Markdown content (let react-markdown handle it) + { + if (url.startsWith('nostr:')) { + return url.slice(6) // Remove 'nostr:' prefix for rendering + } + return url + }} + components={components} + > + {event.content} + + )} + + {/* Hashtags */} + {parsedContent.hashtags.length > 0 && ( +
+ {parsedContent.hashtags.map((tag) => ( +
{ + e.stopPropagation() + push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] })) + }} + > + #{tag} +
+ ))} +
+ )} + + {/* Media thumbnails */} + {parsedContent.media.length > 0 && ( +
+

Images in this article:

+
+ {parsedContent.media.map((media, index) => ( +
+ +
+ ))} +
+
+ )} + + {/* Links summary with OpenGraph previews */} + {parsedContent.links.length > 0 && ( +
+

Links in this article:

+
+ {parsedContent.links.map((link, index) => ( + + ))} +
+
+ )} + + {/* Nostr links summary */} + {parsedContent.nostrLinks.length > 0 && ( +
+

Nostr references:

+
+ {parsedContent.nostrLinks.map((link, index) => ( +
+ {link.type}:{' '} + {link.id} +
+ ))} +
+
+ )} +
+ ) +} \ No newline at end of file diff --git a/src/components/Note/DiscussionContent/index.tsx b/src/components/Note/DiscussionContent/index.tsx index 558f4dc..541049d 100644 --- a/src/components/Note/DiscussionContent/index.tsx +++ b/src/components/Note/DiscussionContent/index.tsx @@ -1,5 +1,5 @@ import { Event } from 'nostr-tools' -import SimpleContent from '../../UniversalContent/SimpleContent' +import ParsedContent from '../../UniversalContent/ParsedContent' export default function DiscussionContent({ event, @@ -9,9 +9,14 @@ export default function DiscussionContent({ className?: string }) { return ( - ) } diff --git a/src/components/Note/PublicationCard.tsx b/src/components/Note/PublicationCard.tsx new file mode 100644 index 0000000..b303fae --- /dev/null +++ b/src/components/Note/PublicationCard.tsx @@ -0,0 +1,143 @@ +import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata' +import { toNote, toNoteList } from '@/lib/link' +import { useSecondaryPage } from '@/PageManager' +import { useContentPolicy } from '@/providers/ContentPolicyProvider' +import { useScreenSize } from '@/providers/ScreenSizeProvider' +import { Event, kinds } from 'nostr-tools' +import { nip19 } from 'nostr-tools' +import { useMemo } from 'react' +import { BookOpen } from 'lucide-react' +import Image from '../Image' + +export default function PublicationCard({ + event, + className +}: { + event: Event + className?: string +}) { + const { isSmallScreen } = useScreenSize() + const { push } = useSecondaryPage() + const { autoLoadMedia } = useContentPolicy() + const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event]) + + // Generate naddr for Alexandria URL + const naddr = useMemo(() => { + try { + const dTag = event.tags.find(tag => tag[0] === 'd')?.[1] || '' + const relays = event.tags + .filter(tag => tag[0] === 'relay') + .map(tag => tag[1]) + .filter(Boolean) + + return nip19.naddrEncode({ + kind: event.kind, + pubkey: event.pubkey, + identifier: dTag, + relays: relays.length > 0 ? relays : undefined + }) + } catch (error) { + console.error('Error generating naddr:', error) + return '' + } + }, [event]) + + const handleCardClick = (e: React.MouseEvent) => { + e.stopPropagation() + push(toNote(event.id)) + } + + const handleAlexandriaClick = (e: React.MouseEvent) => { + e.stopPropagation() + if (naddr) { + window.open(`https://next-alexandria.gitcitadel.eu/publication/naddr/${naddr}`, '_blank', 'noopener,noreferrer') + } + } + + const titleComponent =
{metadata.title}
+ + const tagsComponent = metadata.tags.length > 0 && ( +
+ {metadata.tags.map((tag) => ( +
{ + e.stopPropagation() + push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] })) + }} + > + #{tag} +
+ ))} +
+ ) + + const summaryComponent = metadata.summary && ( +
{metadata.summary}
+ ) + + const alexandriaButton = naddr && ( + + ) + + if (isSmallScreen) { + return ( +
+
+ {metadata.image && autoLoadMedia && ( + + )} +
+ {titleComponent} + {summaryComponent} + {tagsComponent} +
+ {alexandriaButton} +
+
+
+
+ ) + } + + return ( +
+
+
+ {metadata.image && autoLoadMedia && ( + + )} +
+ {titleComponent} + {summaryComponent} + {tagsComponent} +
+ {alexandriaButton} +
+
+
+
+
+ ) +} diff --git a/src/components/Note/WikiCard.tsx b/src/components/Note/WikiCard.tsx new file mode 100644 index 0000000..31db1fb --- /dev/null +++ b/src/components/Note/WikiCard.tsx @@ -0,0 +1,167 @@ +import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata' +import { toNote, toNoteList } from '@/lib/link' +import { useSecondaryPage } from '@/PageManager' +import { useContentPolicy } from '@/providers/ContentPolicyProvider' +import { useScreenSize } from '@/providers/ScreenSizeProvider' +import { Event, kinds } from 'nostr-tools' +import { nip19 } from 'nostr-tools' +import { useMemo } from 'react' +import { BookOpen, Globe } from 'lucide-react' +import Image from '../Image' + +export default function WikiCard({ + event, + className +}: { + event: Event + className?: string +}) { + const { isSmallScreen } = useScreenSize() + const { push } = useSecondaryPage() + const { autoLoadMedia } = useContentPolicy() + const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event]) + + // Extract d-tag for Wikistr URL + const dTag = useMemo(() => { + return event.tags.find(tag => tag[0] === 'd')?.[1] || '' + }, [event]) + + // Generate naddr for Alexandria URL + const naddr = useMemo(() => { + try { + const relays = event.tags + .filter(tag => tag[0] === 'relay') + .map(tag => tag[1]) + .filter(Boolean) + + return nip19.naddrEncode({ + kind: event.kind, + pubkey: event.pubkey, + identifier: dTag, + relays: relays.length > 0 ? relays : undefined + }) + } catch (error) { + console.error('Error generating naddr:', error) + return '' + } + }, [event, dTag]) + + const handleCardClick = (e: React.MouseEvent) => { + e.stopPropagation() + push(toNote(event.id)) + } + + const handleWikistrClick = (e: React.MouseEvent) => { + e.stopPropagation() + if (dTag) { + window.open(`https://wikistr.imwald.eu/${dTag}*${event.pubkey}`, '_blank', 'noopener,noreferrer') + } + } + + const handleAlexandriaClick = (e: React.MouseEvent) => { + e.stopPropagation() + if (naddr) { + window.open(`https://next-alexandria.gitcitadel.eu/publication/naddr/${naddr}`, '_blank', 'noopener,noreferrer') + } + } + + const titleComponent =
{metadata.title}
+ + const tagsComponent = metadata.tags.length > 0 && ( +
+ {metadata.tags.map((tag) => ( +
{ + e.stopPropagation() + push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] })) + }} + > + #{tag} +
+ ))} +
+ ) + + const summaryComponent = metadata.summary && ( +
{metadata.summary}
+ ) + + const buttons = ( +
+ {dTag && ( + + )} + {naddr && ( + + )} +
+ ) + + if (isSmallScreen) { + return ( +
+
+ {metadata.image && autoLoadMedia && ( + + )} +
+ {titleComponent} + {summaryComponent} + {tagsComponent} +
+ {buttons} +
+
+
+
+ ) + } + + return ( +
+
+
+ {metadata.image && autoLoadMedia && ( + + )} +
+ {titleComponent} + {summaryComponent} + {tagsComponent} +
+ {buttons} +
+
+
+
+
+ ) +} diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx index 2e3d3e4..bed9430 100644 --- a/src/components/Note/index.tsx +++ b/src/components/Note/index.tsx @@ -10,7 +10,7 @@ import { Event, kinds } from 'nostr-tools' import { useMemo, useState } from 'react' import AudioPlayer from '../AudioPlayer' import ClientTag from '../ClientTag' -import Content from '../Content' +import EnhancedContent from '../UniversalContent/EnhancedContent' import { FormattedTimestamp } from '../FormattedTimestamp' import Nip05 from '../Nip05' import NoteOptions from '../NoteOptions' @@ -26,8 +26,10 @@ import Highlight from './Highlight' import IValue from './IValue' import LiveEvent from './LiveEvent' -import LongFormArticle from './LongFormArticle' import LongFormArticlePreview from './LongFormArticlePreview' +import Article from './Article' +import PublicationCard from './PublicationCard' +import WikiCard from './WikiCard' import MutedNote from './MutedNote' import NsfwNote from './NsfwNote' import PictureNote from './PictureNote' @@ -98,10 +100,30 @@ export default function Note({ } } else if (event.kind === kinds.LongFormArticle) { content = showFull ? ( - +
) : ( ) + } else if (event.kind === ExtendedKind.WIKI_ARTICLE) { + content = showFull ? ( +
+ ) : ( + + ) + } else if (event.kind === ExtendedKind.WIKI_CHAPTER) { + content = showFull ? ( +
+ ) : ( +
+
Wiki Chapter (part of publication)
+
+ ) + } else if (event.kind === ExtendedKind.PUBLICATION) { + content = showFull ? ( +
+ ) : ( + + ) } else if (event.kind === kinds.LiveEvent) { content = } else if (event.kind === ExtendedKind.GROUP_METADATA) { @@ -120,7 +142,7 @@ export default function Note({ } else if (event.kind === ExtendedKind.POLL) { content = ( <> - + ) @@ -133,11 +155,11 @@ export default function Note({ } else if (event.kind === ExtendedKind.RELAY_REVIEW) { content = } else if (event.kind === ExtendedKind.PUBLIC_MESSAGE) { - content = + content = } else if (event.kind === ExtendedKind.ZAP_REQUEST || event.kind === ExtendedKind.ZAP_RECEIPT) { content = } else { - content = + content = } return ( diff --git a/src/components/Profile/ProfileArticles.tsx b/src/components/Profile/ProfileArticles.tsx index 9cedb86..94370bb 100644 --- a/src/components/Profile/ProfileArticles.tsx +++ b/src/components/Profile/ProfileArticles.tsx @@ -80,18 +80,18 @@ const ProfileArticles = forwardRef<{ refresh: () => void }, ProfileArticlesProps const comprehensiveRelays = await buildComprehensiveRelayList() console.log('[ProfileArticles] Using comprehensive relay list:', comprehensiveRelays.length, 'relays') - // Fetch longform articles (kind 30023) and highlights (kind 9802) + // Fetch longform articles (kind 30023), wiki articles (kind 30818), publications (kind 30040), and highlights (kind 9802) const allEvents = await client.fetchEvents(comprehensiveRelays, { authors: [pubkey], - kinds: [kinds.LongFormArticle, kinds.Highlights], // LongFormArticle and Highlights + kinds: [kinds.LongFormArticle, 30818, 30040, kinds.Highlights], // LongFormArticle, WikiArticle, Publication, and Highlights limit: 100 }) console.log('[ProfileArticles] Fetched total events:', allEvents.length) console.log('[ProfileArticles] Sample events:', allEvents.slice(0, 3).map(e => ({ id: e.id, kind: e.kind, content: e.content.substring(0, 50) + '...', tags: e.tags.slice(0, 3) }))) - // Show ALL events (both longform articles and highlights) - console.log('[ProfileArticles] Showing all events (articles + highlights):', allEvents.length) + // Show ALL events (longform articles, wiki articles, publications, and highlights) + console.log('[ProfileArticles] Showing all events (articles + publications + highlights):', allEvents.length) console.log('[ProfileArticles] Events sample:', allEvents.slice(0, 2).map(e => ({ id: e.id, kind: e.kind, content: e.content.substring(0, 50) + '...' }))) const eventsToShow = allEvents @@ -204,7 +204,7 @@ const ProfileArticles = forwardRef<{ refresh: () => void }, ProfileArticlesProps if (events.length === 0) { return (
-
No articles or highlights found
+
No articles, publications, or highlights found
) } @@ -212,7 +212,7 @@ const ProfileArticles = forwardRef<{ refresh: () => void }, ProfileArticlesProps if (filteredEvents.length === 0 && searchQuery.trim()) { return (
-
No articles or highlights match your search
+
No articles, publications, or highlights match your search
) } diff --git a/src/components/ReplyNote/index.tsx b/src/components/ReplyNote/index.tsx index 9cbeb2e..8ea32d8 100644 --- a/src/components/ReplyNote/index.tsx +++ b/src/components/ReplyNote/index.tsx @@ -11,7 +11,7 @@ import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import ClientTag from '../ClientTag' import Collapsible from '../Collapsible' -import Content from '../Content' +import EnhancedContent from '../UniversalContent/EnhancedContent' import { FormattedTimestamp } from '../FormattedTimestamp' import Nip05 from '../Nip05' import NoteOptions from '../NoteOptions' @@ -55,7 +55,14 @@ export default function ReplyNote({ return (
navigateToNote(toNote(event))} + onClick={(e) => { + // Don't navigate if clicking on interactive elements + const target = e.target as HTMLElement + if (target.closest('button') || target.closest('[role="button"]') || target.closest('a')) { + return + } + navigateToNote(toNote(event)) + }} >
@@ -96,7 +103,7 @@ export default function ReplyNote({ /> )} {show ? ( - + ) : (