diff --git a/package-lock.json b/package-lock.json
index 4724d28..94b019e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -32,6 +32,7 @@
"tailwindcss": "^3.4.13",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0",
+ "unist-util-visit": "^5.0.0",
"unplugin-icons": "^0.19.3",
"vite": "^5.0.3"
}
@@ -3638,9 +3639,9 @@
}
},
"node_modules/package-json-from-dist": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
- "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true
},
"node_modules/package-manager-detector": {
@@ -4812,6 +4813,25 @@
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"dev": true
},
+ "node_modules/unist-util-is": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
+ "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is/node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true
+ },
"node_modules/unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
@@ -4825,6 +4845,47 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/unist-util-visit": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
+ "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
+ "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents/node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true
+ },
+ "node_modules/unist-util-visit/node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true
+ },
"node_modules/unplugin": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz",
diff --git a/package.json b/package.json
index 920d2d5..1cbad47 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"tailwindcss": "^3.4.13",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0",
+ "unist-util-visit": "^5.0.0",
"unplugin-icons": "^0.19.3",
"vite": "^5.0.3"
},
diff --git a/rehype/external-links.js b/rehype/external-links.js
new file mode 100644
index 0000000..ab0a4d5
--- /dev/null
+++ b/rehype/external-links.js
@@ -0,0 +1,17 @@
+import {visit} from 'unist-util-visit'
+
+export default () => {
+ return (tree) => {
+ visit(tree, 'element', function (node) {
+ if (
+ node.tagName === 'a' &&
+ typeof node.properties.href === 'string'
+ ) {
+ const url = node.properties.href
+ if (url.startsWith('http://') || url.startsWith('https://')) {
+ node.properties.target = '_blank'
+ }
+ }
+ })
+ }
+}
diff --git a/src/routes/blog/this-blog/+page.svx b/src/routes/blog/this-blog/+page.svx
index 9bd4592..4c58401 100644
--- a/src/routes/blog/this-blog/+page.svx
+++ b/src/routes/blog/this-blog/+page.svx
@@ -70,10 +70,11 @@ MDX, в конце концов, просто компилируется в об
Ведь эта страница, как и остальные на этом сайте, написана на Svelte!
-К счастью для меня и остальных фанатов MDX, есть подобная альтернатива, интегрирующая Markdown и Svelte: MDsveX.
+К счастью для меня и остальных фанатов MDX, есть подобная альтернатива, интегрирующая Markdown и Svelte: [MDsveX](https://github.com/pngwn/MDsveX).
Хоть название и не лучшее, возможности не уступают оригиналу.
-Самое главное, что у SVX (я буду так его называть), есть возможность передавать в компилятор remark и rehype плагины.
+Самое главное, что у SVX (я буду так его называть), есть возможность передавать
+в компилятор [remark](https://github.com/remarkjs/remark) и [rehype](https://github.com/rehypejs/rehype) плагины.
## Создание проекта
@@ -200,7 +201,7 @@ export const load = async () => {
## Наслаждаемся результатами
-В нашем блоге настроен типограф, что позволяет нам не заботиться о переносах строк в неположенных местах,
+В нашем блоге настроен [типограф](https://github.com/typograf/typograf), что позволяет нам не заботиться о переносах строк в неположенных местах,
он заполняет текст неразрывными пробелами где надо.
Помимо этого, он заменяет `"` на `»`, выносит кавычки за пределы ссылки, заменяет `...` на `…`, превращает `--` в `—`.
diff --git a/svelte.config.js b/svelte.config.js
index 56384af..8ad1345 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -1,7 +1,8 @@
-import adapter from '@sveltejs/adapter-node';
-import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
-import {mdsvex} from "mdsvex";
+import adapter from '@sveltejs/adapter-node'
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+import {mdsvex} from "mdsvex"
import remarkTypograf from "@mavrin/remark-typograf"
+import externalLinks from "./rehype/external-links.js"
/** @type {import('@sveltejs/kit').Config} */
const config = {
@@ -12,7 +13,10 @@ const config = {
remarkPlugins: [
remarkTypograf,
],
- }),
+ rehypePlugins: [
+ externalLinks
+ ]
+ })
],
kit: {
adapter: adapter()
diff --git a/tailwind.config.js b/tailwind.config.js
index c0a9789..0dbc6ce 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,4 +1,3 @@
-/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts,svx}'],
theme: {
@@ -6,4 +5,3 @@ export default {
},
plugins: [],
}
-
diff --git a/tsconfig.json b/tsconfig.json
index 1692ffa..50498ea 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,7 +12,9 @@
"moduleResolution": "bundler"
},
"include": [
- "src/**/*.svx"
+ "*.config.ts",
+ "src/**/*.svx",
+ "rehype/**/*.ts"
]
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files