{"id":51427939,"url":"https://github.com/hexdrinker/remark-cjk-adjacent-strong","last_synced_at":"2026-07-05T02:10:29.858Z","repository":{"id":345934284,"uuid":"1187915653","full_name":"hexdrinker/remark-cjk-adjacent-strong","owner":"hexdrinker","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-21T16:05:26.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-22T02:24:29.685Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://remark-cjk-adjacent-strong.vercel.app","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hexdrinker.png","metadata":{"files":{"readme":"README.en.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-03-21T11:11:21.000Z","updated_at":"2026-03-21T16:14:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hexdrinker/remark-cjk-adjacent-strong","commit_stats":null,"previous_names":["hexdrinker/remark-cjk-adjacent-strong"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/hexdrinker/remark-cjk-adjacent-strong","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexdrinker%2Fremark-cjk-adjacent-strong","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexdrinker%2Fremark-cjk-adjacent-strong/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexdrinker%2Fremark-cjk-adjacent-strong/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexdrinker%2Fremark-cjk-adjacent-strong/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hexdrinker","download_url":"https://codeload.github.com/hexdrinker/remark-cjk-adjacent-strong/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexdrinker%2Fremark-cjk-adjacent-strong/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35141386,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"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":[],"created_at":"2026-07-05T02:10:29.339Z","updated_at":"2026-07-05T02:10:29.843Z","avatar_url":"https://github.com/hexdrinker.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# remark-cjk-adjacent-strong\n\n`remark-cjk-adjacent-strong` is a `remark` plugin that repairs a narrow Markdown/MDX parsing gap where `**...**` emphasis remains plain text because it is immediately followed by CJK text.\n\nTypical examples:\n\n- `**커피(coffee)**가`\n- `**コーヒー(coffee)**が`\n- `**咖啡(coffee)**是`\n\n## README languages\n\n- [한국어](./README.md)\n- [English](./README.en.md)\n- [日本語](./README.ja.md)\n- [简体中文](./README.zh-CN.md)\n\n## When should you use this plugin?\n\nUse it when the closing `**` is immediately followed by CJK text, so the default parser leaves the sequence as literal text instead of building emphasis.\n\nThis usually happens when the last character inside `**...**` is punctuation or a symbol such as `)`, `?`, `!`, quotes, or brackets.\n\n## Package direction\n\n- Public package name: `remark-cjk-adjacent-strong`\n- Default entry targets broad CJK adjacency\n- `./hangul` exposes a Hangul-only preset\n- `./core` exposes the shared factory\n\n## Install\n\n```bash\nnpm install remark-cjk-adjacent-strong\n```\n\n## Compatibility\n\n- Node.js 18+\n- ESM package\n- Works in `remarkPlugins` chains used by `next-mdx-remote`, `@next/mdx`, Contentlayer, Astro MDX, and plain `unified` pipelines\n\n## Which entry point should I use?\n\n### Default package entry\n\n```ts\nimport remarkCjkAdjacentStrong from 'remark-cjk-adjacent-strong'\n```\n\nUse this when you want to repair adjacency for:\n\n- Hangul\n- Han\n- Hiragana\n- Katakana\n\n### Hangul-only entry\n\n```ts\nimport remarkHangulAdjacentStrong from 'remark-cjk-adjacent-strong/hangul'\n```\n\nUse this when you only want Korean adjacency repair.\n\n### Core factory\n\n```ts\nimport { createRemarkAdjacentStrong } from 'remark-cjk-adjacent-strong/core'\n\nconst remarkAsciiAdjacentStrong = createRemarkAdjacentStrong(/[A-Z]/u)\n```\n\nUse this when you want the same rewrite engine with your own suffix-character rule.\n\n## Integration examples\n\n### Plain unified pipeline\n\n```ts\nimport remarkCjkAdjacentStrong from 'remark-cjk-adjacent-strong'\nimport remarkParse from 'remark-parse'\nimport { unified } from 'unified'\n\nconst processor = unified()\n  .use(remarkParse)\n  .use(remarkCjkAdjacentStrong)\n```\n\n### `remarkPlugins` chain\n\n```ts\nimport remarkCjkAdjacentStrong from 'remark-cjk-adjacent-strong'\nimport remarkGfm from 'remark-gfm'\n\nconst mdxOptions = {\n  remarkPlugins: [remarkGfm, remarkCjkAdjacentStrong],\n}\n```\n\n## Exact rewrite rule\n\nThe transformer only rewrites plain `text` nodes when all conditions below are true.\n\n1. The text contains a `**X**Y` pattern.\n2. `X` does not contain `*` or a newline.\n3. The last character of `X` matches `/[\\p{P}\\p{S}]/u`.\n4. The first character of `Y` matches the configured suffix-character pattern.\n5. The text is not inside a protected node.\n\nDefault CJK suffix pattern:\n\n```ts\n/[\\p{Script=Hangul}\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}]/u\n```\n\nHangul-only suffix pattern:\n\n```ts\n/[\\p{Script=Hangul}\\p{Script=Hangul_Jamo}\\p{Script=Hangul_Compatibility_Jamo}]/u\n```\n\n## Covered examples\n\n### Repaired by the default CJK entry\n\n| Source | Result |\n| --- | --- |\n| `**커피(coffee)**가 필요하다.` | `\u003cstrong\u003e커피(coffee)\u003c/strong\u003e가 필요하다.` |\n| `**브런치(brunch)**를 먹으러 가자.` | `\u003cstrong\u003e브런치(brunch)\u003c/strong\u003e를 먹으러 가자.` |\n| `**コーヒー(coffee)**が好きだ。` | `\u003cstrong\u003eコーヒー(coffee)\u003c/strong\u003eが好きだ。` |\n| `**拿铁(latte)**也很受欢迎。` | `\u003cstrong\u003e拿铁(latte)\u003c/strong\u003e也很受欢迎。` |\n| `**咖啡(coffee)**是必需品。` | `\u003cstrong\u003e咖啡(coffee)\u003c/strong\u003e是必需品。` |\n\n### Repaired by the Hangul-only entry\n\n| Source | Result |\n| --- | --- |\n| `**커피(coffee)**가 필요하다.` | `\u003cstrong\u003e커피(coffee)\u003c/strong\u003e가 필요하다.` |\n| `**디저트(dessert)**를 곁들이자.` | `\u003cstrong\u003e디저트(dessert)\u003c/strong\u003e를 곁들이자.` |\n| `**라테(latte)**를 마셔 보자.` | `\u003cstrong\u003e라테(latte)\u003c/strong\u003e를 마셔 보자.` |\n| `**커피(coffee)!**가 먼저다.` | `\u003cstrong\u003e커피(coffee)!\u003c/strong\u003e가 먼저다.` |\n| `**모카(mocha).**도 괜찮다.` | `\u003cstrong\u003e모카(mocha).\u003c/strong\u003e도 괜찮다.` |\n\n## Intentionally not covered\n\n### Cases already handled by CommonMark\n\n- `**커피**는 이미 잘 파싱된다.`\n- `**커피(coffee)** 가 필요하다.`\n- `**커피(coffee)**!`\n- `설명 예시는 **coffee**이렇게도 붙을 수 있다.`\n\n### Non-target suffixes\n\n- `**咖啡(coffee)**abc`\n- `**咖啡(coffee)**123`\n\n### Protected nodes\n\n- `code`\n- `inlineCode`\n- `html`\n- `strong`\n- `emphasis`\n- `delete`\n- `link`\n- `mdx*`\n\nExamples that stay literal:\n\n- `` `**コーヒー(coffee)**が` ``\n- `[**咖啡(coffee)**是](https://example.com)`\n- `\u003cCallout\u003e**커피(coffee)**가\u003c/Callout\u003e`\n- `~~**라테(latte)**를~~`\n\n## Known tradeoff\n\nThis plugin is conservative, but it can still convert documentation-style literal examples into real `strong` nodes.\n\nExample:\n\n- `설명 예시는 **커피(coffee)**가 라고 적는다고 착각할 수 있다.`\n\nIf a literal example must stay literal, put it inside a protected context such as inline code.\n\nRepresentative side-effect candidates are listed in `fixtures/manual-check.mdx`.\n\n## Package structure\n\n- `src/core.ts`: shared traversal and rewrite engine\n- `src/hangul.ts`: Hangul-only preset\n- `src/index.ts`: default CJK preset and main entry\n\n## API\n\n### Default export\n\n- `remarkCjkAdjacentStrong`\n\n### Named exports\n\n- `remarkCjkAdjacentStrong`\n- `CJK_SUFFIX_CHARACTER`\n- `remarkHangulAdjacentStrong`\n- `HANGUL_SUFFIX_CHARACTER`\n- `createRemarkAdjacentStrong`\n\n## Development\n\n```bash\nnpm install\nnpm run verify\nnpm run pack:check\n```\n\n## Publish checklist\n\n1. Run `npm run verify`\n2. Run `npm run pack:check`\n3. Confirm `package.json` metadata\n4. Run `npm publish`\n\n`prepublishOnly` is configured, so publish re-runs verification and a dry-run pack check.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexdrinker%2Fremark-cjk-adjacent-strong","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhexdrinker%2Fremark-cjk-adjacent-strong","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexdrinker%2Fremark-cjk-adjacent-strong/lists"}