GithubHelp home page GithubHelp logo

andrewbranch / gatsby-remark-vscode Goto Github PK

View Code? Open in Web Editor NEW
294.0 6.0 27.0 8.17 MB

Gatsby plugin to provide VS Code’s syntax highlighting to Markdown code fences

License: MIT License

JavaScript 66.11% CSS 0.81% HTML 33.07%
gatsby gatsby-remark gatsby-remark-plugin syntax-highlighting

gatsby-remark-vscode's Introduction

gatsby-remark-vscode

npm

A syntax highlighting plugin for Gatsby that uses VS Code’s extensions, themes, and highlighting engine. Any language and theme VS Code supports, whether built-in or via a third-party extension, can be rendered on your Gatsby site.

Includes OS dark mode support 🌙

v3 is out now! 🎉

If you’re updating from v2.x.x (or v1), see MIGRATING.md. New features are line numbers and diff highlighting (thanks @janosh for the latter!).

Table of contents

Why gatsby-remark-vscode?

JavaScript syntax highlighting libraries that were designed to run in the browser, like Prism, have to make compromises given the constraints of their intended environment. Since they get downloaded and executed whenever a user visits a page, they have to be ultra-fast and ultra-lightweight. Your Gatsby app, on the other hand, renders to HTML at build-time in Node, so these constraints don’t apply. So why make tradeoffs that don’t buy you anything? There’s no reason why the syntax highlighting on your blog should be any less sophisticated than the syntax highlighting in your code editor. And since VS Code is built with JavaScript and CSS, is open source, and has a rich extension ecosystem, it turns out that it’s pretty easy to use its highlighting engine and extensions and get great results. A few examples of where gatsby-remark-vscode excels:

Scenario Others gatsby-remark-vscode
Embedded languages
Complex TypeScript
Tricky template strings
Uncommon languages

Getting started

Install the package:

npm install --save gatsby-remark-vscode

Add to your gatsby-config.js:

{
  // ...
  plugins: [{
    resolve: `gatsby-transformer-remark`,
    options: {
      plugins: [{
        resolve: `gatsby-remark-vscode`,
        options: {
          theme: 'Abyss' // Or install your favorite theme from GitHub
        }
      }]
    }
  }]
}

Write code examples in your markdown file as usual:

```js
this.willBe(highlighted);
```

Multi-theme support

You can select different themes to be activated by media query or by parent selector (e.g. a class or data attribute on the html or body element).

Reacting to OS dark mode with prefers-color-scheme

{
  theme: {
    default: 'Solarized Light',
    dark: 'Monokai Dimmed'
  }
}

Reacting to a parent selector

{
  theme: {
    default: 'Solarized Light',
    parentSelector: {
      // Any CSS selector will work!
      'html[data-theme=dark]': 'Monokai Dimed',
      'html[data-theme=hc]': 'My Cool Custom High Contrast Theme'
    }
  }
}

Reacting to other media queries

The dark option is shorthand for a general-purpose media option that can be used to match any media query:

{
  theme: {
    default: 'Solarized Light',
    media: [{
      // Longhand for `dark` option.
      // Don’t forget the parentheses!
      match: '(prefers-color-scheme: dark)',
      theme: 'Monokai Dimmed'
    }, {
      // Proposed in Media Queries Level 5 Draft
      match: '(prefers-contrast: high)',
      theme: 'My Cool Custom High Contrast Theme'
    }, {
      match: 'print',
      theme: 'My Printer Friendly Theme???'
    }]
  }
}

Built-in languages and themes

The following languages and themes can be used without installing third-party extensions:

Languages

See all 55 languages
  • Batch/CMD
  • Clojure
  • CoffeeScript
  • C
  • C++
  • C Platform
  • C#
  • CSS
  • Dockerfile
  • F#
  • Git Commit
  • Git Rebase
  • Diff
  • Ignore
  • Go
  • Groovy
  • Handlebars
  • Hlsl
  • HTML
  • CSHTML
  • PHP HTML
  • INI
  • Java
  • JavaScript
  • JSX
  • JSON
  • JSON with Comments
  • Less
  • Log
  • Lua
  • Makefile
  • Markdown
  • Objective-C
  • Objective-C++
  • Perl
  • Perl 6
  • PHP
  • Powershell
  • Pug
  • Python
  • R
  • Ruby
  • Rust
  • Sass
  • SassDoc
  • ShaderLab
  • Shell
  • SQL
  • Swift
  • TypeScript
  • TSX
  • ASP VB .NET
  • XML
  • XML XSL
  • YAML

Language names are resolved case-insensitively by any aliases and file extensions listed in the grammar’s metadata. For example, a code fence with C++ code in it can use any of these language codes. You could also check the built-in grammar manifest for an exact list of mappings.

Themes

Pro tip: a good way to preview themes is by flipping through them in VS Code. Here’s the list of included ones:

  • Abyss
  • Dark+ (default dark)
  • Light+ (default light)
  • Dark (Visual Studio)
  • Light (Visual Studio)
  • High Contrast
  • Kimbie Dark
  • Monokai Dimmed
  • Monokai
  • Quiet Light
  • Red
  • Solarized Dark
  • Solarized Light
  • Tomorrow Night Blue

Using languages and themes from an extension

If you want to use a language or theme not included by default, the recommended approach is to npm install it from GitHub, provided its license permits doing so. For example, you can use robb0wen/synthwave-vscode by running

npm install robb0wen/synthwave-vscode

Then, in gatsby-config.js, use the options

{
  theme: `SynthWave '84`, // From package.json: contributes.themes[0].label
  extensions: ['synthwave-vscode'] // From package.json: name
}

You can also clone an extension into your project, or build a .vsix file from its source, and specify its path in extensions:

{
  theme: {
    default: 'My Custom Theme',
    dark: 'My Custom Dark Theme'
  },
  extensions: ['./vendor/my-custom-theme', './vendor/my-custom-dark-theme.vsix']
}

Styles

The CSS for token colors and background colors is generated dynamically from each theme you use and included in the resulting HTML. However, you’ll typically want at least a small amount of additional styling to handle padding and horizontal scrolling. These minimal additional styles are included alongside the dynamically generated token CSS by default, but can be disabled by setting the injectStyles option to false. If you prefer bundling the styles through your app’s normal asset pipeline, you can simply import the CSS file:

