feat: meilisearch
This commit is contained in:
14
package.json
14
package.json
@@ -20,6 +20,7 @@
|
|||||||
"@mantine/core": "^7.6.2",
|
"@mantine/core": "^7.6.2",
|
||||||
"@mantine/hooks": "^7.6.2",
|
"@mantine/hooks": "^7.6.2",
|
||||||
"@mantine/notifications": "^7.6.2",
|
"@mantine/notifications": "^7.6.2",
|
||||||
|
"@meilisearch/instant-meilisearch": "^0.18.1",
|
||||||
"@reduxjs/toolkit": "^2.2.1",
|
"@reduxjs/toolkit": "^2.2.1",
|
||||||
"@sentry/react": "^7.108.0",
|
"@sentry/react": "^7.108.0",
|
||||||
"@sentry/vite-plugin": "^2.16.0",
|
"@sentry/vite-plugin": "^2.16.0",
|
||||||
@@ -28,14 +29,23 @@
|
|||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"i18next": "^23.10.1",
|
"i18next": "^23.10.1",
|
||||||
"i18next-browser-languagedetector": "^7.2.0",
|
"i18next-browser-languagedetector": "^7.2.0",
|
||||||
|
"instantsearch.js": "^4.71.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"meilisearch": "^0.40.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-i18next": "^14.1.0",
|
"react-i18next": "^14.1.0",
|
||||||
|
"react-instantsearch": "^7.11.1",
|
||||||
"react-redux": "^9.1.0",
|
"react-redux": "^9.1.0",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"remark": "^15.0.1",
|
"rehype-highlight": "^7.0.0",
|
||||||
"remark-html": "^16.0.1"
|
"rehype-sanitize": "^6.0.0",
|
||||||
|
"rehype-stringify": "^10.0.0",
|
||||||
|
"remark-gfm": "^4.0.0",
|
||||||
|
"remark-html": "^16.0.1",
|
||||||
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-rehype": "^11.1.0",
|
||||||
|
"unified": "^11.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.1",
|
"@babel/core": "^7.24.1",
|
||||||
|
|||||||
557
pnpm-lock.yaml
generated
557
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ dependencies:
|
|||||||
'@mantine/notifications':
|
'@mantine/notifications':
|
||||||
specifier: ^7.6.2
|
specifier: ^7.6.2
|
||||||
version: 7.6.2(@mantine/core@7.6.2)(@mantine/hooks@7.6.2)(react-dom@18.2.0)(react@18.2.0)
|
version: 7.6.2(@mantine/core@7.6.2)(@mantine/hooks@7.6.2)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@meilisearch/instant-meilisearch':
|
||||||
|
specifier: ^0.18.1
|
||||||
|
version: 0.18.1
|
||||||
'@reduxjs/toolkit':
|
'@reduxjs/toolkit':
|
||||||
specifier: ^2.2.1
|
specifier: ^2.2.1
|
||||||
version: 2.2.1(react-redux@9.1.0)(react@18.2.0)
|
version: 2.2.1(react-redux@9.1.0)(react@18.2.0)
|
||||||
@@ -38,9 +41,15 @@ dependencies:
|
|||||||
i18next-browser-languagedetector:
|
i18next-browser-languagedetector:
|
||||||
specifier: ^7.2.0
|
specifier: ^7.2.0
|
||||||
version: 7.2.0
|
version: 7.2.0
|
||||||
|
instantsearch.js:
|
||||||
|
specifier: ^4.71.1
|
||||||
|
version: 4.71.1(algoliasearch@4.23.3)
|
||||||
lodash:
|
lodash:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
meilisearch:
|
||||||
|
specifier: ^0.40.0
|
||||||
|
version: 0.40.0
|
||||||
react:
|
react:
|
||||||
specifier: ^18.2.0
|
specifier: ^18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
@@ -50,18 +59,39 @@ dependencies:
|
|||||||
react-i18next:
|
react-i18next:
|
||||||
specifier: ^14.1.0
|
specifier: ^14.1.0
|
||||||
version: 14.1.0(i18next@23.10.1)(react-dom@18.2.0)(react@18.2.0)
|
version: 14.1.0(i18next@23.10.1)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
react-instantsearch:
|
||||||
|
specifier: ^7.11.1
|
||||||
|
version: 7.11.1(algoliasearch@4.23.3)(react-dom@18.2.0)(react@18.2.0)
|
||||||
react-redux:
|
react-redux:
|
||||||
specifier: ^9.1.0
|
specifier: ^9.1.0
|
||||||
version: 9.1.0(@types/react@18.2.67)(react@18.2.0)(redux@5.0.1)
|
version: 9.1.0(@types/react@18.2.67)(react@18.2.0)(redux@5.0.1)
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^6.22.3
|
specifier: ^6.22.3
|
||||||
version: 6.22.3(react-dom@18.2.0)(react@18.2.0)
|
version: 6.22.3(react-dom@18.2.0)(react@18.2.0)
|
||||||
remark:
|
rehype-highlight:
|
||||||
specifier: ^15.0.1
|
specifier: ^7.0.0
|
||||||
version: 15.0.1
|
version: 7.0.0
|
||||||
|
rehype-sanitize:
|
||||||
|
specifier: ^6.0.0
|
||||||
|
version: 6.0.0
|
||||||
|
rehype-stringify:
|
||||||
|
specifier: ^10.0.0
|
||||||
|
version: 10.0.0
|
||||||
|
remark-gfm:
|
||||||
|
specifier: ^4.0.0
|
||||||
|
version: 4.0.0
|
||||||
remark-html:
|
remark-html:
|
||||||
specifier: ^16.0.1
|
specifier: ^16.0.1
|
||||||
version: 16.0.1
|
version: 16.0.1
|
||||||
|
remark-parse:
|
||||||
|
specifier: ^11.0.0
|
||||||
|
version: 11.0.0
|
||||||
|
remark-rehype:
|
||||||
|
specifier: ^11.1.0
|
||||||
|
version: 11.1.0
|
||||||
|
unified:
|
||||||
|
specifier: ^11.0.4
|
||||||
|
version: 11.0.4
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@babel/core':
|
'@babel/core':
|
||||||
@@ -235,6 +265,116 @@ packages:
|
|||||||
resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==}
|
resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@algolia/cache-browser-local-storage@4.23.3:
|
||||||
|
resolution: {integrity: sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/cache-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/cache-common@4.23.3:
|
||||||
|
resolution: {integrity: sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/cache-in-memory@4.23.3:
|
||||||
|
resolution: {integrity: sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/cache-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/client-account@4.23.3:
|
||||||
|
resolution: {integrity: sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/client-search': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/client-analytics@4.23.3:
|
||||||
|
resolution: {integrity: sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/client-search': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/client-common@4.23.3:
|
||||||
|
resolution: {integrity: sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/client-personalization@4.23.3:
|
||||||
|
resolution: {integrity: sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/client-search@4.23.3:
|
||||||
|
resolution: {integrity: sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/events@4.0.1:
|
||||||
|
resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/logger-common@4.23.3:
|
||||||
|
resolution: {integrity: sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/logger-console@4.23.3:
|
||||||
|
resolution: {integrity: sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/logger-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/recommend@4.23.3:
|
||||||
|
resolution: {integrity: sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/cache-browser-local-storage': 4.23.3
|
||||||
|
'@algolia/cache-common': 4.23.3
|
||||||
|
'@algolia/cache-in-memory': 4.23.3
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/client-search': 4.23.3
|
||||||
|
'@algolia/logger-common': 4.23.3
|
||||||
|
'@algolia/logger-console': 4.23.3
|
||||||
|
'@algolia/requester-browser-xhr': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/requester-node-http': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/requester-browser-xhr@4.23.3:
|
||||||
|
resolution: {integrity: sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/requester-common@4.23.3:
|
||||||
|
resolution: {integrity: sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/requester-node-http@4.23.3:
|
||||||
|
resolution: {integrity: sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@algolia/transporter@4.23.3:
|
||||||
|
resolution: {integrity: sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/cache-common': 4.23.3
|
||||||
|
'@algolia/logger-common': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@ampproject/remapping@2.3.0:
|
/@ampproject/remapping@2.3.0:
|
||||||
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@@ -2207,6 +2347,14 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@meilisearch/instant-meilisearch@0.18.1:
|
||||||
|
resolution: {integrity: sha512-KxBoEaI1+CQQaSbSZZEllIUwsNofALH0RG+/bFMkNhavuzJn982zOTC7xYtYmXC6nsj32MmAe+rDBtazycDJQQ==}
|
||||||
|
dependencies:
|
||||||
|
meilisearch: 0.40.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@ndelangen/get-tarball@3.0.9:
|
/@ndelangen/get-tarball@3.0.9:
|
||||||
resolution: {integrity: sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==}
|
resolution: {integrity: sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3618,6 +3766,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==}
|
resolution: {integrity: sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/dom-speech-recognition@0.0.1:
|
||||||
|
resolution: {integrity: sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/ejs@3.1.5:
|
/@types/ejs@3.1.5:
|
||||||
resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==}
|
resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3674,6 +3826,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==}
|
resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/google.maps@3.55.10:
|
||||||
|
resolution: {integrity: sha512-XbDu2MIvcKgN+MBrufjWcsQRtXTbrBGBKperbhMLnPSq4770+pvlR66Oqq/Ub4AVkmGc9QciCfwPZpVCLaKAOw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/graceful-fs@4.1.9:
|
/@types/graceful-fs@4.1.9:
|
||||||
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3685,6 +3841,10 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.2
|
'@types/unist': 3.0.2
|
||||||
|
|
||||||
|
/@types/hogan.js@3.0.5:
|
||||||
|
resolution: {integrity: sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/http-errors@2.0.4:
|
/@types/http-errors@2.0.4:
|
||||||
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3779,7 +3939,6 @@ packages:
|
|||||||
|
|
||||||
/@types/qs@6.9.13:
|
/@types/qs@6.9.13:
|
||||||
resolution: {integrity: sha512-iLR+1vTTJ3p0QaOUq6ACbY1mzKTODFDT/XedZI8BksOotFmL4ForwDfRQ/DZeuTHR7/2i4lI1D203gdfxuqTlA==}
|
resolution: {integrity: sha512-iLR+1vTTJ3p0QaOUq6ACbY1mzKTODFDT/XedZI8BksOotFmL4ForwDfRQ/DZeuTHR7/2i4lI1D203gdfxuqTlA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/range-parser@1.2.7:
|
/@types/range-parser@1.2.7:
|
||||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||||
@@ -4245,6 +4404,10 @@ packages:
|
|||||||
deprecated: Use your platform's native atob() and btoa() methods instead
|
deprecated: Use your platform's native atob() and btoa() methods instead
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/abbrev@1.1.1:
|
||||||
|
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/accepts@1.3.8:
|
/accepts@1.3.8:
|
||||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@@ -4372,6 +4535,35 @@ packages:
|
|||||||
uri-js: 4.4.1
|
uri-js: 4.4.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/algoliasearch-helper@3.21.0(algoliasearch@4.23.3):
|
||||||
|
resolution: {integrity: sha512-hjVOrL15I3Y3K8xG0icwG1/tWE+MocqBrhW6uVBWpU+/kVEMK0BnM2xdssj6mZM61eJ4iRxHR0djEI3ENOpR8w==}
|
||||||
|
peerDependencies:
|
||||||
|
algoliasearch: '>= 3.1 < 6'
|
||||||
|
dependencies:
|
||||||
|
'@algolia/events': 4.0.1
|
||||||
|
algoliasearch: 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/algoliasearch@4.23.3:
|
||||||
|
resolution: {integrity: sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==}
|
||||||
|
dependencies:
|
||||||
|
'@algolia/cache-browser-local-storage': 4.23.3
|
||||||
|
'@algolia/cache-common': 4.23.3
|
||||||
|
'@algolia/cache-in-memory': 4.23.3
|
||||||
|
'@algolia/client-account': 4.23.3
|
||||||
|
'@algolia/client-analytics': 4.23.3
|
||||||
|
'@algolia/client-common': 4.23.3
|
||||||
|
'@algolia/client-personalization': 4.23.3
|
||||||
|
'@algolia/client-search': 4.23.3
|
||||||
|
'@algolia/logger-common': 4.23.3
|
||||||
|
'@algolia/logger-console': 4.23.3
|
||||||
|
'@algolia/recommend': 4.23.3
|
||||||
|
'@algolia/requester-browser-xhr': 4.23.3
|
||||||
|
'@algolia/requester-common': 4.23.3
|
||||||
|
'@algolia/requester-node-http': 4.23.3
|
||||||
|
'@algolia/transporter': 4.23.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ansi-escapes@4.3.2:
|
/ansi-escapes@4.3.2:
|
||||||
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -5242,6 +5434,14 @@ packages:
|
|||||||
- ts-node
|
- ts-node
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/cross-fetch@3.1.8:
|
||||||
|
resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==}
|
||||||
|
dependencies:
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cross-fetch@4.0.0:
|
/cross-fetch@4.0.0:
|
||||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5973,6 +6173,11 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/escape-string-regexp@5.0.0:
|
||||||
|
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/escodegen@2.1.0:
|
/escodegen@2.1.0:
|
||||||
resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
|
resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -6962,7 +7167,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/hast-util-parse-selector@4.0.0:
|
/hast-util-parse-selector@4.0.0:
|
||||||
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
|
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
|
||||||
@@ -7031,6 +7235,15 @@ packages:
|
|||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/hast-util-to-text@4.0.2:
|
||||||
|
resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
'@types/unist': 3.0.2
|
||||||
|
hast-util-is-element: 3.0.0
|
||||||
|
unist-util-find-after: 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/hast-util-whitespace@3.0.0:
|
/hast-util-whitespace@3.0.0:
|
||||||
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7047,6 +7260,19 @@ packages:
|
|||||||
space-separated-tokens: 2.0.2
|
space-separated-tokens: 2.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/highlight.js@11.9.0:
|
||||||
|
resolution: {integrity: sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/hogan.js@3.0.2:
|
||||||
|
resolution: {integrity: sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
mkdirp: 0.3.0
|
||||||
|
nopt: 1.0.10
|
||||||
|
dev: false
|
||||||
|
|
||||||
/hoist-non-react-statics@3.3.2:
|
/hoist-non-react-statics@3.3.2:
|
||||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7057,6 +7283,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/htm@3.1.1:
|
||||||
|
resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/html-encoding-sniffer@3.0.0:
|
/html-encoding-sniffer@3.0.0:
|
||||||
resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
|
resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -7218,6 +7448,32 @@ packages:
|
|||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/instantsearch-ui-components@0.6.0:
|
||||||
|
resolution: {integrity: sha512-Jj3F9D46ef8VtzVZTgWsy79P25Q5nhI5XzK0NqfUVVI5yI3vA/3NkvKYtBHBlz50DDyBm6t9kIn/ZfpOwENm2A==}
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.24.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/instantsearch.js@4.71.1(algoliasearch@4.23.3):
|
||||||
|
resolution: {integrity: sha512-4AvEPadnDBf0NsCCw+a1GjmMFEZ3zQzQhCe51cFPLYRXnRyKw5bLvRVaNQckiDG+vl7bPyJrWn5YAh5UhBwA+w==}
|
||||||
|
peerDependencies:
|
||||||
|
algoliasearch: '>= 3.1 < 6'
|
||||||
|
dependencies:
|
||||||
|
'@algolia/events': 4.0.1
|
||||||
|
'@types/dom-speech-recognition': 0.0.1
|
||||||
|
'@types/google.maps': 3.55.10
|
||||||
|
'@types/hogan.js': 3.0.5
|
||||||
|
'@types/qs': 6.9.13
|
||||||
|
algoliasearch: 4.23.3
|
||||||
|
algoliasearch-helper: 3.21.0(algoliasearch@4.23.3)
|
||||||
|
hogan.js: 3.0.2
|
||||||
|
htm: 3.1.1
|
||||||
|
instantsearch-ui-components: 0.6.0
|
||||||
|
preact: 10.22.0
|
||||||
|
qs: 6.9.7
|
||||||
|
search-insights: 2.14.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/internal-slot@1.0.7:
|
/internal-slot@1.0.7:
|
||||||
resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
|
resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -8348,6 +8604,14 @@ packages:
|
|||||||
get-func-name: 2.0.2
|
get-func-name: 2.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/lowlight@3.1.0:
|
||||||
|
resolution: {integrity: sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
devlop: 1.1.0
|
||||||
|
highlight.js: 11.9.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lru-cache@10.2.0:
|
/lru-cache@10.2.0:
|
||||||
resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==}
|
resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==}
|
||||||
engines: {node: 14 || >=16.14}
|
engines: {node: 14 || >=16.14}
|
||||||
@@ -8425,6 +8689,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==}
|
resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/markdown-table@3.0.3:
|
||||||
|
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/markdown-to-jsx@7.3.2(react@18.2.0):
|
/markdown-to-jsx@7.3.2(react@18.2.0):
|
||||||
resolution: {integrity: sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==}
|
resolution: {integrity: sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
@@ -8434,6 +8702,15 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mdast-util-find-and-replace@3.0.1:
|
||||||
|
resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
escape-string-regexp: 5.0.0
|
||||||
|
unist-util-is: 6.0.0
|
||||||
|
unist-util-visit-parents: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mdast-util-from-markdown@2.0.0:
|
/mdast-util-from-markdown@2.0.0:
|
||||||
resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==}
|
resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8453,6 +8730,75 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm-autolink-literal@2.0.0:
|
||||||
|
resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
ccount: 2.0.1
|
||||||
|
devlop: 1.1.0
|
||||||
|
mdast-util-find-and-replace: 3.0.1
|
||||||
|
micromark-util-character: 2.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm-footnote@2.0.0:
|
||||||
|
resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
devlop: 1.1.0
|
||||||
|
mdast-util-from-markdown: 2.0.0
|
||||||
|
mdast-util-to-markdown: 2.1.0
|
||||||
|
micromark-util-normalize-identifier: 2.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm-strikethrough@2.0.0:
|
||||||
|
resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
mdast-util-from-markdown: 2.0.0
|
||||||
|
mdast-util-to-markdown: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm-table@2.0.0:
|
||||||
|
resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
devlop: 1.1.0
|
||||||
|
markdown-table: 3.0.3
|
||||||
|
mdast-util-from-markdown: 2.0.0
|
||||||
|
mdast-util-to-markdown: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm-task-list-item@2.0.0:
|
||||||
|
resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
devlop: 1.1.0
|
||||||
|
mdast-util-from-markdown: 2.0.0
|
||||||
|
mdast-util-to-markdown: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/mdast-util-gfm@3.0.0:
|
||||||
|
resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==}
|
||||||
|
dependencies:
|
||||||
|
mdast-util-from-markdown: 2.0.0
|
||||||
|
mdast-util-gfm-autolink-literal: 2.0.0
|
||||||
|
mdast-util-gfm-footnote: 2.0.0
|
||||||
|
mdast-util-gfm-strikethrough: 2.0.0
|
||||||
|
mdast-util-gfm-table: 2.0.0
|
||||||
|
mdast-util-gfm-task-list-item: 2.0.0
|
||||||
|
mdast-util-to-markdown: 2.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mdast-util-phrasing@4.1.0:
|
/mdast-util-phrasing@4.1.0:
|
||||||
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
|
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8498,6 +8844,14 @@ packages:
|
|||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/meilisearch@0.40.0:
|
||||||
|
resolution: {integrity: sha512-BoRhQMr2mBFLEeCfsvPluksGb01IaOiWvV3Deu3iEY+yYJ4jdGTu+IQi5FCjKlNQ7/TMWSN2XUToSgvH1tj0BQ==}
|
||||||
|
dependencies:
|
||||||
|
cross-fetch: 3.1.8
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
dev: false
|
||||||
|
|
||||||
/memoizee@0.4.15:
|
/memoizee@0.4.15:
|
||||||
resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==}
|
resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8556,6 +8910,78 @@ packages:
|
|||||||
micromark-util-types: 2.0.0
|
micromark-util-types: 2.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-autolink-literal@2.0.0:
|
||||||
|
resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==}
|
||||||
|
dependencies:
|
||||||
|
micromark-util-character: 2.1.0
|
||||||
|
micromark-util-sanitize-uri: 2.0.0
|
||||||
|
micromark-util-symbol: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-footnote@2.0.0:
|
||||||
|
resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==}
|
||||||
|
dependencies:
|
||||||
|
devlop: 1.1.0
|
||||||
|
micromark-core-commonmark: 2.0.0
|
||||||
|
micromark-factory-space: 2.0.0
|
||||||
|
micromark-util-character: 2.1.0
|
||||||
|
micromark-util-normalize-identifier: 2.0.0
|
||||||
|
micromark-util-sanitize-uri: 2.0.0
|
||||||
|
micromark-util-symbol: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-strikethrough@2.0.0:
|
||||||
|
resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==}
|
||||||
|
dependencies:
|
||||||
|
devlop: 1.1.0
|
||||||
|
micromark-util-chunked: 2.0.0
|
||||||
|
micromark-util-classify-character: 2.0.0
|
||||||
|
micromark-util-resolve-all: 2.0.0
|
||||||
|
micromark-util-symbol: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-table@2.0.0:
|
||||||
|
resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==}
|
||||||
|
dependencies:
|
||||||
|
devlop: 1.1.0
|
||||||
|
micromark-factory-space: 2.0.0
|
||||||
|
micromark-util-character: 2.1.0
|
||||||
|
micromark-util-symbol: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-tagfilter@2.0.0:
|
||||||
|
resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
|
||||||
|
dependencies:
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm-task-list-item@2.0.1:
|
||||||
|
resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==}
|
||||||
|
dependencies:
|
||||||
|
devlop: 1.1.0
|
||||||
|
micromark-factory-space: 2.0.0
|
||||||
|
micromark-util-character: 2.1.0
|
||||||
|
micromark-util-symbol: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/micromark-extension-gfm@3.0.0:
|
||||||
|
resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
|
||||||
|
dependencies:
|
||||||
|
micromark-extension-gfm-autolink-literal: 2.0.0
|
||||||
|
micromark-extension-gfm-footnote: 2.0.0
|
||||||
|
micromark-extension-gfm-strikethrough: 2.0.0
|
||||||
|
micromark-extension-gfm-table: 2.0.0
|
||||||
|
micromark-extension-gfm-tagfilter: 2.0.0
|
||||||
|
micromark-extension-gfm-task-list-item: 2.0.1
|
||||||
|
micromark-util-combine-extensions: 2.0.0
|
||||||
|
micromark-util-types: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/micromark-factory-destination@2.0.0:
|
/micromark-factory-destination@2.0.0:
|
||||||
resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
|
resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8813,6 +9239,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mkdirp@0.3.0:
|
||||||
|
resolution: {integrity: sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==}
|
||||||
|
deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mkdirp@1.0.4:
|
/mkdirp@1.0.4:
|
||||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -8886,6 +9317,13 @@ packages:
|
|||||||
/node-releases@2.0.14:
|
/node-releases@2.0.14:
|
||||||
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
||||||
|
|
||||||
|
/nopt@1.0.10:
|
||||||
|
resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
abbrev: 1.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/normalize-package-data@2.5.0:
|
/normalize-package-data@2.5.0:
|
||||||
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9357,6 +9795,10 @@ packages:
|
|||||||
source-map-js: 1.2.0
|
source-map-js: 1.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/preact@10.22.0:
|
||||||
|
resolution: {integrity: sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/prelude-ls@1.2.1:
|
/prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -9498,6 +9940,11 @@ packages:
|
|||||||
side-channel: 1.0.6
|
side-channel: 1.0.6
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/qs@6.9.7:
|
||||||
|
resolution: {integrity: sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/querystringify@2.2.0:
|
/querystringify@2.2.0:
|
||||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -9582,6 +10029,36 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
||||||
|
/react-instantsearch-core@7.11.1(algoliasearch@4.23.3)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-FsfEvefr3AZtsN4NYLxrqWFvzlrR73ejNX9f/1NBDERxaM+dZFKRfWpRXrA1QSwFeAppRmyC5+TMmga8OK8M0g==}
|
||||||
|
peerDependencies:
|
||||||
|
algoliasearch: '>= 3.1 < 5'
|
||||||
|
react: '>= 16.8.0 < 19'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.24.1
|
||||||
|
algoliasearch: 4.23.3
|
||||||
|
algoliasearch-helper: 3.21.0(algoliasearch@4.23.3)
|
||||||
|
instantsearch.js: 4.71.1(algoliasearch@4.23.3)
|
||||||
|
react: 18.2.0
|
||||||
|
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/react-instantsearch@7.11.1(algoliasearch@4.23.3)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-XiCH2SfifJAk5kfdT1Mi3HxX3MzeJL72oF1kUltgmD7fqEi8HsK+vn2wGxAvSGhuLzltV2Lg3xIXd4OAocjeWA==}
|
||||||
|
peerDependencies:
|
||||||
|
algoliasearch: '>= 3.1 < 5'
|
||||||
|
react: '>= 16.8.0 < 19'
|
||||||
|
react-dom: '>= 16.8.0 < 19'
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.24.1
|
||||||
|
algoliasearch: 4.23.3
|
||||||
|
instantsearch-ui-components: 0.6.0
|
||||||
|
instantsearch.js: 4.71.1(algoliasearch@4.23.3)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
react-instantsearch-core: 7.11.1(algoliasearch@4.23.3)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-is@16.13.1:
|
/react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
@@ -9904,6 +10381,23 @@ packages:
|
|||||||
unist-util-visit: 5.0.0
|
unist-util-visit: 5.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/rehype-highlight@7.0.0:
|
||||||
|
resolution: {integrity: sha512-QtobgRgYoQaK6p1eSr2SD1i61f7bjF2kZHAQHxeCHAuJf7ZUDMvQ7owDq9YTkmar5m5TSUol+2D3bp3KfJf/oA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-to-text: 4.0.2
|
||||||
|
lowlight: 3.1.0
|
||||||
|
unist-util-visit: 5.0.0
|
||||||
|
vfile: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/rehype-sanitize@6.0.0:
|
||||||
|
resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-sanitize: 5.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/rehype-slug@6.0.0:
|
/rehype-slug@6.0.0:
|
||||||
resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
|
resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9914,6 +10408,27 @@ packages:
|
|||||||
unist-util-visit: 5.0.0
|
unist-util-visit: 5.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/rehype-stringify@10.0.0:
|
||||||
|
resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-to-html: 9.0.0
|
||||||
|
unified: 11.0.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/remark-gfm@4.0.0:
|
||||||
|
resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
mdast-util-gfm: 3.0.0
|
||||||
|
micromark-extension-gfm: 3.0.0
|
||||||
|
remark-parse: 11.0.0
|
||||||
|
remark-stringify: 11.0.0
|
||||||
|
unified: 11.0.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/remark-html@16.0.1:
|
/remark-html@16.0.1:
|
||||||
resolution: {integrity: sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==}
|
resolution: {integrity: sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9935,6 +10450,16 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/remark-rehype@11.1.0:
|
||||||
|
resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==}
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
'@types/mdast': 4.0.3
|
||||||
|
mdast-util-to-hast: 13.1.0
|
||||||
|
unified: 11.0.4
|
||||||
|
vfile: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/remark-stringify@11.0.0:
|
/remark-stringify@11.0.0:
|
||||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9943,17 +10468,6 @@ packages:
|
|||||||
unified: 11.0.4
|
unified: 11.0.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/remark@15.0.1:
|
|
||||||
resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.3
|
|
||||||
remark-parse: 11.0.0
|
|
||||||
remark-stringify: 11.0.0
|
|
||||||
unified: 11.0.4
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/require-directory@2.1.1:
|
/require-directory@2.1.1:
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -10139,6 +10653,10 @@ packages:
|
|||||||
ajv-keywords: 5.1.0(ajv@8.12.0)
|
ajv-keywords: 5.1.0(ajv@8.12.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/search-insights@2.14.0:
|
||||||
|
resolution: {integrity: sha512-OLN6MsPMCghDOqlCtsIsYgtsC0pnwVTyT9Mu6A3ewOj1DxvzZF6COrn2g86E/c05xbktB0XN04m/t1Z+n+fTGw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/semver@5.7.2:
|
/semver@5.7.2:
|
||||||
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
|
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -11041,6 +11559,13 @@ packages:
|
|||||||
crypto-random-string: 2.0.0
|
crypto-random-string: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/unist-util-find-after@5.0.0:
|
||||||
|
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/unist': 3.0.2
|
||||||
|
unist-util-is: 6.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/unist-util-is@6.0.0:
|
/unist-util-is@6.0.0:
|
||||||
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
export default {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
"postcss-preset-mantine": {},
|
"postcss-preset-mantine": {},
|
||||||
"postcss-simple-vars": {
|
"postcss-simple-vars": {
|
||||||
1
public/_redirects
Normal file
1
public/_redirects
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* /index.html 200
|
||||||
19
src/component/Hits/Hits.module.css
Normal file
19
src/component/Hits/Hits.module.css
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
.img-wrapper{
|
||||||
|
column-count: 3;
|
||||||
|
column-gap: 10px;
|
||||||
|
|
||||||
|
counter-reset: count;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
@media (max-width: $mantine-breakpoint-md) {
|
||||||
|
column-count: 2;
|
||||||
|
}
|
||||||
|
@media (max-width: $mantine-breakpoint-sm) {
|
||||||
|
column-count: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&>div{
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/component/Hits/Hits.tsx
Normal file
17
src/component/Hits/Hits.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Box } from "@mantine/core";
|
||||||
|
import { useHits, UseHitsProps } from "react-instantsearch";
|
||||||
|
import { ParagraphCard } from "../ParagraphCard/ParagraphCard";
|
||||||
|
import styles from "./Hits.module.css";
|
||||||
|
|
||||||
|
export default function Hits(props: UseHitsProps<Paragraph>) {
|
||||||
|
const { results } = useHits(props);
|
||||||
|
return (
|
||||||
|
<Box className={styles["img-wrapper"]}>
|
||||||
|
{results?.hits?.map((hit) => (
|
||||||
|
<Box key={hit.id}>
|
||||||
|
<ParagraphCard {...hit} key={`paragraph-card-${hit.id}`} />
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/component/Pagination/Pagination.tsx
Normal file
18
src/component/Pagination/Pagination.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Center, Group, Pagination as MantinePagination } from "@mantine/core";
|
||||||
|
import { usePagination, UsePaginationProps } from "react-instantsearch";
|
||||||
|
|
||||||
|
export default function Pagination(props: UsePaginationProps) {
|
||||||
|
const { currentRefinement, nbPages, refine } = usePagination(props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Center>
|
||||||
|
<Group>
|
||||||
|
<MantinePagination
|
||||||
|
total={nbPages}
|
||||||
|
value={currentRefinement + 1}
|
||||||
|
onChange={(value) => refine(value - 1)}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</Center>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,47 +8,33 @@ dayjs.extend(relativeTime);
|
|||||||
export function ParagraphCard({
|
export function ParagraphCard({
|
||||||
cover,
|
cover,
|
||||||
title,
|
title,
|
||||||
"@timestamp": time,
|
time,
|
||||||
author,
|
author,
|
||||||
tags,
|
tags,
|
||||||
_id,
|
id,
|
||||||
}: Paragraph) {
|
}: Paragraph) {
|
||||||
const url = `/paragraph/${_id}`;
|
const url = `/paragraph/${id}`;
|
||||||
return (
|
return (
|
||||||
<Card withBorder radius="md" padding="lg" shadow="sm">
|
<Card withBorder radius="md" padding="lg" shadow="sm">
|
||||||
<Card.Section>
|
<Card.Section>
|
||||||
<Link to={url}>
|
<Link to={url} target="_blank">
|
||||||
{cover && <Image src={cover} height={140} width={140} />}
|
{cover && <Image src={cover} height={140} width={140} />}
|
||||||
</Link>
|
</Link>
|
||||||
</Card.Section>
|
</Card.Section>
|
||||||
<Group justify="space-between" mt="md" mb="xs">
|
<Group justify="space-between" mt="md" mb="xs">
|
||||||
<Text component={Link} to={url}>
|
<Text component={Link} to={url} target="_blank">
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
<Group>
|
<Group>
|
||||||
{tags.map((tag, index) => (
|
{tags.map((tag, index) => (
|
||||||
<>
|
<Badge key={index}>{tag}</Badge>
|
||||||
<Badge
|
|
||||||
component={Link}
|
|
||||||
key={index}
|
|
||||||
to={`/tag/${encodeURIComponent(tag)}`}
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</Badge>
|
|
||||||
</>
|
|
||||||
))}
|
))}
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<Group>
|
<Group>
|
||||||
<Text
|
<Text size="xs">{author}</Text>
|
||||||
size="xs"
|
|
||||||
component={Link}
|
|
||||||
to={`/author/${encodeURIComponent(author)}`}
|
|
||||||
>
|
|
||||||
{author}
|
|
||||||
</Text>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Text size="xs" c="dimmed">
|
<Text size="xs" c="dimmed">
|
||||||
•
|
•
|
||||||
|
|||||||
123
src/component/Refinement/Refinement.tsx
Normal file
123
src/component/Refinement/Refinement.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { SourceLabelMap } from "@/constants";
|
||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Box,
|
||||||
|
CheckIcon,
|
||||||
|
ComboboxItem,
|
||||||
|
ComboboxLikeRenderOptionInput,
|
||||||
|
Group,
|
||||||
|
MultiSelect,
|
||||||
|
rem,
|
||||||
|
Select,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import {
|
||||||
|
useHitsPerPage,
|
||||||
|
useRefinementList,
|
||||||
|
useSortBy,
|
||||||
|
} from "react-instantsearch";
|
||||||
|
|
||||||
|
const sortItems = [{ value: "paragraph:time:desc", label: "Newest" }];
|
||||||
|
const hitsPerPageItems = [
|
||||||
|
{ value: 20, label: "20", default: true },
|
||||||
|
{ value: 40, label: "40" },
|
||||||
|
{ value: 60, label: "60" },
|
||||||
|
{ value: 100, label: "100" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Refinement() {
|
||||||
|
const { items, refine } = useRefinementList({ attribute: "source" });
|
||||||
|
const { currentRefinement, refine: refineSortBy } = useSortBy({
|
||||||
|
items: sortItems,
|
||||||
|
});
|
||||||
|
const hitsPerPage = useHitsPerPage({
|
||||||
|
items: hitsPerPageItems,
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentVal = items
|
||||||
|
.filter((item) => item.isRefined)
|
||||||
|
.map((item) => item.value);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
refineSortBy(sortItems[0].value);
|
||||||
|
}, [refineSortBy]);
|
||||||
|
|
||||||
|
function SelectItem(props: ComboboxLikeRenderOptionInput<ComboboxItem>) {
|
||||||
|
return (
|
||||||
|
<Group justify="space-between" w="100%">
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
gap: "0.5em",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{currentVal.includes(props.option.value) && (
|
||||||
|
<CheckIcon
|
||||||
|
style={{
|
||||||
|
opacity: "0.4",
|
||||||
|
width: "0.8em",
|
||||||
|
minWidth: "0.8em",
|
||||||
|
height: "0.8em",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{props.option.label}
|
||||||
|
</Box>
|
||||||
|
<Badge>
|
||||||
|
{items.find((item) => item.value === props.option.value)?.count}
|
||||||
|
</Badge>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Group justify="space-between" align="center" my="md">
|
||||||
|
<Group>
|
||||||
|
<Select
|
||||||
|
data={sortItems}
|
||||||
|
value={currentRefinement}
|
||||||
|
defaultValue={sortItems[0].value}
|
||||||
|
onChange={(value) => value && refineSortBy(value)}
|
||||||
|
label="Sort by"
|
||||||
|
/>
|
||||||
|
<MultiSelect
|
||||||
|
styles={{
|
||||||
|
wrapper: {
|
||||||
|
width: rem(300),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={items.map((item) => ({
|
||||||
|
value: item.label,
|
||||||
|
label: SourceLabelMap[item.label],
|
||||||
|
}))}
|
||||||
|
renderOption={SelectItem}
|
||||||
|
value={currentVal}
|
||||||
|
label="Source"
|
||||||
|
clearable
|
||||||
|
onChange={(values) => {
|
||||||
|
console.log(values);
|
||||||
|
const old = new Set(currentVal);
|
||||||
|
const new_ = new Set(values);
|
||||||
|
const diff = old.difference(new_).union(new_.difference(old));
|
||||||
|
diff.forEach((value) => refine(value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<Group w={rem(96)}>
|
||||||
|
<Select
|
||||||
|
data={hitsPerPageItems.map((item) => ({
|
||||||
|
value: item.value.toString(),
|
||||||
|
label: item.label.toString(),
|
||||||
|
}))}
|
||||||
|
value={hitsPerPage.items
|
||||||
|
.find((item) => item.isRefined)
|
||||||
|
?.value.toString()}
|
||||||
|
onChange={(value) => value && hitsPerPage.refine(parseInt(value))}
|
||||||
|
label="Hits per page"
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
25
src/component/ScrollTop/ScrollTop.tsx
Normal file
25
src/component/ScrollTop/ScrollTop.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { Affix, Button, rem, Transition } from "@mantine/core";
|
||||||
|
import { useWindowScroll } from "@mantine/hooks";
|
||||||
|
import { IconArrowUp } from "@tabler/icons-react";
|
||||||
|
|
||||||
|
export default function ScrollTop() {
|
||||||
|
const [scroll, scrollTo] = useWindowScroll();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Affix position={{ bottom: 20, right: 20 }}>
|
||||||
|
<Transition transition="slide-up" mounted={scroll.y > 0}>
|
||||||
|
{(transitionStyles) => (
|
||||||
|
<Button
|
||||||
|
leftSection={
|
||||||
|
<IconArrowUp style={{ width: rem(16), height: rem(16) }} />
|
||||||
|
}
|
||||||
|
style={transitionStyles}
|
||||||
|
onClick={() => scrollTo({ y: 0 })}
|
||||||
|
>
|
||||||
|
Scroll to top
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
|
</Affix>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
src/component/SearchBox/SearchBox.tsx
Normal file
43
src/component/SearchBox/SearchBox.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { rem, TextInput } from "@mantine/core";
|
||||||
|
import { IconSearch } from "@tabler/icons-react";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { useSearchBox, UseSearchBoxProps } from "react-instantsearch";
|
||||||
|
|
||||||
|
export default function SearchBox(props: UseSearchBoxProps) {
|
||||||
|
const { query, refine } = useSearchBox(props);
|
||||||
|
const [inputValue, setInputValue] = useState(query);
|
||||||
|
|
||||||
|
const setQuery = useCallback(
|
||||||
|
(value: string) => {
|
||||||
|
setInputValue(value);
|
||||||
|
refine(value);
|
||||||
|
},
|
||||||
|
[refine, setInputValue],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
placeholder="Search"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
type="search"
|
||||||
|
leftSection={
|
||||||
|
<IconSearch
|
||||||
|
style={{ width: rem(16), height: rem(16) }}
|
||||||
|
stroke={1.5}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={inputValue}
|
||||||
|
onChange={(event) => setQuery(event.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
src/constants.ts
Normal file
9
src/constants.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export const SourceLabelMap: Record<string, string> = {
|
||||||
|
tttang: "跳跳糖",
|
||||||
|
secin: "Sec-In",
|
||||||
|
seebug: "Seebug",
|
||||||
|
wechat: "微信公众号",
|
||||||
|
xianzhi: "先知",
|
||||||
|
anquanke: "安全客",
|
||||||
|
freebuf: "FreeBuf",
|
||||||
|
};
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import { notifications } from "@mantine/notifications";
|
|
||||||
import axios, { AxiosResponse } from "axios";
|
|
||||||
import { merge } from "lodash";
|
|
||||||
|
|
||||||
export interface PaginationParams {
|
|
||||||
skip?: number;
|
|
||||||
take?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const api = axios.create({
|
|
||||||
withCredentials: false,
|
|
||||||
auth: {
|
|
||||||
username: "viewer",
|
|
||||||
password: "publicviewer1",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
api.interceptors.response.use(
|
|
||||||
(value: AxiosResponse<any, any>) => {
|
|
||||||
if (value.data.error) {
|
|
||||||
notifications.show({
|
|
||||||
title: "API Error on " + value.config.url,
|
|
||||||
message: value.data.error,
|
|
||||||
color: "red",
|
|
||||||
autoClose: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
const value: AxiosResponse<any, any> = error.response;
|
|
||||||
if (value.data.status !== 200) {
|
|
||||||
notifications.show({
|
|
||||||
title: "API Error on " + value.config.url,
|
|
||||||
message: JSON.stringify(value.data),
|
|
||||||
color: "red",
|
|
||||||
autoClose: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export class SearchApi {
|
|
||||||
static async search(
|
|
||||||
baseUrl: string,
|
|
||||||
query: ZincQueryForSDK,
|
|
||||||
): Promise<SearchResponse> {
|
|
||||||
const { data } = await api.post(
|
|
||||||
new URL("/api/paragraph/_search", baseUrl).toString(),
|
|
||||||
query,
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
static wrapParagraph(s3Url: string, paragraph: Paragraph) {
|
|
||||||
const RE = /https:\/\/s3\.yoshino-s\.xyz/g;
|
|
||||||
if (paragraph.cover) {
|
|
||||||
paragraph.cover = paragraph.cover.replace(RE, s3Url);
|
|
||||||
}
|
|
||||||
paragraph.content = paragraph.content?.replace(RE, s3Url);
|
|
||||||
|
|
||||||
return paragraph;
|
|
||||||
}
|
|
||||||
static async getParagraph(baseUrl: string, id: string) {
|
|
||||||
const { data } = await api.get(
|
|
||||||
new URL(`/api/paragraph/_doc/${id}`, baseUrl).toString(),
|
|
||||||
);
|
|
||||||
return merge(data._source, {
|
|
||||||
_id: data._id,
|
|
||||||
"@timestamp": data["@timestamp"],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import { Pagination } from "@mantine/core";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useSearchParams } from "react-router-dom";
|
|
||||||
|
|
||||||
import { useOptionsState } from "@/store/module/options";
|
|
||||||
import { useDebounceCallback, useMediaQuery } from "@mantine/hooks";
|
|
||||||
import { merge } from "lodash";
|
|
||||||
import { SearchApi } from "./api";
|
|
||||||
|
|
||||||
export function usePaginationData<T>(query: ZincQueryForSDK) {
|
|
||||||
const [params, setParams] = useSearchParams({
|
|
||||||
page: "1",
|
|
||||||
size: "10",
|
|
||||||
});
|
|
||||||
const { state: options } = useOptionsState();
|
|
||||||
const [total, setTotal] = useState(0);
|
|
||||||
const [data, setData] = useState<T[]>([]);
|
|
||||||
const [take, _] = useState(parseInt(params.get("size") || "10"));
|
|
||||||
const [page, setPage] = useState(parseInt(params.get("page") || "1"));
|
|
||||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
||||||
|
|
||||||
const update = useDebounceCallback(async function update() {
|
|
||||||
console.log("query", query, page, take, options);
|
|
||||||
const resp = await SearchApi.search(
|
|
||||||
options.zincsearchUrl,
|
|
||||||
merge(
|
|
||||||
{
|
|
||||||
search_type: "matchall",
|
|
||||||
sort_fields: ["-@timestamp"],
|
|
||||||
_source: ["title", "cover", "author", "tags"],
|
|
||||||
},
|
|
||||||
query,
|
|
||||||
{
|
|
||||||
from: (page - 1) * take,
|
|
||||||
max_results: take,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setTotal(resp.hits.total.value);
|
|
||||||
setData(
|
|
||||||
resp.hits.hits.map((hit) =>
|
|
||||||
SearchApi.wrapParagraph(
|
|
||||||
options.s3Url,
|
|
||||||
merge({ _id: hit._id, "@timestamp": hit["@timestamp"] }, hit._source),
|
|
||||||
),
|
|
||||||
) as T[],
|
|
||||||
);
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
useEffect(update, [query, page, take, options, update]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setParams({
|
|
||||||
size: take.toString(),
|
|
||||||
page: page.toString(),
|
|
||||||
});
|
|
||||||
}, [take, page, setParams]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
data,
|
|
||||||
page,
|
|
||||||
pagination: (
|
|
||||||
<Pagination
|
|
||||||
size={isMobile ? "sm" : "md"}
|
|
||||||
total={Math.ceil(total / take)}
|
|
||||||
onChange={setPage}
|
|
||||||
value={page}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,55 +1,69 @@
|
|||||||
|
import SearchBox from "@/component/SearchBox/SearchBox";
|
||||||
import {
|
import {
|
||||||
Affix,
|
|
||||||
AppShell,
|
AppShell,
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
|
||||||
Center,
|
Center,
|
||||||
Group,
|
Group,
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Transition,
|
|
||||||
UnstyledButton,
|
|
||||||
rem,
|
rem,
|
||||||
|
UnstyledButton,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { Suspense, useCallback, useState } from "react";
|
import { Suspense, useEffect, useState } from "react";
|
||||||
import { Outlet, useNavigate } from "react-router";
|
import { Outlet, useLocation } from "react-router";
|
||||||
|
|
||||||
import { TitleContext } from "@/component/Header/Header";
|
import ScrollTop from "@/component/ScrollTop/ScrollTop";
|
||||||
import Loading from "@/page/Loading";
|
import Loading from "@/page/Loading";
|
||||||
|
|
||||||
import { useForm } from "@mantine/form";
|
import { useHeadroom } from "@mantine/hooks";
|
||||||
import { useHeadroom, useMediaQuery, useWindowScroll } from "@mantine/hooks";
|
import { IconSettings } from "@tabler/icons-react";
|
||||||
import { IconArrowUp, IconSearch, IconSettings } from "@tabler/icons-react";
|
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import { useAppSelector } from "@/store";
|
||||||
|
import {
|
||||||
|
instantMeiliSearch,
|
||||||
|
InstantMeiliSearchInstance,
|
||||||
|
} from "@meilisearch/instant-meilisearch";
|
||||||
|
import { InstantSearch } from "react-instantsearch";
|
||||||
|
|
||||||
|
import { singleIndex } from "instantsearch.js/es/lib/stateMappings";
|
||||||
|
|
||||||
export default function MainLayout() {
|
export default function MainLayout() {
|
||||||
const [title, setTitle] = useState("");
|
|
||||||
const pinned = useHeadroom({ fixedAt: 60 });
|
const pinned = useHeadroom({ fixedAt: 60 });
|
||||||
|
const selector = useAppSelector((state) => state.options);
|
||||||
|
|
||||||
const [scroll, scrollTo] = useWindowScroll();
|
const path = useLocation().pathname;
|
||||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const isSearchPage = path === "/";
|
||||||
|
|
||||||
const form = useForm({
|
const [searchClient, setSearchClient] =
|
||||||
initialValues: {
|
useState<InstantMeiliSearchInstance>();
|
||||||
search: "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const search = useCallback(
|
useEffect(() => {
|
||||||
function submit({ search }: { search: string }) {
|
const { meilisearchUrl, meilisearchToken } = selector;
|
||||||
console.log(search);
|
const { searchClient } = instantMeiliSearch(
|
||||||
navigate(`/search/${encodeURIComponent(search)}`);
|
meilisearchUrl,
|
||||||
},
|
meilisearchToken,
|
||||||
[navigate],
|
{
|
||||||
);
|
finitePagination: true,
|
||||||
|
meiliSearchParams: {
|
||||||
|
hybrid: {},
|
||||||
|
attributesToRetrieve: [
|
||||||
|
"cover",
|
||||||
|
"title",
|
||||||
|
"time",
|
||||||
|
"author",
|
||||||
|
"tags",
|
||||||
|
"id",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
setSearchClient(searchClient);
|
||||||
|
}, [selector, setSearchClient]);
|
||||||
|
|
||||||
return (
|
const shell = (
|
||||||
<TitleContext.Provider value={[title, setTitle]}>
|
<>
|
||||||
<AppShell
|
<AppShell
|
||||||
header={{ height: 60, collapsed: !pinned, offset: false }}
|
header={{ height: 60, collapsed: !pinned, offset: false }}
|
||||||
padding="md"
|
|
||||||
h="100vh"
|
h="100vh"
|
||||||
>
|
>
|
||||||
<AppShell.Header>
|
<AppShell.Header>
|
||||||
@@ -58,26 +72,9 @@ export default function MainLayout() {
|
|||||||
<Avatar fw={700} component={Link} to="/">
|
<Avatar fw={700} component={Link} to="/">
|
||||||
DS
|
DS
|
||||||
</Avatar>
|
</Avatar>
|
||||||
{!isMobile && (
|
|
||||||
<Text size="lg" fw={700} ml="sm">
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<form onSubmit={form.onSubmit(search)}>
|
{isSearchPage && <SearchBox />}
|
||||||
<TextInput
|
|
||||||
placeholder="Search"
|
|
||||||
{...form.getInputProps("search")}
|
|
||||||
leftSection={
|
|
||||||
<IconSearch
|
|
||||||
style={{ width: rem(16), height: rem(16) }}
|
|
||||||
stroke={1.5}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
<UnstyledButton component={Link} to="/settings">
|
<UnstyledButton component={Link} to="/settings">
|
||||||
<Center>
|
<Center>
|
||||||
<IconSettings />
|
<IconSettings />
|
||||||
@@ -92,21 +89,26 @@ export default function MainLayout() {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
</AppShell.Main>
|
</AppShell.Main>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
<Affix position={{ bottom: 20, right: 20 }}>
|
<ScrollTop />
|
||||||
<Transition transition="slide-up" mounted={scroll.y > 0}>
|
</>
|
||||||
{(transitionStyles) => (
|
);
|
||||||
<Button
|
|
||||||
leftSection={
|
return (
|
||||||
<IconArrowUp style={{ width: rem(16), height: rem(16) }} />
|
<>
|
||||||
}
|
{searchClient &&
|
||||||
style={transitionStyles}
|
(isSearchPage ? (
|
||||||
onClick={() => scrollTo({ y: 0 })}
|
<InstantSearch
|
||||||
>
|
searchClient={searchClient!}
|
||||||
Scroll to top
|
indexName="paragraph"
|
||||||
</Button>
|
routing={{
|
||||||
)}
|
stateMapping: singleIndex("paragraph"),
|
||||||
</Transition>
|
}}
|
||||||
</Affix>
|
>
|
||||||
</TitleContext.Provider>
|
{shell}
|
||||||
|
</InstantSearch>
|
||||||
|
) : (
|
||||||
|
shell
|
||||||
|
))}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { TitleContext } from "@/component/Header/Header";
|
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Container,
|
Container,
|
||||||
@@ -9,7 +8,6 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
import { useContext, useEffect } from "react";
|
|
||||||
import { useLoaderData } from "react-router";
|
import { useLoaderData } from "react-router";
|
||||||
|
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@@ -55,12 +53,10 @@ function stripStyles(content: string) {
|
|||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
export default function ParagraphPage() {
|
export default function ParagraphPage() {
|
||||||
const [_title, setTitle] = useContext(TitleContext);
|
|
||||||
const paragraph = useLoaderData() as Paragraph;
|
const paragraph = useLoaderData() as Paragraph;
|
||||||
|
console.log(paragraph);
|
||||||
|
|
||||||
useEffect(() => {
|
const content = stripStyles(paragraph.content);
|
||||||
setTitle(paragraph.title);
|
|
||||||
}, [setTitle, paragraph.title]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container py="2rem">
|
<Container py="2rem">
|
||||||
@@ -69,7 +65,7 @@ export default function ParagraphPage() {
|
|||||||
<Group>
|
<Group>
|
||||||
<Text size="sm" c="dimmed">
|
<Text size="sm" c="dimmed">
|
||||||
{" "}
|
{" "}
|
||||||
{dayjs().to(dayjs(paragraph["@timestamp"]))}
|
{dayjs().to(dayjs(paragraph.time))}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
ml="1rem"
|
ml="1rem"
|
||||||
@@ -109,7 +105,7 @@ export default function ParagraphPage() {
|
|||||||
lineBreak: "anywhere",
|
lineBreak: "anywhere",
|
||||||
}}
|
}}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: stripStyles(paragraph.content),
|
__html: content,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</TypographyStylesProvider>
|
</TypographyStylesProvider>
|
||||||
|
|||||||
@@ -1,51 +1,19 @@
|
|||||||
import { Container, Grid, Group } from "@mantine/core";
|
import { Container, Grid, Stack } from "@mantine/core";
|
||||||
import { useContext, useEffect } from "react";
|
|
||||||
import { useLoaderData, useLocation, useParams } from "react-router";
|
|
||||||
|
|
||||||
import { ParagraphCard } from "../component/ParagraphCard/ParagraphCard";
|
import Hits from "@/component/Hits/Hits";
|
||||||
|
import Pagination from "@/component/Pagination/Pagination";
|
||||||
import { TitleContext } from "@/component/Header/Header";
|
import Refinement from "@/component/Refinement/Refinement";
|
||||||
import { usePaginationData } from "@/helper/hooks";
|
|
||||||
|
|
||||||
export default function SearchPage() {
|
export default function SearchPage() {
|
||||||
const [_title, setTitle] = useContext(TitleContext);
|
|
||||||
|
|
||||||
const params = useLoaderData() as ZincQueryForSDK;
|
|
||||||
|
|
||||||
const {
|
|
||||||
page,
|
|
||||||
pagination,
|
|
||||||
data: paragraphs,
|
|
||||||
} = usePaginationData<Paragraph>(params);
|
|
||||||
|
|
||||||
const location = useLocation();
|
|
||||||
const param = useParams();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let action = "Index";
|
|
||||||
if (location.pathname.startsWith("/search/")) {
|
|
||||||
action = "Search";
|
|
||||||
} else if (location.pathname.startsWith("/tag/")) {
|
|
||||||
action = `Tag ${param.tag}`;
|
|
||||||
} else if (location.pathname.startsWith("/author/")) {
|
|
||||||
action = `Author ${param.author}`;
|
|
||||||
}
|
|
||||||
const title = `${action} Page ${page}`;
|
|
||||||
setTitle(title);
|
|
||||||
}, [page, location, param, setTitle]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Grid my="md">
|
<Stack>
|
||||||
{paragraphs.map((paragraph) => {
|
<Refinement />
|
||||||
return (
|
<Grid my="md">
|
||||||
<Grid.Col span={{ base: 12, sm: 6 }} key={paragraph._id}>
|
<Hits />
|
||||||
<ParagraphCard {...paragraph} key={`${paragraph._id}_card`} />
|
</Grid>
|
||||||
</Grid.Col>
|
<Pagination />
|
||||||
);
|
</Stack>
|
||||||
})}
|
|
||||||
</Grid>
|
|
||||||
<Group justify="center">{pagination}</Group>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ import { TitleContext } from "@/component/Header/Header";
|
|||||||
import { ThemeSetting } from "@/component/Settings/Theme";
|
import { ThemeSetting } from "@/component/Settings/Theme";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { useOptionsState } from "@/store/module/options";
|
import { useOptionsState } from "@/store/module/options";
|
||||||
import { setS3Url, setZincsearchUrl } from "@/store/reducer/options";
|
import {
|
||||||
|
setMeilisearchToken,
|
||||||
|
setMeilisearchUrl,
|
||||||
|
setS3Url,
|
||||||
|
} from "@/store/reducer/options";
|
||||||
|
|
||||||
interface SettingItem {
|
interface SettingItem {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -40,13 +44,25 @@ export default function SettingsPage() {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Zincsearch URL",
|
title: "Meilisearch URL",
|
||||||
description: "The URL of your Zincsearch instance",
|
description: "The URL of your Meilisearch instance",
|
||||||
value: (
|
value: (
|
||||||
<TextInput
|
<TextInput
|
||||||
value={options.zincsearchUrl}
|
value={options.meilisearchUrl}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
store.dispatch(setZincsearchUrl(e.currentTarget.value));
|
store.dispatch(setMeilisearchUrl(e.currentTarget.value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Meilisearch Token",
|
||||||
|
description: "The token of your Meilisearch instance",
|
||||||
|
value: (
|
||||||
|
<TextInput
|
||||||
|
value={options.meilisearchToken}
|
||||||
|
onChange={(e) => {
|
||||||
|
store.dispatch(setMeilisearchToken(e.currentTarget.value));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,116 +1,77 @@
|
|||||||
|
/* eslint-disable react-refresh/only-export-components */
|
||||||
import { lazy } from "react";
|
import { lazy } from "react";
|
||||||
import { createHashRouter } from "react-router-dom";
|
import { createBrowserRouter } from "react-router-dom";
|
||||||
import { remark } from "remark";
|
|
||||||
import remarkHtml from "remark-html";
|
|
||||||
|
|
||||||
import { SearchApi } from "@/helper/api";
|
|
||||||
import MainLayout from "@/layout/MainLayout";
|
import MainLayout from "@/layout/MainLayout";
|
||||||
import SearchPage from "@/page/Search";
|
import SearchPage from "@/page/Search";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
import { markdownToHtml } from "@/utils/remark";
|
||||||
|
import { MeiliSearch } from "meilisearch";
|
||||||
|
|
||||||
const NotFound = lazy(() => import("@/page/Exception/NotFound"));
|
const NotFound = lazy(() => import("@/page/Exception/NotFound"));
|
||||||
const ErrorPage = lazy(() => import("@/page/Exception/ErrorPage"));
|
const ErrorPage = lazy(() => import("@/page/Exception/ErrorPage"));
|
||||||
const LoadingPage = lazy(async () => import("@/page/Loading"));
|
const LoadingPage = lazy(async () => import("@/page/Loading"));
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const ParagraphPage = lazy(async () => import("@/page/Paragraph"));
|
const ParagraphPage = lazy(async () => import("@/page/Paragraph"));
|
||||||
const SettingsPage = lazy(async () => import("@/page/Settings"));
|
const SettingsPage = lazy(async () => import("@/page/Settings"));
|
||||||
|
|
||||||
const router = createHashRouter([
|
const router = createBrowserRouter(
|
||||||
{
|
[
|
||||||
path: "/",
|
{
|
||||||
element: <MainLayout />,
|
path: "/",
|
||||||
errorElement: <ErrorPage />,
|
element: <MainLayout />,
|
||||||
children: [
|
errorElement: <ErrorPage />,
|
||||||
{
|
children: [
|
||||||
path: "/",
|
{
|
||||||
element: <SearchPage />,
|
path: "/",
|
||||||
loader() {
|
element: <SearchPage />,
|
||||||
return {};
|
loader() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
path: "/settings",
|
||||||
path: "/settings",
|
element: <SettingsPage />,
|
||||||
element: <SettingsPage />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/tag/:tag",
|
|
||||||
element: <SearchPage />,
|
|
||||||
loader({ params: { tag } }) {
|
|
||||||
if (!tag) {
|
|
||||||
return { redirect: "/" };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
search_type: "querystring",
|
|
||||||
query: {
|
|
||||||
term: `tags:${JSON.stringify(tag)}`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/author/:author",
|
|
||||||
element: <SearchPage />,
|
|
||||||
loader({ params: { author } }) {
|
|
||||||
if (!author) {
|
|
||||||
return { redirect: "/" };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
search_type: "querystring",
|
|
||||||
query: {
|
|
||||||
term: `author:${JSON.stringify(author)}`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/search/:search",
|
|
||||||
element: <SearchPage />,
|
|
||||||
loader({ params: { search } }) {
|
|
||||||
if (!search) {
|
|
||||||
return { redirect: "/" };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
search_type: "querystring",
|
|
||||||
query: {
|
|
||||||
term: search,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/paragraph/:id",
|
|
||||||
element: <ParagraphPage />,
|
|
||||||
async loader({ params: { id } }) {
|
|
||||||
if (!id) {
|
|
||||||
return { redirect: "/" };
|
|
||||||
}
|
|
||||||
|
|
||||||
const paragraph = await SearchApi.getParagraph(
|
{
|
||||||
store.getState().options.zincsearchUrl,
|
path: "/paragraph/:id",
|
||||||
id,
|
element: <ParagraphPage />,
|
||||||
).then((p) =>
|
async loader({ params: { id } }) {
|
||||||
SearchApi.wrapParagraph(store.getState().options.s3Url, p),
|
if (!id) {
|
||||||
);
|
return { redirect: "/" };
|
||||||
|
}
|
||||||
|
|
||||||
console.log(paragraph.markdown);
|
const meilisearch = new MeiliSearch({
|
||||||
if (paragraph.markdown) {
|
host: store.getState().options.meilisearchUrl,
|
||||||
paragraph.content = (
|
apiKey: store.getState().options.meilisearchToken,
|
||||||
await remark().use(remarkHtml).process(paragraph.content)
|
});
|
||||||
).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return paragraph;
|
const paragraph: Paragraph = await meilisearch
|
||||||
|
.index("paragraph")
|
||||||
|
.getDocument(id);
|
||||||
|
|
||||||
|
if (paragraph.markdown) {
|
||||||
|
paragraph.content = await markdownToHtml(paragraph.content);
|
||||||
|
} else {
|
||||||
|
paragraph.content = "NO HTML!";
|
||||||
|
}
|
||||||
|
|
||||||
|
return paragraph;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
},
|
{
|
||||||
{
|
path: "/loading",
|
||||||
path: "/loading",
|
element: <LoadingPage />,
|
||||||
element: <LoadingPage />,
|
},
|
||||||
},
|
{
|
||||||
{
|
path: "*",
|
||||||
path: "*",
|
element: <NotFound />,
|
||||||
element: <NotFound />,
|
},
|
||||||
},
|
],
|
||||||
]);
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -1,29 +1,35 @@
|
|||||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
export interface OptionsState {
|
export interface OptionsState {
|
||||||
zincsearchUrl: string;
|
meilisearchUrl: string;
|
||||||
|
meilisearchToken: string;
|
||||||
s3Url: string;
|
s3Url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZINCSEARCH_URL = "https://zincsearch.yoshino-s.xyz";
|
const initialState: OptionsState = {
|
||||||
const MINIO_URL = "https://minio-hdd.yoshino-s.xyz";
|
meilisearchUrl: "https://meilisearch.yoshino-s.xyz/",
|
||||||
|
meilisearchToken:
|
||||||
|
"a568afad53a4dd124c508b9acd26ec35ff65665c07020913533cd7b176a28a04",
|
||||||
|
s3Url: "https://minio-hdd.yoshino-s.xyz",
|
||||||
|
};
|
||||||
|
|
||||||
const optionsSlice = createSlice({
|
const optionsSlice = createSlice({
|
||||||
name: "stats",
|
name: "stats",
|
||||||
initialState: {
|
initialState,
|
||||||
zincsearchUrl: ZINCSEARCH_URL,
|
|
||||||
s3Url: MINIO_URL,
|
|
||||||
} as OptionsState,
|
|
||||||
reducers: {
|
reducers: {
|
||||||
setZincsearchUrl: (state, action: PayloadAction<string | undefined>) => {
|
setMeilisearchUrl: (state, action: PayloadAction<string | undefined>) => {
|
||||||
state.zincsearchUrl = action.payload ?? ZINCSEARCH_URL;
|
state.meilisearchUrl = action.payload ?? initialState.meilisearchUrl;
|
||||||
|
},
|
||||||
|
setMeilisearchToken: (state, action: PayloadAction<string | undefined>) => {
|
||||||
|
state.meilisearchToken = action.payload ?? initialState.meilisearchToken;
|
||||||
},
|
},
|
||||||
setS3Url: (state, action: PayloadAction<string | undefined>) => {
|
setS3Url: (state, action: PayloadAction<string | undefined>) => {
|
||||||
state.s3Url = action.payload ?? MINIO_URL;
|
state.s3Url = action.payload ?? initialState.s3Url;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setS3Url, setZincsearchUrl } = optionsSlice.actions;
|
export const { setS3Url, setMeilisearchUrl, setMeilisearchToken } =
|
||||||
|
optionsSlice.actions;
|
||||||
|
|
||||||
export default optionsSlice.reducer;
|
export default optionsSlice.reducer;
|
||||||
|
|||||||
4
src/types/paragraph.d.ts
vendored
4
src/types/paragraph.d.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
declare interface Paragraph {
|
declare interface Paragraph {
|
||||||
_id: string;
|
id: string;
|
||||||
"@timestamp": string;
|
time: string;
|
||||||
content: string;
|
content: string;
|
||||||
markdown: string;
|
markdown: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
71
src/utils/remark.ts
Normal file
71
src/utils/remark.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import rehypeHighlight from "rehype-highlight";
|
||||||
|
import rehypeStringify from "rehype-stringify";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
import remarkParse from "remark-parse";
|
||||||
|
import remarkRehype from "remark-rehype";
|
||||||
|
import { unified } from "unified";
|
||||||
|
|
||||||
|
export async function markdownToHtml(markdown: string) {
|
||||||
|
const result = await unified()
|
||||||
|
.use(remarkParse)
|
||||||
|
.use(remarkRehype)
|
||||||
|
.use(remarkGfm)
|
||||||
|
.use(rehypeHighlight, {
|
||||||
|
detect: true,
|
||||||
|
})
|
||||||
|
// .use(rehypeSanitize, {
|
||||||
|
// ...defaultSchema,
|
||||||
|
// attributes: {
|
||||||
|
// ...defaultSchema.attributes,
|
||||||
|
// span: [
|
||||||
|
// ...(defaultSchema.attributes?.span || []),
|
||||||
|
// [
|
||||||
|
// "className",
|
||||||
|
// "hljs-addition",
|
||||||
|
// "hljs-attr",
|
||||||
|
// "hljs-attribute",
|
||||||
|
// "hljs-built_in",
|
||||||
|
// "hljs-bullet",
|
||||||
|
// "hljs-char",
|
||||||
|
// "hljs-code",
|
||||||
|
// "hljs-comment",
|
||||||
|
// "hljs-deletion",
|
||||||
|
// "hljs-doctag",
|
||||||
|
// "hljs-emphasis",
|
||||||
|
// "hljs-formula",
|
||||||
|
// "hljs-keyword",
|
||||||
|
// "hljs-link",
|
||||||
|
// "hljs-literal",
|
||||||
|
// "hljs-meta",
|
||||||
|
// "hljs-name",
|
||||||
|
// "hljs-number",
|
||||||
|
// "hljs-operator",
|
||||||
|
// "hljs-params",
|
||||||
|
// "hljs-property",
|
||||||
|
// "hljs-punctuation",
|
||||||
|
// "hljs-quote",
|
||||||
|
// "hljs-regexp",
|
||||||
|
// "hljs-section",
|
||||||
|
// "hljs-selector-attr",
|
||||||
|
// "hljs-selector-class",
|
||||||
|
// "hljs-selector-id",
|
||||||
|
// "hljs-selector-pseudo",
|
||||||
|
// "hljs-selector-tag",
|
||||||
|
// "hljs-string",
|
||||||
|
// "hljs-strong",
|
||||||
|
// "hljs-subst",
|
||||||
|
// "hljs-symbol",
|
||||||
|
// "hljs-tag",
|
||||||
|
// "hljs-template-tag",
|
||||||
|
// "hljs-template-variable",
|
||||||
|
// "hljs-title",
|
||||||
|
// "hljs-type",
|
||||||
|
// "hljs-variable",
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
.use(rehypeStringify)
|
||||||
|
.process(markdown);
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user