parent
32e82e69ba
commit
21cbd12e00
|
|
@ -92,7 +92,11 @@ module.exports = withBundleAnalyzer(
|
|||
dangerouslyAllowSVG: true,
|
||||
contentSecurityPolicy:
|
||||
"default-src 'self'; script-src 'none'; sandbox; style-src 'unsafe-inline';",
|
||||
remotePatterns: [{ hostname: "**" }],
|
||||
remotePatterns: [
|
||||
{ hostname: "**" },
|
||||
{ protocol: "https", hostname: "pbs.twimg.com" },
|
||||
{ protocol: "https", hostname: "abs.twimg.com" },
|
||||
],
|
||||
},
|
||||
|
||||
async generateBuildId() {
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@
|
|||
"react-popper": "^2.3.0",
|
||||
"react-sortablejs": "6.1.4",
|
||||
"react-string-replace": "^1.1.0",
|
||||
"react-tweet": "^2.0.1",
|
||||
"react-virtuoso": "4.3.6",
|
||||
"refractor": "4.8.1",
|
||||
"rehype-autolink-headings": "6.1.1",
|
||||
|
|
|
|||
|
|
@ -232,6 +232,9 @@ dependencies:
|
|||
react-string-replace:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
react-tweet:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1(react-dom@18.2.0)(react@18.2.0)
|
||||
react-virtuoso:
|
||||
specifier: 4.3.6
|
||||
version: 4.3.6(react-dom@18.2.0)(react@18.2.0)
|
||||
|
|
@ -4322,6 +4325,12 @@ packages:
|
|||
string.prototype.matchall: 4.0.8
|
||||
dev: true
|
||||
|
||||
/@swc/helpers@0.4.14:
|
||||
resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==}
|
||||
dependencies:
|
||||
tslib: 2.5.0
|
||||
dev: false
|
||||
|
||||
/@swc/helpers@0.5.1:
|
||||
resolution: {integrity: sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==}
|
||||
dependencies:
|
||||
|
|
@ -6909,6 +6918,13 @@ packages:
|
|||
whatwg-url: 12.0.1
|
||||
dev: false
|
||||
|
||||
/date-fns@2.30.0:
|
||||
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
||||
engines: {node: '>=0.11'}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.5
|
||||
dev: false
|
||||
|
||||
/dayjs@1.11.7:
|
||||
resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==}
|
||||
dev: false
|
||||
|
|
@ -11605,6 +11621,20 @@ packages:
|
|||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-tweet@2.0.1(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-r8Yrv+cW8ajpCcT2AJCIji9crbbVxiaYSagqU4IW4Btsm3b3Ui65pFOV9gZmnt2xorn8L98kqj8REEuGxwnaeA==}
|
||||
peerDependencies:
|
||||
react: '>= 18.0.0'
|
||||
react-dom: '>= 18.0.0'
|
||||
dependencies:
|
||||
'@swc/helpers': 0.4.14
|
||||
clsx: 1.2.1
|
||||
date-fns: 2.30.0
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
swr: 2.1.5(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-virtuoso@4.3.6(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-t2yzA9QKwMrcECLytVfZcBZMusuQ9Ahgt62SL8uC/sYm9Sk/h14sYTJC0MVO6CAtl3BzKiLKSC79Vp+W3KOXMg==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
@ -12673,6 +12703,15 @@ packages:
|
|||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
/swr@2.1.5(react@18.2.0):
|
||||
resolution: {integrity: sha512-/OhfZMcEpuz77KavXST5q6XE9nrOBOVcBLWjMT+oAE/kQHyE3PASrevXCtQDZ8aamntOfFkbVJp7Il9tNBQWrw==}
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
dev: false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import Image from "next/image"
|
||||
import { Tweet as ReactTweet } from "react-tweet"
|
||||
import type { TweetComponents } from "react-tweet"
|
||||
|
||||
const components: TweetComponents = {
|
||||
AvatarImg: (props) => <Image {...props} />,
|
||||
MediaImg: (props) => <Image {...props} fill unoptimized />,
|
||||
}
|
||||
|
||||
export function Tweet({ id }: { id: string }) {
|
||||
return <ReactTweet id={id} components={components} />
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import { APlayer } from "~/components/ui/APlayer"
|
|||
import { ZoomedImage } from "~/components/ui/Image"
|
||||
import { Mention } from "~/components/ui/Mention"
|
||||
import { Mermaid } from "~/components/ui/Mermaid"
|
||||
import { Tweet } from "~/components/ui/Tweet"
|
||||
|
||||
import { rehypeAudio } from "./rehype-audio"
|
||||
import {
|
||||
|
|
@ -41,6 +42,7 @@ import {
|
|||
} from "./rehype-custom-wrapper"
|
||||
import { rehypeImage } from "./rehype-image"
|
||||
import { rehypeTable } from "./rehype-table"
|
||||
import { rehypeTweet } from "./rehype-tweet"
|
||||
import { rehypeWrapCode } from "./rehype-wrap-code"
|
||||
import { rehypeExternalLink } from "./rehyper-external-link"
|
||||
import { remarkCallout } from "./remark-callout"
|
||||
|
|
@ -165,6 +167,7 @@ export const renderPageContent = (
|
|||
.use(rehypeExternalLink)
|
||||
.use(rehypeWrapCode)
|
||||
.use(rehypeInferDescriptionMeta)
|
||||
.use(rehypeTweet)
|
||||
.use(rehypeRewrite, {
|
||||
selector: "p, li",
|
||||
rewrite: (node: any) => {
|
||||
|
|
@ -213,6 +216,7 @@ export const renderPageContent = (
|
|||
mention: Mention,
|
||||
mermaid: Mermaid,
|
||||
audio: APlayer,
|
||||
tweet: Tweet,
|
||||
style: Style,
|
||||
} as any,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
import { Root } from "rehype-raw"
|
||||
import { Plugin } from "unified"
|
||||
import { visit } from "unist-util-visit"
|
||||
|
||||
export const rehypeTweet: Plugin<Array<void>, Root> = () => (tree) => {
|
||||
visit(tree, { tagName: "a" }, (node, i, parent) => {
|
||||
if (
|
||||
!parent ||
|
||||
!("tagName" in parent) ||
|
||||
parent.tagName !== "p" ||
|
||||
parent.children.length > 1
|
||||
)
|
||||
return
|
||||
|
||||
const tweetRegex =
|
||||
/^https?:\/\/(?:www\.)?twitter\.com\/\w+\/status\/(\d+)(?:\?.*)?(?:#.*)?$/
|
||||
|
||||
const href = node.properties?.href
|
||||
|
||||
if (typeof href === "string") {
|
||||
const match = href.match(tweetRegex)
|
||||
if (match && match[0] === href) {
|
||||
const tweetId = match[1]
|
||||
node.tagName = "tweet"
|
||||
node.properties = {
|
||||
id: tweetId,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue