diff --git a/astro.config.mjs b/astro.config.mjs
index 132abf0..c59dd17 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -7,6 +7,7 @@ import remarkReadingTime from "remark-reading-time";
import remarkUnwrapImages from "remark-unwrap-images";
import { remarkR2Images } from "./src/plugins/remark-r2-images.mjs";
import { rehypePictureWebp } from "./src/plugins/rehype-picture-webp.mjs";
+import { remarkYouTube } from "./src/plugins/remark-youtube.mjs";
export default defineConfig({
site: "https://balodeplao.com/",
@@ -22,6 +23,7 @@ export default defineConfig({
},
remarkR2Images,
remarkUnwrapImages,
+ remarkYouTube,
],
rehypePlugins: [rehypePictureWebp],
},
diff --git a/package-lock.json b/package-lock.json
index 4049a90..cdd4090 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@tailwindcss/vite": "^4.1.18",
"astro": "^6.0.4",
"astro-icon": "^1.1.5",
+ "lite-youtube-embed": "^0.3.4",
"remark-reading-time": "^2.0.2",
"remark-unwrap-images": "^4.0.1",
"tailwindcss": "^4.1.18",
@@ -1300,6 +1301,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1322,6 +1324,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1344,6 +1347,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1360,6 +1364,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1376,6 +1381,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1392,6 +1398,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1408,6 +1415,7 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1424,6 +1432,7 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1440,6 +1449,7 @@
"cpu": [
"s390x"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1456,6 +1466,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1472,6 +1483,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1488,6 +1500,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1504,6 +1517,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1526,6 +1540,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1548,6 +1563,7 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1570,6 +1586,7 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1592,6 +1609,7 @@
"cpu": [
"s390x"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1614,6 +1632,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1636,6 +1655,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1658,6 +1678,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
@@ -1680,6 +1701,7 @@
"cpu": [
"wasm32"
],
+ "dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
@@ -1699,6 +1721,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1718,6 +1741,7 @@
"cpu": [
"ia32"
],
+ "dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -1737,6 +1761,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
@@ -7389,6 +7414,12 @@
"node": ">=20.0.0"
}
},
+ "node_modules/lite-youtube-embed": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.3.4.tgz",
+ "integrity": "sha512-aXgxpwK7AIW58GEbRzA8EYaY4LWvF3FKak6B9OtSJmuNyLhX2ouD4cMTxz/yR5HFInhknaYd2jLWOTRTvT8oAw==",
+ "license": "Apache-2.0"
+ },
"node_modules/local-pkg": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
diff --git a/package.json b/package.json
index 5678e80..50013c0 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"@tailwindcss/vite": "^4.1.18",
"astro": "^6.0.4",
"astro-icon": "^1.1.5",
+ "lite-youtube-embed": "^0.3.4",
"remark-reading-time": "^2.0.2",
"remark-unwrap-images": "^4.0.1",
"tailwindcss": "^4.1.18",
diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro
index 0957672..41908f8 100644
--- a/src/pages/[...slug].astro
+++ b/src/pages/[...slug].astro
@@ -6,6 +6,7 @@ import Categories from "@/components/ui/Categories.astro";
import Destinations from "@/components/ui/Destinations.astro";
import { toR2Url } from "@/utils/r2";
import Picture from "@/components/ui/Picture.astro";
+import "lite-youtube-embed/src/lite-yt-embed.css";
import { getCollection, render, type CollectionEntry } from "astro:content";
@@ -119,4 +120,7 @@ const metadata = {
}
+
diff --git a/src/plugins/remark-youtube.mjs b/src/plugins/remark-youtube.mjs
new file mode 100644
index 0000000..ad572b1
--- /dev/null
+++ b/src/plugins/remark-youtube.mjs
@@ -0,0 +1,24 @@
+import { visit } from "unist-util-visit";
+
+const YT_REGEX =
+ /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
+
+export function remarkYouTube() {
+ return (tree) => {
+ visit(tree, "paragraph", (node, index, parent) => {
+ if (node.children.length !== 1) return;
+ const child = node.children[0];
+ if (child.type !== "link" && child.type !== "text") return;
+
+ const url = child.type === "link" ? child.url : child.value;
+ const match = url?.match(YT_REGEX);
+ if (!match) return;
+
+ const videoId = match[1];
+ parent.children.splice(index, 1, {
+ type: "html",
+ value: `Play Video`,
+ });
+ });
+ };
+}