Skip to content

lempiji/md

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

md

日本語

This is a tool to run Markdown code blocks.

This can be used by CI to guarantee that the samples written in the README will work.

Example repo: https://github.com/lempiji/sandbox-vuepress

Usage

Run it as dub fetch md and dub run md -- README.md

Also, this README.md is executable.

You can configure how your generated D source file is run by passing in command line arguments to md:

show help

dub run md -- --help

Features

The code block whose language is specified as d or D will be executed.

Combine blocks

If there are multiple blocks as shown below, they will be combined and executed.

block 1

import std;

auto message = "Hello, " ~ "Markdown!";

block 2

writeln(message); // Hello, Markdown!

Disabled block

Code blocks specified as disabled will not be executed, as shown below.

```d disabled
```

disabled code block

throw new Exception("disabled");

Named block

Can give an independent scope to a block of code by giving it a name like the following. Even if they are written separately, they will be combined like a block if they have the same name.

```d name=test
```
import std;

auto buf = iota(10).array();
writeln(buf);

If name is not specified, it is treated as the name main.

Scoped block

To make a single block of code run independently without being combined with other blocks, give it the attribute single.

```d single
```

single block

import std;

auto message = "single code block";
writeln(message);

dub Build Options Support

The tool supports several options that can be passed to the execution (dub run). These options are directly passed as arguments to dub run.

  1. --build
  2. --compiler
  3. --arch

Example

dub run md -- README.md --build=release --compiler=ldc2 --arch=x86_64

Current package reference

If the current directory is a dub package, the dependency will be automatically added. (using a "path" based dependency)

For example, if this README is in the same directory as md/dub.sdl, then can import commands.main of md.

import commands.main;
import std.stdio;

writeln("current package: ", loadCurrentProjectName());

Additional dependencies

It's possible to specify -d <packageName> or -d <packageName>@<versionString> such as -d mir-ion@~>2.0.16 to add further dependencies. (long name: --dependency)

Instruction to dub.sdl (not tested)

It's possible to specify --dubsdl "<instruction>" to add a dub.sdl recipe line into the generated file. This option can be used multiple times to add multiple lines.

Specifying this option disables the built-in CWD package dependency addition described above.

Global

The normal code blocks are executed as if they were written in void main() {}. The source will be generated with void main() { and } appended before and after.

If you want the code block to be interpreted as a single source file, you can add a global attribute to the code block, which will not be combined with other code blocks as with the single attribute.

```d global
```

single file

import std;

void main()
{
    writeln("Hello, Markdown!");
}

Othres

How it works

Create a .md directory in the temp directory, generate the source in dub single file format, and run it with a command like dub run --single md_xxx.md.

It also automatically adds the following comment to the beginning of the source to achieve default package references.

/+ dub.sdl:
    dependency "md" path="C:\\work\md"
 +/

Limits

UFCS

A normal code block will generate the source enclosed in void main() {}. UFCS will not work because the function definition is not a global function.

this code doesn't work

auto sum(R)(R range)
{
    import std.range : ElementType;

    alias E = ElementType!R;
    auto result = E(0);
    foreach (x; range)
    {
        result += x;
    }
    return result;
}

auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
auto result = arr.sum();

It works by setting the global attribute and writing the main function appropriately.

this code works

auto sum(R)(R range)
{
    import std.range : ElementType;

    alias E = ElementType!R;
    auto result = E(0);
    foreach (x; range)
    {
        result += x;
    }
    return result;
}

void main()
{
    auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    auto result = arr.sum();
}