From 8f819f3ab1fc186dbb07fee4ac066b114aba1df2 Mon Sep 17 00:00:00 2001 From: Anatoly Kopyl Date: Sat, 5 Oct 2024 00:34:31 +0300 Subject: [PATCH] External links --- package-lock.json | 67 +++++++++++++++++++++++++++-- package.json | 1 + rehype/external-links.js | 17 ++++++++ src/routes/blog/this-blog/+page.svx | 7 +-- svelte.config.js | 12 ++++-- tailwind.config.js | 2 - tsconfig.json | 4 +- 7 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 rehype/external-links.js 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