\n\n \n \n \n ```\n\n Konfigurasikan secara global melalui plugin `intlayerMarkdown` (mendukung komponen kustom 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), // Komponen MDX\n },\n });\n ```\n\n > Jika plugin `intlayerMarkdown` tidak diinstal, Intlayer akan merender menggunakan kompilator default.\n\n Anda juga dapat memberikan pengesampingan lokal untuk simpul tertentu menggunakan metode `.use()`:\n\n ```vue\n h('h1', { style: { color: 'red' } }, props.children),\n })\" />\n ```\n\n Anda dapat mengambil Markdown sebagai sebuah string:\n\n ```vue\n {{ myMarkdownContent.value }}\n {{ String(myMarkdownContent) }}\n {{ myMarkdownContent.toString() }}\n ```\n\n Dan Anda dapat mengakses metadata markdown Anda seperti ini:\n\n ```vue\n \n \n ```\n\n \n \n Svelte merender Markdown sebagai string HTML secara default. Gunakan `{@html}` untuk merendernya.\n\n ```svelte fileName=\"App.svelte\"\n \n\n \n {@html $content.myMarkdownContent}\n \n ```\n\n > Jika `MarkdownProvider` tidak ada, Intlayer akan merender markdown menggunakan kompilator default.\n\n Anda juga dapat memberikan pengesampingan lokal untuk simpul tertentu menggunakan metode `.use()`:\n\n ```svelte\n {@html $content.myMarkdownContent.use({ ... })}\n ```\n\n Anda dapat mengambil Markdown sebagai sebuah string:\n\n ```svelte\n {$content.myMarkdownContent.value}\n {String($content.myMarkdownContent)}\n {$content.myMarkdownContent.toString()}\n ```\n\n Dan Anda dapat mengakses metadata markdown Anda seperti ini:\n\n ```svelte\n {$content.myMarkdownContent.metadata}\n {$content.myMarkdownContent.metadata.title}\n ```\n\n \n \n Preact mendukung simpul Markdown secara langsung di 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) => , // Komponen MDX\n }}\n >\n \n \n );\n ```\n\n > Jika `MarkdownProvider` tidak ada, Intlayer akan merender markdown menggunakan parser default Markdown ke JSX.\n\n Anda juga dapat memberikan pengesampingan lokal untuk simpul tertentu menggunakan metode `.use()`:\n\n ```tsx\n {myMarkdownContent.use({\n h1: ({ children }) =>
{children}
,\n })}\n ```\n\n Anda dapat mengambil Markdown sebagai sebuah string:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n Dan Anda dapat mengakses metadata markdown Anda seperti ini:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Solid mendukung simpul Markdown secara langsung di 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) => , // Komponen MDX\n }}\n >\n \n \n );\n ```\n\n > Jika `MarkdownProvider` tidak ada, Intlayer akan merender markdown menggunakan parser default Markdown ke JSX.\n\n Anda juga dapat memberikan pengesampingan lokal untuk simpul tertentu menggunakan metode `.use()`:\n\n ```tsx\n {myMarkdownContent.use({\n h1: (props) =>
{props.children}
,\n })}\n ```\n\n Anda dapat mengambil Markdown sebagai sebuah string:\n\n ```tsx\n {myMarkdownContent.value}\n {String(myMarkdownContent)}\n {myMarkdownContent.toString()}\n ```\n\n Dan Anda dapat mengakses metadata markdown Anda seperti ini:\n\n ```tsx\n {myMarkdownContent.metadata}\n {myMarkdownContent.metadata.title}\n ```\n\n \n \n Angular menggunakan direktif `[innerHTML]` untuk merender konten 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 > Jika penyedia IntlayerMarkdown tidak dikonfigurasi, Intlayer akan merender menggunakan kompilator default.\n\n Anda juga dapat memberikan pengesampingan lokal untuk simpul tertentu menggunakan metode `.use()`:\n\n ```typescript\n content().myMarkdownContent.use({\n h1: { class: \"text-3xl font-bold\" },\n })\n ```\n\n Anda dapat mengambil Markdown sebagai sebuah string:\n\n ```typescript\n content().myMarkdownContent.value\n String(content().myMarkdownContent)\n content().myMarkdownContent.toString()\n ```\n\n Dan Anda dapat mengakses metadata markdown Anda seperti ini:\n\n ```typescript\n content().myMarkdownContent.metadata\n content().myMarkdownContent.metadata.title\n ```\n\n \n\n\n### 2. Utilitas Pembantu (Hanya String Markdown)\n\nUtilitas ini merender **hanya string Markdown mentah** dan independen dari `useIntlayer`. Gunakan utilitas ini saat Anda perlu merender Markdown dari sumber selain dari kamus Anda.\n\n\n \n \n #### Komponen ``\n\n Merender string Markdown dengan opsi tertentu.\n\n ```tsx\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n \n {\"# Judul Saya\"}\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n Mendapatkan fungsi perender yang sudah dikonfigurasi sebelumnya.\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(\"# Judul Saya\");\n ```\n\n #### Utilitas `renderMarkdown()`\n Utilitas mandiri untuk rendering di luar komponen.\n\n ```tsx\n import { renderMarkdown } from \"react-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# Judul Saya\", { forceBlock: true });\n ```\n\n \n \n \n #### Komponen ``\n\n Merender string Markdown dengan opsi tertentu.\n\n ```tsx\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n \n {\"# Judul Saya\"}\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n Mendapatkan fungsi perender yang sudah dikonfigurasi sebelumnya.\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(\"# Judul Saya\");\n ```\n\n #### Utilitas `renderMarkdown()`\n Utilitas mandiri untuk rendering di luar komponen.\n\n ```tsx\n import { renderMarkdown } from \"next-intlayer/markdown\";\n\n const jsx = renderMarkdown(\"# Judul Saya\", { forceBlock: true });\n ```\n\n \n \n\n #### Komponen ``\n\n ```vue\n \n\n \n \n \n ```\n\n \n \n\n #### Komponen ``\n\n ```svelte\n \n\n \n ```\n\n #### Hook `useMarkdownRenderer()`\n\n ```svelte\n \n\n {@html render(\"# Judul Saya\")}\n ```\n\n #### Utilitas `renderMarkdown()`\n\n ```svelte\n \n\n {@html renderMarkdown(\"# Judul Saya\")}\n ```\n\n \n \n #### Komponen ``\n\n ```tsx\n import { MarkdownRenderer } from \"preact-intlayer/markdown\";\n\n \n {\"# Judul Saya\"}\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 #### Layanan `IntlayerMarkdownService`\n Merender string Markdown menggunakan layanan.\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## Konfigurasi Global dengan `MarkdownProvider`\n\n`MarkdownProvider` (atau padanan kerangka kerjanya) mengonfigurasi jalur rendering Markdown untuk seluruh aplikasi Anda. Ini berlaku baik untuk rendering `useIntlayer` otomatis maupun utilitas pembantu. Opsi yang ditetapkan di sini adalah default — `.use()` mengesampingkannya di tingkat simpul.\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 didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\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 didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\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 didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\n\n \n \n\n ```svelte fileName=\"App.svelte\"\n \n\n \n \n \n ```\n\n\n > MDX didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\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 didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\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 didukung — nama komponen apa pun yang digunakan di dalam Markdown Anda (misalnya ``) diselesaikan terhadap peta `components`.\n\n Anda juga dapat menggunakan perender markdown Anda sendiri:\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\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 > Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.\n\n \n\n\n## Suspense\n\nPerender Markdown Intlayer dimuat secara dinamis. Meskipun dioptimalkan, ukuran parser dasarnya sekitar 55kb. Memuat ini secara sinkron menunda perenderan halaman awal dan menurunkan First Contentful Paint (FCP).\n\nUntuk mencegah pemblokiran UI, Intlayer terintegrasi dengan API Suspense dari React. Ia mengambil parser di latar belakang dan melempar Promise selama pengunduhan.\n\nBungkus komponen apa pun yang merender Markdown Intlayer di dalam batasan ``. Ini menampilkan status fallback yang dilokalkan saat chunk diunduh, memungkinkan sisa DOM Anda segera dirender.\n\nPeringatan: Jika Anda tidak menyediakan batasan ``, React akan ditangguhkan pada tingkat root atau memblokir seluruh pohon komponen dari perenderan hingga chunk 55kb dimuat sepenuhnya.\n\n\n \n\nDi Next.js App Router, Anda dapat menggunakan `Suspense` React untuk komponen klien atau file `loading.tsx` untuk komponen server.\n\n**Komponen Klien:**\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**Komponen Server dengan `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 memiliki komponen `` bawaan. Bungkus komponen yang merender konten Markdown dalam batasan ``.\n\n```vue fileName=\"MyComponent.vue\"\n\n\n\n \n \n \n
Loading...
\n \n \n\n```\n\n \n \n\nSvelte tidak memiliki API Suspense yang setara. Gunakan blok `{#await}` untuk menangani perenderan asinkron dari konten 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 mendukung API Suspense React melalui `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 memiliki komponen `` sendiri dari `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 tidak memiliki API Suspense. Gunakan tampilan yang ditangguhkan (`@defer`) milik Angular untuk menangani konten Markdown yang dimuat secara lambat (membutuhkan 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## Rendering Sisi Server (SSR) dan Hidrasi\n\nDibandingkan dengan parser Markdown lainnya seperti remark / rehype, Intlayer Markdown bebas ketergantungan dan berjalan di sisi klien maupun server.\n\nNamun Intlayer mengoptimalkan parsing untuk framework Server-Side Rendering (SSR) (seperti Next.js App Router, React Router, Nuxt, SvelteKit, dll.).\n\nHidrasi di browser memakan waktu, sehingga Intlayer memungkinkan Anda untuk mem-parsing Markdown terlebih dahulu ke dalam Abstract Syntax Tree (AST) di server, lalu mengirimkannya sebagai objek JSON yang dapat diserialisasi ke frontend.\n\nAnda dapat menggunakan fungsi `parseMarkdown` dari paket Intlayer framework Anda di sisi server untuk menghasilkan AST yang dapat diserialisasi (objek `ParsedMarkdown`), dan meneruskannya secara langsung ke frontend. Semua utilitas rendering Intlayer (seperti ``, `useMarkdownRenderer`, dll.) secara otomatis menerima objek AST ini dan merendernya dengan lancar.\n\n### Contoh dalam Arsitektur Server/Klien\n\n\n \n\n ```tsx fileName=\"server.ts\"\n import { parseMarkdown } from \"react-intlayer/markdown\";\n\n // 1. Di server: Parsing markdown ke dalam AST yang dapat diserialisasi\n export const loader = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Kembalikan AST sebagai JSON ke klien\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. Di klien: Render AST secara langsung tanpa mem-parsing ulang\n export default function Page() {\n const { content } = useLoaderData();\n\n // Renderer menerima string mentah atau AST hasil parsing\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. Parsing markdown ke dalam AST yang dapat diserialisasi di server\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 2. Render AST secara langsung\n // Dalam Server Component, ini bekerja dengan lancar dan meneruskan AST\n // secara langsung ke komponen klien di bawahnya jika diperlukan.\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. Di server: Parsing markdown ke dalam AST yang dapat diserialisasi\n export const load = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Kembalikan AST ke klien\n return { content: ast };\n };\n ```\n\n ```svelte fileName=\"+page.svelte\"\n \n\n \n \n ```\n\n \n \n\n Angular SSR biasanya menyelesaikan data di server selama pemuatan awal dan menghidrasi di klien. Anda dapat menggunakan resolver untuk meneruskan 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. Di server: Parsing markdown ke dalam AST yang dapat diserialisasi\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. Di klien: Render AST secara langsung tanpa mem-parsing ulang\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\nPola ini memastikan bahwa logika parsing Markdown dieksekusi sepenuhnya di server, secara signifikan mengurangi waktu eksekusi di sisi klien dan meningkatkan kecepatan hidrasi awal.\n\n## Referensi Opsi\n\nOpsi ini dapat diteruskan ke `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer`, dan `renderMarkdown`.\n\n| Option | Type | Default | Deskripsi |\n| :-------------------- | :---------- | :------ | :--------------------------------------------------------------------------------------------------- |\n| `forceBlock` | `boolean` | `false` | Memaksa output untuk dibungkus dalam elemen tingkat blok (mis., `
`). |\n| `forceInline` | `boolean` | `false` | Memaksa output untuk dibungkus dalam elemen sebaris (mis., ``). |\n| `tagfilter` | `boolean` | `true` | Mengaktifkan GitHub Tag Filter untuk keamanan yang ditingkatkan dengan menghapus tag HTML berbahaya. |\n| `preserveFrontmatter` | `boolean` | `false` | Jika `true`, frontmatter di awal string Markdown tidak akan dihapus. |\n| `components` | `Overrides` | `{}` | Peta tag HTML ke komponen kustom (mis., `{ h1: MyHeading }`). |\n| `wrapper` | `Component` | `null` | Komponen kustom untuk membungkus Markdown yang dirender. |\n| `renderMarkdown` | `Function` | `null` | Fungsi perenderan kustom untuk sepenuhnya menggantikan kompilator Markdown default. |\n","description":"Pelajari cara mendeklarasikan dan menggunakan konten Markdown di situs web multibahasa Anda dengan Intlayer. Ikuti langkah-langkah dalam dokumentasi online ini untuk mengintegrasikan Markdown dengan mulus ke dalam proyek Anda.","url":"https://intlayer.org/id/doc/concept/content/markdown","datePublished":"2025-02-07","dateModified":"2026-05-19","version":"8.11.0","keywords":"Markdown, Internasionalisasi, Dokumentasi, Intlayer, Next.js, JavaScript, React","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"Pengembang, Manajer Konten"}}
Intlayer mendukung konten teks kaya yang didefinisikan menggunakan sintaks Markdown. Ini memungkinkan Anda dengan mudah menulis dan memelihara konten berformat kaya seperti blog, artikel, dan lainnya.
Mendeklarasikan Konten Markdown
Anda dapat mendeklarasikan konten Markdown menggunakan fungsi md atau cukup sebagai string (jika mengandung sintaks Markdown).
Mulai dari versi 8.10.0, Anda dapat mendeklarasikan konten Markdown langsung di dalam file .content.md. Intlayer akan secara otomatis mendeteksi dan mem-parsing konten Markdown.
Bidang locale pada front-matter adalah bidang yang mendefinisikan bahasa konten. Ini bersifat opsional. Jika tidak diberikan, Intlayer akan menggunakan bahasa default, yang juga digunakan sebagai bahasa cadangan jika tidak ada terjemahan yang tersedia untuk bahasa tertentu.
Anda dapat menambahkan properti apa pun yang didefinisikan dalam Definisi Kamus ke dalam front-matter
Gunakan fungsi md untuk mendeklarasikan konten Markdown secara eksplisit. Ini berguna jika Anda ingin memastikan sebuah string diperlakukan sebagai Markdown bahkan jika tidak mengandung sintaks yang jelas.
Jika string mengandung indikator Markdown umum (seperti judul, daftar, tautan, dll.), Intlayer akan secara otomatis mengubahnya.
markdownDictionary.content.ts
Salin kode
Salin kode ke clipboard
export default { key: "app", contentAutoTransformation: true, // Mengaktifkan deteksi otomatis dari konten Markdown - Dapat diatur secara global di intlayer.config.ts content: { myMarkdownContent: "## Judul saya \n\nLorem Ipsum", },};
Merender Markdown
Intlayer menyediakan dua cara independen untuk merender Markdown:
Melalui useIntlayer
— Intlayer secara otomatis mengubah simpul md menjadi keluaran asli kerangka kerja (JSX, VNode, string HTML).
Frontmatter diparsing dan diekspos sebagai .metadata. Anda dapat mengesampingkan rendering pada dua tingkat — secara global dengan MarkdownProvider (atau yang setara di kerangka kerja) dan secara lokal per simpul dengan .use(). Keduanya dapat digabungkan; .use() diutamakan daripada MarkdownProvider, yang pada gilirannya diutamakan daripada nilai default.
Utilitas Pembantu — <MarkdownRenderer />, useMarkdownRenderer(), dan renderMarkdown() adalah alat mandiri yang menerima hanya string Markdown mentah. Alat-alat ini independen dari useIntlayer dan tidak bekerja dengan simpul dekoratif yang dikembalikannya.
Rendering Markdown mendukung MDX — gunakan komponen JSX/kerangka kerja apa pun berdasarkan namanya langsung di dalam Markdown Anda.
1. Rendering Otomatis (melalui useIntlayer)
Simpul Markdown dapat dirender langsung sebagai JSX.
Utilitas ini merender hanya string Markdown mentah dan independen dari useIntlayer. Gunakan utilitas ini saat Anda perlu merender Markdown dari sumber selain dari kamus Anda.
import { renderMarkdown } from "solid-intlayer/markdown";return <div>{renderMarkdown("# Judul Saya")}</div>;
Layanan IntlayerMarkdownService
Merender string Markdown menggunakan layanan.
typescript
Salin kode
Salin kode ke clipboard
import { IntlayerMarkdownService } from "angular-intlayer/markdown";export class MyComponent { constructor(private markdownService: IntlayerMarkdownService) {} renderMarkdown(markdown: string) { return this.markdownService.renderMarkdown(markdown); }}
Konfigurasi Global dengan MarkdownProvider
MarkdownProvider (atau padanan kerangka kerjanya) mengonfigurasi jalur rendering Markdown untuk seluruh aplikasi Anda. Ini berlaku baik untuk rendering useIntlayer otomatis maupun utilitas pembantu. Opsi yang ditetapkan di sini adalah default — .use() mengesampingkannya di tingkat simpul.
Mengimpor perender Markdown Anda secara dinamis adalah cara yang bagus untuk mengurangi ukuran bundel aplikasi Anda.
Suspense
Perender Markdown Intlayer dimuat secara dinamis. Meskipun dioptimalkan, ukuran parser dasarnya sekitar 55kb. Memuat ini secara sinkron menunda perenderan halaman awal dan menurunkan First Contentful Paint (FCP).
Untuk mencegah pemblokiran UI, Intlayer terintegrasi dengan API Suspense dari React. Ia mengambil parser di latar belakang dan melempar Promise selama pengunduhan.
Bungkus komponen apa pun yang merender Markdown Intlayer di dalam batasan <Suspense>. Ini menampilkan status fallback yang dilokalkan saat chunk diunduh, memungkinkan sisa DOM Anda segera dirender.
Peringatan: Jika Anda tidak menyediakan batasan <Suspense>, React akan ditangguhkan pada tingkat root atau memblokir seluruh pohon komponen dari perenderan hingga chunk 55kb dimuat sepenuhnya.
Di Next.js App Router, Anda dapat menggunakan Suspense React untuk komponen klien atau file loading.tsx untuk komponen server.
Angular tidak memiliki API Suspense. Gunakan tampilan yang ditangguhkan (@defer) milik Angular untuk menangani konten Markdown yang dimuat secara lambat (membutuhkan Angular 17+).
my.component.ts
Salin kode
Salin kode ke clipboard
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");}
Rendering Sisi Server (SSR) dan Hidrasi
Dibandingkan dengan parser Markdown lainnya seperti remark / rehype, Intlayer Markdown bebas ketergantungan dan berjalan di sisi klien maupun server.
Namun Intlayer mengoptimalkan parsing untuk framework Server-Side Rendering (SSR) (seperti Next.js App Router, React Router, Nuxt, SvelteKit, dll.).
Hidrasi di browser memakan waktu, sehingga Intlayer memungkinkan Anda untuk mem-parsing Markdown terlebih dahulu ke dalam Abstract Syntax Tree (AST) di server, lalu mengirimkannya sebagai objek JSON yang dapat diserialisasi ke frontend.
Anda dapat menggunakan fungsi parseMarkdown dari paket Intlayer framework Anda di sisi server untuk menghasilkan AST yang dapat diserialisasi (objek ParsedMarkdown), dan meneruskannya secara langsung ke frontend. Semua utilitas rendering Intlayer (seperti <MarkdownRenderer>, useMarkdownRenderer, dll.) secara otomatis menerima objek AST ini dan merendernya dengan lancar.
Contoh dalam Arsitektur Server/Klien
server.ts
Salin kode
Salin kode ke clipboard
import { parseMarkdown } from "react-intlayer/markdown";// 1. Di server: Parsing markdown ke dalam AST yang dapat diserialisasiexport const loader = async () => { const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // Kembalikan AST sebagai JSON ke klien return Response.json({ content: ast });};
client.tsx
Salin kode
Salin kode ke clipboard
import { useLoaderData } from "react-router";import { MarkdownRenderer } from "react-intlayer/markdown";// 2. Di klien: Render AST secara langsung tanpa mem-parsing ulangexport default function Page() { const { content } = useLoaderData(); // Renderer menerima string mentah atau AST hasil parsing return <MarkdownRenderer content={content} />;}
app/page.tsx
Salin kode
Salin kode ke clipboard
import { parseMarkdown } from "next-intlayer/markdown";import { MarkdownRenderer } from "next-intlayer/markdown";export default async function Page() { // 1. Parsing markdown ke dalam AST yang dapat diserialisasi di server const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // 2. Render AST secara langsung // Dalam Server Component, ini bekerja dengan lancar dan meneruskan AST// secara langsung ke komponen klien di bawahnya jika diperlukan. return <MarkdownRenderer content={ast} />;}
pages/index.vue
Salin kode
Salin kode ke clipboard
<script setup lang="ts">import { parseMarkdown } from "vue-intlayer/markdown";import { MarkdownRenderer } from "vue-intlayer/markdown";// 1. Ambil dan parsing markdown ke dalam AST di serverconst { data: ast } = await useAsyncData('markdown', () => { const markdownString = "## My title \n\nLorem Ipsum"; return parseMarkdown(markdownString);});</script><template> <!-- 2. Di klien: Render AST secara langsung tanpa mem-parsing ulang --> <MarkdownRenderer :content="ast" /></template>
+page.server.ts
Salin kode
Salin kode ke clipboard
import { parseMarkdown } from "svelte-intlayer/markdown";// 1. Di server: Parsing markdown ke dalam AST yang dapat diserialisasiexport const load = async () => { const markdownString = "## My title \n\nLorem Ipsum"; const ast = parseMarkdown(markdownString); // Kembalikan AST ke klien return { content: ast };};
+page.svelte
Salin kode
Salin kode ke clipboard
<script lang="ts"> import { MarkdownRenderer } from "svelte-intlayer/markdown"; export let data;</script><!-- 2. Di klien: Render AST secara langsung tanpa mem-parsing ulang --><MarkdownRenderer value={data.content} />
Angular SSR biasanya menyelesaikan data di server selama pemuatan awal dan menghidrasi di klien. Anda dapat menggunakan resolver untuk meneruskan AST.
app.resolver.ts
Salin kode
Salin kode ke clipboard
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. Di server: Parsing markdown ke dalam AST yang dapat diserialisasi return parseMarkdown(markdownString); }}
app.component.ts
Salin kode
Salin kode ke clipboard
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. Di klien: Render AST secara langsung tanpa mem-parsing ulang this.route.data.subscribe((data) => { this.renderedMarkdown = this.markdownService.renderMarkdown( data.markdownAst ) as string; }); }}
Pola ini memastikan bahwa logika parsing Markdown dieksekusi sepenuhnya di server, secara signifikan mengurangi waktu eksekusi di sisi klien dan meningkatkan kecepatan hidrasi awal.
Referensi Opsi
Opsi ini dapat diteruskan ke MarkdownProvider, MarkdownRenderer, useMarkdownRenderer, dan renderMarkdown.
Tampilkan semua isi tabel
Buka tabel dalam modal untuk melihat semua isi data dengan jelas
Option
Type
Default
Deskripsi
forceBlock
boolean
false
Memaksa output untuk dibungkus dalam elemen tingkat blok (mis., <div>).
forceInline
boolean
false
Memaksa output untuk dibungkus dalam elemen sebaris (mis., <span>).
tagfilter
boolean
true
Mengaktifkan GitHub Tag Filter untuk keamanan yang ditingkatkan dengan menghapus tag HTML berbahaya.
preserveFrontmatter
boolean
false
Jika true, frontmatter di awal string Markdown tidak akan dihapus.
components
Overrides
{}
Peta tag HTML ke komponen kustom (mis., { h1: MyHeading }).
wrapper
Component
null
Komponen kustom untuk membungkus Markdown yang dirender.
renderMarkdown
Function
null
Fungsi perenderan kustom untuk sepenuhnya menggantikan kompilator Markdown default.