\n\n \n \n \n ```\n\n Skonfiguruj globalnie za pomocą wtyczki `intlayerMarkdown` (obsługuje komponenty niestandardowe MDX):\n\n ```ts fileName=\"main.ts\"\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n\n app.use(intlayerMarkdown, {\n components: {\n h1: (props) => h('h1', { style: { color: 'green' } }, props.children),\n MyButton: (props) => h('button', props), // Komponent MDX\n },\n });\n ```\n\n > Jeśli wtyczka `intlayerMarkdown` nie jest zainstalowana, Intlayer wyrenderuje za pomocą domyślnego kompilatora.\n\n Możesz również zapewnić lokalne nadpisania dla określonych węzłów za pomocą metody `.use()`:\n\n ```vue\n h('h1', { style: { color: 'red' } }, props.children),\n })\" />\n ```\n\n Możesz pobrać Markdown jako ciąg znaków:\n\n ```vue\n {{ myMarkdownContent.value }}\n {{ String(myMarkdownContent) }}\n {{ myMarkdownContent.toString() }}\n ```\n\n Możesz uzyskać dostęp do metadanych markdown w ten sposób:\n\n ```vue\n \n \n ```\n\n \n \n Svelte domyślnie renderuje Markdown jako ciąg znaków HTML. Użyj `{@html}`, aby go wyrenderować.\n\n ```svelte fileName=\"App.svelte\"\n \n\n \n {@html $content.myMarkdownContent}\n \n ```\n\n > Jeśli `MarkdownProvider` nie jest obecny, Intlayer wyrenderuje markdown używając domyślnego kompilatora.\n\n Możesz również zapewnić lokalne nadpisania dla określonych węzłów za pomocą metody `.use()`:\n\n ```svelte\n {@html $content.myMarkdownContent.use({ ... })}\n ```\n\n Możesz pobrać Markdown jako ciąg znaków:\n\n ```svelte\n {$content.myMarkdownContent.value}\n {String($content.myMarkdownContent)}\n {$content.myMarkdownContent.toString()}\n ```\n\n Możesz uzyskać dostęp do metadanych markdown w ten sposób:\n\n ```svelte\n {$content.myMarkdownContent.metadata}\n {$content.myMarkdownContent.metadata.title}\n ```\n\n \n \n Preact obsługuje węzły Markdown bezpośrednio w JSX.\n\n ```tsx fileName=\"App.tsx\"\n import { useIntlayer } from \"preact-intlayer\";\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n const AppContent = () => {\n const { myMarkdownContent } = useIntlayer(\"app\");\n return
{myMarkdownContent}
;\n };\n\n const App = () => (\n
{children}
,\n MyButton: (props) => , // Komponent MDX\n }}\n >\n \n \n );\n ```\n\n > Jeśli `MarkdownProvider` nie jest obecny, Intlayer użyje domyślnego parsera Markdown do JSX do wyrenderowania markdownu.\n\n Możesz również zapewnić lokalne nadpisania dla określonych węzłów za pomocą metody `.use()`:\n\n ```tsx\n {myMarkdownContent.use({\n h1: ({ children }) =>
{children}
,\n })}\n ```\n\n Możesz pobrać Markdown jako ciąg znaków:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n Możesz uzyskać dostęp do metadanych markdown w ten sposób:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Solid obsługuje węzły Markdown bezpośrednio w JSX.\n\n ```tsx fileName=\"App.tsx\"\n import { useIntlayer } from \"solid-intlayer\";\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n const AppContent = () => {\n const { myMarkdownContent } = useIntlayer(\"app\");\n return
{myMarkdownContent}
;\n };\n\n const App = () => (\n
{props.children}
,\n MyButton: (props) => , // Komponent MDX\n }}\n >\n \n \n );\n ```\n\n > Jeśli `MarkdownProvider` nie jest obecny, Intlayer użyje domyślnego parsera Markdown do JSX do wyrenderowania markdownu.\n\n Możesz również zapewnić lokalne nadpisania dla określonych węzłów za pomocą metody `.use()`:\n\n ```tsx\n {myMarkdownContent.use({\n h1: (props) =>
{props.children}
,\n })}\n ```\n\n Możesz pobrać Markdown jako ciąg znaków:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n Możesz uzyskać dostęp do metadanych markdown w ten sposób:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Angular używa dyrektywy `[innerHTML]` do renderowania treści Markdown.\n\n ```typescript fileName=\"app.component.ts\"\n import { Component } from \"@angular/core\";\n import { useIntlayer } from \"angular-intlayer\";\n\n @Component({\n selector: \"app-root\",\n template: ``,\n })\n export class AppComponent {\n content = useIntlayer(\"app\");\n }\n ```\n\n > Jeśli dostawca IntlayerMarkdown nie jest skonfigurowany, Intlayer wyrenderuje za pomocą domyślnego kompilatora.\n\n Możesz również zapewnić lokalne nadpisania dla określonych węzłów za pomocą metody `.use()`:\n\n ```typescript\n content().myMarkdownContent.use({\n h1: { class: \"text-3xl font-bold\" },\n })\n ```\n\n Możesz pobrać Markdown jako ciąg znaków:\n\n ```typescript\n content().myMarkdownContent.value\n String(content().myMarkdownContent)\n content().myMarkdownContent.toString()\n ```\n\n Możesz uzyskać dostęp do metadanych markdown w ten sposób:\n\n ```typescript\n content().myMarkdownContent.metadata\n content().myMarkdownContent.metadata.title\n ```\n\n \n\n\n### 2. Narzędzia pomocnicze (tylko ciągi znaków Markdown)\n\nTe narzędzia renderują **tylko surowe ciągi znaków Markdown** i są niezależne od `useIntlayer`. Używaj ich, gdy musisz wyrenderować Markdown ze źródeł innych niż słowniki.\n\n\n \n \n #### Komponent ``\n\n Renderuje ciąg znaków Markdown z określonymi opcjami.\n\n ```tsx\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n \n {\"# Mój Tytuł\"}\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n Pobierz wstępnie skonfigurowaną funkcję renderowania.\n\n ```tsx\n import { useMarkdownRenderer } from \"react-intlayer/markdown\";\n\n const renderMarkdown = useMarkdownRenderer({\n forceBlock: true,\n components: { h1: (props) => }\n });\n\n return renderMarkdown(\"# Mój Tytuł\");\n ```\n\n #### Narzędzie `renderMarkdown()`\n Samodzielne narzędzie do renderowania poza komponentami.\n\n ```tsx\n import { renderMarkdown } from \"react-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# Mój Tytuł\", { forceBlock: true });\n ```\n\n \n \n \n #### Komponent ``\n\n Renderuje ciąg znaków Markdown z określonymi opcjami.\n\n ```tsx\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n \n {\"# Mój Tytuł\"}\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n Pobierz wstępnie skonfigurowaną funkcję renderowania.\n\n ```tsx\n import { useMarkdownRenderer } from \"next-intlayer/markdown\";\n\n const renderMarkdown = useMarkdownRenderer({\n forceBlock: true,\n components: { h1: (props) => }\n });\n\n return renderMarkdown(\"# Mój Tytuł\");\n ```\n\n #### Narzędzie `renderMarkdown()`\n Samodzielne narzędzie do renderowania poza komponentami.\n\n ```tsx\n import { renderMarkdown } from \"next-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# Mój Tytuł\", { forceBlock: true });\n ```\n\n \n \n\n #### Komponent ``\n\n ```vue\n \n\n \n \n \n ```\n\n \n \n\n #### Komponent ``\n\n ```svelte\n \n\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n ```svelte\n \n\n {@html render(\"# Mój Tytuł\")}\n ```\n\n #### Narzędzie `renderMarkdown()`\n\n ```svelte\n \n\n {@html renderMarkdown(\"# Mój Tytuł\")}\n ```\n\n \n \n #### Komponent ``\n\n ```tsx\n import { MarkdownRenderer } from \"preact-intlayer/markdown\";\n\n \n {\"# Mój Tytuł\"}\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n ```tsx\n import { useMarkdownRenderer } from \"preact-intlayer/markdown\";\n\n const render = useMarkdownRenderer();\n\n return
;\n ```\n\n \n \n #### Usługa `IntlayerMarkdownService`\n Renderuje ciąg znaków Markdown przy użyciu usługi.\n\n ```typescript\n import { IntlayerMarkdownService } from \"angular-intlayer/markdown\";\n\n export class MyComponent {\n constructor(private markdownService: IntlayerMarkdownService) {}\n\n renderMarkdown(markdown: string) {\n return this.markdownService.renderMarkdown(markdown);\n }\n }\n ```\n\n \n\n\n## Konfiguracja globalna z `MarkdownProvider`\n\n`MarkdownProvider` (lub jego odpowiednik we frameworku) konfiguruje potok renderowania Markdown dla całej aplikacji. Dotyczy to zarówno automatycznego renderowania `useIntlayer`, jak i narzędzi pomocniczych. Ustawione tutaj opcje są ustawieniami domyślnymi — `.use()` nadpisuje je na poziomie węzła.\n\n\n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"react-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n ,\n a: ({ href, ...props }) => ,\n MyCustomJSXComponent: (props) => ,\n }}\n >\n {children}\n \n );\n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"react-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n // Use dynamic import to reduce the bundle size of your application\n const { renderMarkdown } = await import('react-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"next-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n ,\n a: ({ href, ...props }) => ,\n MyCustomJSXComponent: (props) => ,\n }}\n >\n {children}\n \n );\n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"next-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n // Use dynamic import to reduce the bundle size of your application\n const { renderMarkdown } = await import('next-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```typescript fileName=\"main.ts\"\n import { createApp } from \"vue\";\n import { intlayer } from \"vue-intlayer\";\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n import App from \"./App.vue\";\n\n const app = createApp(App);\n\n app.use(intlayer);\n app.use(intlayerMarkdown, {\n components: {\n h1: (props) =>\n h('h1', { style: { color: 'orange' }, ...props }, props.children),\n ComponentDemo: () => h('div', { style: { background: 'grey' } }, 'DEMO'),\n bold: (props) => h('strong', props),\n code: (props) => h('code', props),\n },\n });\n\n app.mount(\"#app\");\n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```typescript fileName=\"main.ts\"\n import { createApp } from \"vue\";\n import { intlayer } from \"vue-intlayer\";\n import { intlayerMarkdown } from \"vue-intlayer/markdown\";\n import App from \"./App.vue\";\n\n const app = createApp(App);\n\n app.use(intlayer);\n app.use(intlayerMarkdown, {\n renderMarkdown: async (md) => {\n const { renderMarkdown } = await import('vue-intlayer/markdown');\n return renderMarkdown(md);\n },\n });\n\n app.mount(\"#app\");\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```svelte fileName=\"App.svelte\"\n \n\n \n \n \n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```svelte fileName=\"App.svelte\"\n \n\n {\n const { renderMarkdown } = await import('svelte-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n \n \n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n
{children}
,\n }}\n >\n {children}\n \n );\n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"preact-intlayer/markdown\";\n\n export const AppProvider = ({ children }) => (\n {\n const { renderMarkdown } = await import('preact-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {children}\n \n );\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n export const AppProvider = (props) => (\n
{props.children}
,\n }}\n >\n {props.children}\n \n );\n ```\n\n\n > MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. ``) jest rozwiązywana względem mapy `components`.\n\n Możesz również użyć własnego renderera markdown:\n\n ```tsx fileName=\"AppProvider.tsx\"\n import { MarkdownProvider } from \"solid-intlayer/markdown\";\n\n export const AppProvider = (props) => (\n {\n const { renderMarkdown } = await import('solid-intlayer/markdown');\n return renderMarkdown(md);\n }}\n >\n {props.children}\n \n );\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n \n\n ```typescript fileName=\"app.module.ts\"\n import { NgModule } from '@angular/core';\n import { IntlayerMarkdownModule } from 'angular-intlayer/markdown';\n\n @NgModule({\n imports: [\n IntlayerMarkdownModule.forRoot({\n renderMarkdown: async (md) => {\n const { renderMarkdown } = await import('angular-intlayer/markdown');\n return renderMarkdown(md);\n }\n })\n ]\n })\n export class AppModule {}\n ```\n\n > Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.\n\n \n\n\n## Suspense\n\nRenderer Markdown Intlayer jest ładowany dynamicznie. Mimo optymalizacji, bazowy fragment parsera zajmuje około 55 kb. Synchroniczne ładowanie tego opóźnia początkowe renderowanie strony i pogarsza First Contentful Paint (FCP).\n\nAby zapobiec blokowaniu interfejsu użytkownika, Intlayer integruje się z API Suspense Reacta. Pobiera parser w tle i rzuca Promise podczas pobierania.\n\nZawiń dowolny komponent renderujący Intlayer Markdown w granicę ``. Wyświetli to zlokalizowany stan rezerwowy podczas pobierania fragmentu, umożliwiając natychmiastowe renderowanie reszty DOM.\n\nOstrzeżenie: Jeśli nie zapewnisz granicy ``, React wstrzyma działanie na poziomie głównym lub zablokuje renderowanie całego drzewa komponentów do czasu pełnego załadowania 55 kb fragmentu.\n\n\n \n\nW Next.js App Router można użyć React `Suspense` dla komponentów klienckich lub pliku `loading.tsx` dla komponentów serwerowych.\n\n**Komponent kliencki:**\n\n```tsx fileName=\"components/MyComponent.tsx\"\n\"use client\";\nimport { useIntlayer } from \"next-intlayer\";\nimport { Suspense } from \"react\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n**Komponent serwerowy z `loading.tsx`:**\n\n```tsx fileName=\"app/loading.tsx\"\nexport default function Loading() {\n return
;\n};\n\nexport default MyPage;\n```\n\n \n\n \n\n```tsx\nimport { useIntlayer } from \"react-intlayer\";\nimport { Suspense } from \"react\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n \n\nVue ma wbudowany komponent ``. Zawiń komponent renderujący zawartość Markdown w granicę ``.\n\n```vue fileName=\"MyComponent.vue\"\n\n\n\n \n \n \n
Loading...
\n \n \n\n```\n\n \n \n\nSvelte nie ma odpowiednika API Suspense. Użyj bloku `{#await}`, aby obsłużyć asynchroniczne renderowanie zawartości Markdown.\n\n```svelte fileName=\"MyComponent.svelte\"\n\n\n{#await $content.markdownContent}\n
Loading...
\n{:then rendered}\n {@html rendered}\n{/await}\n```\n\n \n \n\nPreact obsługuje API Suspense Reacta przez `preact/compat`.\n\n```tsx fileName=\"MyComponent.tsx\"\nimport { useIntlayer } from \"preact-intlayer\";\nimport { Suspense } from \"preact/compat\";\n\nconst MyComponent = () => {\n const markdownContent = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n\nSolid ma swój własny komponent `` z `solid-js`.\n\n```tsx fileName=\"MyComponent.tsx\"\nimport { useIntlayer } from \"solid-intlayer\";\nimport { Suspense } from \"solid-js\";\n\nconst MyComponent = () => {\n const { markdownContent } = useIntlayer(\"my-markdown\");\n\n return (\n Loading...}>{markdownContent}\n );\n};\n```\n\n \n \n\nAngular nie ma API Suspense. Użyj odroczonych widoków (`@defer`) w Angular, aby obsługiwać leniwie ładowaną zawartość Markdown (wymaga Angular 17+).\n\n```typescript fileName=\"my.component.ts\"\nimport { Component } from \"@angular/core\";\nimport { useIntlayer } from \"angular-intlayer\";\n\n@Component({\n selector: \"app-my\",\n template: `\n @defer {\n \n } @loading {\n
Loading...
\n }\n `,\n})\nexport class MyComponent {\n content = useIntlayer(\"my-markdown\");\n}\n```\n\n \n\n\n---\n\n## Renderowanie po stronie serwera (SSR) i hydratacja\n\nW porównaniu do innych parserów Markdown, takich jak remark / rehype, Intlayer Markdown jest pozbawiony zależności i działa zarówno po stronie klienta, jak i serwera.\n\nJednak Intlayer optymalizuje parsowanie dla frameworków renderowania po stronie serwera (SSR) (takich jak Next.js App Router, React Router, Nuxt, SvelteKit itp.).\n\nZamiast wysyłać surowe ciągi Markdown do klienta i parsować je w przeglądarce (co powoduje spadek wydajności), Intlayer pozwala na wstępne sparsowanie Markdown do abstrakcyjnego drzewa składniowego (AST) na serwerze.\n\nMożesz użyć funkcji `parseMarkdown` z pakietu Intlayer swojego frameworka po stronie serwera, aby wygenerować serializowalne AST (obiekt `ParsedMarkdown`) i przekazać je bezpośrednio do frontendu. Wszystkie narzędzia renderujące Intlayer (takie jak ``, `useMarkdownRenderer` itp.) automatycznie akceptują ten obiekt AST i renderują go bez zakłóceń.\n\n### Przykład w architekturze serwer/klient\n\n\n \n\n ```tsx fileName=\"server.ts\"\n import { parseMarkdown } from \"react-intlayer/markdown\";\n\n // 1. Na serwerze: Sparsuj markdown do serializowalnego AST\n export const loader = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Zwróć AST jako JSON do klienta\n return Response.json({ content: ast });\n };\n ```\n\n ```tsx fileName=\"client.tsx\"\n import { useLoaderData } from \"react-router\";\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n // 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowania\n export default function Page() {\n const { content } = useLoaderData();\n\n // Renderer akceptuje surowy ciąg znaków lub sparsowane AST\n return ;\n }\n ```\n\n \n \n\n ```tsx fileName=\"app/page.tsx\"\n import { parseMarkdown } from \"next-intlayer/markdown\";\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n export default async function Page() {\n // 1. Sparsuj markdown do serializowalnego AST na serwerze\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 2. Renderuj AST bezpośrednio\n // W Server Component działa to bezproblemowo i przekazuje AST\n // bezpośrednio do bazowych komponentów klienckich, jeśli to konieczne.\n return ;\n }\n ```\n\n \n \n\n ```vue fileName=\"pages/index.vue\"\n \n\n \n \n \n \n ```\n\n \n \n\n ```typescript fileName=\"+page.server.ts\"\n import { parseMarkdown } from \"svelte-intlayer/markdown\";\n\n // 1. Na serwerze: Sparsuj markdown do serializowalnego AST\n export const load = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Zwróć AST do klienta\n return { content: ast };\n };\n ```\n\n ```svelte fileName=\"+page.svelte\"\n \n\n \n \n ```\n\n \n \n\n Angular SSR zazwyczaj pobiera dane na serwerze podczas początkowego ładowania i hydratuje na kliencie. Możesz użyć resolverów do przekazania AST.\n\n ```typescript fileName=\"app.resolver.ts\"\n import { Injectable } from \"@angular/core\";\n import { Resolve } from \"@angular/router\";\n import { parseMarkdown, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Injectable({ providedIn: \"root\" })\n export class MarkdownResolver implements Resolve {\n resolve(): ParsedMarkdown {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n // 1. Na serwerze: Sparsuj markdown do serializowalnego AST\n return parseMarkdown(markdownString);\n }\n }\n ```\n\n ```typescript fileName=\"app.component.ts\"\n import { Component } from \"@angular/core\";\n import { ActivatedRoute } from \"@angular/router\";\n import { IntlayerMarkdownService, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Component({\n selector: \"app-root\",\n template: ``,\n })\n export class AppComponent {\n renderedMarkdown: string = \"\";\n\n constructor(\n private route: ActivatedRoute,\n private markdownService: IntlayerMarkdownService\n ) {\n // 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowania\n this.route.data.subscribe((data) => {\n this.renderedMarkdown = this.markdownService.renderMarkdown(\n data.markdownAst\n ) as string;\n });\n }\n }\n ```\n\n \n\n\nTen wzorzec zapewnia, że logika parsowania Markdown jest wykonywana całkowicie na serwerze, co znacznie skraca czas wykonywania po stronie klienta i poprawia szybkość początkowej hydratacji.\n\n## Opcje referencyjne\n\nTe opcje można przekazać do `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer` i `renderMarkdown`.\n\n| Option | Type | Default | Opis |\n| :-------------------- | :---------- | :------ | :------------------------------------------------------------------------------------------------------ |\n| `forceBlock` | `boolean` | `false` | Wymusza zawijanie wyjścia w element blokowy (np. `
`). |\n| `forceInline` | `boolean` | `false` | Wymusza zawijanie wyjścia w element liniowy (np. ``). |\n| `tagfilter` | `boolean` | `true` | Włącza GitHub Tag Filter w celu zwiększenia bezpieczeństwa poprzez usuwanie niebezpiecznych tagów HTML. |\n| `preserveFrontmatter` | `boolean` | `false` | Jeśli `true`, frontmatter na początku ciągu Markdown nie zostanie usunięty. |\n| `components` | `Overrides` | `{}` | Mapa tagów HTML na niestandardowe komponenty (np. `{ h1: MyHeading }`). |\n| `wrapper` | `Component` | `null` | Niestandardowy komponent do zawijania renderowanego Markdown. |\n| `renderMarkdown` | `Function` | `null` | Niestandardowa funkcja renderowania, aby całkowicie zastąpić domyślny kompilator Markdown. |\n","description":"Dowiedz się, jak deklarować i używać treści Markdown na swojej wielojęzycznej stronie internetowej za pomocą Intlayer. Postępuj zgodnie z instrukcjami w tej dokumentacji online, aby bezproblemowo zintegrować Markdown ze swoim projektem.","url":"https://intlayer.org/pl/doc/concept/content/markdown","datePublished":"2025-02-07","dateModified":"2026-05-19","version":"8.11.0","keywords":"Markdown, Internacjonalizacja, Dokumentacja, Intlayer, Next.js, JavaScript, React","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"Programiści, Menedżerowie treści"}}
Intlayer obsługuje treści w postaci tekstu sformatowanego (Rich Text) definiowane za pomocą składni Markdown. Pozwala to na łatwe pisanie i utrzymywanie bogato sformatowanych treści, takich jak blogi, artykuły i inne.
Deklarowanie treści Markdown
Możesz zadeklarować treść Markdown używając funkcji md lub po prostu jako ciąg znaków (jeśli zawiera składnię Markdown).
Począwszy od wersji 8.10.0, możesz deklarować treść Markdown bezpośrednio w plikach .content.md. Intlayer automatycznie wykryje i przetworzy treść Markdown.
markdown-file.en.content.md
Kopiuj kod
Skopiuj kod do schowka
---key: my-markdown-contentdescription: Moja treśćlocale: en---# Moja treśćOto przykład treści markdown
Pole front-matter locale to pole, które definiuje język treści. Jest ono opcjonalne. Jeśli nie zostanie podane, Intlayer użyje języka domyślnego, który służy również jako język zastępczy, jeśli nie jest dostępne tłumaczenie dla określonego języka.
Do front-matter można dodać dowolne właściwości zdefiniowane w Definicji słownika
Użyj funkcji md, aby jawnie zadeklarować treść Markdown. Jest to przydatne, jeśli chcesz upewnić się, że ciąg znaków jest traktowany jako Markdown, nawet jeśli nie zawiera wyraźnej składni.
markdownDictionary.content.ts
Kopiuj kod
Skopiuj kod do schowka
import { md, type Dictionary } from "intlayer";const markdownDictionary = { key: "app", content: { myMarkdownContent: md("## Mój tytuł \n\nLorem Ipsum"), },} satisfies Dictionary;export default markdownDictionary;
Importuj pliki .md bezpośrednio za pomocą funkcji file.
Jeśli ciąg znaków zawiera typowe wskaźniki Markdown (takie jak nagłówki, listy, linki itp.), Intlayer automatycznie je przekształci.
markdownDictionary.content.ts
Kopiuj kod
Skopiuj kod do schowka
export default { key: "app", contentAutoTransformation: true, // Włącz automatyczne wykrywanie treści Markdown - Można ustawić globalnie w intlayer.config.ts content: { myMarkdownContent: "## Mój tytuł \n\nLorem Ipsum", },};
Renderowanie Markdown
Intlayer zapewnia dwa niezależne sposoby renderowania Markdown:
Przez useIntlayer
— Intlayer automatycznie przekształca węzeł md w natywny wynik frameworka (JSX, VNode, ciąg znaków HTML).
Frontmatter jest analizowany i eksponowany jako .metadata. Możesz nadpisać renderowanie na dwóch poziomach — globalnie za pomocą MarkdownProvider (lub odpowiednika frameworka) i lokalnie dla węzła za pomocą .use(). Oba można łączyć; .use() ma pierwszeństwo przed MarkdownProvider, który z kolei ma pierwszeństwo przed ustawieniami domyślnymi.
Narzędzia pomocnicze — <MarkdownRenderer />, useMarkdownRenderer() i renderMarkdown() to samodzielne narzędzia, które akceptują tylko surowe ciągi znaków Markdown. Są one niezależne od useIntlayer i nie działają ze zwracanymi przez nie udekorowanymi węzłami.
Renderowanie Markdown obsługuje MDX — użyj dowolnego komponentu JSX/frameworka podając jego nazwę bezpośrednio w swoim Markdown.
1. Automatyczne renderowanie (przez useIntlayer)
Węzły Markdown można renderować bezpośrednio jako JSX.
Te narzędzia renderują tylko surowe ciągi znaków Markdown i są niezależne od useIntlayer. Używaj ich, gdy musisz wyrenderować Markdown ze źródeł innych niż słowniki.
Komponent <MarkdownRenderer />
Renderuje ciąg znaków Markdown z określonymi opcjami.
import { renderMarkdown } from "solid-intlayer/markdown";return <div>{renderMarkdown("# Mój Tytuł")}</div>;
Usługa IntlayerMarkdownService
Renderuje ciąg znaków Markdown przy użyciu usługi.
typescript
Kopiuj kod
Skopiuj kod do schowka
import { IntlayerMarkdownService } from "angular-intlayer/markdown";export class MyComponent { constructor(private markdownService: IntlayerMarkdownService) {} renderMarkdown(markdown: string) { return this.markdownService.renderMarkdown(markdown); }}
Konfiguracja globalna z MarkdownProvider
MarkdownProvider (lub jego odpowiednik we frameworku) konfiguruje potok renderowania Markdown dla całej aplikacji. Dotyczy to zarówno automatycznego renderowania useIntlayer, jak i narzędzi pomocniczych. Ustawione tutaj opcje są ustawieniami domyślnymi — .use() nadpisuje je na poziomie węzła.
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
Możesz również użyć własnego renderera markdown:
AppProvider.tsx
Kopiuj kod
Skopiuj kod do schowka
import { MarkdownProvider } from "react-intlayer/markdown";export const AppProvider = ({ children }) => ( <MarkdownProvider renderMarkdown={async (md) => { // Use dynamic import to reduce the bundle size of your application const { renderMarkdown } = await import('react-intlayer/markdown'); return renderMarkdown(md); }} > {children} </MarkdownProvider>);
Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
Możesz również użyć własnego renderera markdown:
AppProvider.tsx
Kopiuj kod
Skopiuj kod do schowka
import { MarkdownProvider } from "next-intlayer/markdown";export const AppProvider = ({ children }) => ( <MarkdownProvider renderMarkdown={async (md) => { // Use dynamic import to reduce the bundle size of your application const { renderMarkdown } = await import('next-intlayer/markdown'); return renderMarkdown(md); }} > {children} </MarkdownProvider>);
Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
Możesz również użyć własnego renderera markdown:
main.ts
Kopiuj kod
Skopiuj kod do schowka
import { createApp } from "vue";import { intlayer } from "vue-intlayer";import { intlayerMarkdown } from "vue-intlayer/markdown";import App from "./App.vue";const app = createApp(App);app.use(intlayer);app.use(intlayerMarkdown, { renderMarkdown: async (md) => { const { renderMarkdown } = await import('vue-intlayer/markdown'); return renderMarkdown(md); },});app.mount("#app");
Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.
App.svelte
Kopiuj kod
Skopiuj kod do schowka
<script lang="ts"> import { MarkdownProvider } from "svelte-intlayer/markdown"; import MyHeading from "./MyHeading.svelte";</script><MarkdownProvider components={{ h1: MyHeading, }}> <slot /></MarkdownProvider>
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.
AppProvider.tsx
Kopiuj kod
Skopiuj kod do schowka
import { MarkdownProvider } from "preact-intlayer/markdown";export const AppProvider = ({ children }) => ( <MarkdownProvider components={{ h1: ({ children }) => <h1 className="text-2xl font-bold">{children}</h1>, }} > {children} </MarkdownProvider>);
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
MDX jest obsługiwany — każda nazwa komponentu użyta wewnątrz twojego Markdown (np. <MyCustomJSXComponent />) jest rozwiązywana względem mapy components.
Dynamiczne importowanie twojego renderera Markdown to świetny sposób na zmniejszenie rozmiaru pakietu twojej aplikacji.
Suspense
Renderer Markdown Intlayer jest ładowany dynamicznie. Mimo optymalizacji, bazowy fragment parsera zajmuje około 55 kb. Synchroniczne ładowanie tego opóźnia początkowe renderowanie strony i pogarsza First Contentful Paint (FCP).
Aby zapobiec blokowaniu interfejsu użytkownika, Intlayer integruje się z API Suspense Reacta. Pobiera parser w tle i rzuca Promise podczas pobierania.
Zawiń dowolny komponent renderujący Intlayer Markdown w granicę <Suspense>. Wyświetli to zlokalizowany stan rezerwowy podczas pobierania fragmentu, umożliwiając natychmiastowe renderowanie reszty DOM.
Ostrzeżenie: Jeśli nie zapewnisz granicy <Suspense>, React wstrzyma działanie na poziomie głównym lub zablokuje renderowanie całego drzewa komponentów do czasu pełnego załadowania 55 kb fragmentu.
W Next.js App Router można użyć React Suspense dla komponentów klienckich lub pliku loading.tsx dla komponentów serwerowych.
Angular nie ma API Suspense. Użyj odroczonych widoków (@defer) w Angular, aby obsługiwać leniwie ładowaną zawartość Markdown (wymaga Angular 17+).
my.component.ts
Kopiuj kod
Skopiuj kod do schowka
import { Component } from "@angular/core";import { useIntlayer } from "angular-intlayer";@Component({selector: "app-my",template: ` @defer { <div [innerHTML]="content().markdownContent"></div> } @loading { <div>Loading...</div> }`,})export class MyComponent {content = useIntlayer("my-markdown");}
Renderowanie po stronie serwera (SSR) i hydratacja
W porównaniu do innych parserów Markdown, takich jak remark / rehype, Intlayer Markdown jest pozbawiony zależności i działa zarówno po stronie klienta, jak i serwera.
Jednak Intlayer optymalizuje parsowanie dla frameworków renderowania po stronie serwera (SSR) (takich jak Next.js App Router, React Router, Nuxt, SvelteKit itp.).
Zamiast wysyłać surowe ciągi Markdown do klienta i parsować je w przeglądarce (co powoduje spadek wydajności), Intlayer pozwala na wstępne sparsowanie Markdown do abstrakcyjnego drzewa składniowego (AST) na serwerze.
Możesz użyć funkcji parseMarkdown z pakietu Intlayer swojego frameworka po stronie serwera, aby wygenerować serializowalne AST (obiekt ParsedMarkdown) i przekazać je bezpośrednio do frontendu. Wszystkie narzędzia renderujące Intlayer (takie jak <MarkdownRenderer>, useMarkdownRenderer itp.) automatycznie akceptują ten obiekt AST i renderują go bez zakłóceń.
Przykład w architekturze serwer/klient
server.ts
Kopiuj kod
Skopiuj kod do schowka
import { parseMarkdown } from "react-intlayer/markdown";// 1. Na serwerze: Sparsuj markdown do serializowalnego ASTexport const loader = async () => { const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // Zwróć AST jako JSON do klienta return Response.json({ content: ast });};
client.tsx
Kopiuj kod
Skopiuj kod do schowka
import { useLoaderData } from "react-router";import { MarkdownRenderer } from "react-intlayer/markdown";// 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowaniaexport default function Page() { const { content } = useLoaderData(); // Renderer akceptuje surowy ciąg znaków lub sparsowane AST return <MarkdownRenderer content={content} />;}
app/page.tsx
Kopiuj kod
Skopiuj kod do schowka
import { parseMarkdown } from "next-intlayer/markdown";import { MarkdownRenderer } from "next-intlayer/markdown";export default async function Page() { // 1. Sparsuj markdown do serializowalnego AST na serwerze const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // 2. Renderuj AST bezpośrednio // W Server Component działa to bezproblemowo i przekazuje AST// bezpośrednio do bazowych komponentów klienckich, jeśli to konieczne. return <MarkdownRenderer content={ast} />;}
pages/index.vue
Kopiuj kod
Skopiuj kod do schowka
<script setup lang="ts">import { parseMarkdown } from "vue-intlayer/markdown";import { MarkdownRenderer } from "vue-intlayer/markdown";// 1. Pobierz i sparsuj markdown do AST na serwerzeconst { data: ast } = await useAsyncData('markdown', () => { const markdownString = "## My title \n\nLorem Ipsum"; return parseMarkdown(markdownString);});</script><template> <!-- 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowania --> <MarkdownRenderer :content="ast" /></template>
+page.server.ts
Kopiuj kod
Skopiuj kod do schowka
import { parseMarkdown } from "svelte-intlayer/markdown";// 1. Na serwerze: Sparsuj markdown do serializowalnego ASTexport const load = async () => { const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // Zwróć AST do klienta return { content: ast };};
+page.svelte
Kopiuj kod
Skopiuj kod do schowka
<script lang="ts"> import { MarkdownRenderer } from "svelte-intlayer/markdown"; export let data;</script><!-- 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowania --><MarkdownRenderer value={data.content} />
Angular SSR zazwyczaj pobiera dane na serwerze podczas początkowego ładowania i hydratuje na kliencie. Możesz użyć resolverów do przekazania AST.
app.resolver.ts
Kopiuj kod
Skopiuj kod do schowka
import { Injectable } from "@angular/core";import { Resolve } from "@angular/router";import { parseMarkdown, type ParsedMarkdown } from "angular-intlayer/markdown";@Injectable({ providedIn: "root" })export class MarkdownResolver implements Resolve<ParsedMarkdown> { resolve(): ParsedMarkdown { const markdownString = "## My title \n\nLorem Ipsum"; // 1. Na serwerze: Sparsuj markdown do serializowalnego AST return parseMarkdown(markdownString); }}
app.component.ts
Kopiuj kod
Skopiuj kod do schowka
import { Component } from "@angular/core";import { ActivatedRoute } from "@angular/router";import { IntlayerMarkdownService, type ParsedMarkdown } from "angular-intlayer/markdown";@Component({ selector: "app-root", template: `<div [innerHTML]="renderedMarkdown"></div>`,})export class AppComponent { renderedMarkdown: string = ""; constructor( private route: ActivatedRoute, private markdownService: IntlayerMarkdownService ) { // 2. Na kliencie: Renderuj AST bezpośrednio bez ponownego parsowania this.route.data.subscribe((data) => { this.renderedMarkdown = this.markdownService.renderMarkdown( data.markdownAst ) as string; }); }}
Ten wzorzec zapewnia, że logika parsowania Markdown jest wykonywana całkowicie na serwerze, co znacznie skraca czas wykonywania po stronie klienta i poprawia szybkość początkowej hydratacji.
Opcje referencyjne
Te opcje można przekazać do MarkdownProvider, MarkdownRenderer, useMarkdownRenderer i renderMarkdown.
Pokaż całą zawartość tabeli
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
Option
Type
Default
Opis
forceBlock
boolean
false
Wymusza zawijanie wyjścia w element blokowy (np. <div>).
forceInline
boolean
false
Wymusza zawijanie wyjścia w element liniowy (np. <span>).
tagfilter
boolean
true
Włącza GitHub Tag Filter w celu zwiększenia bezpieczeństwa poprzez usuwanie niebezpiecznych tagów HTML.
preserveFrontmatter
boolean
false
Jeśli true, frontmatter na początku ciągu Markdown nie zostanie usunięty.
components
Overrides
{}
Mapa tagów HTML na niestandardowe komponenty (np. { h1: MyHeading }).
wrapper
Component
null
Niestandardowy komponent do zawijania renderowanego Markdown.
renderMarkdown
Function
null
Niestandardowa funkcja renderowania, aby całkowicie zastąpić domyślny kompilator Markdown.