{"id":28192983,"url":"https://github.com/lempiji/md","last_synced_at":"2025-05-16T12:16:18.204Z","repository":{"id":82858337,"uuid":"364257367","full_name":"lempiji/md","owner":"lempiji","description":"Tool to execute code blocks in Markdown","archived":false,"fork":false,"pushed_at":"2025-02-03T13:06:48.000Z","size":57,"stargazers_count":7,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-03T14:22:36.021Z","etag":null,"topics":["dlang","markdown","tool"],"latest_commit_sha":null,"homepage":"","language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lempiji.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2021-05-04T13:01:02.000Z","updated_at":"2025-02-03T13:06:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"3ed43cfd-bb30-4b11-b9f5-55d45bc86cf9","html_url":"https://github.com/lempiji/md","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lempiji%2Fmd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lempiji%2Fmd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lempiji%2Fmd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lempiji%2Fmd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lempiji","download_url":"https://codeload.github.com/lempiji/md/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254527093,"owners_count":22085920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["dlang","markdown","tool"],"created_at":"2025-05-16T12:16:16.448Z","updated_at":"2025-05-16T12:16:18.167Z","avatar_url":"https://github.com/lempiji.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"# md\r\n\r\n[English](README.md)\r\n\r\nMarkdownのコードブロックを実行するツールです。\r\n\r\nこれを使うことで、READMEに書かれたサンプルが動作することをCIで保証することなどができます。\r\n\r\nサンプルリポジトリ: https://github.com/lempiji/sandbox-vuepress\r\n\r\n## 実行方法\r\n\r\n`dub fetch md` および `dub run md -- README.md` といったコマンドで実行できます。\r\n\r\nこの `README.md` も実行可能となっています。\r\n\r\nなお、 `md` にコマンドライン引数を渡すことで、生成した D ソースファイルをどのように実行するか設定することもできます。\r\n\r\n__ヘルプの参照方法__\r\n\r\n```\r\ndub run md -- --help\r\n```\r\n\r\n\r\n## 機能概要\r\n\r\n言語に `d` または `D` と指定されているコードブロックが実行されます。\r\n\r\n### ブロックの結合\r\n\r\n以下のように複数のブロックがある場合、それらが結合されて実行されます。\r\n\r\n__1ブロック目__\r\n\r\n```d\r\nimport std;\r\n\r\nauto message = \"Hello, \" ~ \"Markdown!\";\r\n```\r\n\r\n__2ブロック目__\r\n\r\n```d\r\nwriteln(message); // Hello, Markdown!\r\n```\r\n\r\n### 除外設定\r\n\r\n以下のように `disabled` と指定したコードブロックは実行されません。\r\n\r\n~~~\r\n```d disabled\r\n```\r\n~~~\r\n\r\n__実行されないブロック__\r\n\r\n```d disabled\r\nthrow new Exception(\"disabled\");\r\n```\r\n\r\n### 名前指定\r\n\r\nコードブロックに対して、以下のような名前を指定することで独立したスコープを与えることができます。\r\n離れた位置に書かれていても、同じ名前を与えると1つのブロックとして結合されます。\r\n\r\n~~~\r\n```d name=test\r\n```\r\n~~~\r\n\r\n```d name=test\r\nimport std;\r\n\r\nauto buf = iota(10).array();\r\nwriteln(buf);\r\n```\r\n\r\n`name` 指定がない場合は `main` という名前として扱われます。\r\n\r\n#### 名前フィルター\r\n\r\n`--filter` オプションを指定することで、特定の名前を持つコードブロックのみを実行することができます。\r\n\r\n__例__\r\n\r\n~~~\r\n```d name=filter_test\r\n```\r\n~~~\r\n\r\n```\r\ndub run md -- README.md --filter=filter_test --filter=filter_test2\r\n```\r\n\r\n```d name=filter_test\r\nimport std;\r\n\r\nauto message = \"filter test\";\r\nwriteln(message);\r\n```\r\n\r\n```d name=filter_test2\r\nimport std;\r\n\r\nauto message2 = \"another filter test\";\r\nwriteln(message2);\r\n```\r\n\r\n### 独立実行\r\n\r\n1つのコードブロックを他のブロックと結合せず、独立して実行させるためには `single` という属性を付与します。\r\n\r\n~~~\r\n```d single\r\n```\r\n~~~\r\n\r\n__他のブロックと結合しない例__\r\n\r\n```d single\r\nimport std;\r\n\r\nauto message = \"single code block\";\r\nwriteln(message);\r\n```\r\n\r\n### dubのビルドオプションサポート\r\n\r\nツールによる実行(`dub run`)に渡すことができるいくつかのオプションをサポートしています。\r\nこれらのオプションは、指定された値をそのまま `dub run` の引数として渡します。\r\n\r\n1. `--build`\r\n2. `--compiler`\r\n3. `--arch`\r\n\r\n__例__\r\n\r\n```\r\ndub run md -- README.md --build=release --compiler=ldc2 --arch=x86_64\r\n```\r\n\r\n### 既定のパッケージ参照\r\n\r\nライブラリのREADMEなどをサポートするため、実行時のカレントディレクトリがdubパッケージであった場合、自動的に `dub` プロジェクトとしての依存関係が追加されます。（これは `dub.sdl` に `path` ベースの `dependency` が追加されます）\r\n\r\nたとえば、 `dub.sdl` と同じディレクトリにある本READMEの場合、内部で使っている `commands.main` を `import` することができます。\r\n\r\n```d name=package_ref\r\nimport commands.main;\r\nimport std.stdio;\r\n\r\nwriteln(\"current package: \", loadCurrentProjectName());\r\n```\r\n\r\n### 追加のパッケージ参照\r\n\r\n`-d \u003cpakageName\u003e` や `-d \u003cpakageName\u003e@\u003cversionString\u003e` （`-d mir-ion@~\u003e2.0.16` など）の指定によって追加の依存関係を設定することもできます。（`-d` の正式名は `--dependency` です）\r\n\r\n\r\n### dub.sdlの直接設定（テストされていません）\r\n\r\n`--dubsdl \u003cinstruction\u003e` を指定すると、生成されるファイルに dub.sdl の行を直接追加することができます。このオプションは複数回指定することで複数の行を追加することもできます。\r\nこのオプションを指定した場合、上記の「既定のパッケージ参照機能」が無効化され、参照が追加されなくなります。\r\n\r\n\r\n### グローバル宣言\r\n\r\n通常のコードブロックはサンプル用の記述を想定し、 `void main() {}` の中に書かれたものとして実行されます。（前後に `void main() {` と `}` が補われたソースが生成されます）\r\n\r\nコードブロックを1つのソースファイルとして解釈させる場合、コードブロックに `global` という設定を追加します。これは `single` を指定した場合と同様、他のコードブロックとは結合されません。\r\n\r\n~~~\r\n```d global\r\n```\r\n~~~\r\n\r\n__1つのソースとして実行される例__\r\n\r\n```d global\r\nimport std;\r\n\r\nvoid main()\r\n{\r\n    writeln(\"Hello, Markdown!\");\r\n}\r\n```\r\n\r\n\r\n## その他\r\n\r\n### 実行時の仕組み\r\n\r\ntempディレクトリに `.md` ディレクトリを作り、dubのシングルファイル形式のソースを生成、 `dub run --single md_xxx.md` といったコマンドで実行します。\r\n\r\nまた、既定のパッケージ参照を実現するため、ソースの先頭に以下のようなコメントを自動的に付与します。\r\n\r\n```d disabled\r\n/+ dub.sdl:\r\n    dependency \"md\" path=\"C:\\\\work\\md\"\r\n +/\r\n```\r\n\r\n### 制限\r\n\r\n#### UFCS\r\n\r\n通常のコードブロックでは、 `void main() {}` で囲んだソースを生成します。\r\n関数定義がグローバル関数ではないため、UFCSは動作しません\r\n\r\n__UFCSが解決されず動かない例__\r\n\r\n```d disabled\r\nauto sum(R)(R range)\r\n{\r\n    import std.range : ElementType;\r\n\r\n    alias E = ElementType!R;\r\n    auto result = E(0);\r\n    foreach (x; range)\r\n    {\r\n        result += x;\r\n    }\r\n    return result;\r\n}\r\n\r\nauto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\r\nauto result = arr.sum();\r\n```\r\n\r\nglobal設定を行い、main関数を適切に書くことで動作します。\r\n\r\n__UFCSのためglobal指定を追加した例__\r\n\r\n```d global\r\nauto sum(R)(R range)\r\n{\r\n    import std.range : ElementType;\r\n\r\n    alias E = ElementType!R;\r\n    auto result = E(0);\r\n    foreach (x; range)\r\n    {\r\n        result += x;\r\n    }\r\n    return result;\r\n}\r\n\r\nvoid main()\r\n{\r\n    auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\r\n    auto result = arr.sum();\r\n}\r\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flempiji%2Fmd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flempiji%2Fmd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flempiji%2Fmd/lists"}