diff --git a/package.json b/package.json
index 58ba215..2c77225 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
],
"repository": "https://github.com/themashcodee/slack-blocks-to-jsx.git",
"license": "MIT",
- "version": "0.2.2",
+ "version": "0.3.0",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
@@ -29,19 +29,21 @@
"release": "pnpm run build && changeset publish"
},
"dependencies": {
- "html-react-parser": "^4.2.2",
+ "@yozora/ast": "^2.3.2",
+ "@yozora/character": "^2.3.2",
+ "@yozora/core-tokenizer": "^2.3.2",
+ "@yozora/parser": "^2.3.2",
"node-emoji": "^2.1.0",
- "slack-markdown": "^0.3.0",
"zustand": "^4.5.2"
},
"peerDependencies": {
- "react": "^17.0.0 || ^18.0.0",
- "react-dom": "^17.0.0 || ^18.0.0"
+ "react": "^17 || ^18",
+ "react-dom": "^17 || ^18"
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
- "@types/react": "17.0.0",
- "@types/react-dom": "17.0.0",
+ "@types/react": "^17",
+ "@types/react-dom": "^17",
"autoprefixer": "^10.4.17",
"cssnano": "^6.0.3",
"postcss": "^8.4.33",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7bfb9aa..d4dff6a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2,35 +2,39 @@ lockfileVersion: 5.4
specifiers:
'@changesets/cli': ^2.26.2
- '@types/react': 17.0.0
- '@types/react-dom': 17.0.0
+ '@types/react': ^17
+ '@types/react-dom': ^17
+ '@yozora/ast': ^2.3.2
+ '@yozora/character': ^2.3.2
+ '@yozora/core-tokenizer': ^2.3.2
+ '@yozora/parser': ^2.3.2
autoprefixer: ^10.4.17
cssnano: ^6.0.3
- html-react-parser: ^4.2.2
node-emoji: ^2.1.0
postcss: ^8.4.33
postcss-cli: ^11.0.0
postcss-nesting: ^12.0.2
- react: ^17.0.0 || ^18.0.0
- react-dom: ^17.0.0 || ^18.0.0
- slack-markdown: ^0.3.0
+ react: ^17 || ^18
+ react-dom: ^17 || ^18
tailwindcss: ^3.4.1
tsup: ^7.2.0
typescript: ^5.2.2
zustand: ^4.5.2
dependencies:
- html-react-parser: 4.2.2_react@18.3.1
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/parser': 2.3.2
node-emoji: 2.1.0
react: 18.3.1
react-dom: 18.3.1_react@18.3.1
- slack-markdown: 0.3.0
- zustand: 4.5.2_lkaryubz2bolmitu7rok3kbwrm
+ zustand: 4.5.2_ugm3hist2nig7ypm6usfhfueka
devDependencies:
'@changesets/cli': 2.26.2
- '@types/react': 17.0.0
- '@types/react-dom': 17.0.0
+ '@types/react': 17.0.80
+ '@types/react-dom': 17.0.25
autoprefixer: 10.4.17_postcss@8.4.33
cssnano: 6.0.3_postcss@8.4.33
postcss: 8.4.33
@@ -571,25 +575,400 @@ packages:
resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==}
dev: true
- /@types/prop-types/15.7.7:
- resolution: {integrity: sha512-FbtmBWCcSa2J4zL781Zf1p5YUBXQomPEcep9QZCfRfQgTxz3pJWiDFLebohZ9fFntX5ibzOkSsrJ0TEew8cAog==}
+ /@types/prop-types/15.7.12:
+ resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
- /@types/react-dom/17.0.0:
- resolution: {integrity: sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==}
+ /@types/react-dom/17.0.25:
+ resolution: {integrity: sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA==}
dependencies:
- '@types/react': 17.0.0
+ '@types/react': 17.0.80
dev: true
- /@types/react/17.0.0:
- resolution: {integrity: sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==}
+ /@types/react/17.0.80:
+ resolution: {integrity: sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==}
dependencies:
- '@types/prop-types': 15.7.7
- csstype: 3.1.2
+ '@types/prop-types': 15.7.12
+ '@types/scheduler': 0.16.8
+ csstype: 3.1.3
+
+ /@types/scheduler/0.16.8:
+ resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
/@types/semver/7.5.3:
resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
dev: true
+ /@yozora/ast-util/2.3.2:
+ resolution: {integrity: sha512-mW8r/gbgIfACarWfgLzBMU6mSJLmLYdPgAvHttGVm7Ucd+zWwZLmJ3JeNbUvcvAOpTQkE7s2WNVZTbeuO5z2nA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ dev: false
+
+ /@yozora/ast/2.3.2:
+ resolution: {integrity: sha512-YDA8TdWjufVYEqLwuONDLNwW5epBWlsNT2IQtats/Y8i4QOYYE56bAGaTVsGcq4TMF8qmkVUt9bsKuPYmHRJ3Q==}
+ engines: {node: '>= 16.0.0'}
+ dev: false
+
+ /@yozora/character/2.3.2:
+ resolution: {integrity: sha512-jdzmFnMLKbFkCT/vVhQAk/kBY6Ot0ks84ws/En7pDRxiubXfrSGgkdID0SahfQCQbfqffo4tUit0O/Q3vQZPlw==}
+ engines: {node: '>= 16.0.0'}
+ dev: false
+
+ /@yozora/core-parser/2.3.2:
+ resolution: {integrity: sha512-WVAjGa0UwKZctwqRJirUiznAZ9UoiPgSuKBhxqg10H6dV50+x0ScFAr9cQwC3mdT9UlHxG+0JaMnr0atyfsToA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/ast-util': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/invariant': 2.3.2
+ dev: false
+
+ /@yozora/core-tokenizer/2.3.2:
+ resolution: {integrity: sha512-g7Xw0puubmet0UVMmX4mi+Q5/Pb4xkzlnqZF23sWOB2ug7MkTGR3xH0BBBNtQQs2gV8NdGuoyCMmG+bhsZIejQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ dev: false
+
+ /@yozora/invariant/2.3.2:
+ resolution: {integrity: sha512-gcqjGyWUi5JGO2/Kka35G6Kn2ecDhPYhSgLKP+aHmqL/tUnSxbK+AITJu7eDa9Ro1RVetRfXIG2XFZbjg2xH5w==}
+ engines: {node: '>= 16.0.0'}
+ dev: false
+
+ /@yozora/parser/2.3.2:
+ resolution: {integrity: sha512-DLnZ7OIj6Eau5+drE6mc9vprol7QWeouQmX8QXSOx6j8hxFfSFAfcBqN35frqdG9D7cZODL3GqBAbQId1p3P3A==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/core-parser': 2.3.2
+ '@yozora/tokenizer-admonition': 2.3.2
+ '@yozora/tokenizer-autolink': 2.3.2
+ '@yozora/tokenizer-autolink-extension': 2.3.2
+ '@yozora/tokenizer-blockquote': 2.3.2
+ '@yozora/tokenizer-break': 2.3.2
+ '@yozora/tokenizer-definition': 2.3.2
+ '@yozora/tokenizer-delete': 2.3.2
+ '@yozora/tokenizer-ecma-import': 2.3.2
+ '@yozora/tokenizer-emphasis': 2.3.2
+ '@yozora/tokenizer-fenced-code': 2.3.2
+ '@yozora/tokenizer-footnote': 2.3.2
+ '@yozora/tokenizer-footnote-definition': 2.3.2
+ '@yozora/tokenizer-footnote-reference': 2.3.2
+ '@yozora/tokenizer-heading': 2.3.2
+ '@yozora/tokenizer-html-block': 2.3.2
+ '@yozora/tokenizer-html-inline': 2.3.2
+ '@yozora/tokenizer-image': 2.3.2
+ '@yozora/tokenizer-image-reference': 2.3.2
+ '@yozora/tokenizer-indented-code': 2.3.2
+ '@yozora/tokenizer-inline-code': 2.3.2
+ '@yozora/tokenizer-inline-math': 2.3.2
+ '@yozora/tokenizer-link': 2.3.2
+ '@yozora/tokenizer-link-reference': 2.3.2
+ '@yozora/tokenizer-list': 2.3.2
+ '@yozora/tokenizer-math': 2.3.2
+ '@yozora/tokenizer-paragraph': 2.3.2
+ '@yozora/tokenizer-setext-heading': 2.3.2
+ '@yozora/tokenizer-table': 2.3.2
+ '@yozora/tokenizer-text': 2.3.2
+ '@yozora/tokenizer-thematic-break': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-admonition/2.3.2:
+ resolution: {integrity: sha512-ZUV6RVJy0n6tI32AbkiccI2mN3nH4EWykLdiCUyNFsCYNT+RJKRbZ0/0U9q7nuenJfbewurh7SxSnZrGZFwPZQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-fenced-block': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-autolink-extension/2.3.2:
+ resolution: {integrity: sha512-s4Q/wkO2nIMTkjcWH5SG+B8U0lLy0PhR8nzV00yBgrWTaTRcxpN16ecvS2Abrc+ezDnFmFB9pb1ZJ1jzturDyQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-autolink': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-autolink/2.3.2:
+ resolution: {integrity: sha512-WQnMrKTN20KSp0OW375ofrkOw1CbIJi+eP1d5kgxx+aFhbHS0qS9zykQ8roz7Ovi6v3fBWDLxLS4J8s96VlPxA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-blockquote/2.3.2:
+ resolution: {integrity: sha512-j9vCvVWJ+JVW16PhBRh5DXHO1X3Y2sro6zht1nAiWn722sM9tb6Ha7FTcLl0aTs5uu+Hguo3e1XiihVZF9Ud4Q==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-break/2.3.2:
+ resolution: {integrity: sha512-vvkgNGsrGC3ggdXjmcH13h28z/rGtC/siEeuNtrZt+1I6VeD54nbN19KSSYYI1gERDU3zPADqBcrPcNRvXe3/g==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-definition/2.3.2:
+ resolution: {integrity: sha512-GxdSi6ykgDiSIhH95dv0K+kf2RLhYAtKb6df7n33Zy7aDQPEiUrLH+MWAME0WKKUmY7+sWlDLhtOWcbecFcZHw==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-delete/2.3.2:
+ resolution: {integrity: sha512-lUgv6Vr0D0/+LdxHsK8nWta/WiHTGXQB2fhXyE2g8uGoOvp6FX5oNss1UcSXpr/wMvWgT/39YtcDvEeIJnO6wQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-ecma-import/2.3.2:
+ resolution: {integrity: sha512-4TClGwDatfCR5BVAkHQy1YOWeR258KoCCOXFxEwngpIirfNr7u/U6oOFGwctLuQafvGAkRwvdjllwoxxVmLUQA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-emphasis/2.3.2:
+ resolution: {integrity: sha512-RWfxj/rmglwKklpgTdz17MdoywsJs6RgHQn3gwJ21A2FL1VajbSEbMcV42BJPYFmzlpPU0ZNeeOIUu7QF3Z/hw==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-fenced-block/2.3.2:
+ resolution: {integrity: sha512-YELd4nBRmpBw5X+oGt2z24w9V2yhm4ltXpukFkiBRPlPHin5K3G8KXlLkF+5KLGhr0duTmJEztgZ5Bxo7Qa9+w==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-fenced-code/2.3.2:
+ resolution: {integrity: sha512-17zokbGr7pCdIZSQdx2wChfsPa91bzBXTDvWUgrGXSCn+XTCfnUgFqlNidnVtc32mwRvsSxdtf6NGHHb4E7xtw==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-fenced-block': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-footnote-definition/2.3.2:
+ resolution: {integrity: sha512-0qgxZSIJflbtKMJun+mrwMWT4RX8SPXRx/6G45XxrGzJDBV9UN6us7Q5hLetKKeLojdJBJ1WEpnRaEbOdF0Wqw==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-footnote-reference/2.3.2:
+ resolution: {integrity: sha512-6Zkqmo4pv4tGYMDgNwo92cR0UwCxaLdstyjLV9RP7HMBp43sSxmbDeGxnDPInaIdYpj6N95thTmkdkl3kc39OQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-footnote-definition': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-footnote/2.3.2:
+ resolution: {integrity: sha512-sA7t/9blPkO0jcggqPeirKGrLUNGu03uu7uePow/Bg04RgL14lHNjyDWDJJpbYgczINdNxb/xpePjCOpLzESjA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-link': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-heading/2.3.2:
+ resolution: {integrity: sha512-Vf0EFKYTKyZ2kdpMSjhbfbwjJrjCITVvCmWnfAhp3rUgICe30CUQuvsOFco2B9JHnpUdqc0wWHdUs4fvt6lTxQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-html-block/2.3.2:
+ resolution: {integrity: sha512-klLFjO0kRWwNZHLcmLJle8StIqAysstvgnYg3evYmd7fnVv8gnfROCseoOUJ0Jh1Fr0Uz3iQz4Xx0D11Q8uiWQ==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-html-inline/2.3.2:
+ resolution: {integrity: sha512-SbQlRQQ7cM6TUqiwdMJSZdsw5p59T8rpgbvzlrqcfzI1Jgo9zlw0pFWYjhDLowIdX68LldYfQLbqYKmlJLaxKA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-html-block': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-image-reference/2.3.2:
+ resolution: {integrity: sha512-Suw9muo/eDpj+deKaoKSECDCzuf+Xr/10s0lm/GY/LYbJnOcnQtxD4nasF2W6fQcQJcbJcs7JAd3n3eI/0ZRFg==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-image': 2.3.2
+ '@yozora/tokenizer-link': 2.3.2
+ '@yozora/tokenizer-link-reference': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-image/2.3.2:
+ resolution: {integrity: sha512-2v4bkHeOoZYOuFCsmnoUY/4oHfoPsIWtaFuTSj3iuqYSgNJszm2ghgNESz1q8oQZPC6XL00ilGaEsaCeJuhd9w==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-link': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-indented-code/2.3.2:
+ resolution: {integrity: sha512-iT8JBMPbghy/ITrU+Ms8stzfDFmVIGv3Kb04yVUiUrtIO1fQ0yMNWsCXwMQ5C4d+yW1DHKtMJf7RHOD5ppjWKA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-inline-code/2.3.2:
+ resolution: {integrity: sha512-Pf5c7qVkOuRwGwLh1u6U+DIEH2J0SQooCrG2JnAS7RJCscKTqrPU+UNeALDqapThsF7SWFYVEQbBeTuLkarZlA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-inline-math/2.3.2:
+ resolution: {integrity: sha512-rogTL8dQeDEmVZwGbzCtYn9dPb6dr52eb7ZxXHZouhRJxKUOV+CQ+90hCj8o3M5lOX0Qx1JLtrMo+uVnnYFaBg==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-link-reference/2.3.2:
+ resolution: {integrity: sha512-sgHGYSapxodJRLwEJoHDVbqhLXWT5lLKSsMj1rVPUEmIfE/vl06OUOuMD+62csU7Kkj9IbbGmBu6zMPc4uuApw==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-link': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-link/2.3.2:
+ resolution: {integrity: sha512-LlqZeB0O9/oUjHWUYW3wefDPXYu2C9NXQ8M1fWgCrc8whSN7vdh+/hU1AWKVF6mIiRXAnKM7o26WQk+0Fgc3uA==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-list/2.3.2:
+ resolution: {integrity: sha512-6KaOC84c7BCwJBIWGiGZUa2nT0xCPv0E7vfZyaxiReCeW+IMptxt0ZrrX+iWIFvwKig8x0X0nbJHf/gaxLYV+w==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-math/2.3.2:
+ resolution: {integrity: sha512-sjPYFxiKqlkxpL92nYqbruwGynixgjk2lbOmTxEfTw4Qw+rrTUKFrAN3SyhNHkwWMZ7lKWUAknoyipEBSsWRpg==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ '@yozora/tokenizer-fenced-block': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-paragraph/2.3.2:
+ resolution: {integrity: sha512-3l6iH71WeOwzVLZ+hujU9b2YoeMEfX8jD4GzVBo8dgwlg1xNrdLqdtfroFMuibB0Cs+bRQGbsYxXlzyyMi3vWg==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-setext-heading/2.3.2:
+ resolution: {integrity: sha512-knI5oOoUQH7LoIHlqm3YjndAxNMx9okY82fGCZunpI2tSbZyLKqJmGomdmodzgEjPqv483ZtKt5T6keupRf23A==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-table/2.3.2:
+ resolution: {integrity: sha512-pRcxpGEjMETi5KT33AnjcHN6oNkdXN1/2x63a9MZqUsweLpu4cRNB/ixwrfxCr9WJH6nEzmZGFKW0HOqwvbm7A==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-text/2.3.2:
+ resolution: {integrity: sha512-s3zJ5bdebrdgZDtdoVAkUZ0LYOfA4nIbq3gyUMOZq1ygNDxjTzMcgGr6mzMw8OzYkrWQT2XyN17YWR+zsgUw4w==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
+ /@yozora/tokenizer-thematic-break/2.3.2:
+ resolution: {integrity: sha512-taYZ9iMJ7f3c0QEEkskf+84T0Ri1m+rxnJquZxIYRDHybjgpmquqyYPF4jp9ZozFShw5mxzN03Qqs1ryMiXm/A==}
+ engines: {node: '>= 16.0.0'}
+ dependencies:
+ '@yozora/ast': 2.3.2
+ '@yozora/character': 2.3.2
+ '@yozora/core-tokenizer': 2.3.2
+ dev: false
+
/ansi-colors/4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
@@ -1037,8 +1416,8 @@ packages:
css-tree: 2.2.1
dev: true
- /csstype/3.1.2:
- resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
+ /csstype/3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
/csv-generate/3.4.3:
resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==}
@@ -1142,15 +1521,18 @@ packages:
domelementtype: 2.3.0
domhandler: 5.0.3
entities: 4.5.0
+ dev: true
/domelementtype/2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ dev: true
/domhandler/5.0.3:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
dependencies:
domelementtype: 2.3.0
+ dev: true
/domutils/3.1.0:
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
@@ -1158,6 +1540,7 @@ packages:
dom-serializer: 2.0.0
domelementtype: 2.3.0
domhandler: 5.0.3
+ dev: true
/electron-to-chromium/1.4.646:
resolution: {integrity: sha512-vThkQ0JuF45qT/20KbRgM56lV7IuGt7SjhawQ719PDHzhP84KAO1WJoaxgCoAffKHK47FmVKP1Fqizx7CwK1SA==}
@@ -1182,6 +1565,7 @@ packages:
/entities/4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
+ dev: true
/error-ex/1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
@@ -1293,10 +1677,6 @@ packages:
engines: {node: '>=6'}
dev: true
- /escape-html/1.0.3:
- resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
- dev: false
-
/escape-string-regexp/1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
@@ -1616,34 +1996,6 @@ packages:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
dev: true
- /html-dom-parser/4.0.0:
- resolution: {integrity: sha512-TUa3wIwi80f5NF8CVWzkopBVqVAtlawUzJoLwVLHns0XSJGynss4jiY0mTWpiDOsuyw+afP+ujjMgRh9CoZcXw==}
- dependencies:
- domhandler: 5.0.3
- htmlparser2: 9.0.0
- dev: false
-
- /html-react-parser/4.2.2_react@18.3.1:
- resolution: {integrity: sha512-lh0wEGISnFZEAmvQqK4xc0duFMUh/m9YYyAhFursWxdtNv+hCZge0kj1y4wep6qPB5Zm33L+2/P6TcGWAJJbjA==}
- peerDependencies:
- react: 0.14 || 15 || 16 || 17 || 18
- dependencies:
- domhandler: 5.0.3
- html-dom-parser: 4.0.0
- react: 18.3.1
- react-property: 2.0.0
- style-to-js: 1.1.4
- dev: false
-
- /htmlparser2/9.0.0:
- resolution: {integrity: sha512-uxbSI98wmFT/G4P2zXx4OVx04qWUmyFPrD2/CNepa2Zo3GPNaCaaxElDgwUrwYWkK1nr9fft0Ya8dws8coDLLQ==}
- dependencies:
- domelementtype: 2.3.0
- domhandler: 5.0.3
- domutils: 3.1.0
- entities: 4.5.0
- dev: false
-
/human-id/1.0.2:
resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==}
dev: true
@@ -1681,10 +2033,6 @@ packages:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
- /inline-style-parser/0.1.1:
- resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==}
- dev: false
-
/internal-slot/1.0.5:
resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
engines: {node: '>= 0.4'}
@@ -1965,10 +2313,6 @@ packages:
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
dev: true
- /lodash/4.17.21:
- resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
- dev: false
-
/loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -2090,12 +2434,6 @@ packages:
hasBin: true
dev: true
- /node-emoji/1.11.0:
- resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==}
- dependencies:
- lodash: 4.17.21
- dev: false
-
/node-emoji/2.1.0:
resolution: {integrity: sha512-tcsBm9C6FmPN5Wo7OjFi9lgMyJjvkAeirmjR/ax8Ttfqy4N8PoFic26uqFTIgayHPNI5FH4ltUvfh9kHzwcK9A==}
dependencies:
@@ -2771,10 +3109,6 @@ packages:
scheduler: 0.23.2
dev: false
- /react-property/2.0.0:
- resolution: {integrity: sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==}
- dev: false
-
/react/18.3.1:
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
engines: {node: '>=0.10.0'}
@@ -2977,12 +3311,6 @@ packages:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: true
- /simple-markdown/0.7.3:
- resolution: {integrity: sha512-uGXIc13NGpqfPeFJIt/7SHHxd6HekEJYtsdoCM06mEBPL9fQH/pSD7LRM6PZ7CKchpSvxKL4tvwMamqAaNDAyg==}
- dependencies:
- '@types/react': 17.0.0
- dev: false
-
/skin-tone/2.0.0:
resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
engines: {node: '>=8'}
@@ -2990,14 +3318,6 @@ packages:
unicode-emoji-modifier-base: 1.0.0
dev: false
- /slack-markdown/0.3.0:
- resolution: {integrity: sha512-LNOwBXZ1xzOYNo9ZU0gPXZN0rqlAPOiVQMTjz+rMq1ZTGg655UNHDRos+NqSU20BC+SV7VeA/3lLOs5DG+UEvA==}
- dependencies:
- escape-html: 1.0.3
- node-emoji: 1.11.0
- simple-markdown: 0.7.3
- dev: false
-
/slash/3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -3130,18 +3450,6 @@ packages:
min-indent: 1.0.1
dev: true
- /style-to-js/1.1.4:
- resolution: {integrity: sha512-zEeU3vy9xL/hdLBFmzqjhm+2vJ1Y35V0ctDeB2sddsvN1856OdMZUCOOfKUn3nOjjEKr6uLhOnY4CrX6gLDRrA==}
- dependencies:
- style-to-object: 0.4.2
- dev: false
-
- /style-to-object/0.4.2:
- resolution: {integrity: sha512-1JGpfPB3lo42ZX8cuPrheZbfQ6kqPPnPHlKMyeRYtfKD+0jG+QsXgXN57O/dvJlzlB2elI6dGmrPnl5VPQFPaA==}
- dependencies:
- inline-style-parser: 0.1.1
- dev: false
-
/stylehacks/6.0.2_postcss@8.4.33:
resolution: {integrity: sha512-00zvJGnCu64EpMjX8b5iCZ3us2Ptyw8+toEkb92VdmkEaRaSGBNKAoK6aWZckhXxmQP8zWiTaFaiMGIU8Ve8sg==}
engines: {node: ^14 || ^16 || >=18.0}
@@ -3619,7 +3927,7 @@ packages:
engines: {node: '>=10'}
dev: true
- /zustand/4.5.2_lkaryubz2bolmitu7rok3kbwrm:
+ /zustand/4.5.2_ugm3hist2nig7ypm6usfhfueka:
resolution: {integrity: sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==}
engines: {node: '>=12.7.0'}
peerDependencies:
@@ -3634,7 +3942,7 @@ packages:
react:
optional: true
dependencies:
- '@types/react': 17.0.0
+ '@types/react': 17.0.80
react: 18.3.1
use-sync-external-store: 1.2.0_react@18.3.1
dev: false
diff --git a/src/components/blocks/rich_text/rich_text_section_broadcast.tsx b/src/components/blocks/rich_text/rich_text_section_broadcast.tsx
index b74b659..848eeb1 100644
--- a/src/components/blocks/rich_text/rich_text_section_broadcast.tsx
+++ b/src/components/blocks/rich_text/rich_text_section_broadcast.tsx
@@ -7,10 +7,13 @@ export const RichTextSectionBroadcast = (props: Props) => {
const { range, style } = props;
const { hooks } = useGlobalData();
+ if (range === "channel" && hooks.atChannel) return <>{hooks.atChannel()}>;
+ if (range === "everyone" && hooks.atEveryone) return <>{hooks.atEveryone()}>;
+ if (range === "here" && hooks.atHere) return <>{hooks.atHere()}>;
+
return (
-
{
${style?.bold ? "font-medium" : ""}
`}
>
- {range === "channel" && (hooks.atChannel ? hooks.atChannel() : `@${range}`)}
- {range === "everyone" && (hooks.atEveryone ? hooks.atEveryone() : `@${range}`)}
- {range === "here" && (hooks.atHere ? hooks.atHere() : `@${range}`)}
-
+ @{range}
+
);
};
diff --git a/src/components/blocks/rich_text/rich_text_section_channel.tsx b/src/components/blocks/rich_text/rich_text_section_channel.tsx
index 5bf4cc6..3928034 100644
--- a/src/components/blocks/rich_text/rich_text_section_channel.tsx
+++ b/src/components/blocks/rich_text/rich_text_section_channel.tsx
@@ -7,14 +7,15 @@ export const RichTextSectionChannel = (props: Props) => {
const { channel_id, style } = props;
const { channels, hooks } = useGlobalData();
- const channel = channels.find((u) => u.id === channel_id);
+ const channel = channels.find((u) => u.id === channel_id || u.name === channel_id);
const label = channel?.name || channel_id;
+ if (hooks.channel) return <>{hooks.channel(channel || { id: channel_id, name: label })}>;
+
return (
- {
${style?.bold ? "font-medium" : ""}
`}
>
- {hooks.user
- ? hooks.user(
- channel || {
- id: channel_id,
- name: label,
- },
- )
- : `#${label}`}
-
+ #{label}
+
);
};
diff --git a/src/components/blocks/rich_text/rich_text_section_user.tsx b/src/components/blocks/rich_text/rich_text_section_user.tsx
index f989ff5..607e6ae 100644
--- a/src/components/blocks/rich_text/rich_text_section_user.tsx
+++ b/src/components/blocks/rich_text/rich_text_section_user.tsx
@@ -7,14 +7,15 @@ export const RichTextSectionUser = (props: Props) => {
const { user_id, style } = props;
const { users, hooks } = useGlobalData();
- const user = users.find((u) => u.id === user_id);
+ const user = users.find((u) => u.id === user_id || u.name === user_id);
const label = user?.name || user_id;
+ if (hooks.user) return <>{hooks.user(user || { id: user_id, name: label })}>;
+
return (
- {
${style?.bold ? "font-medium" : ""}
`}
>
- {hooks.user
- ? hooks.user(
- user || {
- id: user_id,
- name: label,
- },
- )
- : `@${label}`}
-
+ @{label}
+
);
};
diff --git a/src/components/blocks/rich_text/rich_text_section_user_group.tsx b/src/components/blocks/rich_text/rich_text_section_user_group.tsx
index 59308be..3425579 100644
--- a/src/components/blocks/rich_text/rich_text_section_user_group.tsx
+++ b/src/components/blocks/rich_text/rich_text_section_user_group.tsx
@@ -7,14 +7,15 @@ export const RichTextSectionUserGroup = (props: Props) => {
const { usergroup_id, style } = props;
const { user_groups, hooks } = useGlobalData();
- const group = user_groups.find((u) => u.id === usergroup_id);
+ const group = user_groups.find((u) => u.id === usergroup_id || u.name === usergroup_id);
const label = group?.name || usergroup_id;
+ if (hooks.usergroup) return <>{hooks.usergroup(group || { id: usergroup_id, name: label })}>;
+
return (
- {
${style?.bold ? "font-medium" : ""}
`}
>
- {hooks.usergroup ? hooks.usergroup(usergroup_id) : `@${label}`}
-
+ @{label}
+
);
};
diff --git a/src/components/composition_objects/text_object.tsx b/src/components/composition_objects/text_object.tsx
index c80fd99..b8d806e 100644
--- a/src/components/composition_objects/text_object.tsx
+++ b/src/components/composition_objects/text_object.tsx
@@ -1,6 +1,6 @@
import { useGlobalData } from "../../store";
import type { TextObject as TextObjectType } from "../../types";
-import { parseEmojis, slack_text_to_jsx } from "../../utils";
+import { markdown_parser, parseEmojis } from "../../utils";
type TextObjectProps = {
data: TextObjectType;
@@ -23,13 +23,13 @@ export const TextObject = (props: TextObjectProps) => {
if (type === "plain_text")
return (
- {slack_text_to_jsx(emoji_parsed, { markdown: false, users, channels, hooks })}
+ {markdown_parser(emoji_parsed, { markdown: false, users, channels, hooks })}
);
return (
- {slack_text_to_jsx(emoji_parsed, { markdown: true, users, channels, hooks })}
+ {markdown_parser(emoji_parsed, { markdown: true, users, channels, hooks })}
);
};
diff --git a/src/message.tsx b/src/message.tsx
index 605c6d4..49e4f38 100644
--- a/src/message.tsx
+++ b/src/message.tsx
@@ -48,11 +48,12 @@ export const Message = (props: Props) => {
withoutWrapper = false,
} = props;
- const { setChannels, setUsers, setHooks } = useGlobalData();
+ const { setChannels, setUsers, setHooks, setUserGroups } = useGlobalData();
useEffect(() => {
if (data?.users) setUsers(data.users);
if (data?.channels) setChannels(data.channels);
+ if (data?.user_groups) setUserGroups(data.user_groups);
if (hooks) setHooks(hooks);
}, [data, hooks]);
diff --git a/src/store/useGlobalData.ts b/src/store/useGlobalData.ts
index f035437..1c5f216 100644
--- a/src/store/useGlobalData.ts
+++ b/src/store/useGlobalData.ts
@@ -11,13 +11,18 @@ type Channel = {
name: string;
};
+type UserGroup = {
+ id: string;
+ name: string;
+};
+
type Hooks = {
user?: (data: User) => ReactNode;
channel?: (data: Channel) => ReactNode;
+ usergroup?: (data: UserGroup) => ReactNode;
atChannel?: () => ReactNode;
atEveryone?: () => ReactNode;
atHere?: () => ReactNode;
- usergroup?: (id: string) => ReactNode;
emoji?: (emoji_text: string) => ReactNode;
date?: (data: {
timestamp: string;
@@ -30,10 +35,11 @@ type Hooks = {
type Data = {
users: User[];
channels: Channel[];
- user_groups: Channel[];
+ user_groups: UserGroup[];
hooks: Hooks;
setUsers: (users: User[]) => void;
setChannels: (channels: Channel[]) => void;
+ setUserGroups: (channels: UserGroup[]) => void;
setHooks: (hooks: Hooks) => void;
};
@@ -46,11 +52,13 @@ const useBearStore = create((set) => ({
hooks: {},
setUsers: (users) => set({ users }),
setChannels: (channels) => set({ channels }),
+ setUserGroups: (user_groups) => set({ user_groups }),
setHooks: (hooks) => set({ hooks }),
}));
export const useGlobalData = () => {
- const { users, channels, user_groups, hooks, setChannels, setUsers, setHooks } = useBearStore();
+ const { users, channels, user_groups, hooks, setChannels, setUsers, setHooks, setUserGroups } =
+ useBearStore();
return {
users,
@@ -60,5 +68,6 @@ export const useGlobalData = () => {
setChannels,
setUsers,
setHooks,
+ setUserGroups,
};
};
diff --git a/src/style.css b/src/style.css
index 277b467..d586de0 100644
--- a/src/style.css
+++ b/src/style.css
@@ -269,6 +269,10 @@
/* #endregion */
/* #region CUSTOM STYLES */
+ & .slack_code_inline {
+ @apply inline-block px-1 text-xs leading-[1.5] whitespace-pre-wrap break-words rounded-[3px] border border-black-primary/[0.13] bg-black-primary/[0.04] text-red-primary;
+ }
+
& .slack_code {
@apply block p-2 text-xs leading-[1.5] whitespace-pre-wrap break-words rounded-[3px] border border-black-primary/[0.13] bg-black-primary/[0.04] w-full my-1;
}
@@ -322,21 +326,18 @@
color: rgb(18, 100, 163);
background: rgb(29, 155, 209, 0.1);
user-select: none;
- cursor: pointer;
}
& .slack_channel {
color: rgb(18, 100, 163);
background: rgb(29, 155, 209, 0.1);
user-select: none;
- cursor: pointer;
}
& .slack_user_group {
color: rgb(18, 100, 163);
background: rgb(29, 155, 209, 0.1);
user-select: none;
- cursor: pointer;
}
& .slack_broadcast {
@@ -350,7 +351,11 @@
}
& .slack_blocks_to_jsx__line_break_not_first {
display: block;
- height: 8px;
+ height: 3px;
+ }
+
+ & .slack_link {
+ color: rgb(18, 100, 163);
}
/* #endregion */
diff --git a/src/utils/index.ts b/src/utils/index.ts
index c3ce864..00854dd 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,4 +1,4 @@
export * from "./date";
export * from "./emojis";
-export * from "./slack_text_to_jsx";
+export * from "./markdown_parser";
export * from "./is_accessory_stacked";
diff --git a/src/utils/markdown_parser/elements/blockquote.tsx b/src/utils/markdown_parser/elements/blockquote.tsx
new file mode 100644
index 0000000..392c229
--- /dev/null
+++ b/src/utils/markdown_parser/elements/blockquote.tsx
@@ -0,0 +1,18 @@
+import { BlockQuoteElement } from "../types";
+import { Paragraph } from "./paragraph";
+
+type Props = {
+ element: BlockQuoteElement;
+};
+
+export const Blockquote = (props: Props) => {
+ const { element } = props;
+
+ return (
+ <>
+ {element.children.map((para) => {
+ return ;
+ })}
+ >
+ );
+};
diff --git a/src/utils/markdown_parser/elements/code.tsx b/src/utils/markdown_parser/elements/code.tsx
new file mode 100644
index 0000000..8876bf5
--- /dev/null
+++ b/src/utils/markdown_parser/elements/code.tsx
@@ -0,0 +1,11 @@
+import { CodeElement } from "../types";
+
+type Props = {
+ element: CodeElement;
+};
+
+export const Code = (props: Props) => {
+ const { element } = props;
+
+ return {element.value}
;
+};
diff --git a/src/utils/markdown_parser/elements/index.ts b/src/utils/markdown_parser/elements/index.ts
new file mode 100644
index 0000000..95184d9
--- /dev/null
+++ b/src/utils/markdown_parser/elements/index.ts
@@ -0,0 +1,3 @@
+export * from "./paragraph";
+export * from "./blockquote";
+export * from "./code";
diff --git a/src/utils/markdown_parser/elements/paragraph.tsx b/src/utils/markdown_parser/elements/paragraph.tsx
new file mode 100644
index 0000000..02161f2
--- /dev/null
+++ b/src/utils/markdown_parser/elements/paragraph.tsx
@@ -0,0 +1,44 @@
+import {
+ Delete,
+ Emphasis,
+ InlineCode,
+ Link,
+ SlackBroadcast,
+ SlackChannelMention,
+ SlackUserGroupMention,
+ SlackUserMention,
+ Strong,
+ Text,
+} from "../sub_elements";
+import { ParagraphElement } from "../types";
+
+type Props = {
+ element: ParagraphElement;
+};
+
+export const Paragraph = (props: Props) => {
+ const { element } = props;
+
+ return (
+ <>
+ {element.children.map((subelement, i) => {
+ if (subelement.type === "text") return ;
+ if (subelement.type === "emphasis") return ;
+ if (subelement.type === "inlineCode") return ;
+ if (subelement.type === "delete") return ;
+ if (subelement.type === "strong") return ;
+ if (subelement.type === "link") return ;
+ if (subelement.type === "slack_user_mention")
+ return ;
+ if (subelement.type === "slack_channel_mention")
+ return ;
+ if (subelement.type === "slack_user_group_mention")
+ return ;
+ if (subelement.type === "slack_broadcast")
+ return ;
+
+ return null;
+ })}
+ >
+ );
+};
diff --git a/src/utils/markdown_parser/index.ts b/src/utils/markdown_parser/index.ts
new file mode 100644
index 0000000..5c58fd8
--- /dev/null
+++ b/src/utils/markdown_parser/index.ts
@@ -0,0 +1 @@
+export * from "./parser";
diff --git a/src/utils/markdown_parser/parser.tsx b/src/utils/markdown_parser/parser.tsx
new file mode 100644
index 0000000..71b2d67
--- /dev/null
+++ b/src/utils/markdown_parser/parser.tsx
@@ -0,0 +1,68 @@
+import YozoraParser from "@yozora/parser";
+import { MarkdownElement } from "./types";
+import { Blockquote, Paragraph, Code } from "./elements";
+import { GlobalStore } from "../../store";
+import {
+ SlackUserMentionTokenizer,
+ SlackChannelMentionTokenizer,
+ SlackUserGroupMentionTokenizer,
+ SlackBroadcastTokenizer,
+} from "./tokenizers";
+import { ReactNode } from "react";
+
+const parser = new YozoraParser()
+ .unmountTokenizer("@yozora/tokenizer-list")
+ .useTokenizer(new SlackUserMentionTokenizer())
+ .useTokenizer(new SlackChannelMentionTokenizer())
+ .useTokenizer(new SlackUserGroupMentionTokenizer())
+ .useTokenizer(new SlackBroadcastTokenizer());
+
+type Options = {
+ markdown: boolean;
+ users: GlobalStore["users"];
+ channels: GlobalStore["channels"];
+ hooks: GlobalStore["hooks"];
+};
+
+// #region HELPER CODE
+// TODO: HANDLE DATE PARSING ...(hooks.date && { date: hooks.date }),
+// #endregion
+
+export const markdown_parser = (markdown: string, options: Options): ReactNode => {
+ if (!markdown) return null;
+
+ let text_string = markdown;
+
+ // TRANSFORM ``` TO MAKE IT A CODE BLOCK INSTEAD OF INLINE CODE BLOCK
+ text_string = text_string.replace(/```/g, `\n\`\`\`\n`);
+ // REPLACE SINGLE asterisk WITH DOUBLE asterisk
+ text_string = text_string.replace(/(? to [label](link)
+ text_string = text_string.replace(/<([^|>]+)\|([^>]+)>/g, "[$2]($1)");
+ // REPLACE \n\n WITH '[[DOUBLE_LINE_BREAK]]' to prevent @yozora/parser to eat it
+ text_string = text_string.replace(/\n\n/g, "[[DOUBLE_LINE_BREAK]]");
+ // REPLACE with @here
+ text_string = text_string.replace(//g, "@here");
+ // REPLACE with @everyone
+ text_string = text_string.replace(//g, "@everyone");
+ // REPLACE with @channel
+ text_string = text_string.replace(//g, "@channel");
+
+ const parsed_data = parser.parse(text_string);
+
+ const elements = parsed_data.children as unknown as MarkdownElement[];
+
+ return (
+
+ {elements.map((element, i) => {
+ if (element.type === "paragraph") return
;
+ if (element.type === "blockquote") return
;
+ if (element.type === "code") return
;
+
+ return null;
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/delete.tsx b/src/utils/markdown_parser/sub_elements/delete.tsx
new file mode 100644
index 0000000..4a79cbf
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/delete.tsx
@@ -0,0 +1,18 @@
+import { DeleteSubElement } from "../types";
+import { Text } from "./text";
+
+type Props = {
+ element: DeleteSubElement;
+};
+
+export const Delete = (props: Props) => {
+ const { element } = props;
+
+ return (
+
+ {element.children.map((child, i) => {
+ return ;
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/emphasis.tsx b/src/utils/markdown_parser/sub_elements/emphasis.tsx
new file mode 100644
index 0000000..18d11c3
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/emphasis.tsx
@@ -0,0 +1,32 @@
+import { EmphasisSubElement } from "../types";
+import { Delete } from "./delete";
+import { SlackBroadcast } from "./slack_broadcast";
+import { SlackChannelMention } from "./slack_channel_mention";
+import { SlackUserGroupMention } from "./slack_user_group_mention";
+import { SlackUserMention } from "./slack_user_mention";
+import { Text } from "./text";
+
+type Props = {
+ element: EmphasisSubElement;
+};
+
+export const Emphasis = (props: Props) => {
+ const { element } = props;
+
+ return (
+
+ {element.children.map((child, i) => {
+ if (child.type === "delete") return ;
+ if (child.type === "slack_user_mention")
+ return ;
+ if (child.type === "slack_channel_mention")
+ return ;
+ if (child.type === "slack_user_group_mention")
+ return ;
+ if (child.type === "slack_broadcast") return ;
+
+ return ;
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/index.ts b/src/utils/markdown_parser/sub_elements/index.ts
new file mode 100644
index 0000000..2f9006f
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/index.ts
@@ -0,0 +1,10 @@
+export * from "./emphasis";
+export * from "./text";
+export * from "./inline_code";
+export * from "./strong";
+export * from "./delete";
+export * from "./link";
+export * from "./slack_user_mention";
+export * from "./slack_channel_mention";
+export * from "./slack_user_group_mention";
+export * from "./slack_broadcast";
diff --git a/src/utils/markdown_parser/sub_elements/inline_code.tsx b/src/utils/markdown_parser/sub_elements/inline_code.tsx
new file mode 100644
index 0000000..d74da6c
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/inline_code.tsx
@@ -0,0 +1,11 @@
+import { InlineCodeSubElement } from "../types";
+
+type Props = {
+ element: InlineCodeSubElement;
+};
+
+export const InlineCode = (props: Props) => {
+ const { element } = props;
+
+ return {element.value}
;
+};
diff --git a/src/utils/markdown_parser/sub_elements/link.tsx b/src/utils/markdown_parser/sub_elements/link.tsx
new file mode 100644
index 0000000..cd2d9f9
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/link.tsx
@@ -0,0 +1,24 @@
+import { LinkSubElement } from "../types";
+import { Delete } from "./delete";
+import { Emphasis } from "./emphasis";
+import { Strong } from "./strong";
+import { Text } from "./text";
+
+type Props = {
+ element: LinkSubElement;
+};
+
+export const Link = (props: Props) => {
+ const { element } = props;
+
+ return (
+
+ {element.children.map((child, i) => {
+ if (child.type === "delete") return ;
+ if (child.type === "emphasis") return ;
+ if (child.type === "strong") return ;
+ return ;
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/slack_broadcast.tsx b/src/utils/markdown_parser/sub_elements/slack_broadcast.tsx
new file mode 100644
index 0000000..6d96880
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/slack_broadcast.tsx
@@ -0,0 +1,17 @@
+import { useGlobalData } from "../../../store";
+import { SlackBroadcastSubElement } from "../types";
+
+type Props = {
+ element: SlackBroadcastSubElement;
+};
+
+export const SlackBroadcast = (props: Props) => {
+ const { element } = props;
+ const { hooks } = useGlobalData();
+
+ if (element.value === "here" && hooks.atHere) return <>{hooks.atHere()}>;
+ if (element.value === "everyone" && hooks.atEveryone) return <>{hooks.atEveryone()}>;
+ if (element.value === "channel" && hooks.atChannel) return <>{hooks.atChannel()}>;
+
+ return @{element.value};
+};
diff --git a/src/utils/markdown_parser/sub_elements/slack_channel_mention.tsx b/src/utils/markdown_parser/sub_elements/slack_channel_mention.tsx
new file mode 100644
index 0000000..caff8db
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/slack_channel_mention.tsx
@@ -0,0 +1,23 @@
+import { useGlobalData } from "../../../store";
+import { SlackChannelMentionSubElement } from "../types";
+
+type Props = {
+ element: SlackChannelMentionSubElement;
+};
+
+export const SlackChannelMention = (props: Props) => {
+ const { element } = props;
+ const { hooks, channels } = useGlobalData();
+
+ const channel_id = element.value;
+ const channel = channels.find((u) => u.id === channel_id || u.name === channel_id);
+ const label = channel?.name || channel_id;
+
+ if (hooks.channel) return <>{hooks.channel(channel || { id: channel_id, name: label })}>;
+
+ return (
+
+ #{label}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/slack_user_group_mention.tsx b/src/utils/markdown_parser/sub_elements/slack_user_group_mention.tsx
new file mode 100644
index 0000000..4c8a61a
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/slack_user_group_mention.tsx
@@ -0,0 +1,23 @@
+import { useGlobalData } from "../../../store";
+import { SlackUserGroupMentionSubElement } from "../types";
+
+type Props = {
+ element: SlackUserGroupMentionSubElement;
+};
+
+export const SlackUserGroupMention = (props: Props) => {
+ const { element } = props;
+ const { hooks, user_groups } = useGlobalData();
+
+ const group_id = element.value;
+ const group = user_groups.find((u) => u.id === group_id || u.name === group_id);
+ const label = group?.name || group_id;
+
+ if (hooks.usergroup) return <>{hooks.usergroup(group || { id: group_id, name: label })}>;
+
+ return (
+
+ @{label}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/slack_user_mention.tsx b/src/utils/markdown_parser/sub_elements/slack_user_mention.tsx
new file mode 100644
index 0000000..c02705f
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/slack_user_mention.tsx
@@ -0,0 +1,22 @@
+import { useGlobalData } from "../../../store";
+import { SlackUserMentionSubElement } from "../types";
+
+type Props = {
+ element: SlackUserMentionSubElement;
+};
+
+export const SlackUserMention = (props: Props) => {
+ const { element } = props;
+ const { hooks, users } = useGlobalData();
+
+ const user_id = element.value;
+ const user = users.find((u) => u.id === user_id || u.name === user_id);
+ if (hooks.user) return <>{hooks.user(user || { id: user_id, name: user_id })}>;
+ const label = user?.name || user_id;
+
+ return (
+
+ @{label}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/strong.tsx b/src/utils/markdown_parser/sub_elements/strong.tsx
new file mode 100644
index 0000000..5ea6c41
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/strong.tsx
@@ -0,0 +1,32 @@
+import { StrongSubElement } from "../types";
+import { Delete } from "./delete";
+import { SlackBroadcast } from "./slack_broadcast";
+import { SlackChannelMention } from "./slack_channel_mention";
+import { SlackUserGroupMention } from "./slack_user_group_mention";
+import { SlackUserMention } from "./slack_user_mention";
+import { Text } from "./text";
+
+type Props = {
+ element: StrongSubElement;
+};
+
+export const Strong = (props: Props) => {
+ const { element } = props;
+
+ return (
+
+ {element.children.map((child, i) => {
+ if (child.type === "delete") return ;
+ if (child.type === "slack_user_mention")
+ return ;
+ if (child.type === "slack_channel_mention")
+ return ;
+ if (child.type === "slack_user_group_mention")
+ return ;
+ if (child.type === "slack_broadcast") return ;
+
+ return ;
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/sub_elements/text.tsx b/src/utils/markdown_parser/sub_elements/text.tsx
new file mode 100644
index 0000000..1441613
--- /dev/null
+++ b/src/utils/markdown_parser/sub_elements/text.tsx
@@ -0,0 +1,22 @@
+import { TextSubElement } from "../types";
+
+type Props = {
+ element: TextSubElement;
+};
+
+export const Text = (props: Props) => {
+ const { element } = props;
+
+ return (
+
+ {element.value.split("[[DOUBLE_LINE_BREAK]]").map((line, index) => {
+ return (
+
+ {index > 0 && }
+ {line}
+
+ );
+ })}
+
+ );
+};
diff --git a/src/utils/markdown_parser/tokenizers/index.ts b/src/utils/markdown_parser/tokenizers/index.ts
new file mode 100644
index 0000000..e17dc8a
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/index.ts
@@ -0,0 +1,4 @@
+export * from "./slack_user_mention";
+export * from "./slack_channel_mention";
+export * from "./slack_user_group_mention";
+export * from "./slack_broadcast";
diff --git a/src/utils/markdown_parser/tokenizers/slack_broadcast/index.ts b/src/utils/markdown_parser/tokenizers/slack_broadcast/index.ts
new file mode 100644
index 0000000..816278d
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_broadcast/index.ts
@@ -0,0 +1 @@
+export * from "./tokenizer";
diff --git a/src/utils/markdown_parser/tokenizers/slack_broadcast/match.ts b/src/utils/markdown_parser/tokenizers/slack_broadcast/match.ts
new file mode 100644
index 0000000..1585a85
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_broadcast/match.ts
@@ -0,0 +1,88 @@
+import type { INodePoint } from "@yozora/character";
+import { AsciiCodePoint } from "@yozora/character";
+import type {
+ IMatchInlineHookCreator,
+ IResultOfFindDelimiters,
+ IResultOfProcessSingleDelimiter,
+} from "@yozora/core-tokenizer";
+import { SlackBroadcastType, type IDelimiter, type IThis, type IToken, type T } from "./types";
+
+export const match: IMatchInlineHookCreator = function (api) {
+ return { findDelimiter, processSingleDelimiter };
+
+ function* findDelimiter(): IResultOfFindDelimiters {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ const blockStartIndex: number = api.getBlockStartIndex();
+ const blockEndIndex: number = api.getBlockEndIndex();
+
+ const targets = ["@everyone", "@here", "@channel"];
+ const potentialDelimiters: IDelimiter[] = [];
+
+ for (let i = blockStartIndex; i < blockEndIndex; ++i) {
+ if (nodePoints[i]?.codePoint === AsciiCodePoint.AT_SIGN) {
+ for (const target of targets) {
+ if (matchTarget(nodePoints, i, target)) {
+ potentialDelimiters.push({
+ type: "full",
+ startIndex: i,
+ endIndex: i + target.length,
+ thickness: target.length,
+ });
+ i += target.length - 1; // Skip past the matched target
+ break;
+ }
+ }
+ }
+ }
+
+ let pIndex = 0;
+ let lastEndIndex = -1;
+ let currentDelimiter: IDelimiter | null = null;
+ while (pIndex < potentialDelimiters.length) {
+ const [startIndex, endIndex] = yield currentDelimiter;
+
+ if (lastEndIndex === endIndex) {
+ if (currentDelimiter == null || currentDelimiter.startIndex >= startIndex) continue;
+ }
+ lastEndIndex = endIndex;
+
+ for (; pIndex < potentialDelimiters.length; ++pIndex) {
+ const delimiter = potentialDelimiters[pIndex]!;
+ if (delimiter.startIndex >= startIndex) {
+ currentDelimiter = {
+ type: "full",
+ startIndex: delimiter.startIndex,
+ endIndex: delimiter.endIndex,
+ thickness: delimiter.thickness,
+ };
+ break;
+ }
+ }
+ }
+ }
+
+ function matchTarget(
+ nodePoints: ReadonlyArray,
+ startIndex: number,
+ target: string,
+ ): boolean {
+ for (let j = 0; j < target.length; ++j) {
+ if (nodePoints[startIndex + j]?.codePoint !== target.charCodeAt(j)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function processSingleDelimiter(
+ delimiter: IDelimiter,
+ ): IResultOfProcessSingleDelimiter {
+ const token: IToken = {
+ nodeType: SlackBroadcastType,
+ startIndex: delimiter.startIndex,
+ endIndex: delimiter.endIndex,
+ thickness: delimiter.thickness,
+ };
+ return [token];
+ }
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_broadcast/parse.ts b/src/utils/markdown_parser/tokenizers/slack_broadcast/parse.ts
new file mode 100644
index 0000000..c794b33
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_broadcast/parse.ts
@@ -0,0 +1,21 @@
+import type { INodePoint } from "@yozora/character";
+import { calcStringFromNodePoints } from "@yozora/character";
+import type { IParseInlineHookCreator } from "@yozora/core-tokenizer";
+import { SlackBroadcastType, type INode, type IThis, type IToken, type T } from "./types";
+
+export const parse: IParseInlineHookCreator = function (api) {
+ return {
+ parse: (tokens) =>
+ tokens.map((token) => {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ let startIndex: number = token.startIndex + 1; // skip @
+ let endIndex: number = token.endIndex;
+
+ const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex);
+ const node: INode = api.shouldReservePosition
+ ? { type: SlackBroadcastType, position: api.calcPosition(token), value }
+ : { type: SlackBroadcastType, value };
+ return node;
+ }),
+ };
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_broadcast/tokenizer.ts b/src/utils/markdown_parser/tokenizers/slack_broadcast/tokenizer.ts
new file mode 100644
index 0000000..ff8e985
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_broadcast/tokenizer.ts
@@ -0,0 +1,32 @@
+import type {
+ IInlineTokenizer,
+ IMatchInlineHookCreator,
+ IParseInlineHookCreator,
+} from "@yozora/core-tokenizer";
+import { BaseInlineTokenizer, TokenizerPriority } from "@yozora/core-tokenizer";
+import { match } from "./match";
+import { parse } from "./parse";
+import {
+ SlackBroadcastType,
+ type IDelimiter,
+ type INode,
+ type IThis,
+ type IToken,
+ type ITokenizerProps,
+ type T,
+} from "./types";
+
+export class SlackBroadcastTokenizer
+ extends BaseInlineTokenizer
+ implements IInlineTokenizer
+{
+ constructor(props: ITokenizerProps = {}) {
+ super({
+ name: SlackBroadcastType,
+ priority: props.priority || TokenizerPriority.ATOMIC,
+ });
+ }
+
+ public override readonly match: IMatchInlineHookCreator = match;
+ public override readonly parse: IParseInlineHookCreator = parse;
+}
diff --git a/src/utils/markdown_parser/tokenizers/slack_broadcast/types.ts b/src/utils/markdown_parser/tokenizers/slack_broadcast/types.ts
new file mode 100644
index 0000000..2ed174c
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_broadcast/types.ts
@@ -0,0 +1,23 @@
+import { Literal } from "@yozora/ast";
+import type {
+ IBaseInlineTokenizerProps,
+ IPartialInlineToken,
+ ITokenDelimiter,
+ ITokenizer,
+} from "@yozora/core-tokenizer";
+
+export const SlackBroadcastType = "slack_broadcast";
+export type T = typeof SlackBroadcastType;
+export type INode = Literal;
+
+export interface IToken extends IPartialInlineToken {
+ thickness: number;
+}
+
+export interface IDelimiter extends ITokenDelimiter {
+ type: "full";
+ thickness: number;
+}
+
+export type IThis = ITokenizer;
+export type ITokenizerProps = Partial;
diff --git a/src/utils/markdown_parser/tokenizers/slack_channel_mention/index.ts b/src/utils/markdown_parser/tokenizers/slack_channel_mention/index.ts
new file mode 100644
index 0000000..816278d
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_channel_mention/index.ts
@@ -0,0 +1 @@
+export * from "./tokenizer";
diff --git a/src/utils/markdown_parser/tokenizers/slack_channel_mention/match.ts b/src/utils/markdown_parser/tokenizers/slack_channel_mention/match.ts
new file mode 100644
index 0000000..457bb1c
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_channel_mention/match.ts
@@ -0,0 +1,95 @@
+import type { INodeInterval, INodePoint } from "@yozora/character";
+import { AsciiCodePoint } from "@yozora/character";
+import type {
+ IMatchInlineHookCreator,
+ IResultOfFindDelimiters,
+ IResultOfProcessSingleDelimiter,
+ ITokenDelimiter,
+} from "@yozora/core-tokenizer";
+import { eatOptionalCharacters } from "@yozora/core-tokenizer";
+import { SlackChannelMentionType, type IDelimiter, type IThis, type IToken, type T } from "./types";
+
+export const match: IMatchInlineHookCreator = function (api) {
+ return { findDelimiter, processSingleDelimiter };
+
+ function* findDelimiter(): IResultOfFindDelimiters {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ const blockStartIndex: number = api.getBlockStartIndex();
+ const blockEndIndex: number = api.getBlockEndIndex();
+
+ const potentialDelimiters: ITokenDelimiter[] = [];
+ for (let i = blockStartIndex; i < blockEndIndex; ++i) {
+ const c = nodePoints[i]?.codePoint;
+ if (
+ c === AsciiCodePoint.OPEN_ANGLE &&
+ nodePoints[i + 1]?.codePoint === AsciiCodePoint.NUMBER_SIGN
+ ) {
+ const j = eatOptionalCharacters(nodePoints, i + 2, blockEndIndex, AsciiCodePoint.AT_SIGN);
+ if (j < blockEndIndex) {
+ potentialDelimiters.push({
+ type: "opener",
+ startIndex: i,
+ endIndex: j,
+ });
+ }
+ } else if (c === AsciiCodePoint.CLOSE_ANGLE) {
+ potentialDelimiters.push({
+ type: "closer",
+ startIndex: i,
+ endIndex: i + 1,
+ });
+ }
+ }
+
+ let pIndex = 0;
+ let lastEndIndex = -1;
+ let delimiter: IDelimiter | null = null;
+ while (pIndex < potentialDelimiters.length) {
+ const [startIndex, endIndex] = yield delimiter;
+
+ if (lastEndIndex === endIndex) {
+ if (delimiter == null || delimiter.startIndex >= startIndex) continue;
+ }
+ lastEndIndex = endIndex;
+
+ let openerDelimiter: INodeInterval | null = null;
+ let closerDelimiter: INodeInterval | null = null;
+ for (; pIndex < potentialDelimiters.length; ++pIndex) {
+ const delimiter = potentialDelimiters[pIndex]!;
+ if (delimiter.startIndex >= startIndex && delimiter.type !== "closer") {
+ openerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ for (let i = pIndex + 1; i < potentialDelimiters.length; ++i) {
+ const delimiter = potentialDelimiters[i]!;
+ if (delimiter.type === "closer") {
+ closerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ if (closerDelimiter == null) return;
+
+ delimiter = {
+ type: "full",
+ startIndex: openerDelimiter!.startIndex,
+ endIndex: closerDelimiter.endIndex,
+ thickness: closerDelimiter.endIndex - closerDelimiter.startIndex,
+ };
+ }
+ }
+
+ function processSingleDelimiter(
+ delimiter: IDelimiter,
+ ): IResultOfProcessSingleDelimiter {
+ const token: IToken = {
+ nodeType: SlackChannelMentionType,
+ startIndex: delimiter.startIndex,
+ endIndex: delimiter.endIndex,
+ thickness: delimiter.thickness,
+ };
+ return [token];
+ }
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_channel_mention/parse.ts b/src/utils/markdown_parser/tokenizers/slack_channel_mention/parse.ts
new file mode 100644
index 0000000..f661c72
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_channel_mention/parse.ts
@@ -0,0 +1,21 @@
+import type { INodePoint } from "@yozora/character";
+import { calcStringFromNodePoints } from "@yozora/character";
+import type { IParseInlineHookCreator } from "@yozora/core-tokenizer";
+import { SlackChannelMentionType, type INode, type IThis, type IToken, type T } from "./types";
+
+export const parse: IParseInlineHookCreator = function (api) {
+ return {
+ parse: (tokens) =>
+ tokens.map((token) => {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ let startIndex: number = token.startIndex + 2; // Skip `<#`
+ let endIndex: number = token.endIndex - 1; // Skip `>`
+
+ const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex);
+ const node: INode = api.shouldReservePosition
+ ? { type: SlackChannelMentionType, position: api.calcPosition(token), value }
+ : { type: SlackChannelMentionType, value };
+ return node;
+ }),
+ };
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_channel_mention/tokenizer.ts b/src/utils/markdown_parser/tokenizers/slack_channel_mention/tokenizer.ts
new file mode 100644
index 0000000..0b06cec
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_channel_mention/tokenizer.ts
@@ -0,0 +1,32 @@
+import type {
+ IInlineTokenizer,
+ IMatchInlineHookCreator,
+ IParseInlineHookCreator,
+} from "@yozora/core-tokenizer";
+import { BaseInlineTokenizer, TokenizerPriority } from "@yozora/core-tokenizer";
+import { match } from "./match";
+import { parse } from "./parse";
+import {
+ SlackChannelMentionType,
+ type IDelimiter,
+ type INode,
+ type IThis,
+ type IToken,
+ type ITokenizerProps,
+ type T,
+} from "./types";
+
+export class SlackChannelMentionTokenizer
+ extends BaseInlineTokenizer
+ implements IInlineTokenizer
+{
+ constructor(props: ITokenizerProps = {}) {
+ super({
+ name: SlackChannelMentionType,
+ priority: props.priority || TokenizerPriority.ATOMIC,
+ });
+ }
+
+ public override readonly match: IMatchInlineHookCreator = match;
+ public override readonly parse: IParseInlineHookCreator = parse;
+}
diff --git a/src/utils/markdown_parser/tokenizers/slack_channel_mention/types.ts b/src/utils/markdown_parser/tokenizers/slack_channel_mention/types.ts
new file mode 100644
index 0000000..64a7076
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_channel_mention/types.ts
@@ -0,0 +1,23 @@
+import { Literal } from "@yozora/ast";
+import type {
+ IBaseInlineTokenizerProps,
+ IPartialInlineToken,
+ ITokenDelimiter,
+ ITokenizer,
+} from "@yozora/core-tokenizer";
+
+export const SlackChannelMentionType = "slack_channel_mention";
+export type T = typeof SlackChannelMentionType;
+export type INode = Literal;
+
+export interface IToken extends IPartialInlineToken {
+ thickness: number;
+}
+
+export interface IDelimiter extends ITokenDelimiter {
+ type: "full";
+ thickness: number;
+}
+
+export type IThis = ITokenizer;
+export type ITokenizerProps = Partial;
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_group_mention/index.ts b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/index.ts
new file mode 100644
index 0000000..816278d
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/index.ts
@@ -0,0 +1 @@
+export * from "./tokenizer";
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_group_mention/match.ts b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/match.ts
new file mode 100644
index 0000000..ab85518
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/match.ts
@@ -0,0 +1,109 @@
+import type { INodeInterval, INodePoint } from "@yozora/character";
+import { AsciiCodePoint } from "@yozora/character";
+import type {
+ IMatchInlineHookCreator,
+ IResultOfFindDelimiters,
+ IResultOfProcessSingleDelimiter,
+ ITokenDelimiter,
+} from "@yozora/core-tokenizer";
+import { eatOptionalCharacters } from "@yozora/core-tokenizer";
+import {
+ SlackUserGroupMentionType,
+ type IDelimiter,
+ type IThis,
+ type IToken,
+ type T,
+} from "./types";
+
+export const match: IMatchInlineHookCreator = function (api) {
+ return { findDelimiter, processSingleDelimiter };
+
+ function* findDelimiter(): IResultOfFindDelimiters {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ const blockStartIndex: number = api.getBlockStartIndex();
+ const blockEndIndex: number = api.getBlockEndIndex();
+
+ const potentialDelimiters: ITokenDelimiter[] = [];
+ for (let i = blockStartIndex; i < blockEndIndex; ++i) {
+ const c = nodePoints[i]?.codePoint;
+ if (
+ c === AsciiCodePoint.OPEN_ANGLE &&
+ nodePoints[i + 1]?.codePoint === AsciiCodePoint.EXCLAMATION_MARK &&
+ nodePoints[i + 2]?.codePoint === AsciiCodePoint.LOWERCASE_S &&
+ nodePoints[i + 3]?.codePoint === AsciiCodePoint.LOWERCASE_U &&
+ nodePoints[i + 4]?.codePoint === AsciiCodePoint.LOWERCASE_B &&
+ nodePoints[i + 5]?.codePoint === AsciiCodePoint.LOWERCASE_T &&
+ nodePoints[i + 6]?.codePoint === AsciiCodePoint.LOWERCASE_E &&
+ nodePoints[i + 7]?.codePoint === AsciiCodePoint.LOWERCASE_A &&
+ nodePoints[i + 8]?.codePoint === AsciiCodePoint.LOWERCASE_M &&
+ nodePoints[i + 9]?.codePoint === AsciiCodePoint.CARET
+ ) {
+ const j = eatOptionalCharacters(nodePoints, i + 10, blockEndIndex, AsciiCodePoint.CARET);
+ if (j < blockEndIndex) {
+ potentialDelimiters.push({
+ type: "opener",
+ startIndex: i,
+ endIndex: j,
+ });
+ }
+ } else if (c === AsciiCodePoint.CLOSE_ANGLE) {
+ potentialDelimiters.push({
+ type: "closer",
+ startIndex: i,
+ endIndex: i + 1,
+ });
+ }
+ }
+
+ let pIndex = 0;
+ let lastEndIndex = -1;
+ let delimiter: IDelimiter | null = null;
+ while (pIndex < potentialDelimiters.length) {
+ const [startIndex, endIndex] = yield delimiter;
+
+ if (lastEndIndex === endIndex) {
+ if (delimiter == null || delimiter.startIndex >= startIndex) continue;
+ }
+ lastEndIndex = endIndex;
+
+ let openerDelimiter: INodeInterval | null = null;
+ let closerDelimiter: INodeInterval | null = null;
+ for (; pIndex < potentialDelimiters.length; ++pIndex) {
+ const delimiter = potentialDelimiters[pIndex]!;
+ if (delimiter.startIndex >= startIndex && delimiter.type !== "closer") {
+ openerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ for (let i = pIndex + 1; i < potentialDelimiters.length; ++i) {
+ const delimiter = potentialDelimiters[i]!;
+ if (delimiter.type === "closer") {
+ closerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ if (closerDelimiter == null) return;
+
+ delimiter = {
+ type: "full",
+ startIndex: openerDelimiter!.startIndex,
+ endIndex: closerDelimiter.endIndex,
+ thickness: closerDelimiter.endIndex - closerDelimiter.startIndex,
+ };
+ }
+ }
+
+ function processSingleDelimiter(
+ delimiter: IDelimiter,
+ ): IResultOfProcessSingleDelimiter {
+ const token: IToken = {
+ nodeType: SlackUserGroupMentionType,
+ startIndex: delimiter.startIndex,
+ endIndex: delimiter.endIndex,
+ thickness: delimiter.thickness,
+ };
+ return [token];
+ }
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_group_mention/parse.ts b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/parse.ts
new file mode 100644
index 0000000..ca6096b
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/parse.ts
@@ -0,0 +1,21 @@
+import type { INodePoint } from "@yozora/character";
+import { calcStringFromNodePoints } from "@yozora/character";
+import type { IParseInlineHookCreator } from "@yozora/core-tokenizer";
+import { SlackUserGroupMentionType, type INode, type IThis, type IToken, type T } from "./types";
+
+export const parse: IParseInlineHookCreator = function (api) {
+ return {
+ parse: (tokens) =>
+ tokens.map((token) => {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ let startIndex: number = token.startIndex + 10; // Skip ``
+
+ const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex);
+ const node: INode = api.shouldReservePosition
+ ? { type: SlackUserGroupMentionType, position: api.calcPosition(token), value }
+ : { type: SlackUserGroupMentionType, value };
+ return node;
+ }),
+ };
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_group_mention/tokenizer.ts b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/tokenizer.ts
new file mode 100644
index 0000000..49cf291
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/tokenizer.ts
@@ -0,0 +1,32 @@
+import type {
+ IInlineTokenizer,
+ IMatchInlineHookCreator,
+ IParseInlineHookCreator,
+} from "@yozora/core-tokenizer";
+import { BaseInlineTokenizer, TokenizerPriority } from "@yozora/core-tokenizer";
+import { match } from "./match";
+import { parse } from "./parse";
+import {
+ SlackUserGroupMentionType,
+ type IDelimiter,
+ type INode,
+ type IThis,
+ type IToken,
+ type ITokenizerProps,
+ type T,
+} from "./types";
+
+export class SlackUserGroupMentionTokenizer
+ extends BaseInlineTokenizer
+ implements IInlineTokenizer
+{
+ constructor(props: ITokenizerProps = {}) {
+ super({
+ name: SlackUserGroupMentionType,
+ priority: props.priority || TokenizerPriority.ATOMIC,
+ });
+ }
+
+ public override readonly match: IMatchInlineHookCreator = match;
+ public override readonly parse: IParseInlineHookCreator = parse;
+}
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_group_mention/types.ts b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/types.ts
new file mode 100644
index 0000000..e515fe2
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_group_mention/types.ts
@@ -0,0 +1,23 @@
+import { Literal } from "@yozora/ast";
+import type {
+ IBaseInlineTokenizerProps,
+ IPartialInlineToken,
+ ITokenDelimiter,
+ ITokenizer,
+} from "@yozora/core-tokenizer";
+
+export const SlackUserGroupMentionType = "slack_user_group_mention";
+export type T = typeof SlackUserGroupMentionType;
+export type INode = Literal;
+
+export interface IToken extends IPartialInlineToken {
+ thickness: number;
+}
+
+export interface IDelimiter extends ITokenDelimiter {
+ type: "full";
+ thickness: number;
+}
+
+export type IThis = ITokenizer;
+export type ITokenizerProps = Partial;
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_mention/index.ts b/src/utils/markdown_parser/tokenizers/slack_user_mention/index.ts
new file mode 100644
index 0000000..816278d
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_mention/index.ts
@@ -0,0 +1 @@
+export * from "./tokenizer";
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_mention/match.ts b/src/utils/markdown_parser/tokenizers/slack_user_mention/match.ts
new file mode 100644
index 0000000..b376cba
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_mention/match.ts
@@ -0,0 +1,95 @@
+import type { INodeInterval, INodePoint } from "@yozora/character";
+import { AsciiCodePoint } from "@yozora/character";
+import type {
+ IMatchInlineHookCreator,
+ IResultOfFindDelimiters,
+ IResultOfProcessSingleDelimiter,
+ ITokenDelimiter,
+} from "@yozora/core-tokenizer";
+import { eatOptionalCharacters } from "@yozora/core-tokenizer";
+import { SlackUserMentionType, type IDelimiter, type IThis, type IToken, type T } from "./types";
+
+export const match: IMatchInlineHookCreator = function (api) {
+ return { findDelimiter, processSingleDelimiter };
+
+ function* findDelimiter(): IResultOfFindDelimiters {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ const blockStartIndex: number = api.getBlockStartIndex();
+ const blockEndIndex: number = api.getBlockEndIndex();
+
+ const potentialDelimiters: ITokenDelimiter[] = [];
+ for (let i = blockStartIndex; i < blockEndIndex; ++i) {
+ const c = nodePoints[i]?.codePoint;
+ if (
+ c === AsciiCodePoint.OPEN_ANGLE &&
+ nodePoints[i + 1]?.codePoint === AsciiCodePoint.AT_SIGN
+ ) {
+ const j = eatOptionalCharacters(nodePoints, i + 2, blockEndIndex, AsciiCodePoint.AT_SIGN);
+ if (j < blockEndIndex) {
+ potentialDelimiters.push({
+ type: "opener",
+ startIndex: i,
+ endIndex: j,
+ });
+ }
+ } else if (c === AsciiCodePoint.CLOSE_ANGLE) {
+ potentialDelimiters.push({
+ type: "closer",
+ startIndex: i,
+ endIndex: i + 1,
+ });
+ }
+ }
+
+ let pIndex = 0;
+ let lastEndIndex = -1;
+ let delimiter: IDelimiter | null = null;
+ while (pIndex < potentialDelimiters.length) {
+ const [startIndex, endIndex] = yield delimiter;
+
+ if (lastEndIndex === endIndex) {
+ if (delimiter == null || delimiter.startIndex >= startIndex) continue;
+ }
+ lastEndIndex = endIndex;
+
+ let openerDelimiter: INodeInterval | null = null;
+ let closerDelimiter: INodeInterval | null = null;
+ for (; pIndex < potentialDelimiters.length; ++pIndex) {
+ const delimiter = potentialDelimiters[pIndex]!;
+ if (delimiter.startIndex >= startIndex && delimiter.type !== "closer") {
+ openerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ for (let i = pIndex + 1; i < potentialDelimiters.length; ++i) {
+ const delimiter = potentialDelimiters[i]!;
+ if (delimiter.type === "closer") {
+ closerDelimiter = delimiter;
+ break;
+ }
+ }
+
+ if (closerDelimiter == null) return;
+
+ delimiter = {
+ type: "full",
+ startIndex: openerDelimiter!.startIndex,
+ endIndex: closerDelimiter.endIndex,
+ thickness: closerDelimiter.endIndex - closerDelimiter.startIndex,
+ };
+ }
+ }
+
+ function processSingleDelimiter(
+ delimiter: IDelimiter,
+ ): IResultOfProcessSingleDelimiter {
+ const token: IToken = {
+ nodeType: SlackUserMentionType,
+ startIndex: delimiter.startIndex,
+ endIndex: delimiter.endIndex,
+ thickness: delimiter.thickness,
+ };
+ return [token];
+ }
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_mention/parse.ts b/src/utils/markdown_parser/tokenizers/slack_user_mention/parse.ts
new file mode 100644
index 0000000..b38186c
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_mention/parse.ts
@@ -0,0 +1,21 @@
+import type { INodePoint } from "@yozora/character";
+import { calcStringFromNodePoints } from "@yozora/character";
+import type { IParseInlineHookCreator } from "@yozora/core-tokenizer";
+import { SlackUserMentionType, type INode, type IThis, type IToken, type T } from "./types";
+
+export const parse: IParseInlineHookCreator = function (api) {
+ return {
+ parse: (tokens) =>
+ tokens.map((token) => {
+ const nodePoints: ReadonlyArray = api.getNodePoints();
+ let startIndex: number = token.startIndex + 2; // Skip `<@`
+ let endIndex: number = token.endIndex - 1; // Skip `>`
+
+ const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex);
+ const node: INode = api.shouldReservePosition
+ ? { type: SlackUserMentionType, position: api.calcPosition(token), value }
+ : { type: SlackUserMentionType, value };
+ return node;
+ }),
+ };
+};
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_mention/tokenizer.ts b/src/utils/markdown_parser/tokenizers/slack_user_mention/tokenizer.ts
new file mode 100644
index 0000000..5d6c1fe
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_mention/tokenizer.ts
@@ -0,0 +1,32 @@
+import type {
+ IInlineTokenizer,
+ IMatchInlineHookCreator,
+ IParseInlineHookCreator,
+} from "@yozora/core-tokenizer";
+import { BaseInlineTokenizer, TokenizerPriority } from "@yozora/core-tokenizer";
+import { match } from "./match";
+import { parse } from "./parse";
+import {
+ SlackUserMentionType,
+ type IDelimiter,
+ type INode,
+ type IThis,
+ type IToken,
+ type ITokenizerProps,
+ type T,
+} from "./types";
+
+export class SlackUserMentionTokenizer
+ extends BaseInlineTokenizer
+ implements IInlineTokenizer
+{
+ constructor(props: ITokenizerProps = {}) {
+ super({
+ name: SlackUserMentionType,
+ priority: props.priority || TokenizerPriority.ATOMIC,
+ });
+ }
+
+ public override readonly match: IMatchInlineHookCreator = match;
+ public override readonly parse: IParseInlineHookCreator = parse;
+}
diff --git a/src/utils/markdown_parser/tokenizers/slack_user_mention/types.ts b/src/utils/markdown_parser/tokenizers/slack_user_mention/types.ts
new file mode 100644
index 0000000..6732eea
--- /dev/null
+++ b/src/utils/markdown_parser/tokenizers/slack_user_mention/types.ts
@@ -0,0 +1,23 @@
+import { Literal } from "@yozora/ast";
+import type {
+ IBaseInlineTokenizerProps,
+ IPartialInlineToken,
+ ITokenDelimiter,
+ ITokenizer,
+} from "@yozora/core-tokenizer";
+
+export const SlackUserMentionType = "slack_user_mention";
+export type T = typeof SlackUserMentionType;
+export type INode = Literal;
+
+export interface IToken extends IPartialInlineToken {
+ thickness: number;
+}
+
+export interface IDelimiter extends ITokenDelimiter {
+ type: "full";
+ thickness: number;
+}
+
+export type IThis = ITokenizer;
+export type ITokenizerProps = Partial;
diff --git a/src/utils/markdown_parser/types.ts b/src/utils/markdown_parser/types.ts
new file mode 100644
index 0000000..a8b964e
--- /dev/null
+++ b/src/utils/markdown_parser/types.ts
@@ -0,0 +1,94 @@
+export type SlackBroadcastSubElement = {
+ type: "slack_broadcast";
+ value: "here" | "everyone" | "channel";
+};
+
+export type SlackUserMentionSubElement = {
+ type: "slack_user_mention";
+ value: string;
+};
+
+export type SlackChannelMentionSubElement = {
+ type: "slack_channel_mention";
+ value: string;
+};
+
+export type SlackUserGroupMentionSubElement = {
+ type: "slack_user_group_mention";
+ value: string;
+};
+
+export type TextSubElement = {
+ type: "text";
+ value: string;
+};
+
+export type InlineCodeSubElement = {
+ type: "inlineCode";
+ value: string;
+};
+
+export type EmphasisSubElement = {
+ type: "emphasis";
+ children: (
+ | TextSubElement
+ | DeleteSubElement
+ | SlackUserMentionSubElement
+ | SlackChannelMentionSubElement
+ | SlackUserGroupMentionSubElement
+ | SlackBroadcastSubElement
+ )[];
+};
+
+export type StrongSubElement = {
+ type: "strong";
+ children: (
+ | TextSubElement
+ | DeleteSubElement
+ | SlackUserMentionSubElement
+ | SlackChannelMentionSubElement
+ | SlackUserGroupMentionSubElement
+ | SlackBroadcastSubElement
+ )[];
+};
+
+export type DeleteSubElement = {
+ type: "delete";
+ children: TextSubElement[];
+};
+
+export type LinkSubElement = {
+ type: "link";
+ url: "http://www.example.com";
+ children: (TextSubElement | EmphasisSubElement | StrongSubElement | DeleteSubElement)[];
+};
+
+export type ParagraphElement = {
+ type: "paragraph";
+ children: (
+ | EmphasisSubElement
+ | TextSubElement
+ | StrongSubElement
+ | InlineCodeSubElement
+ | DeleteSubElement
+ | LinkSubElement
+ | SlackUserMentionSubElement
+ | SlackChannelMentionSubElement
+ | SlackUserGroupMentionSubElement
+ | SlackBroadcastSubElement
+ )[];
+};
+
+export type BlockQuoteElement = {
+ type: "blockquote";
+ children: ParagraphElement[];
+};
+
+export type CodeElement = {
+ type: "code";
+ lang: null | string;
+ meta: null | string;
+ value: string;
+};
+
+export type MarkdownElement = ParagraphElement | BlockQuoteElement | CodeElement;
diff --git a/src/utils/slack_text_to_jsx.tsx b/src/utils/slack_text_to_jsx.tsx
deleted file mode 100644
index 41fd1b1..0000000
--- a/src/utils/slack_text_to_jsx.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { ReactNode } from "react";
-import parse from "html-react-parser";
-import { toHTML as slack_text_parser } from "slack-markdown";
-import { GlobalStore } from "../store";
-
-type Options = {
- markdown: boolean;
- users: GlobalStore["users"];
- channels: GlobalStore["channels"];
- hooks: GlobalStore["hooks"];
-};
-
-export const slack_text_to_jsx = (text: string, parse_options: Options): ReactNode => {
- const { users, channels } = parse_options;
-
- if (!text) return null;
-
- let text_string = text;
-
- // REPLACE LINE BREAKS
- text_string = text_string.replace(/(\n)+/g, (match) => {
- return match.replace(/\n/g, (newline, index) => {
- return index === 0
- ? ""
- : "";
- });
- });
-
- text_string = slack_text_parser(text_string, {
- escapeHTML: false,
- slackCallbacks: {
- user(data) {
- const user = users.find((u) => u.id === data.id || u.name === data.name);
- // if (hooks.user) return hooks.user(user || data);
- const label = user?.name || data.id || data.name;
- return `@${label}`;
- },
- channel(data) {
- const channel = channels.find((c) => c.id === data.id || c.name === data.name);
- // if (hooks.channel) return hooks.channel(channel || data);
- const label = channel?.name || data.id || data.name;
- return `#${label}`;
- },
- atChannel(data) {
- const channel = channels.find((c) => c.name === data.name);
- // if (hooks.atChannel) return hooks.atChannel(channel || data);
- const label = channel?.name || data.name;
- return `#${label}`;
- },
- atEveryone() {
- return `@everyone`;
- },
- atHere() {
- return `@everyone`;
- },
- // ...(hooks.date && { date: hooks.date }),
- // ...(hooks.usergroup && { usergroup: hooks.usergroup }),
- },
- });
-
- return parse(text_string, { trim: false });
-};