# All files / src/lib/markdown-it/plugins markdown-it-alt-frontmatter.ts

28.57% Statements 10/35
9.09% Branches 1/11
66.66% Functions 2/3
28.57% Lines 10/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70

    21x

    520x
    520x

    520x
    520x
    520x
    520x
    520x

    21x
    21x

     import MarkdownIt, { Options } from 'markdown-it';
    import StateBlock from 'markdown-it/lib/rules_block/state_block';
    import Token from 'markdown-it/lib/token';
    import Renderer from 'markdown-it/lib/renderer';

    /*
     * This file exports a MarkdownIt plugin that converts YAML-style frontmatter syntax (---)
     * into HTML-style `<frontmatter>` tags.
     * Only if there are two sets of `---` and the content inside contains key-value pairs or blank space.
     */
    export = function alt_frontmatter_plugin(md: MarkdownIt): void {
      function alt_frontmatter(state: StateBlock, startLine: number, endLine: number): boolean {
        const fmSymbol = '---';
        const keyValueRegex = /^\w+:\s+.*/;

        let lineStart = state.bMarks[startLine] + state.tShift[startLine];
        let lineEnd = state.eMarks[startLine];
        const marker = state.src.slice(lineStart, lineEnd);
        if (marker !== fmSymbol) {
          return false;
        }

        let haveEndMarker = false;
        let nextLine = startLine + 1;
        for (; nextLine < endLine; nextLine += 1) {
          lineStart = state.bMarks[nextLine] + state.tShift[nextLine];
          lineEnd = state.eMarks[nextLine];

          const currLine = state.src.slice(lineStart, lineEnd).trim();
          Iif (currLine === fmSymbol) {
            haveEndMarker = true;
            break;
          }
          Iif (!(keyValueRegex.test(currLine) || currLine.length === 0)) {
            // terminates if not key value or blank line.
            return false;
          }
        }

        Iif (!haveEndMarker) {
          return false;
        }
        // If a fence has heading spaces, they should be removed from its inner block
        const len = state.sCount[startLine];
        state.line = nextLine + (haveEndMarker ? 1 : 0);

        const token: Token = state.push('alt_frontmatter', '', 0);
        token.info = fmSymbol;
        token.content = state.getLines(startLine + 1, nextLine, len, true);
        token.markup = marker;
        token.map = [startLine, state.line];
        return true;
      }

      md.block.ruler.before('fence', 'alt_frontmatter', alt_frontmatter);
      md.renderer.rules.alt_frontmatter = (
        tokens: Token[],
        idx: number,
        options: Options,
        env: any,
        slf: Renderer,
      ) => {
        const token = tokens[idx];
        Iif (token.type === 'alt_frontmatter' && token.info === '---') {
          return `<frontmatter>\n${token.content}</frontmatter>\n`;
        }
        return slf.renderToken(tokens, idx, options);
      };
    };