import 'gatsby-remark-vscode/styles.css';

Class names

The generated HTML has ample stable class names, and you can add your own with the wrapperClassName and getLineClassName option. All (non-token-color) included styles have a single class name’s worth of specificity, so it should be easy to override the built-in styles.

Variables

The styles also include a few CSS variables you can define to override defaults. The included CSS is written as:

.grvsc-container {
  padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
  padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
  border-radius: var(--grvsc-border-radius, 8px);
}

.grvsc-line {
  padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
  padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
}

/* See “Line Highlighting” section for details */
.grvsc-line-highlighted {
  background-color: var(--grvsc-line-highlighted-background-color, transparent);
  box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
}

The padding values are written with cascading fallbacks. As an example, let’s consider the top and bottom padding of .grvsc-container. Each is set to its own CSS variable, --grvsc-padding-top and --grvsc-padding-bottom, respectively. Neither of these is defined by default, so it uses the value of its fallback, which is another CSS variable, --grvsc-padding-v, with another fallback, 1rem. Since --grvsc-padding-v is also not defined by default, both padding properties will evaluate to the final fallback, 1rem.

So, if you want to adjust the vertical padding, you could add the following to your own CSS:

:root {
  --grvsc-padding-v: 20px; /* Adjust padding-top and padding-bottom */
}

If you want to adjust the padding-top or padding-bottom independently, you can use those variables:

:root {
  --grvsc-padding-top: 24px; /* Adjust padding-top by itself */
}

Tweaking or replacing theme colors

Since the CSS for token colors is auto-generated, it’s fragile and inconvenient to try to override colors by writing more specific CSS. Instead, you can use the replaceColor option to replace any value specified by the theme with another valid CSS value. This is especially handy for replacing static colors with variables if you want to support a “dark mode” for your site:

{
  replaceColor: oldColor => ({
    '#ff0000': 'var(--red)',
    '#00ff00': 'var(--green)',
    '#0000ff': 'var(--blue)',
  })[oldColor.toLowerCase()] || oldColor
}

Extra stuff

Inline code highlighting

To highlight inline code spans, add an inlineCode key to the plugin options and choose a marker string:

{
  inlineCode: {
    marker: '•'
  }
}

Then, in your Markdown, you can prefix code spans by the language name followed by the marker string to opt into highlighting that span:

Now you can highlight inline code: `js•Array.prototype.concat.apply([], array)`.

The syntax theme defaults to the one selected for code blocks, but you can control the inline code theme independently:

{
  theme: 'Default Dark+',
  inlineCode: {
    marker: '•',
    theme: {
      default: 'Default Light+',
      dark: 'Default Dark+'
    }
  }
}

See inlineCode in the options reference for more API details.

Line highlighting

gatsby-remark-vscode offers the same line-range-after-language-name strategy of highlighting or emphasizing lines as gatsby-remark-prismjs:

MarkdownRendered result
```js{1,3-5}
this.isLine(1); // highlighted
this.isLine(2);
this.isLine(3); // highlighted
this.isLine(4); // highlighted
this.isLine(5); // highlighted
```

Comment directives are also supported:

MarkdownRendered result
```js
function constant(value) {
  return () => value; // highlight-line
}

// highlight-next-line
const alwaysFour = constant(4);

// highlight-start
const zero = [0, 1, 2, 3, 4, 5]
  .map(alwaysFour)
  .filter(x => x !== 4)
  .length;
// highlight-end
```

You can customize the default background color and left border width and color for the highlighted lines by setting CSS variables:

:root {
  --grvsc-line-highlighted-background-color: rgba(255, 255, 255, 0.2);
  --grvsc-line-highlighted-border-color: rgba(255, 255, 255, 0.5);
  --grvsc-line-highlighted-border-width: 2px;
}

Line numbers

With code fence info:

```js {numberLines}
import * as React from 'react';

React.createElement('span', {});
```

Rendered result of the example code above

With code fence info specifying a starting line:

```js {numberLines: 21}
  return 'blah';
```

Rendered result of the example code above

With a comment:

```ts
function getDefaultLineTransformers(pluginOptions, cache) {
  return [
    one, // L4
    two,
    three
  ];
}
```

Rendered result of the example code above

With both:

```ts {numberLines}
import * as React from 'react';

// ...

function SomeComponent(props) { // L29
  return <div />;
}
```

Rendered result of the example code above

The line number cell’s styling can be overridden on the .grvsc-line-number class.

Diff highlighting

You can combine syntax highlighting with diff highlighting:

MarkdownRendered result
```ts {diff}
function add(x, y) {
-  return x + x;
+  return x + y;
}
```

The highlight color can be customized with the CSS variables --grvsc-line-diff-add-background-color and --grvsc-line-diff-del-background-color. The default color is static and might not be accessible with all syntax themes. Consider contrast ratios and choose appropriate colors when using this feature.

Using different themes for different code fences

The theme option can take a function instead of a constant value. The function is called once per code fence with information about that code fence, and should return either a string or an object. See the following section for an example.

Arbitrary code fence options

Line numbers and ranges aren’t the only things you can pass as options on your code fence. A JSON-like syntax is supported:

```jsx{theme: 'Monokai', someNumbers: {1,2,3}, nested: {objects: 'yep'}}
<Amazing><Stuff /></Amazing>
```

gatsby-remark-vscode doesn’t inherently understand these things, but it parses the input and allows you to access it in the theme, wrapperClassName and getLineClassName functions:

{
  theme: ({ parsedOptions, language, markdownNode, node }) => {
    // 'language' is 'jsx', in this case
    // 'markdownNode' is the gatsby-transformer-remark GraphQL node
    // 'node' is the Markdown AST node of the current code fence
    // 'parsedOptions' is your parsed object that looks like this:
    // {
    //   theme: 'Monokai',
    //   someNumbers: { '1': true, '2': true, '3': true },
    //   nested: { objects: 'yep' }
    // }
    return parsedOptions.theme || 'Dark+ (default dark)';
  },
  wrapperClassName: ({ parsedOptions, language, markdownNode, node }) => '';
}

