{"id":49457010,"url":"https://github.com/ngtrio/mdian","last_synced_at":"2026-04-30T07:00:59.517Z","repository":{"id":352444668,"uuid":"1214883624","full_name":"ngtrio/mdian","owner":"ngtrio","description":"Obsidian Flavored Markdown for unified + react-markdown","archived":false,"fork":false,"pushed_at":"2026-04-28T02:01:28.000Z","size":239,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-28T04:04:38.254Z","etag":null,"topics":["obsidian","react-markdown","unified"],"latest_commit_sha":null,"homepage":"https://ngtrio.github.io/mdian/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ngtrio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T07:16:36.000Z","updated_at":"2026-04-28T02:01:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ngtrio/mdian","commit_stats":null,"previous_names":["ngtrio/mdian"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ngtrio/mdian","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngtrio%2Fmdian","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngtrio%2Fmdian/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngtrio%2Fmdian/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngtrio%2Fmdian/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngtrio","download_url":"https://codeload.github.com/ngtrio/mdian/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngtrio%2Fmdian/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32457110,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"online","status_checked_at":"2026-04-30T02:00:05.929Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["obsidian","react-markdown","unified"],"created_at":"2026-04-30T07:00:54.402Z","updated_at":"2026-04-30T07:00:59.503Z","avatar_url":"https://github.com/ngtrio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mdian\n\n`mdian` is a TypeScript toolkit for parsing and rendering Obsidian Flavored Markdown (OFM) with unified-compatible pipelines.\n\nIt provides:\n\n- `remarkOfm` and `rehypeOfm` for OFM syntax and HTML transforms\n- URL and anchor helpers for applications that need OFM-style wiki navigation\n- a small CSS entrypoint for sensible default styling\n\n## Supported OFM Syntax\n\n`mdian` currently supports:\n\n- Wikilinks: `[[Page]]`, `[[Page#Heading]]`, `[[Page#^block-id]]`, `[[Page|Alias]]`\n- Embeds: `![[Page]]`, `![[Page#Heading]]`, `![[Page#^block-id]]`\n- Highlights: `==highlight==`\n- Comments: `%%hidden note%%`\n- Callouts\n- External embeds from standard Markdown image syntax for supported YouTube and X/Twitter URLs\n\nSee the showcase at https://ngtrio.github.io/mdian\n\nRegular Markdown still works as usual. GFM and math are not bundled by this package; add `remark-gfm`, `remark-math`, `rehype-katex`, or other plugins yourself when needed.\n\n## Usage\n\n### Core unified usage\n\n`mdian` ships the core OFM plugins for unified-compatible pipelines.\n\nInstall the package and styles entrypoint:\n\n```bash\npnpm add mdian\n```\n\nUse `remarkOfm` and `rehypeOfm` in any unified-compatible pipeline:\n\n```ts\nimport rehypeStringify from 'rehype-stringify'\nimport {rehypeOfm, remarkOfm} from 'mdian'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport {unified} from 'unified'\nimport 'mdian/styles.css'\n\nconst html = String(\n  await unified()\n    .use(remarkParse)\n    .use(remarkOfm, {wikilinks: true, embeds: true})\n    .use(remarkRehype)\n    .use(rehypeOfm, {hrefPrefix: 'wiki'})\n    .use(rehypeStringify)\n    .process(source)\n)\n```\n\nIf you also need GFM or math, add those plugins around `remarkOfm` and `rehypeOfm` in the same pipeline.\n\n## ReactMarkdown Usage\n\nIf you are using `react-markdown`, prefer the high-level React preset from `mdian/react`.\nInstall the React dependencies in your app before using this subpath:\n\n```bash\npnpm add mdian react react-markdown\n```\n\n```ts\nimport ReactMarkdown from 'react-markdown'\nimport {createOfmReactPreset} from 'mdian/react'\n\nconst notes = new Map([\n  ['Project Notes', {markdown: '# Project Notes\\n\\nHello world.', title: 'Project Notes'}]\n])\n\nconst ofm = createOfmReactPreset({\n  ofm: {\n    remark: {wikilinks: true, embeds: true},\n    rehype: {externalEmbeds: true}\n  },\n  wikiLink: {\n    resolve(target) {\n      return {\n        href: `/wiki/${encodeURIComponent(target.path)}`,\n        title: target.fragment\n          ? `${target.path}#${target.fragment}`\n          : target.path\n      }\n    }\n  },\n  noteEmbed: {\n    resolve(target) {\n      const note = notes.get(target.path)\n      return note ? {markdown: note.markdown, title: note.title} : undefined\n    }\n  },\n  image: {\n    transformSrc(src) {\n      return src.startsWith('assets/') ? `/${src}` : src\n    }\n  },\n  externalEmbeds: {\n    twitter: {\n      enhance: true\n    }\n  }\n})\n\nexport function Markdown({markdown}: {markdown: string}) {\n  return (\n    \u003cReactMarkdown\n      components={ofm.components}\n      rehypePlugins={ofm.rehypePlugins}\n      remarkPlugins={ofm.remarkPlugins}\n    \u003e\n      {markdown}\n    \u003c/ReactMarkdown\u003e\n  )\n}\n```\n\nThis path keeps OFM parsing in `mdian` while letting your app inject link resolution, note resolution, image URL rewriting, and optional router rendering. Set `externalEmbeds.twitter.enhance` to `true` only when you want the built-in X/Twitter widget enhancement path; otherwise the preset keeps the static fallback container while the core OFM output remains a single Twitter container `div` with canonical URL text content. You can also override the script loader with `loadTwitterWidgets({loadScript})`.\n\n## Breaking Target Model\n\n`mdian` models OFM targets as `path + fragment`:\n\n- `path: string`\n- `fragment?: string`\n\n`fragment` never includes the leading `#`.\nBlock refs are represented as `fragment: '^block-id'`.\nNested headings are represented as `fragment: 'Heading#Subheading'`.\n`[[Page#Heading#^block-id]]` is intentionally unsupported and is not assigned special semantics.\n\n`buildOfmTargetUrl()` accepts that shape directly. Rendered OFM metadata exposes `data-ofm-fragment`, while wikilinks and embeds no longer emit `data-ofm-block-id`.\n\n## External Embeds\n\n`rehypeOfm` also upgrades plain Markdown image URLs from supported providers into embeds:\n\n- `![](https://www.youtube.com/watch?v=...)`, `![](https://youtu.be/...)`, and `![](https://www.youtube.com/shorts/...)` render as YouTube `\u003ciframe\u003e` embeds with the `ofm-external-embed` class.\n- `![](https://x.com/.../status/...)` and `![](https://twitter.com/.../status/...)` render as tweet embed containers with `data-ofm-provider=\"twitter\"` and the `ofm-external-embed` class; the static core output is a single `div` whose text content is the canonical Twitter status URL.\n\nSet `externalEmbeds: false` to keep those URLs on the normal Markdown image path.\nIf you want interactive X/Twitter widgets instead of the static container output, load the provider script in your app after render.\n\n## Development\n\nFrom the repository root:\n\n```bash\npnpm install\npnpm build\npnpm test\npnpm demo:dev\n```\n\n## Releasing\n\n- Regular feature and fix PRs do not change `package.json.version`.\n- To cut a release, merge the desired version bump to `main`, then run `pnpm release`.\n- `pnpm release` tags the current `main` commit as `v\u003cversion\u003e` and pushes that tag to `origin`.\n- The publish workflow runs from that tag, verifies the package, publishes to npm, and creates the matching GitHub Release.\n\n## License\n\nApache-2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngtrio%2Fmdian","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngtrio%2Fmdian","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngtrio%2Fmdian/lists"}