“This is the fifth day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

preface

In “A blog with VuePress + Github Pages”, we build a blog with VuePress and see what the final TypeScript Chinese document looks like.

In the process of building a blog, we explained how to write a markdown-it plug-in in “VuePress Blog Optimization extension Markdown Syntax”, and explained the implementation principle of Markdown-it in “Markdown-IT Principle Analysis”. In this article we will explain the actual code to help you better write plug-ins.

markdown-it-inline

Markdown-it’s authors provide Markdown-it-Inine for easy modification of inline tokens. For example, if we were to add target=”_blank” to all links, you would normally write:

// Remember old renderer, if overridden, or proxy to default renderer
var defaultRender = md.renderer.rules.link_open || function(tokens, idx, options, env, self) {
  return self.renderToken(tokens, idx, options);
};

md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
  // If you are sure other plugins can't add `target` - drop check below
  var aIndex = tokens[idx].attrIndex('target');

  if (aIndex < 0) {
    tokens[idx].attrPush(['target'.'_blank']); // add new attribute
  } else {
    tokens[idx].attrs[aIndex][1] = '_blank';    // replace value of existing attr
  }

  // pass token to default renderer.
  return defaultRender(tokens, idx, options, env, self);
};
Copy the code

After using markdown-it-for-inline:

var iterator = require('markdown-it-for-inline');

var md = require('markdown-it')()
            .use(iterator, 'url_new_win'.'link_open'.function (tokens, idx) {
              var aIndex = tokens[idx].attrIndex('target');

              if (aIndex < 0) {
                tokens[idx].attrPush(['target'.'_blank']);
              } else {
                tokens[idx].attrs[aIndex][1] = '_blank'; }});Copy the code

If we want to replace a text, we can also use markdown-it-for-inline:

var iterator = require('markdown-it-for-inline');

// plugin params are:
//
// - rule name (should be unique)
// - token type to apply
// - function
//
var md = require('markdown-it')()
            .use(iterator, 'foo_replace'.'text'.function (tokens, idx) {
              tokens[idx].content = tokens[idx].content.replace(/foo/g.'bar');
            });
Copy the code

markdown-it-container

Plugin for creating block-level custom containers for markdown-it markdown parser.

Markdown – it the author provides the same [markdown – it – the container] (https://github.com/markdown-it/markdown-it-container) is used to quickly create block-level custom container.

With this plugin, you can use markdown syntax like this:

::: spoiler click me
*content*: : :Copy the code

Note that ::: is plugin-defined syntax, which takes characters after :::, in this case warning, and provides methods to customize the rendering result:

var md = require('markdown-it') (); md.use(require('markdown-it-container'), 'spoiler', {

  validate: function(params) {
    return params.trim().match(/^spoiler\s+(.*)$/);
  },

  render: function (tokens, idx) {
    // Tokens [idx].info.trim() fetch 'click me' string
    var m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/);

    Nesting for the start tag is 1, and nesting for the end tag is -1
    if (tokens[idx].nesting === 1) {
      // Start tag
      return '<details><summary>' + md.utils.escapeHtml(m[1]) + '</summary>\n';
    } else {
      // End tag
      return '</details>\n'; }}});Copy the code

The final render result is:

<details><summary>click me</summary>
<p><em>content</em></p>
</details>
Copy the code

Custom containers like VuePress provide:

Markdown-it-container is used to implement markdown-it-container.

const container = require('markdown-it-container')

module.exports = md= >{ md .use(... createContainer('tip'.'TIP')) .use(... createContainer('warning'.'WARNING')) .use(... createContainer('danger'.'WARNING'))
		// ...
}

function createContainer (klass, defaultTitle) {
  return [container, klass, {
    render (tokens, idx) {
      const token = tokens[idx]
      const info = token.info.trim().slice(klass.length).trim()
      if (token.nesting === 1) {
        return `<div class="${klass} custom-block"><p class="custom-block-title">${info || defaultTitle}</p>\n`
      } else {
        return `</div>\n`}}}}]Copy the code

series

Blog building series is the only practical series I have written so far. It is estimated to be about 20 articles, explaining how to use VuePress to build and optimize a blog and deploy it to GitHub, Gitee, private server and other platforms. This is the 18th article in a series at github.com/mqyqingfeng…

Wechat: “MQyqingfeng”, add me Into Hu Yu’s only readership group.

If there is any mistake or not precise place, please be sure to give correction, thank you very much. If you like or are inspired by it, welcome star and encourage the author.