Usage as a remark plugin without Gatsby

This package exports a remarkPlugin property that accepts the same options as the main Gatsby plugin and is usable as a remark plugin in any unifiedjs processing pipeline.

First, install the required dependencies:

npm install unified remark-parse gatsby-remark-vscode remark-rehype rehype-raw rehype-stringify

Then, in an ES Module file, e.g., index.mjs:

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkVscode from 'gatsby-remark-vscode'
import remarkToRehype from 'remark-rehype'
import rehypeRaw from 'rehype-raw'
import rehypeStringify from 'rehype-stringify'

const markdownSource = `
# Code example with awesome syntax highlighting

\`\`\`ts {numberLines}
export function sum(a: number, b: number): number {
  return a + b;
}
\`\`\`

This is a paragraph after the code example.
`

const processor = unified()
  // parse markdown to remark AST
  .use(remarkParse)
  // apply syntax highlighting using `remarkPlugin`
  // with your preferred options
  .use(remarkVscode.remarkPlugin, {
    theme: 'Default Light+',
  })
  // convert remark AST to rehype AST
  .use(remarkToRehype, { allowDangerousHtml: true })
  .use(rehypeRaw)
  // stringify
  .use(rehypeStringify, {
    allowDangerousHtml: true,
    closeSelfClosing: true,
  });

const vfile = await processor.process(markdownSource);
console.log(vfile.value); // logs resulting HTML

Options reference

theme

The syntax theme used for code blocks.

  • Default: 'Default Dark+'

  • Accepted types:

    • string: The name or id of a theme. (See Built-in themes and Using languages and themes from an extension.)
    • ThemeSettings: An object that selects different themes to use in different contexts. (See Multi-theme support.)
    • (data: CodeBlockData) => string | ThemeSettings: A function returning the theme selection for a given code block. CodeBlockData is an object with properties:
      • language: The language of the code block, if one was specified.
      • markdownNode: The MarkdownRemark GraphQL node (not available if used as remarkPlugin)
      • node: The Remark AST node of the code block.
      • parsedOptions: The object form of of any code fence info supplied. (See Arbitrary code fence options.)

wrapperClassName

A custom class name to be set on the pre tag.

  • Default: None, but the class grvsc-container will always be on the tag.
  • Accepted types:
    • string: The class name to add.
    • (data: CodeBlockData) => string: A function returning the class name to add for a given code block. (See the theme option above for the details of CodeBlockData.)

languageAliases

An object that allows additional language names to be mapped to recognized languages so they can be used on opening code fences.

  • Default: None, but many built-in languages are already recognized by a variety of names.

  • Accepted type: Record<string, string>; that is, an object with string keys and string values.

  • Example:

    {
      languageAliases: {
        fish: 'sh'
      }
    }
    Then you can use code fences like this:
    
    ```fish
    ls -la
    ```
    
    And they’ll be parsed as shell script (`sh`).

extensions

A list of third party extensions to search for additional langauges and themes. (See Using languages and themes from an extension.)

  • Default: None
  • Accepted type: string[]; that is, an array of strings, where the strings are the package names of the extensions.

inlineCode

Enables syntax highlighting for inline code spans. (See Inline code highlighting.)

  • Default: None
  • Accepted type: An object with properties:
    • theme: A string or ThemeSettings object selecting the theme, or a function returning a string or ThemeSettings object for a given code span. The type is the same as the one documented in the top-level theme option. Defaults to the value of the top-level theme option.
    • marker: A string used as a separator between the language name and the content of a code span. For example, with a marker of value '•', you can highlight a code span as JavaScript by writing the Markdown code span as `js•Code.to.highlight("inline")`.
    • className: A string, or function returning a string for a given code span, that sets a custom class name on the wrapper code HTML tag. If the function form is used, it is passed an object parameter describing the code span with properties:
      • language: The language of the code span (the bit before the marker character).
      • markdownNode: The MarkdownRemark GraphQL node. (not available if used as remarkPlugin)
      • node: The Remark AST node of the code span.

injectStyles

Whether to add supporting CSS to the end of the Markdown document. (See Styles.)

  • Default: true
  • Accepted type: boolean

replaceColor

A function allowing individual color values to be replaced in the generated CSS. (See Tweaking or replacing theme colors.)

  • Default: None
  • Accepted type: (colorValue: string, theme: string) => string; that is, a function that takes the original color and the identifier of the theme it came from and returns a new color value.

logLevel

The verbosity of logging. Useful for diagnosing unexpected behavior.

  • Default: 'warn'
  • Accepted values: From most verbose to least verbose, 'trace', 'debug', 'info', 'warn', or 'error'.

Contributing

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

See CONTRIBUTING.md for development instructions.

gatsby-remark-vscode's People

Contributors

ajliu avatar andrewbranch avatar aral avatar chadly avatar chivandikwa avatar codepunkt avatar dependabot[bot] avatar greenkeeper[bot] avatar janosh avatar kevin940726 avatar mdluo avatar rodrigo54 avatar tnorlund avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gatsby-remark-vscode's Issues

Problem when trying to use theme from vscode marketplace

This error is when I try to fetch the html code from markdown.

Here is my gatsby-config.js:

'use strict';

const siteConfig = require('./config.js');
const postCssPlugins = require('./postcss-config.js');

