Рендеринг Markdown из строки в Svelte (mdsvex / SvelteKit)

Учебники Svelte по Markdown, которые я видел, предполагают, что у вас есть доступ к файлу .md или вы пишете Markdown непосредственно в предварительно обработанном файле.

А что если вы хотите отобразить необработанную строку, содержащую Markdown? Пример использования: Вам нужна гибкость, чтобы иметь возможность обслуживать содержимое в формате Markdown из CMS (например, Strapi) без необходимости вносить изменения в файл .md.

Есть несколько способов добиться этого, в данном решении мы будем использовать mdsvex для преобразования Markdown в HTML формат, а затем для рендеринга HTML. mdsvex — это препроцессор Markdown, который по сути является оберткой для MDX, что делает его совместимым со Svelte.

Установка

Если вы не используете SvelteKit, ознакомьтесь с документацией по MDsveX для альтернативной установки, если используете:

Начните с установки его как dev-зависимости.

npm i --save-dev mdsvex
Вход в полноэкранный режим Выйти из полноэкранного режима

или…

yarn add --dev mdsvex
Войти в полноэкранный режим Выйдите из полноэкранного режима

Затем обновите конфигурацию Svelte, включив в нее массив extensions:

(Мы будем использовать файл .svelte, но вы также можете включить расширения, такие как .svx, если вы планируете использовать эти типы файлов).

svelte.config.js

export default {
  preprocess: [
    // your existing config
  ],

  extensions: ['.svelte'], // Add this

  kit: {
    // your existing config...
  }
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Это вся конфигурация, которая нам нужна на данный момент. ☑️

Передача скомпилированной строки компоненту

Давайте настроим загрузчик маршрутов, который имитирует получение данных из API:

+page.server.ts

import type { Load } from '@sveltejs/kit';

const MOCK_RESPONSE_FROM_API = `
## Lorem

Lorem is currently extended with the following plugins.
Instructions on how to use them in your application are linked below.

| Plugin | README |
| ------ | ------ |
| Dropbox | [plugins/dropbox/README.md](Link) |
| Medium | [plugins/medium/README.md](Link) |
| Google Analytics | [plugins/googleanalytics/README.md](Link) |
`;

export const load: Load = async () => {
    const response = MOCK_RESPONSE_FROM_API; // Get data with eg. `fetch`

    return response;
};
Вход в полноэкранный режим Выход из полноэкранного режима

Далее мы можем импортировать функцию compile из mdsvex, объявить переменную, передав в нее (mock) response, и вернуть ее, чтобы она была доступна в нашем компоненте. Мы также занесем его в журнал, чтобы увидеть, что возвращается после compile:

+page.server.ts

import { compile } from 'mdsvex';
// ...
const compiledResponse = await compile(response);

console.log('compiledResponse is: ', compiledResponse);

return compiledResponse;
// ...
Вход в полноэкранный режим Выход из полноэкранного режима

вывод консоли (Учитывая, что это выполняется на стороне сервера, это можно увидеть в терминале, а не в консоли браузера)

Как вы можете видеть, Markdown был скомпилирован в то, что похоже на формат HTML-строки, добавленной вместе с оператором + под ключом code.

Поэтому мы можем обновить оператор возврата, включив в него только то, что нам нужно:

+page.server.ts

export const load: Load = async () => {
    const res = MOCK_RESPONSE_FROM_API; // Get data with eg. `fetch`
    const compiledResponse = await compile(res);

    return { content: compiledResponse?.code };
};
Войти в полноэкранный режим Выход из полноэкранного режима

Рендеринг HTML непосредственно в компоненте

Теперь из нашего компонента нам нужно только получить data через export let и отрендерить его.

Обычно строки вставляются как обычный текст, то есть такие символы, как < и > не имеют специального значения. Поэтому, учитывая, что у нас есть HTML, который мы хотим отобразить напрямую, мы можем использовать HTML-теги:

<p>{@html string}</p>
Войти в полноэкранный режим Выйти из полноэкранного режима

Так что в нашем случае…

+page.svelte

<script lang="ts">
    export let data = {
        content: ''
    };
</script>

<div>{@html data.content}</div>
Войти в полноэкранный режим Выйти из полноэкранного режима

В результате мы получим отрендеренный Markdown 🪄:

Примечание из документации:

Svelte не проверяет выражения перед внедрением HTML. Если данные поступают из ненадежного источника, вы должны их санировать, иначе вы подвергаете своих пользователей XSS-уязвимости.

Дальнейшая настройка

Метод compile принимает второй параметр, options:

interface MdsvexOptions {
    extensions: string[];
    smartypants: boolean | smartypantsOptions;
    layout: string | { [name: string]: string };
    remarkPlugins: Array<plugin> | Array<[plugin, plugin_options]>;
    rehypePlugins: Array<plugin> | Array<[plugin, plugin_options]>;
    highlight: { highlighter: Function, alias: { [alias]: lang } };
    frontmatter: { parse: Function; marker: string };
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Это означает, что вы можете преобразовать ваш HTML с помощью таких инструментов, как rehype или remark. Вы можете узнать больше о доступных опциях здесь.

Вот и все! 👨💻

Если вам нужна дополнительная информация по вышеизложенному или чему-либо еще, связанному с этим — загляните в документацию SvelteKit, документацию MDX или в официальный дискорд Svelte.

Оцените статью
devanswers.ru
Добавить комментарий