@intlayer/docs 8.11.1 → 8.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blog/en/i18n_using_next-i18next.md +3 -3
- package/blog/en/i18n_using_next-intl.md +3 -3
- package/blog/en/list_i18n_technologies/frameworks/angular.md +3 -3
- package/blog/en/list_i18n_technologies/frameworks/react-native.md +3 -3
- package/blog/en/list_i18n_technologies/frameworks/react.md +3 -3
- package/blog/en/list_i18n_technologies/frameworks/svelte.md +3 -3
- package/blog/en/list_i18n_technologies/frameworks/vue.md +3 -3
- package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +3 -3
- package/dist/cjs/generated/blog.entry.cjs +0 -1
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +0 -1
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +0 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +0 -1
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/docs/ar/dictionary/markdown.md +161 -0
- package/docs/de/dictionary/markdown.md +161 -0
- package/docs/en/dictionary/markdown.md +163 -0
- package/docs/en/intlayer_with_adonisjs.md +3 -3
- package/docs/en/intlayer_with_analog.md +3 -3
- package/docs/en/intlayer_with_angular_19.md +3 -3
- package/docs/en/intlayer_with_angular_21.md +3 -3
- package/docs/en/intlayer_with_astro.md +3 -3
- package/docs/en/intlayer_with_astro_lit.md +3 -3
- package/docs/en/intlayer_with_astro_preact.md +3 -3
- package/docs/en/intlayer_with_astro_react.md +3 -3
- package/docs/en/intlayer_with_astro_solid.md +3 -3
- package/docs/en/intlayer_with_astro_svelte.md +3 -3
- package/docs/en/intlayer_with_astro_vanilla.md +3 -3
- package/docs/en/intlayer_with_astro_vue.md +3 -3
- package/docs/en/intlayer_with_create_react_app.md +3 -3
- package/docs/en/intlayer_with_express.md +3 -3
- package/docs/en/intlayer_with_fastify.md +3 -3
- package/docs/en/intlayer_with_hono.md +3 -3
- package/docs/en/intlayer_with_lynx+react.md +3 -3
- package/docs/en/intlayer_with_nestjs.md +3 -3
- package/docs/en/intlayer_with_next-i18next.md +3 -3
- package/docs/en/intlayer_with_next-intl.md +3 -3
- package/docs/en/intlayer_with_nextjs_14.md +3 -3
- package/docs/en/intlayer_with_nextjs_15.md +3 -3
- package/docs/en/intlayer_with_nextjs_16.md +3 -3
- package/docs/en/intlayer_with_nextjs_compiler.md +3 -3
- package/docs/en/intlayer_with_nextjs_no_locale_path.md +3 -3
- package/docs/en/intlayer_with_nextjs_page_router.md +3 -3
- package/docs/en/intlayer_with_nuxt.md +3 -3
- package/docs/en/intlayer_with_react_native+expo.md +3 -3
- package/docs/en/intlayer_with_react_router_v7.md +3 -3
- package/docs/en/intlayer_with_react_router_v7_fs_routes.md +3 -3
- package/docs/en/intlayer_with_svelte_kit.md +3 -3
- package/docs/en/intlayer_with_tanstack+solid.md +3 -3
- package/docs/en/intlayer_with_tanstack.md +3 -3
- package/docs/en/intlayer_with_vanilla.md +3 -3
- package/docs/en/intlayer_with_vite+lit.md +3 -3
- package/docs/en/intlayer_with_vite+preact.md +3 -3
- package/docs/en/intlayer_with_vite+react.md +3 -3
- package/docs/en/intlayer_with_vite+react_compiler.md +3 -3
- package/docs/en/intlayer_with_vite+solid.md +3 -3
- package/docs/en/intlayer_with_vite+svelte.md +3 -3
- package/docs/en/intlayer_with_vite+vanilla.md +3 -3
- package/docs/en/intlayer_with_vite+vue.md +3 -3
- package/docs/en-GB/dictionary/markdown.md +161 -0
- package/docs/es/dictionary/markdown.md +161 -0
- package/docs/fr/dictionary/markdown.md +161 -0
- package/docs/hi/dictionary/markdown.md +161 -0
- package/docs/id/dictionary/markdown.md +161 -0
- package/docs/it/dictionary/markdown.md +161 -0
- package/docs/ko/dictionary/markdown.md +161 -0
- package/docs/pl/dictionary/markdown.md +161 -0
- package/docs/pt/dictionary/markdown.md +161 -0
- package/docs/ru/dictionary/markdown.md +161 -0
- package/docs/tr/dictionary/markdown.md +161 -0
- package/docs/uk/dictionary/markdown.md +161 -0
- package/docs/vi/dictionary/markdown.md +161 -0
- package/docs/zh/dictionary/markdown.md +161 -0
- package/package.json +7 -7
|
@@ -17,6 +17,9 @@ slugs:
|
|
|
17
17
|
- content
|
|
18
18
|
- markdown
|
|
19
19
|
history:
|
|
20
|
+
- version: 8.11.0
|
|
21
|
+
date: 2026-05-28
|
|
22
|
+
changes: "Разрешить предварительный синтаксический анализ AST Markdown для SSR / гидратации"
|
|
20
23
|
- version: 8.10.0
|
|
21
24
|
date: 2026-05-19
|
|
22
25
|
changes: "Добавлена поддержка файлов `.content.md`"
|
|
@@ -661,6 +664,164 @@ export class MyComponent {
|
|
|
661
664
|
|
|
662
665
|
---
|
|
663
666
|
|
|
667
|
+
## Рендеринг на стороне сервера (SSR) и гидратация
|
|
668
|
+
|
|
669
|
+
По сравнению с другими парсерами Markdown, такими как remark / rehype, Intlayer Markdown не имеет зависимостей и работает как на клиенте, так и на сервере.
|
|
670
|
+
|
|
671
|
+
Однако Intlayer оптимизирует синтаксический анализ для фреймворков серверного рендеринга (SSR) (таких как Next.js App Router, React Router, Nuxt, SvelteKit и т. д.).
|
|
672
|
+
|
|
673
|
+
Вместо отправки необработанных строк Markdown клиенту и их анализа в браузере (что приводит к снижению производительности), Intlayer позволяет предварительно проанализировать Markdown в абстрактное синтаксическое дерево (AST) на сервере.
|
|
674
|
+
|
|
675
|
+
Вы можете использовать функцию `parseMarkdown` из пакета Intlayer вашего фреймворка на стороне сервера для генерации сериализуемого AST (объекта `ParsedMarkdown`) и передачи его непосредственно на фронтенд. Все утилиты рендеринга Intlayer (такие как `<MarkdownRenderer>`, `useMarkdownRenderer` и т. д.) автоматически принимают этот объект AST и плавно рендерят его.
|
|
676
|
+
|
|
677
|
+
### Пример в архитектуре Сервер/Клиент
|
|
678
|
+
|
|
679
|
+
<Tabs group="framework">
|
|
680
|
+
<Tab label="React Router" value="react">
|
|
681
|
+
|
|
682
|
+
```tsx fileName="server.ts"
|
|
683
|
+
import { parseMarkdown } from "react-intlayer/markdown";
|
|
684
|
+
|
|
685
|
+
// 1. На сервере: преобразовать markdown в сериализуемое AST
|
|
686
|
+
export const loader = async () => {
|
|
687
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
688
|
+
const ast = parseMarkdown(markdownString);
|
|
689
|
+
|
|
690
|
+
// Возвратить AST клиенту в формате JSON
|
|
691
|
+
return Response.json({ content: ast });
|
|
692
|
+
};
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
```tsx fileName="client.tsx"
|
|
696
|
+
import { useLoaderData } from "react-router";
|
|
697
|
+
import { MarkdownRenderer } from "react-intlayer/markdown";
|
|
698
|
+
|
|
699
|
+
// 2. На клиенте: отрендерить AST напрямую без повторного анализа
|
|
700
|
+
export default function Page() {
|
|
701
|
+
const { content } = useLoaderData();
|
|
702
|
+
|
|
703
|
+
// Рендерер принимает либо необработанную строку, либо проанализированное AST
|
|
704
|
+
return <MarkdownRenderer content={content} />;
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
</Tab>
|
|
709
|
+
<Tab label="Next.js" value="nextjs">
|
|
710
|
+
|
|
711
|
+
```tsx fileName="app/page.tsx"
|
|
712
|
+
import { parseMarkdown } from "next-intlayer/markdown";
|
|
713
|
+
import { MarkdownRenderer } from "next-intlayer/markdown";
|
|
714
|
+
|
|
715
|
+
export default async function Page() {
|
|
716
|
+
// 1. Преобразовать markdown в сериализуемое AST на сервере
|
|
717
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
718
|
+
const ast = parseMarkdown(markdownString);
|
|
719
|
+
|
|
720
|
+
// 2. Отрендерить AST напрямую
|
|
721
|
+
// В серверном компоненте это работает бесшовно и передает AST
|
|
722
|
+
// напрямую в базовые клиентские компоненты, если это необходимо.
|
|
723
|
+
return <MarkdownRenderer content={ast} />;
|
|
724
|
+
}
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
</Tab>
|
|
728
|
+
<Tab label="Vue / Nuxt" value="vue">
|
|
729
|
+
|
|
730
|
+
```vue fileName="pages/index.vue"
|
|
731
|
+
<script setup lang="ts">
|
|
732
|
+
import { parseMarkdown } from "vue-intlayer/markdown";
|
|
733
|
+
import { MarkdownRenderer } from "vue-intlayer/markdown";
|
|
734
|
+
|
|
735
|
+
// 1. Получить и преобразовать markdown в AST на сервере
|
|
736
|
+
const { data: ast } = await useAsyncData('markdown', () => {
|
|
737
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
738
|
+
return parseMarkdown(markdownString);
|
|
739
|
+
});
|
|
740
|
+
</script>
|
|
741
|
+
|
|
742
|
+
<template>
|
|
743
|
+
<!-- 2. На клиенте: отрендерить AST напрямую без повторного анализа -->
|
|
744
|
+
<MarkdownRenderer :content="ast" />
|
|
745
|
+
</template>
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
</Tab>
|
|
749
|
+
<Tab label="SvelteKit" value="svelte">
|
|
750
|
+
|
|
751
|
+
```typescript fileName="+page.server.ts"
|
|
752
|
+
import { parseMarkdown } from "svelte-intlayer/markdown";
|
|
753
|
+
|
|
754
|
+
// 1. На сервере: преобразовать markdown в сериализуемое AST
|
|
755
|
+
export const load = async () => {
|
|
756
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
757
|
+
const ast = parseMarkdown(markdownString);
|
|
758
|
+
|
|
759
|
+
// Возвратить AST клиенту
|
|
760
|
+
return { content: ast };
|
|
761
|
+
};
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
```svelte fileName="+page.svelte"
|
|
765
|
+
<script lang="ts">
|
|
766
|
+
import { MarkdownRenderer } from "svelte-intlayer/markdown";
|
|
767
|
+
export let data;
|
|
768
|
+
</script>
|
|
769
|
+
|
|
770
|
+
<!-- 2. На клиенте: отрендерить AST напрямую без повторного анализа -->
|
|
771
|
+
<MarkdownRenderer value={data.content} />
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
</Tab>
|
|
775
|
+
<Tab label="Angular" value="angular">
|
|
776
|
+
|
|
777
|
+
Angular SSR обычно разрешает данные на сервере во время первоначальной загрузки и выполняет гидратацию на клиенте. Вы можете использовать резолверы для передачи AST.
|
|
778
|
+
|
|
779
|
+
```typescript fileName="app.resolver.ts"
|
|
780
|
+
import { Injectable } from "@angular/core";
|
|
781
|
+
import { Resolve } from "@angular/router";
|
|
782
|
+
import { parseMarkdown, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
783
|
+
|
|
784
|
+
@Injectable({ providedIn: "root" })
|
|
785
|
+
export class MarkdownResolver implements Resolve<ParsedMarkdown> {
|
|
786
|
+
resolve(): ParsedMarkdown {
|
|
787
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
788
|
+
// 1. На сервере: преобразовать markdown в сериализуемое AST
|
|
789
|
+
return parseMarkdown(markdownString);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
```typescript fileName="app.component.ts"
|
|
795
|
+
import { Component } from "@angular/core";
|
|
796
|
+
import { ActivatedRoute } from "@angular/router";
|
|
797
|
+
import { IntlayerMarkdownService, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
798
|
+
|
|
799
|
+
@Component({
|
|
800
|
+
selector: "app-root",
|
|
801
|
+
template: `<div [innerHTML]="renderedMarkdown"></div>`,
|
|
802
|
+
})
|
|
803
|
+
export class AppComponent {
|
|
804
|
+
renderedMarkdown: string = "";
|
|
805
|
+
|
|
806
|
+
constructor(
|
|
807
|
+
private route: ActivatedRoute,
|
|
808
|
+
private markdownService: IntlayerMarkdownService
|
|
809
|
+
) {
|
|
810
|
+
// 2. На клиенте: отрендерить AST напрямую без повторного анализа
|
|
811
|
+
this.route.data.subscribe((data) => {
|
|
812
|
+
this.renderedMarkdown = this.markdownService.renderMarkdown(
|
|
813
|
+
data.markdownAst
|
|
814
|
+
) as string;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
</Tab>
|
|
821
|
+
</Tabs>
|
|
822
|
+
|
|
823
|
+
Этот подход гарантирует, что логика анализа Markdown полностью выполняется на сервере, что значительно сокращает время выполнения на стороне клиента и повышает скорость первоначальной гидратации.
|
|
824
|
+
|
|
664
825
|
## Справочник по опциям
|
|
665
826
|
|
|
666
827
|
Эти параметры могут быть переданы в `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer` и `renderMarkdown`.
|
|
@@ -17,6 +17,9 @@ slugs:
|
|
|
17
17
|
- content
|
|
18
18
|
- markdown
|
|
19
19
|
history:
|
|
20
|
+
- version: 8.11.0
|
|
21
|
+
date: 2026-05-28
|
|
22
|
+
changes: "SSR / hidrasyon için Markdown AST'sinin önceden ayrıştırılmasına izin ver"
|
|
20
23
|
- version: 8.10.0
|
|
21
24
|
date: 2026-05-19
|
|
22
25
|
changes: "`.content.md` dosyaları için destek eklendi"
|
|
@@ -1149,6 +1152,164 @@ export class MyComponent {
|
|
|
1149
1152
|
|
|
1150
1153
|
---
|
|
1151
1154
|
|
|
1155
|
+
## Sunucu Tarafı İşleme (SSR) ve Hidrasyon
|
|
1156
|
+
|
|
1157
|
+
Remark / rehype gibi diğer Markdown ayrıştırıcılarıyla karşılaştırıldığında, Intlayer Markdown bağımlılık içermez ve hem istemci hem de sunucu tarafında çalışır.
|
|
1158
|
+
|
|
1159
|
+
Ancak Intlayer, Sunucu Tarafı İşleme (SSR) çerçeveleri (Next.js App Router, React Router, Nuxt, SvelteKit vb. gibi) için ayrıştırmayı optimize etmiştir.
|
|
1160
|
+
|
|
1161
|
+
Ham Markdown dizelerini istemciye göndermek ve tarayıcıda ayrıştırmak (bu da performans kaybına neden olur) yerine, Intlayer, Markdown'u sunucuda bir Soyut Sözdizimi Ağacı (AST) olarak önceden ayrıştırmanıza olanak tanır.
|
|
1162
|
+
|
|
1163
|
+
Serileştirilebilir bir AST (`ParsedMarkdown` nesnesi) oluşturmak için sunucu tarafında çerçevenizin Intlayer paketindeki `parseMarkdown` işlevini kullanabilir ve bunu doğrudan ön uca aktarabilirsiniz. Tüm Intlayer işleme yardımcı programları ( `<MarkdownRenderer>`, `useMarkdownRenderer` vb. gibi) bu AST nesnesini otomatik olarak kabul eder ve sorunsuz bir şekilde işler.
|
|
1164
|
+
|
|
1165
|
+
### Sunucu/İstemci Mimarisinde Örnek
|
|
1166
|
+
|
|
1167
|
+
<Tabs group="framework">
|
|
1168
|
+
<Tab label="React Router" value="react">
|
|
1169
|
+
|
|
1170
|
+
```tsx fileName="server.ts"
|
|
1171
|
+
import { parseMarkdown } from "react-intlayer/markdown";
|
|
1172
|
+
|
|
1173
|
+
// 1. Sunucuda: Markdown'u serileştirilebilir bir AST'ye ayrıştırın
|
|
1174
|
+
export const loader = async () => {
|
|
1175
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1176
|
+
const ast = parseMarkdown(markdownString);
|
|
1177
|
+
|
|
1178
|
+
// AST'yi istemciye JSON olarak döndürün
|
|
1179
|
+
return Response.json({ content: ast });
|
|
1180
|
+
};
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
```tsx fileName="client.tsx"
|
|
1184
|
+
import { useLoaderData } from "react-router";
|
|
1185
|
+
import { MarkdownRenderer } from "react-intlayer/markdown";
|
|
1186
|
+
|
|
1187
|
+
// 2. İstemcide: AST'yi yeniden ayrıştırmadan doğrudan işleyin
|
|
1188
|
+
export default function Page() {
|
|
1189
|
+
const { content } = useLoaderData();
|
|
1190
|
+
|
|
1191
|
+
// İşleyici, ham bir dizeyi veya ayrıştırılmış AST'yi kabul eder
|
|
1192
|
+
return <MarkdownRenderer content={content} />;
|
|
1193
|
+
}
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
</Tab>
|
|
1197
|
+
<Tab label="Next.js" value="nextjs">
|
|
1198
|
+
|
|
1199
|
+
```tsx fileName="app/page.tsx"
|
|
1200
|
+
import { parseMarkdown } from "next-intlayer/markdown";
|
|
1201
|
+
import { MarkdownRenderer } from "next-intlayer/markdown";
|
|
1202
|
+
|
|
1203
|
+
export default async function Page() {
|
|
1204
|
+
// 1. Sunucuda Markdown'u serileştirilebilir bir AST'ye ayrıştırın
|
|
1205
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1206
|
+
const ast = parseMarkdown(markdownString);
|
|
1207
|
+
|
|
1208
|
+
// 2. AST'yi doğrudan işleyin
|
|
1209
|
+
// Bir Server Component içinde bu sorunsuz çalışır ve gerekirse AST'yi
|
|
1210
|
+
// doğrudan alt istemci bileşenlerine iletir.
|
|
1211
|
+
return <MarkdownRenderer content={ast} />;
|
|
1212
|
+
}
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
</Tab>
|
|
1216
|
+
<Tab label="Vue / Nuxt" value="vue">
|
|
1217
|
+
|
|
1218
|
+
```vue fileName="pages/index.vue"
|
|
1219
|
+
<script setup lang="ts">
|
|
1220
|
+
import { parseMarkdown } from "vue-intlayer/markdown";
|
|
1221
|
+
import { MarkdownRenderer } from "vue-intlayer/markdown";
|
|
1222
|
+
|
|
1223
|
+
// 1. Sunucuda markdown'u getirin ve bir AST'ye ayrıştırın
|
|
1224
|
+
const { data: ast } = await useAsyncData('markdown', () => {
|
|
1225
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1226
|
+
return parseMarkdown(markdownString);
|
|
1227
|
+
});
|
|
1228
|
+
</script>
|
|
1229
|
+
|
|
1230
|
+
<template>
|
|
1231
|
+
<!-- 2. İstemcide: AST'yi yeniden ayrıştırmadan doğrudan işleyin -->
|
|
1232
|
+
<MarkdownRenderer :content="ast" />
|
|
1233
|
+
</template>
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
</Tab>
|
|
1237
|
+
<Tab label="SvelteKit" value="svelte">
|
|
1238
|
+
|
|
1239
|
+
```typescript fileName="+page.server.ts"
|
|
1240
|
+
import { parseMarkdown } from "svelte-intlayer/markdown";
|
|
1241
|
+
|
|
1242
|
+
// 1. Sunucuda: Markdown'u serileştirilebilir bir AST'ye ayrıştırın
|
|
1243
|
+
export const load = async () => {
|
|
1244
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1245
|
+
const ast = parseMarkdown(markdownString);
|
|
1246
|
+
|
|
1247
|
+
// AST'yi istemciye döndürün
|
|
1248
|
+
return { content: ast };
|
|
1249
|
+
};
|
|
1250
|
+
```
|
|
1251
|
+
|
|
1252
|
+
```svelte fileName="+page.svelte"
|
|
1253
|
+
<script lang="ts">
|
|
1254
|
+
import { MarkdownRenderer } from "svelte-intlayer/markdown";
|
|
1255
|
+
export let data;
|
|
1256
|
+
</script>
|
|
1257
|
+
|
|
1258
|
+
<!-- 2. İstemcide: AST'yi yeniden ayrıştırmadan doğrudan işleyin -->
|
|
1259
|
+
<MarkdownRenderer value={data.content} />
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
</Tab>
|
|
1263
|
+
<Tab label="Angular" value="angular">
|
|
1264
|
+
|
|
1265
|
+
Angular SSR, verileri genellikle ilk yükleme sırasında sunucuda çözümler ve istemcide hidrasyon gerçekleştirir. AST'yi iletmek için çözümleyiciler (resolvers) kullanabilirsiniz.
|
|
1266
|
+
|
|
1267
|
+
```typescript fileName="app.resolver.ts"
|
|
1268
|
+
import { Injectable } from "@angular/core";
|
|
1269
|
+
import { Resolve } from "@angular/router";
|
|
1270
|
+
import { parseMarkdown, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
1271
|
+
|
|
1272
|
+
@Injectable({ providedIn: "root" })
|
|
1273
|
+
export class MarkdownResolver implements Resolve<ParsedMarkdown> {
|
|
1274
|
+
resolve(): ParsedMarkdown {
|
|
1275
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1276
|
+
// 1. Sunucuda: Markdown'u serileştirilebilir bir AST'ye ayrıştırın
|
|
1277
|
+
return parseMarkdown(markdownString);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
```
|
|
1281
|
+
|
|
1282
|
+
```typescript fileName="app.component.ts"
|
|
1283
|
+
import { Component } from "@angular/core";
|
|
1284
|
+
import { ActivatedRoute } from "@angular/router";
|
|
1285
|
+
import { IntlayerMarkdownService, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
1286
|
+
|
|
1287
|
+
@Component({
|
|
1288
|
+
selector: "app-root",
|
|
1289
|
+
template: `<div [innerHTML]="renderedMarkdown"></div>`,
|
|
1290
|
+
})
|
|
1291
|
+
export class AppComponent {
|
|
1292
|
+
renderedMarkdown: string = "";
|
|
1293
|
+
|
|
1294
|
+
constructor(
|
|
1295
|
+
private route: ActivatedRoute,
|
|
1296
|
+
private markdownService: IntlayerMarkdownService
|
|
1297
|
+
) {
|
|
1298
|
+
// 2. İstemcide: AST'yi yeniden ayrıştırmadan doğrudan işleyin
|
|
1299
|
+
this.route.data.subscribe((data) => {
|
|
1300
|
+
this.renderedMarkdown = this.markdownService.renderMarkdown(
|
|
1301
|
+
data.markdownAst
|
|
1302
|
+
) as string;
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
</Tab>
|
|
1309
|
+
</Tabs>
|
|
1310
|
+
|
|
1311
|
+
Bu model, Markdown ayrıştırma mantığının tamamen sunucuda çalıştırılmasını sağlayarak istemci tarafındaki yürütme süresini önemli ölçüde azaltır ve ilk hidrasyon hızını artırır.
|
|
1312
|
+
|
|
1152
1313
|
## Seçenek Referansı
|
|
1153
1314
|
|
|
1154
1315
|
Bu seçenekler `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer` ve `renderMarkdown`a iletilebilir.
|
|
@@ -17,6 +17,9 @@ slugs:
|
|
|
17
17
|
- content
|
|
18
18
|
- markdown
|
|
19
19
|
history:
|
|
20
|
+
- version: 8.11.0
|
|
21
|
+
date: 2026-05-28
|
|
22
|
+
changes: "Дозволити попередній синтаксичний аналіз AST Markdown для SSR / гідратації"
|
|
20
23
|
- version: 8.10.0
|
|
21
24
|
date: 2026-05-19
|
|
22
25
|
changes: "Додано підтримку файлів `.content.md`"
|
|
@@ -1149,6 +1152,164 @@ export class MyComponent {
|
|
|
1149
1152
|
|
|
1150
1153
|
---
|
|
1151
1154
|
|
|
1155
|
+
## Рендеринг на стороні сервера (SSR) та гідратація
|
|
1156
|
+
|
|
1157
|
+
У порівнянні з іншими парсерами Markdown, такими як remark / rehype, Intlayer Markdown не має залежностей і працює як на клієнті, так і на сервері.
|
|
1158
|
+
|
|
1159
|
+
Однак Intlayer оптимізує синтаксичний аналіз для фреймворків серверного рендерингу (SSR) (таких як Next.js App Router, React Router, Nuxt, SvelteKit тощо).
|
|
1160
|
+
|
|
1161
|
+
Замість надсилання необроблених рядків Markdown клієнту та їх аналізу в браузері (що призводить до зниження продуктивності), Intlayer дозволяє попередньо проаналізувати Markdown в абстрактне синтаксичне дерево (AST) на сервері.
|
|
1162
|
+
|
|
1163
|
+
Ви можете використовувати функцію `parseMarkdown` з пакету Intlayer вашого фреймворку на стороні сервера для генерації серіалізованого AST (об'єкта `ParsedMarkdown`) і передачі його безпосередньо на фронтенд. Всі утиліти рендерингу Intlayer (такі як `<MarkdownRenderer>`, `useMarkdownRenderer` тощо) автоматично приймають цей об'єкт AST і плавно рендерять його.
|
|
1164
|
+
|
|
1165
|
+
### Приклад в архітектурі Сервер/Клієнт
|
|
1166
|
+
|
|
1167
|
+
<Tabs group="framework">
|
|
1168
|
+
<Tab label="React Router" value="react">
|
|
1169
|
+
|
|
1170
|
+
```tsx fileName="server.ts"
|
|
1171
|
+
import { parseMarkdown } from "react-intlayer/markdown";
|
|
1172
|
+
|
|
1173
|
+
// 1. На сервері: перетворити markdown на серіалізоване AST
|
|
1174
|
+
export const loader = async () => {
|
|
1175
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1176
|
+
const ast = parseMarkdown(markdownString);
|
|
1177
|
+
|
|
1178
|
+
// Повернути AST клієнту у форматі JSON
|
|
1179
|
+
return Response.json({ content: ast });
|
|
1180
|
+
};
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
```tsx fileName="client.tsx"
|
|
1184
|
+
import { useLoaderData } from "react-router";
|
|
1185
|
+
import { MarkdownRenderer } from "react-intlayer/markdown";
|
|
1186
|
+
|
|
1187
|
+
// 2. На клієнті: відрендерити AST безпосередньо без повторного аналізу
|
|
1188
|
+
export default function Page() {
|
|
1189
|
+
const { content } = useLoaderData();
|
|
1190
|
+
|
|
1191
|
+
// Рендерер приймає або необроблений рядок, або проаналізоване AST
|
|
1192
|
+
return <MarkdownRenderer content={content} />;
|
|
1193
|
+
}
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
</Tab>
|
|
1197
|
+
<Tab label="Next.js" value="nextjs">
|
|
1198
|
+
|
|
1199
|
+
```tsx fileName="app/page.tsx"
|
|
1200
|
+
import { parseMarkdown } from "next-intlayer/markdown";
|
|
1201
|
+
import { MarkdownRenderer } from "next-intlayer/markdown";
|
|
1202
|
+
|
|
1203
|
+
export default async function Page() {
|
|
1204
|
+
// 1. Перетворити markdown на серіалізоване AST на сервері
|
|
1205
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1206
|
+
const ast = parseMarkdown(markdownString);
|
|
1207
|
+
|
|
1208
|
+
// 2. Відрендерити AST безпосередньо
|
|
1209
|
+
// У серверному компоненті це працює безшовно і передає AST
|
|
1210
|
+
// безпосередньо в базові клієнтські компоненти, якщо це необхідно.
|
|
1211
|
+
return <MarkdownRenderer content={ast} />;
|
|
1212
|
+
}
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
</Tab>
|
|
1216
|
+
<Tab label="Vue / Nuxt" value="vue">
|
|
1217
|
+
|
|
1218
|
+
```vue fileName="pages/index.vue"
|
|
1219
|
+
<script setup lang="ts">
|
|
1220
|
+
import { parseMarkdown } from "vue-intlayer/markdown";
|
|
1221
|
+
import { MarkdownRenderer } from "vue-intlayer/markdown";
|
|
1222
|
+
|
|
1223
|
+
// 1. Отримати та перетворити markdown на AST на сервері
|
|
1224
|
+
const { data: ast } = await useAsyncData('markdown', () => {
|
|
1225
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1226
|
+
return parseMarkdown(markdownString);
|
|
1227
|
+
});
|
|
1228
|
+
</script>
|
|
1229
|
+
|
|
1230
|
+
<template>
|
|
1231
|
+
<!-- 2. На клієнті: відрендерити AST безпосередньо без повторного аналізу -->
|
|
1232
|
+
<MarkdownRenderer :content="ast" />
|
|
1233
|
+
</template>
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
</Tab>
|
|
1237
|
+
<Tab label="SvelteKit" value="svelte">
|
|
1238
|
+
|
|
1239
|
+
```typescript fileName="+page.server.ts"
|
|
1240
|
+
import { parseMarkdown } from "svelte-intlayer/markdown";
|
|
1241
|
+
|
|
1242
|
+
// 1. На сервері: перетворити markdown на серіалізоване AST
|
|
1243
|
+
export const load = async () => {
|
|
1244
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1245
|
+
const ast = parseMarkdown(markdownString);
|
|
1246
|
+
|
|
1247
|
+
// Повернути AST клієнту
|
|
1248
|
+
return { content: ast };
|
|
1249
|
+
};
|
|
1250
|
+
```
|
|
1251
|
+
|
|
1252
|
+
```svelte fileName="+page.svelte"
|
|
1253
|
+
<script lang="ts">
|
|
1254
|
+
import { MarkdownRenderer } from "svelte-intlayer/markdown";
|
|
1255
|
+
export let data;
|
|
1256
|
+
</script>
|
|
1257
|
+
|
|
1258
|
+
<!-- 2. На клієнті: відрендерити AST безпосередньо без повторного аналізу -->
|
|
1259
|
+
<MarkdownRenderer value={data.content} />
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
</Tab>
|
|
1263
|
+
<Tab label="Angular" value="angular">
|
|
1264
|
+
|
|
1265
|
+
Angular SSR зазвичай отримує дані на сервері під час початкового завантаження та виконує гідратацію на клієнті. Ви можете використовувати резолвери для передачі AST.
|
|
1266
|
+
|
|
1267
|
+
```typescript fileName="app.resolver.ts"
|
|
1268
|
+
import { Injectable } from "@angular/core";
|
|
1269
|
+
import { Resolve } from "@angular/router";
|
|
1270
|
+
import { parseMarkdown, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
1271
|
+
|
|
1272
|
+
@Injectable({ providedIn: "root" })
|
|
1273
|
+
export class MarkdownResolver implements Resolve<ParsedMarkdown> {
|
|
1274
|
+
resolve(): ParsedMarkdown {
|
|
1275
|
+
const markdownString = "## My title \n\nLorem Ipsum";
|
|
1276
|
+
// 1. На сервері: перетворити markdown на серіалізоване AST
|
|
1277
|
+
return parseMarkdown(markdownString);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
```
|
|
1281
|
+
|
|
1282
|
+
```typescript fileName="app.component.ts"
|
|
1283
|
+
import { Component } from "@angular/core";
|
|
1284
|
+
import { ActivatedRoute } from "@angular/router";
|
|
1285
|
+
import { IntlayerMarkdownService, type ParsedMarkdown } from "angular-intlayer/markdown";
|
|
1286
|
+
|
|
1287
|
+
@Component({
|
|
1288
|
+
selector: "app-root",
|
|
1289
|
+
template: `<div [innerHTML]="renderedMarkdown"></div>`,
|
|
1290
|
+
})
|
|
1291
|
+
export class AppComponent {
|
|
1292
|
+
renderedMarkdown: string = "";
|
|
1293
|
+
|
|
1294
|
+
constructor(
|
|
1295
|
+
private route: ActivatedRoute,
|
|
1296
|
+
private markdownService: IntlayerMarkdownService
|
|
1297
|
+
) {
|
|
1298
|
+
// 2. На клієнті: відрендерити AST безпосередньо без повторного аналізу
|
|
1299
|
+
this.route.data.subscribe((data) => {
|
|
1300
|
+
this.renderedMarkdown = this.markdownService.renderMarkdown(
|
|
1301
|
+
data.markdownAst
|
|
1302
|
+
) as string;
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
</Tab>
|
|
1309
|
+
</Tabs>
|
|
1310
|
+
|
|
1311
|
+
Цей підхід гарантує, що логіка аналізу Markdown повністю виконується на сервері, що значно скорочує час виконання на стороні клієнта та підвищує швидкість початкової гідратації.
|
|
1312
|
+
|
|
1152
1313
|
## Довідник опцій
|
|
1153
1314
|
|
|
1154
1315
|
Ці параметри можна передати до `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer` та `renderMarkdown`.
|