module.exports = {
  pathPrefix: siteConfig.pathPrefix,
  siteMetadata: {
    url: siteConfig.url,
    title: siteConfig.title,
    subtitle: siteConfig.subtitle,
    copyright: siteConfig.copyright,
    disqusShortname: siteConfig.disqusShortname,
    menu: siteConfig.menu,
    author: siteConfig.author
  },
  plugins: [
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/content`,
        name: 'pages'
      }
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/static/media`,
        name: 'media'
      }
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'css',
        path: `${__dirname}/static/css`
      }
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'assets',
        path: `${__dirname}/static`
      }
    },
    {
      resolve: 'gatsby-plugin-feed',
      options: {
        query: `
          {
            site {
              siteMetadata {
                site_url: url
                title
                description: subtitle
              }
            }
          }
        `,
        feeds: [{
          serialize: ({ query: { site, allMarkdownRemark } }) => (
            allMarkdownRemark.edges.map((edge) => Object.assign({}, edge.node.frontmatter, {
              description: edge.node.frontmatter.description,
              date: edge.node.frontmatter.date,
              url: site.siteMetadata.site_url + edge.node.fields.slug,
              guid: site.siteMetadata.site_url + edge.node.fields.slug,
              custom_elements: [{ 'content:encoded': edge.node.html }]
            }))
          ),
          query: `
              {
                allMarkdownRemark(
                  limit: 1000,
                  sort: { order: DESC, fields: [frontmatter___date] },
                  filter: { frontmatter: { template: { eq: "post" }, draft: { ne: true } } }
                ) {
                  edges {
                    node {
                      html
                      fields {
                        slug
                      }
                      frontmatter {
                        title
                        date
                        template
                        draft
                        description
                      }
                    }
                  }
                }
              }
            `,
          output: '/rss.xml'
        }]
      }
    },
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: [
          'gatsby-remark-relative-images',
          {
            resolve: 'gatsby-remark-katex',
            options: {
              strict: 'ignore'
            }
          },
          {
            resolve: 'gatsby-remark-images',
            options: {
              maxWidth: 960,
              withWebp: true,
              ignoreFileExtensions: [],
            }
          },
          {
            resolve: 'gatsby-remark-responsive-iframe',
            options: { wrapperStyle: 'margin-bottom: 1.0725rem' }
          },
          {
            resolve: 'gatsby-remark-vscode',
            options: {
              extensions: [{
                identifier: 'RobbOwen.synthwave-vscode',
                version: '0.0.7'
              }]
            }
          },
          'gatsby-remark-autolink-headers',
          'gatsby-remark-copy-linked-files',
          'gatsby-remark-smartypants',
          'gatsby-remark-external-links'
        ]
      }
    },
    'gatsby-transformer-sharp',
    'gatsby-plugin-sharp',
    'gatsby-plugin-netlify',
    {
      resolve: 'gatsby-plugin-netlify-cms',
      options: {
        modulePath: `${__dirname}/src/cms/index.js`,
      }
    },
    {
      resolve: 'gatsby-plugin-google-gtag',
      options: {
        trackingIds: [siteConfig.googleAnalyticsId],
        pluginConfig: {
          head: true,
        },
      },
    },
    {
      resolve: 'gatsby-plugin-sitemap',
      options: {
        query: `
          {
            site {
              siteMetadata {
                siteUrl: url
              }
            }
            allSitePage(
              filter: {
                path: { regex: "/^(?!/404/|/404.html|/dev-404-page/)/" }
              }
            ) {
              edges {
                node {
                  path
                }
              }
            }
          }
        `,
        output: '/sitemap.xml',
        serialize: ({ site, allSitePage }) => allSitePage.edges.map((edge) => ({
          url: site.siteMetadata.siteUrl + edge.node.path,
          changefreq: 'daily',
          priority: 0.7
        }))
      }
    },
    {
      resolve: 'gatsby-plugin-manifest',
      options: {
        name: siteConfig.title,
        short_name: siteConfig.title,
        start_url: '/',
        background_color: '#FFF',
        theme_color: '#F7A046',
        display: 'standalone',
        icon: 'static/photo.jpg'
      },
    },
    'gatsby-plugin-offline',
    'gatsby-plugin-catch-links',
    'gatsby-plugin-react-helmet',
    {
      resolve: 'gatsby-plugin-sass',
      options: {
        postCssPlugins: [...postCssPlugins],
        cssLoaderOptions: {
          camelCase: false,
        }
      }
    },
    'gatsby-plugin-flow',
    'gatsby-plugin-optimize-svgs',
  ]
};

Here is the error I am getting:

The GraphQL query from /home/leo/Desktop/projects/blog/src/templates/post-template.js failed.

