Skip to content

Inline GitHub Code Snippets through Remark

Published: at 09:23 PM

Inline GitHub Code Snippets through Remark

I want to post a lot about code I write in Open Source software and I was searching for a nice way to include up-to-date code without littering my Markdown files. My blogging platform (Astro with the Astro Paper theme) has Remark set up already. Remark is a markdown processor that relies on plugins to change or validate the markdown files of my blog and e.g. add the table of contents. Very convenient and it feels a bit like magic.

I looked through a lot of remark plugins and found none that suits my needs so I decided to build my own plugin, how hard can it be?

The idea

I host all of my code in GitHub so the idea I had was:

  1. Take a permalink to GitHub file with start and end line
  2. Put it in a link in Markdown
  3. Have the plugin download and inline the code

In practice this would look like this:

## Look at this code

This code does XYZ:

[inline](https://github.com/facebook/react/blob/b943feba35476196fa674de276f2b87624086896/compiler/packages/react-compiler-runtime/src/index.ts#L13-L17)

And it should render

Look at this code

This code does XYZ:

// Source: https://github.com/facebook/react/blob/b943feba35476196fa674de276f2b87624086896/compiler/packages/react-compiler-runtime/src/index.ts#L13-L17
const ReactSecretInternals =
  //@ts-ignore
  React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ??
  //@ts-ignore
  React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

The plugin

If you want to skip directly to the result: https://github.com/danielmschmidt/remark-inline-github-code-snippets/.

First of all we need to find all the links in our document that should be replaced by snippets:

// Source: https://github.com/DanielMSchmidt/remark-inline-github-code-snippets/blob/fd6f45bbc8622c3dea9b2673c5e95ac1d5036e2a/src/index.ts#L40-L55
    visit(tree, (node, index, parent) => {
      // Search for links starting with github.com and containing the inlineMarker
      if (
        node.type === "link" &&
        node.children[0].type === "text" &&
        node.children[0].value === settings.inlineMarker &&
        node.url.startsWith("https://github.com")
      ) {
        inlineSnippets.push({
          url: node.url,
          inline: (codeblock) => {
            parent!.children[index!] = codeblock;
          },
        });
      }
    });

We visit all nodes using unist-util-visit’s visit utility. For each link we check for the text to be a specific keyword used so we don’t replace normal links by accident.

We then transform all links into two parts, the start and end line and the url needed to download the contents of the entire file. Then we just need to only return the selected lines and guess the Markdown tag via the file extension.

// Source: https://github.com/DanielMSchmidt/remark-inline-github-code-snippets/blob/fd6f45bbc8622c3dea9b2673c5e95ac1d5036e2a/src/index.ts#L111-L122
export const supportedLanguageExtensions: Record<string, LanguageHandler> = {
  ".js": {
    markdown: "javascript",
    comment: (c) => `// ${c}\n`,
  },
  ".ts": {
    markdown: "typescript",
    comment: (c) => `// ${c}\n`,
  },
  ".py": {
    markdown: "python",
    comment: (c) => `# ${c}\n`,

We also add a comment with the source so you as the reader can look deeper into the code parts mentioned and voila, we have the inline snippets you see here.

Since we use an unauthenicated request to GitHub to load the snippet we don’t support private repositories with this plugin, but since I’m writing in the context of Open Source that’s good enough for me.

I hope this plugin helps someone else, but just the joy of being able to skim through my markdown without needing to scroll by code passages was already a good enough reason for building this.




Next Post
Development Environment Setup with Chezmoi