# react-markdown-to-html **Repository Path**: mirrors_svenanders/react-markdown-to-html ## Basic Information - **Project Name**: react-markdown-to-html - **Description**: React Component that converts a Markdown file to HTML - **Primary Language**: Unknown - **License**: ISC - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-18 - **Last Updated**: 2026-09-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # react-markdown-remote [![npm](https://img.shields.io/npm/v/react-markdown-remote.svg)](https://www.npmjs.com/package/react-markdown-remote) [![types](https://img.shields.io/npm/types/react-markdown-remote.svg)](https://www.npmjs.com/package/react-markdown-remote) [![license](https://img.shields.io/npm/l/react-markdown-remote.svg)](./LICENSE) **Point `src` at a markdown file. Relative images and links actually work.** `react-markdown` takes a string. This package takes a **URL**. It fetches the file, rewrites `./shot.png` and `./api.md` against that file — not against the page you dropped the component on — and renders React elements. GitHub blob URLs, GitLab files, gists, and any `http(s)` markdown document. No `dangerouslySetInnerHTML`. No jQuery. GitHub-flavored markdown is on by default. Using an LLM or coding agent? Copy the [agent spec](#for-llms) into the prompt. ```bash npm install react-markdown-remote ``` ```tsx import { RemoteMarkdown } from "react-markdown-remote"; import "react-markdown-remote/styles.css"; // optional typography ``` Peer: `react >= 18`. Dual ESM/CJS. `"use client"` for Next.js App Router. [npm](https://www.npmjs.com/package/react-markdown-remote) · [GitHub](https://github.com/robbestad/react-markdown-remote) ## The problem this solves Drop a README into a React app and the pictures die. ```md ![diagram](./images/flow.png) [API](./api.md) ``` On GitHub those paths are relative to the **markdown file**. In your app the browser resolves them against the current page, so they 404. Blob URLs cannot be used as `img src` either — images need `raw.githubusercontent.com`, links need `github.com/.../blob/...`. That glue is the whole product. Parsing is [`react-markdown`](https://github.com/remarkjs/react-markdown). Fetch + rewrite is this package. | You have | Use | | --- | --- | | A markdown string already in memory | `react-markdown` | | A **file at a URL**, with `./` images and links | **react-markdown-remote** | | JSX inside markdown | MDX | ## What `src` accepts | `src` | Fetches | `./shot.png` becomes | | --- | --- | --- | | `https://github.com/org/repo/blob/main/docs/guide.md` | raw GitHub | raw image under `docs/` | | `https://github.com/org/repo` | `README.md` on `HEAD` | raw image at repo root | | `https://github.com/org/repo/tree/main/docs` | `docs/README.md` | raw image under `docs/` | | `https://gitlab.com/group/app/-/blob/main/README.md` | GitLab `/-/raw/` | GitLab raw image | | `https://gist.github.com/user/id` | gist raw | gist raw | | `https://example.com/docs/guide.md` | that URL | `https://example.com/docs/shot.png` | | `/docs/README.md` | same origin | same-origin, relative to the file | On GitHub and GitLab, `/root.png` is the **repo root**, matching how those hosts render READMEs. On a generic URL it is the host root. Slash-branches: `.../blob/refs/heads/feature/foo/README.md`. ## Rewrite, without the component ```ts import { resolveDocument, rewriteUrl } from "react-markdown-remote"; const doc = resolveDocument("https://github.com/acme/app/blob/main/docs/guide.md"); rewriteUrl("./shot.png", doc, "image"); // https://raw.githubusercontent.com/acme/app/main/docs/shot.png rewriteUrl("./extra.md", doc, "link"); // https://github.com/acme/app/blob/main/docs/extra.md ``` `javascript:`, `data:`, `vbscript:`, and `file:` are dropped. Absolute `http(s)` links stay. GitHub **blob** URLs used as images become raw. Need the string on the server? `await loadMarkdown(src)` returns `{ markdown, document }`. ## API ```tsx Loading…

} error={(err) =>

{err.message}

} onLoad={({ markdown, document }) => console.log(document.fetchUrl)} components={{ a: (props) => }} /> ``` | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `src` | `string` | required | Document URL | | `fetch` | `typeof fetch` | `globalThis.fetch` | Proxy for hosts without CORS. **Keep `src` as the real document URL** | | `requestInit` | `RequestInit` | — | Merged in; `signal` is owned by the component | | `gfm` | `boolean` | `true` | `remark-gfm` (tables, task lists, strikethrough) | | `loading` | `ReactNode` | status text | `null` hides it | | `error` | `ReactNode` \| `(Error) => ReactNode` | alert with the message | `null` hides it | | `onLoad` | `(result) => void` | — | Markdown + resolved document | | `onError` | `(Error) => void` | — | Not called for aborted fetches | | `origin` | `string` | `window.location.href` | Base for relative `src` | Every [`react-markdown`](https://github.com/remarkjs/react-markdown) option except `children` is forwarded (`components`, `remarkPlugins`, `rehypePlugins`, `urlTransform`, …). Your `urlTransform` runs **after** the relative rewrite; `defaultUrlTransform` sanitizes last. ```ts import { RemoteMarkdown, useRemoteMarkdown, loadMarkdown, resolveDocument, rewriteUrl, } from "react-markdown-remote"; ``` ## CORS and XSS `raw.githubusercontent.com` sends `Access-Control-Allow-Origin: *`. Many other hosts do not. If the browser blocks the request, pass a `fetch` that hits **your** proxy, and leave `src` pointing at the real file so rewrite still has the right base. Untrusted markdown is safe by default: no `dangerouslySetInnerHTML`, no raw HTML parsing. Do not add `rehype-raw` unless you sanitize. ## Demo ```bash npm install npm run demo ``` Local fixture (relative image + link) and a live GitHub README preset. ## Migration from `react-markdown-to-html` That 2015 package dumped `marked` through `innerHTML`. It is deprecated on npm. This is the replacement. ```diff - import Markdown2HTML from "react-markdown-to-html" - + import { RemoteMarkdown } from "react-markdown-remote" + ``` React 18+ is required. jQuery, lodash, and `marked` are gone. A bare `README.md` only works if that file is served from the current origin. ## For LLMs Copy everything in the block below into an LLM or coding-agent prompt when you want it to use `react-markdown-remote`. ``` Use react-markdown-remote v2 to fetch a markdown FILE from a URL and render it in React 18+. Install: npm install react-markdown-remote Import: import { RemoteMarkdown } from "react-markdown-remote" Optional CSS: import "react-markdown-remote/styles.css" Peer: react >= 18. Dual ESM/CJS. The published bundle starts with "use client". Default export is the same component. This is NOT a markdown parser you pass a string to. react-markdown already does that. This package's job is: fetch src + rewrite relative images/links against THAT file. API: ReactNode) // default alert; null to hide onLoad?: (result: { markdown: string, document: ResolvedDocument }) => void onError?: (err: Error) => void // not called on abort className?: string style?: CSSProperties id?: string ...reactMarkdownOptions // components, remarkPlugins, rehypePlugins, urlTransform, … /> // Headless: useRemoteMarkdown(src, { fetch, requestInit, origin }) -> { status: "loading" } | { status: "ready", markdown, document } | { status: "error", error: Error } await loadMarkdown(src, { fetch, requestInit, signal, origin }) -> { markdown, document } resolveDocument(src, origin?) -> ResolvedDocument rewriteUrl(url, document, "image" | "link") -> string src mapping: - github.com/org/repo/blob/ref/path.md -> fetch raw.githubusercontent.com/.../path.md images: raw under the file's directory links: github.com/.../blob/... under the file's directory - github.com/org/repo -> README.md on HEAD - github.com/org/repo/tree/ref/dir -> dir/README.md - gitlab.com/group/app/-/blob/ref/file -> /-/raw/ for fetch and images, /-/blob/ for links - gist.github.com/user/id -> gist.githubusercontent.com/user/id/raw - https://example.com/docs/guide.md -> that URL; relatives against /docs/ - /docs/README.md -> same origin (needs a browser origin or origin option) - Slash branches: .../blob/refs/heads/feature/foo/README.md - On GitHub/GitLab, /foo.png is REPO root. On generic URLs, /foo.png is HOST root. Rules: - Do NOT use dangerouslySetInnerHTML. Do NOT add rehype-raw unless the caller sanitizes. - Do NOT pass the markdown string as children. Pass src. - If you proxy fetch, src must still be the original GitHub/GitLab/file URL so rewrite works. - javascript:, data:, vbscript:, file: URLs are stripped. Leave that alone. - User urlTransform runs AFTER rewrite; defaultUrlTransform sanitizes last. - Do not fetch on every render. The component aborts in-flight work when src changes. - Successor to the deprecated package react-markdown-to-html (jQuery + marked + innerHTML). Never revive that API. Minimal: import { RemoteMarkdown } from "react-markdown-remote" export function Readme() { return } ``` ## License ISC