Errors:
  Unexpected token }

  GraphQL request:6:5
  5 |     id
  6 |     html
    |     ^
  7 |     fields {
URL path:
  /posts/a-brief-history-of-typography/
Context:
  {
    "slug": "/posts/a-brief-history-of-typography/"
  }
Plugin:
  none
Query:
  query PostBySlug(
    $slug: String!
  ) {
    markdownRemark(fields: {slug: {eq: $slug}}) {
      id
      html
      fields {
        slug
        tagSlugs
      }
      frontmatter {
        date
        description
        tags
        title
      }
    }
  }

If I try to use a supported theme such as Dark+ it works fine.

v2.0.0 Tracking Issue

Short version: several things are necessitating some breaking changes, and it’s a good opportunity to think about what else I would want to see in a v2. I haven’t gone into the details much here, but thoughts and questions are welcome.

WIP in the v2 branch. You can try it out now! npm install gatsby-remark-vscode@alpha

Meta/infrastructure

  • Publish alpha releases from v2 branch (#65)
  • Improved integration test infrastructure
  • Add migration guide, contributing guide, COC, etc.
  • Infrastructure for marking options as deprecated

Breaking changes

  • Breaking changes to token CSS/HTML to fix multi-theme conflicts (#63)
  • Replace extension downloading capability with extension retrieval from node_modules (#67)

Stable features

  • Parent-selector-based theme switching (#39, #66)
  • Replace oniguruma with onigasm by default, use oniguruma if available (#22, #24) (vscode-textmate has a hard dependency on oniguruma)

Preview features

(Hoping to make stable for 2.1)

  • Populate GraphQL with tokenization data (#59, #53)

Way to load and cache extensions in CI builds?

No idea how resource requests for VS Code extensions are authorized so this might be a dumb question. Is there an alternative to committing extensions to VC in order to get CI builds to work? I'm getting something like this on Netlify.

{
  "$id": "1",
  "innerException": null,
  "message": "Request was blocked due to exceeding usage of resource 'Count' in namespace 'AnonymousId'. For more information on why your request was blocked, see the topic \"Rate limits\" on the Microsoft Web site (https://go.microsoft.com/fwlink/?LinkId=823950).",
  "typeName": "Microsoft.TeamFoundation.Framework.Server.RequestBlockedException, Microsoft.TeamFoundation.Framework.Server",
  "typeKey": "RequestBlockedException",
  "errorCode": 0,
  "eventId": 3000
}

This sounds like providing a proper value for AnonymousId as an environment variable might help.

Line highlight comment directives stopped working in v2 alpha

It seems my verdict in #69 was a little premature. Looks like the line transformer for highlight comment directives isn't active or stopped working.

Never mind what I wrote above. (You should never try to diagnose and fix bugs in a hurry. 😅) The line transformer isn't the problem. It's either the class name being attached to highlighted lines or the migration guide which states

If you wrote custom CSS targeting any other class beginning with .vscode-highlight, replace the .vscode-highlight prefix with .grvsc. For example, .vscode-highlight-line is now .grvsc-line.

So I modified the CSS selector for highlighted lines from

.vscode-highlight .vscode-highlight-line-highlighted {
  background: rgba(255, 255, 255, 0.15);
  box-shadow: inset 0.3em 0 0 0 ${props => props.theme.lighterBlue};
}

to

.grvsc-container .grvsc-line-highlighted {
  background: rgba(255, 255, 255, 0.15);
  box-shadow: inset 0.3em 0 0 0 ${props => props.theme.lighterBlue};
}

The class name that's actually being applied is grvsc-highlightedthough. Is this intentional? I think I prefer grvsc-line-highlighted here as it's more descriptive and specific. But we can also leave it at that and modify the migration guide.

v2 alpha: extension issues

Hey @andrewbranch, great progress you've been making on v2! Really excited to see this!

Just installed the alpha, tried to convert my extensions to node_modules and attempted gatsby build. I got

  TypeError: Cannot read property 'map' of undefined
  
  - createNodeRegistry.js:55 Object.getAllPossibleThemes
    [gatsby-remark-vscode]/src/createNode    Registry.js:55:40
  
  - index.js:196 textmateHighlight
    /[gatsby-remark-vscode]/src/index.js:1    96:45

Not sure if this is the same bug as #68.

I only "tried to replace my extensions" above because one of them wouldn't install. I use:

  1. MDX
  2. vscode-styled-components

yarn add silvenon/vscode-mdx worked fine. But yarn add styled-components/vscode-styled-components failed with

Error: Cannot find module './node_modules/vscode-styled-components/node_modules/vscode/bin/install'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:797:15)
    at Function.Module._load (internal/modules/cjs/loader.js:690:27)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
    at internal/main/run_main_module.js:17:11 {
  code: 'MODULE_NOT_FOUND',

Wasn't able to troubleshoot this so far. In any case, this has nothing to do with GRV but maybe it's a restriction to this way of adding extensions? If so, it might apply to more than one repo in which case it should be noted in the migration guide.

So as a workaround I downloaded the VSIX file for vscode-styled-components and added

{
    resolve: `gatsby-remark-vscode`,
    options: {
      extensions: [
        `mdx`,
        `./src/utils/jpoissonnier.vscode-styled-components-0.0.27.vsix`,
      ],
    },
  },

to my gatsby-config.js. That threw

Error: Invalid option 'extensions': Extension paths must be absolute. Received './src/utils/jpoissonni er.vscode-styled-components-0.0.27.vsix'.

even though the current version of the migration guide says both relative and absolute paths should work.

So I pasted the absolute path and now I'm getting the above mentioned TypeError: Cannot read property 'map' of undefined. Any way to proceed here?

Failed to install gatsby-remark-vscode on windows 10 with python 3.7.3

I failed to execute

npm install --save gatsby-remark-vscode

with Python 3.7.3 installed on a Windows 10 machine. I got an error about

oniguruma > node-gyp rebuild configure error

On unistalling that version of python and replacing it with 2.7.16 was I only able to get this to work. By that time I also had to execute

npm install --global --production windows-build-tools

not sure if the windows-build-tools where necessary as I have Visual Studio 2017 installed with the required C++ dependencies also.

Allow manual switch of dark/light mode

First I would like to say this is a great idea! :)

Now to the matter at hand, prefers-color-scheme: dark is all the hot fuss, but I would like to allow my users to override that if they want, so I have a switch to select the themes.

Is there an easy way to switch themes like that? Be it a css variable or a className?

Support for comment directives?

Are there any plans to add support for comment directives (// highlight-line)? They are in quite popular use and make highlights in code blocks much easier to maintain if the code (and hence the line numbers) change over time.

Error on update to v2

🐞 bug report

I get a error on updated to version 2

image

i think gatsby-remark-embed-gist it clash this package in version 2

in version 1.4.0 it works

🔬 Minimal Reproduction

clone this repo
git clone -b feature/gatsby --single-branch https://github.com/Rodrigo54/rodrigoalves.me.git

and upgrade npm package gatsby-remark-vscode to alfa version
npm install gatsby-remark-vscode@alpha

🌍 My Environment

gatsby info

  System:
    OS: Windows 10 10.0.18363
    CPU: (6) x64 Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
  Binaries:
    Node: 12.1.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.15.2 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.9.0 - C:\Program Files\nodejs\npm.CMD
  Languages:
    Python: 2.7.16 - /c/Python27/python
  Browsers:
    Edge: 44.18362.449.0
  npmPackages:
    gatsby: ^2.18.12 => 2.18.12
    gatsby-image: ^2.2.34 => 2.2.34
    gatsby-plugin-manifest: ^2.2.31 => 2.2.31
    gatsby-plugin-offline: ^3.0.27 => 3.0.27
    gatsby-plugin-react-helmet: ^3.1.16 => 3.1.16
    gatsby-plugin-sharp: ^2.3.10 => 2.3.10
    gatsby-plugin-styled-components: ^3.1.16 => 3.1.16
    gatsby-plugin-transition-link: ^1.17.7 => 1.17.7
    gatsby-plugin-typescript: ^2.1.23 => 2.1.23
    gatsby-remark-embed-gist: ^1.1.9 => 1.1.9
    gatsby-remark-images: ^3.1.39 => 3.1.39
    gatsby-remark-lazy-load: ^1.0.2 => 1.0.2
    gatsby-remark-relative-images: ^0.2.3 => 0.2.3
    gatsby-remark-vscode: ^2.0.0-alpha.20191227 => 2.0.0-alpha.20191227
    gatsby-source-filesystem: ^2.1.40 => 2.1.40
    gatsby-transformer-remark: ^2.6.45 => 2.6.45
    gatsby-transformer-sharp: ^2.3.7 => 2.3.7

Proposal: Multi-theme API, CSS & HTML changes

Would love feedback from contributors (and any other users): @janosh @codepunkt @JCQuintas @chivandikwa

Background

gatsby-remark-vscode currently supports multiple themes activated by prefers-color-scheme media queries. Many users’ sites, however, have a manual theme selection switch, which typically works by reading the system theme preference via matchMedia, using that as the default state of the switch, then writing a class name to the html or body element reflecting the current theme selection, so the system preference can be overridden by interacting with a switch. (Example implementation: donavon/use-dark-mode.) In these cases, theme-specific CSS is usually written with respect to that class name and prefers-color-scheme media queries are omitted entirely. gatsby-remark-vscode has poor support for this convention. #39 tracks this feature request, and #55 is a working prototype of it by @codepunkt.

Additionally, discussion in #55 made me aware of a subtle bug with HTML and CSS generation in existing multi-theme support where token styles can leak from the default theme into a media-query-activated theme, and fixing it will require fairly significant changes in how token class names are generated.

Problem(s)

I was having trouble figuring out an API for #39 that struck a balance between simple and flexible without introducing breaking changes. Given that the aforementioned newly discovered bug will require changes that could potentially break users relying on the current token class name generation strategy, I think it might be time to embrace breaking changes and consider releasing a new major version. With the freedom that affords us to change things, I would like to:

  1. fix the aforementioned token class name generation bug
  2. allow users to choose an arbitrary number of themes to be selected by a parent selector (#39, but more flexible)
  3. future-proof the API against new values for prefers-color-scheme and other potentially relevant media queries in the draft of Media Queries Level 5
  4. reduce the confusion around the difference between defaultTheme and prefersLightTheme in the current API

Proposal

New theme options API

To address problems 2), 3), and 4) above, I propose to introduce a new top-level options key called theme, and deprecate colorTheme. Use of colorTheme in v2 will continue to work, but will issue a deprecation warning. Examples usage of the new option:

Single-theme

{
  theme: 'Default Dark+'
}

Parent selector theme selection with light, dark, and high-contrast

I anticipate this to be the most common configuration used for anyone using a dark mode switch.

{
  theme: {
    default: 'Solarized Light',
    parentSelector: {
      'html.dark': 'Default Dark+',
      'html.high-contrast': 'Some High Contrast Theme'
    }
  }
}

Advanced media query theme selection with light, dark, high-contrast, and print-optimized

{
  theme: {
    default: 'Default Light+',
    media: [{
      match: 'screen and (prefers-color-scheme: dark)',
      theme: 'Default Dark+'
    }, {
      match: 'screen and (prefers-contrast: high)',
      theme: 'Some High Contrast Theme'
    }, {
      match: 'print',
      theme: 'Some Printer-Friendly Theme'
    }]
  }
}

Shorthand preset for prefers-color-scheme: dark

{
  theme: {
    default: 'Solarized Light',
    dark: 'Oceanic Next'
  }
}

Parent selector theme selection with media query fallback

The parent selector strategy has naturally higher CSS precedence than the media query strategy, but it might be desirable to use media queries as a fallback while JavaScript is loading, or if JS fails to execute for some reason.

{
  theme: {
    default: 'Solarized Light',
    parentSelector: {
      'html.light': 'Solarized Light',
      'html.dark': 'Default Dark+',
    },
    media: [{
      match: '(prefers-color-scheme: dark)',
      theme: 'Default Dark+'
    }]
  }
}

Callback option value

This will work the same as it does today with colorTheme.

{
  theme: ({ language }) => {
    // Only enable dark theme for JavaScript
    if (language === 'js') {
      return {
        default: 'Default Light+',
        parentSelector: {
          '.dark': 'Default Dark+',
          '.hc': 'High Contrast'
        }
      };
    }
    return 'Default Light+';
  }
}

New class name generation

To explain the motivation for this, I have to explain the leaking token styles bug mentioned earlier. Imagine a config where the default theme has lots of different token colors, and then a media-query-activated theme has only one color:

{
  theme: {
    default: 'Default Dark+',
    dark: 'Monotone Purple'
  }
}

The way tokenization works is that the code is split into tokens with different scopes based on the TextMate grammar for whatever language of code is being analyzed. These scopes are independent of theme. As an example, the keyword const in JavaScript has the scopes storage.type.js, meta.var.expr.js, and source.js (and may have more in other contexts). Then, TextMate themes map these scopes to colors. The tokenizer keeps track of how many unique colors a theme contains and maps these to sequentially numbered class names in the form of mkt0, mkt1, and so on.

So, even though the keyword const has the same scopes regardless of theme, it will almost certainly receive a different class name depending on which theme is set during tokenization, because “Monotone Purple” will label every token as mkt0. The current bug is that I only tokenize once, with the last theme set. In this config example, “Monotone Purple” would be activated during tokenization, which means every token would have the class name mkt0, so the “Default Dark+” theme will also be monotone, with whatever color it associates with mkt0.

To fix this, we need to run the tokenizer once per theme (or at least translate scopes to class names once per theme), and assign theme-specific class names to tokens when themes produce different class names, so our const token becomes something like

- <span class="mkt0">const</span>
+ <span class="default-dark-mkt8 monotone-purple-mkt0">const</span>

And of course, the would have to update with it. Eventually, this substantially increases the weight of the CSS and HTML generated. The current global class names are also not terribly principled, so I want to adopt a grvsc prefix (for Gatsby-Remark-VSCode), and use either a hash or an index in place of serializing theme names:

- .default-dark .default-dark-mkt8 { color: #efefef; }
- .monotone-purple .monotone-purple-mkt0 { color: purple; }
+ .grvsc-t0 .grvsc-t0-8 { color: #efefef; }
+ .grvsc-t1 .grvsc-t1-0 { color: purple; }

- <span class="default-dark-mkt8 monotone-purple-mkt0">const</span>
+ <span class="grvsc-t0-8 grvsc-t1-0">const</span>

(I’d continue to put a more human-readable theme class name on the pre tag for consumers to target, but internal class names can be mangled for brevity.)

I’ll likely take this opportunity to add similarly prefixed class names and CSS variables as aliases for existing ones (e.g. .vscode-highlight-line) for backward compatibility for the duration of v2, perhaps with a flag to drop the old ones.

Notable restrictions

  • While a user can choose to employ both a parent selector strategy and a media query strategy, the parent selector will always have higher precedence. It’s intentionally not possible to activate a theme by the compound criteria of a matching media query and a parent selector. It’s also not possible increase the specificity of a media query theme such that it would win over a parent selector theme. Although the API leaves room for that as a future possibility, my current thinking is that any more complex media query logic can be implemented by the user with custom JavaScript by setting parent selectors in response to matchMedia.
  • Since it’s possible for multiple media queries to match at the same time, the user will have to take some care to order the media array appropriately. The last theme in the array will have the highest precedence since it will be written to the stylesheet last.

Weird colors in Safari

With #14 resolved, the rest of the process of replacing gatsby-remark-prismjs with gatsby-remark-vscode was really smooth! Syntax highlighting with gatsby-remark-vscode takes much less configuration! It even fixed an annoying problem I had with the background of highlighted lines not extending beyond the initial viewport, i.e. being cutoff on narrow screens when scrolling to the right.

highlighted-lines-cutoff

Thanks for providing this great addition to Gatsby's plugin ecosystem!

I deployed a test version of my site after the swap gatsby-remark-prismjs -> gatsby-remark-vscode. Everything looks great in Chrome and Firefox but for some reason, the colors are very different in Safari. For example, tokens like brackets, =, etc. are black in Safari and hence invisible on a dark background

safari-colors

whereas they are white in Chrome and Firefox.

chrome-colors

Any ideas what might be causing this?

Make line highlighting work without custom CSS

From the README:

You need to pick your own background color, and optionally a left border width and color, for the highlighted lines. This can be done by setting CSS variables:

This is a bad default UX. We should be able to pick a reasonable highlight color from the theme text color. Dark themes are usually highlighted with ~10% opacity white; what are light themes usually highlighted with? 10% black is better than no default, but maybe we can pick one of the darker non-black syntax colors.

Error: Cannot find module '../lib/grammars/manifest.json'

Can't build my gatsby site anymore.

I'm not sure what happened or where this came from, but i don't have anything inside my node_modules/gatsby-remark-vscode/lib folder except a vscode folder, but neither grammars nor themes.

Will this plugin work with gatsby-remark-embed-gist

Will this great plugin 😄 work with gatsby-remark-embed-gist to highlight the code embedded fro m a gist? I have failed to get this to work and I am unsure If my configuration is wrong or this is not supported.

Error: Cannot find module '../lib/vscode/colorThemeData`

Hello. I'm so excited about this plugin. Great work!
Sadly, as soon as I installed the plugin and turned on my development server, the following error was invoked.

error Plugin gatsby-transformer-remark returned an error


  Error: Cannot find module '../lib/vscode/colorThemeData'
  
  - loader.js:582 Function.Module._resolveFilename
    internal/modules/cjs/loader.js:582:15
  
  - loader.js:508 Function.Module._load
    internal/modules/cjs/loader.js:508:25
  
  - loader.js:637 Module.require
    internal/modules/cjs/loader.js:637:17
  
  - v8-compile-cache.js:159 require
    [rinae.dev]/[v8-compile-cache]/v8-compile-cache.js:159:20
  
  - index.js:9 Object.<anonymous>
    [rinae.dev]/[gatsby-remark-vscode]/src/index.js:9:28 // <- Look like this file caused the problem
  
  - v8-compile-cache.js:178 Module._compile
    [rinae.dev]/[v8-compile-cache]/v8-compile-cache.js:178:30
  
  - loader.js:712 Object.Module._extensions..js
    internal/modules/cjs/loader.js:712:10
  
  - loader.js:600 Module.load
    internal/modules/cjs/loader.js:600:32
  
  - loader.js:539 tryModuleLoad
    internal/modules/cjs/loader.js:539:12
  
  - loader.js:531 Function.Module._load
    internal/modules/cjs/loader.js:531:3
  
  - loader.js:637 Module.require
    internal/modules/cjs/loader.js:637:17
  
  - v8-compile-cache.js:159 require
    [rinae.dev]/[v8-compile-cache]/v8-compile-cache.js:159:20
  
  - index.js:2 Object.<anonymous>
    [rinae.dev]/[gatsby-remark-vscode]/index.js:2:18
  
  - v8-compile-cache.js:178 Module._compile
    [rinae.dev]/[v8-compile-cache]/v8-compile-cache.js:178:30
  
  - loader.js:712 Object.Module._extensions..js
    internal/modules/cjs/loader.js:712:10
  
  - loader.js:600 Module.load
    internal/modules/cjs/loader.js:600:32

What I found is that even though you wrote lib/vscode/colorThemeData.js in the source repository, those files were not included in the npm package.

Combine syntax highlighting and diff highlighting

I think I may have run into a use case for a new line transformer. I'd like to combine syntax highlighting and diff highlighting. As an example, this

```js-diff
- export const oldNoop = () => {}
+ export const newNoop = () => {}
```

should render as a combination of regular highlights

export const oldNoop = () => {}
export const newNoop = () => {}

plus added lines in green and removed lines in red.

- export const oldNoop = () => {}
+ export const newNoop = () => {}

What's your take on this? Would a line transformer be the best way to accomplish this?

Question: targeting inline code

Another small issue:
I cannot target inline code (it is small and dull right now) that has only one backtick.

I tried chaining not()

code:not(.vscode-highlight):not(.vscode-highlight-code):not(.vscode-highlight-line) {

but it is still partly targetting vs-code.
Any work around?
Screenshot 2019-09-07 at 21 41 30

Option to show line numbers

Hey Andrew,

you've built an amazing plugin, thanks a lot for your effort!
Is there a way to show line numbers for code snippets yet?

Visual Studio Marketplace rate limiting

When downloading extensions from visual studio marketplace, rate limiting can kick in for anonymous requests like the one made in this plugin.

As a company with hundreds of developers downloading lots plugins, extensions and more for both Visual Studio and Visual Studio Code, running a gatsby build in our CI regularly breaks because the request made here returns with a 429 because the rate limit for anonymous requests from our IP is reached.

I have a few ideas how we could work around this (in the scope of this plugin), but i'd love to hear yours. What would you suggest?

Version 2 fails with ‘UNHANDLED REJECTION createNodeId is not a function’

Minimal Working Example

package.json:

{
  "dependencies": {
    "@mdx-js/mdx": "^1.5.5",
    "@mdx-js/react": "^1.5.5",
    "gatsby": "^2.19.10",
    "gatsby-plugin-mdx": "^1.0.69",
    "gatsby-remark-vscode": "^2.0.1",
    "gatsby-source-filesystem": "^2.1.47",
    "react": "^16.12.0",
    "react-dom": "^16.12.0"
  }
}

gatsby-config.js:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`,
        path: `${__dirname}/src/pages/`
      }
    },
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        extensions: [`.md`],
        gatsbyRemarkPlugins: [`gatsby-remark-vscode`]
      }
    }
  ]
};

src/pages/index.md:

```js
this.willBe(highlighted);
```

Error

$ npx gatsby develop
...
 ERROR 

UNHANDLED REJECTION createNodeId is not a function



  TypeError: createNodeId is not a function
  
  - index.js:135 
    [vscode-bug-demo]/[gatsby-remark-vscode]/src/index.js:135:13
  
  - Map.forEach
  
  - index.js:119 textmateHighlight
    [vscode-bug-demo]/[gatsby-remark-vscode]/src/index.js:119:23
  
  - get-source-plugins-as-remark-plugins.js:58 async transformer
    [vscode-bug-demo]/[gatsby-plugin-mdx]/utils/get-source-plugins-as-remark-plugins.js:58:11

GraphQL error: Cannot read property 'path' of undefined

Really cool plugin! Thanks for the excellent documentation. Love the Why gatsby-remark-vscode? section.

Just trying it out as a drop-in replacement for gatsby-remark-prismjs gave me a bunch of errors of the sort

The GraphQL query from ./src/templates/post.js failed.
Errors:
  Cannot read property 'path' of undefined
  
  GraphQL request (26:3)
  25:   }
  26:   timeToRead
           ^
  27:   excerpt(pruneLength: 200)

Sounds like gatsby-remark-vscode isn't getting along with gatsby-transformer-remark. Any ideas what might be causing this?

Also, it would be nice to explicitly list available languageAliases in the readme. I assume any of the 55 built-in languages can be used as the alias target but it'd still be good to know the exact names the use there. For instance, should I write

options: {
  languageAliases: { env: `sh` }, \\ is it `sh` or `shell` or `bash`
}

Clash with gatsby-remark-code-titles

I just realized there's a little more to #17. I'm using gatsby-remark-code-titles which prepends a div.gatsby-code-title to code fences with a title option.

If I include gatsby-remark-vscode before gatsby-remark-code-titles in gatsby-config.js all the titles disappear, presumably because gatsby-remark-vscode prunes all code fence options. I think it would be good to mention in the readme that gatsby-remark-vscode should be loaded after all other plugins that rely on code fence options.
If I include gatsby-remark-code-titles first, then all titles reappear. However, for code fences in markdown lists, the titles are ill-placed (way above their corresponding fence) as seen here:


Screenshot 2019-05-07 at 09 08 48

There may be more gatsby-remark plugins that rely on code fence options not to be stripped but the HTML for that fence to already be in place. Would there be a problem with leaving the options in place?

Also, do you think gatsby-remark-vscode might support adding markup around code fences based on options or is that outside its scope?

Language specific class names on PRE tag.

Is it possible to add class names on the pre tag depending on what language the code block is in.
Like add language-jsx class name if the language is in jsx for example.

<pre class="dark-default-dark vscode-highlight language-jsx" data-language="jsx">
  <code class="vscode-highlight-code"></code>
</pre>

Horizontal scrolling even when blocks fit their container

Using gatsby-remark-vscode with its default configuration, I get a little bit of horizontal scrolling in code blocks even when their content fits within the <pre> container as can be seen e.g. on this page. Passing the option injectStyles: false removes this horizontal scrolling but also some padding that I'd like to keep. Is this scrolling behavior intentional?

Extensions not working (maybe)

Hi!
I feel really rude to open an issue, I just have a question! The importation of extensions does not seem to work (for me):

  {
            resolve: `gatsby-remark-vscode`,
            ... some default options ...
              extensions: [
                {
                  identifier: "aaron-bond.better-comments",
                  version: "2.0.5",
                },
                {
                  identifier: "oderwat.indent-rainbow",
                  version: "7.4.0",
                },
              
              ]            
            ... some default options ...
          },

Is it something I am doing wrong?

Code blocks in markdown lists

Sorry for bothering you again so quickly but I believe I discovered an issue, a real one this time. :)

I have a post with a bunch of code blocks in a markdown list and gatsby-remark-vscode doesn't seem to pick up on them. This worked before with gatsby-remark-prismjs so maybe there's a problem in how gatsby-remark-vscode parses markdown? In this case, the markdown has the following structure:

1. Step 1
2. Step 2
 
    ```sh
   some code
   ```
3. Step 3

   ```sh
   some more code
   ```

Targeting code not working

Dear Andrew,
There appear to be no way to target comments.
None of this is working:

.vscode-highlight-code .vscode-highlight-line span.mtk3 {
  color: blue;
}
div#gatsby-focus-wrapper span > span.mtk3 {
  color: blue;
}

.mtk3 {
  color: blue;
}

span > .mtk3 {
  color: blue;
}

.dark-default-dark .vscode-highlight-code .vscode-highlight-line span.mtk3 {
  color: blue;
}

Language fence for c++ not showing

Hello everyone!
I implemented the language block highlight with help of @gagan0723. It works really well, except for c++!
The code block shows only c. Why is that? (I tried to escape the +, and " ")

This is how it looks on the page:

Screenshot 2019-09-12 at 14 26 00

This is the markdown:

Screenshot 2019-09-12 at 14 26 08

This is the css module (it works for other languages):
Screenshot 2019-09-12 at 14 27 04

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.