feat: add XEmbedClient component for embedding X posts and integrate into MDX components
This commit is contained in:
parent
37f011cf74
commit
aea55ee4bb
@ -35,6 +35,14 @@ After that, you can return to the blog post and you can read the rest of the blo
|
||||
|
||||
For more details, please check out the documentation: [Blog](https://mksaas.com/docs/blog).
|
||||
|
||||
Test show Tweet in the blog post.
|
||||
|
||||
<XEmbedClient url="https://x.com/mksaascom/status/1960417768505008291" width={500} />
|
||||
|
||||
Test show YouTube video in the blog post.
|
||||
|
||||
<YoutubeVideo url="https://www.youtube.com/embed/xvoeSnlFZJk" width={500} />
|
||||
|
||||
Now the rest of the blog post is premium content.
|
||||
|
||||
<PremiumContent>
|
||||
|
@ -35,6 +35,14 @@ CVV: 567
|
||||
|
||||
更多详情,请参考文档:[博客](https://mksaas.com/docs/blog)。
|
||||
|
||||
测试展示 X 帖子。
|
||||
|
||||
<XEmbedClient url="https://x.com/mksaascom/status/1960417768505008291" width={500} />
|
||||
|
||||
测试展示 YouTube 视频。
|
||||
|
||||
<YoutubeVideo url="https://www.youtube.com/embed/xvoeSnlFZJk" width={500} />
|
||||
|
||||
现在剩下的内容是付费内容。
|
||||
|
||||
<PremiumContent>
|
||||
|
@ -120,6 +120,7 @@
|
||||
"react-hook-form": "^7.62.0",
|
||||
"react-remove-scroll": "^2.6.3",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"react-social-media-embed": "^2.5.18",
|
||||
"react-syntax-highlighter": "^15.6.3",
|
||||
"react-tweet": "^3.2.2",
|
||||
"react-use-measure": "^2.1.7",
|
||||
|
125
pnpm-lock.yaml
generated
125
pnpm-lock.yaml
generated
@ -293,6 +293,9 @@ importers:
|
||||
react-resizable-panels:
|
||||
specifier: ^2.1.7
|
||||
version: 2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react-social-media-embed:
|
||||
specifier: ^2.5.18
|
||||
version: 2.5.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react-syntax-highlighter:
|
||||
specifier: ^15.6.3
|
||||
version: 15.6.3(react@19.0.0)
|
||||
@ -3676,6 +3679,9 @@ packages:
|
||||
'@types/unist@3.0.3':
|
||||
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
||||
|
||||
'@types/youtube-player@5.5.11':
|
||||
resolution: {integrity: sha512-pM41CDBqJqBmTeJWnF7NOGz82IQoYOhqzMYXv5vKCXBqGiYSLldxMtpCk6KAEtADTy49S45AriYaCaZyeUX38Q==}
|
||||
|
||||
'@typescript-eslint/project-service@8.40.0':
|
||||
resolution: {integrity: sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
@ -3939,6 +3945,9 @@ packages:
|
||||
class-variance-authority@0.7.1:
|
||||
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
|
||||
|
||||
classnames@2.5.1:
|
||||
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
|
||||
|
||||
cli-cursor@3.1.0:
|
||||
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -4086,6 +4095,14 @@ packages:
|
||||
resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
debug@2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.3.7:
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -4983,6 +5000,9 @@ packages:
|
||||
resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
load-script@1.0.0:
|
||||
resolution: {integrity: sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==}
|
||||
|
||||
locate-path@6.0.0:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
@ -5269,6 +5289,9 @@ packages:
|
||||
react-dom:
|
||||
optional: true
|
||||
|
||||
ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@ -5698,6 +5721,12 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18 || ^19
|
||||
|
||||
react-html-props@2.1.1:
|
||||
resolution: {integrity: sha512-tM+YCYlr90m3JontKUAa+gNVU2zkyprlCS7OQ9aa3z2MfyJjAioJzrSmi1Vef/+UCTE6CQlPqLX4ebdLIJDKxw==}
|
||||
peerDependencies:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
|
||||
react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
@ -5761,6 +5790,12 @@ packages:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
react-social-media-embed@2.5.18:
|
||||
resolution: {integrity: sha512-+PkzLRGAwnySkxKajaiK5VD+EjOhlFsh/vjNxgHsDfKBTseDpFxPrMXXQWkk6BRCwFBNVWX+V1HZ9AU0y54Wgw==}
|
||||
peerDependencies:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
|
||||
react-style-singleton@2.2.3:
|
||||
resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==}
|
||||
engines: {node: '>=10'}
|
||||
@ -5771,6 +5806,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-sub-unsub@2.2.8:
|
||||
resolution: {integrity: sha512-o3tmiOOZPdQUCmRhkdCHXRFLOHnCwdz/N3QZ1JQ14fQGA2HysKMF0kWu56ERnQUCK7wYVCQzI8pFbnivAYNQ+A==}
|
||||
peerDependencies:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0
|
||||
|
||||
react-syntax-highlighter@15.6.3:
|
||||
resolution: {integrity: sha512-HebdyA9r20hgmA0q8RyRJ4c/vB4E6KL2HeWb5MNjU3iJEiT2w9jfU2RJsmI6f3Cy3SGE5tm0AIkBzM/E7e9/lQ==}
|
||||
peerDependencies:
|
||||
@ -5788,6 +5829,13 @@ packages:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
react-dom: ^18.0.0 || ^19.0.0
|
||||
|
||||
react-twitter-embed@4.0.4:
|
||||
resolution: {integrity: sha512-2JIL7qF+U62zRzpsh6SZDXNI3hRNVYf5vOZ1WRcMvwKouw+xC00PuFaD0aEp2wlyGaZ+f4x2VvX+uDadFQ3HVA==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
react: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
|
||||
react-use-measure@2.1.7:
|
||||
resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==}
|
||||
peerDependencies:
|
||||
@ -5797,6 +5845,12 @@ packages:
|
||||
react-dom:
|
||||
optional: true
|
||||
|
||||
react-youtube@10.1.0:
|
||||
resolution: {integrity: sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==}
|
||||
engines: {node: '>= 14.x'}
|
||||
peerDependencies:
|
||||
react: '>=0.14.1'
|
||||
|
||||
react@19.0.0:
|
||||
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -5908,6 +5962,9 @@ packages:
|
||||
scheduler@0.25.0:
|
||||
resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
|
||||
|
||||
scriptjs@2.5.9:
|
||||
resolution: {integrity: sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==}
|
||||
|
||||
scroll-into-view-if-needed@3.1.0:
|
||||
resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==}
|
||||
|
||||
@ -5970,6 +6027,9 @@ packages:
|
||||
simple-swizzle@0.2.2:
|
||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||
|
||||
sister@3.0.2:
|
||||
resolution: {integrity: sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==}
|
||||
|
||||
smol-toml@1.3.4:
|
||||
resolution: {integrity: sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==}
|
||||
engines: {node: '>= 18'}
|
||||
@ -6338,6 +6398,9 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
youtube-player@5.5.2:
|
||||
resolution: {integrity: sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==}
|
||||
|
||||
zod-to-json-schema@3.24.2:
|
||||
resolution: {integrity: sha512-pNUqrcSxuuB3/+jBbU8qKUbTbDqYUaG1vf5cXFjbhGgoUuA1amO/y4Q8lzfOhHU8HNPK6VFJ18lBDKj3OHyDsg==}
|
||||
peerDependencies:
|
||||
@ -9420,6 +9483,8 @@ snapshots:
|
||||
|
||||
'@types/unist@3.0.3': {}
|
||||
|
||||
'@types/youtube-player@5.5.11': {}
|
||||
|
||||
'@typescript-eslint/project-service@8.40.0(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.40.0(typescript@5.8.3)
|
||||
@ -9675,6 +9740,8 @@ snapshots:
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
|
||||
classnames@2.5.1: {}
|
||||
|
||||
cli-cursor@3.1.0:
|
||||
dependencies:
|
||||
restore-cursor: 3.1.0
|
||||
@ -9800,6 +9867,10 @@ snapshots:
|
||||
|
||||
debounce@2.0.0: {}
|
||||
|
||||
debug@2.6.9:
|
||||
dependencies:
|
||||
ms: 2.0.0
|
||||
|
||||
debug@4.3.7:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
@ -10813,6 +10884,8 @@ snapshots:
|
||||
lightningcss-win32-arm64-msvc: 1.29.2
|
||||
lightningcss-win32-x64-msvc: 1.29.2
|
||||
|
||||
load-script@1.0.0: {}
|
||||
|
||||
locate-path@6.0.0:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
@ -11362,6 +11435,8 @@ snapshots:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
ms@2.0.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
nan@2.22.0:
|
||||
@ -11859,6 +11934,11 @@ snapshots:
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
|
||||
react-html-props@2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
react-is@16.13.1: {}
|
||||
|
||||
react-is@18.3.1: {}
|
||||
@ -11933,6 +12013,19 @@ snapshots:
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
react-transition-group: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
|
||||
react-social-media-embed@2.5.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
'@types/youtube-player': 5.5.11
|
||||
classnames: 2.5.1
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
react-html-props: 2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react-sub-unsub: 2.2.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react-twitter-embed: 4.0.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
react-youtube: 10.1.0(react@19.0.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
react-style-singleton@2.2.3(@types/react@19.0.9)(react@19.0.0):
|
||||
dependencies:
|
||||
get-nonce: 1.0.1
|
||||
@ -11941,6 +12034,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.0.9
|
||||
|
||||
react-sub-unsub@2.2.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
react-syntax-highlighter@15.6.3(react@19.0.0):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
@ -11968,12 +12066,27 @@ snapshots:
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
swr: 2.3.2(react@19.0.0)
|
||||
|
||||
react-twitter-embed@4.0.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
scriptjs: 2.5.9
|
||||
|
||||
react-use-measure@2.1.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||
dependencies:
|
||||
react: 19.0.0
|
||||
optionalDependencies:
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
react-youtube@10.1.0(react@19.0.0):
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
react: 19.0.0
|
||||
youtube-player: 5.5.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
react@19.0.0: {}
|
||||
|
||||
readable-stream@3.6.2:
|
||||
@ -12156,6 +12269,8 @@ snapshots:
|
||||
|
||||
scheduler@0.25.0: {}
|
||||
|
||||
scriptjs@2.5.9: {}
|
||||
|
||||
scroll-into-view-if-needed@3.1.0:
|
||||
dependencies:
|
||||
compute-scroll-into-view: 3.1.1
|
||||
@ -12271,6 +12386,8 @@ snapshots:
|
||||
is-arrayish: 0.3.2
|
||||
optional: true
|
||||
|
||||
sister@3.0.2: {}
|
||||
|
||||
smol-toml@1.3.4: {}
|
||||
|
||||
socket.io-adapter@2.5.5:
|
||||
@ -12655,6 +12772,14 @@ snapshots:
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
youtube-player@5.5.2:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
load-script: 1.0.0
|
||||
sister: 3.0.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
zod-to-json-schema@3.24.2(zod@3.25.64):
|
||||
dependencies:
|
||||
zod: 3.25.64
|
||||
|
@ -12,6 +12,7 @@ import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
import * as LucideIcons from 'lucide-react';
|
||||
import type { MDXComponents } from 'mdx/types';
|
||||
import type { ComponentProps, FC } from 'react';
|
||||
import { XEmbedClient } from './xembed';
|
||||
|
||||
/**
|
||||
* Enhanced MDX Content component that includes commonly used MDX components
|
||||
@ -23,6 +24,7 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents {
|
||||
...defaultMdxComponents,
|
||||
...LucideIcons,
|
||||
// ...((await import('lucide-react')) as unknown as MDXComponents),
|
||||
XEmbedClient,
|
||||
YoutubeVideo,
|
||||
PremiumContent,
|
||||
Tabs,
|
||||
|
16
src/components/docs/xembed.tsx
Normal file
16
src/components/docs/xembed.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { XEmbed, type XEmbedProps } from 'react-social-media-embed';
|
||||
|
||||
/**
|
||||
* Embedding X Posts in Fumadocs
|
||||
*
|
||||
* https://rjv.im/blog/solution/embed-x-post-in-fuma-docs
|
||||
*/
|
||||
export function XEmbedClient({ ...props }: XEmbedProps) {
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<XEmbed {...props} />
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user