UNPKG

hackmd-to-html-cli

Version:

A node.js CLI tool for converting HackMD markdown to HTML.

137 lines 5.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkdownItContainer = MarkdownItContainer; const names = ['success', 'info', 'warning', 'danger', 'spoiler']; // modified from // https://github.com/markdown-it/markdown-it-container function MarkdownItContainer(md, _options) { // eslint-disable-next-line @typescript-eslint/no-explicit-any function renderContainer(tokens, idx, _option, _env, slf) { // add a class to the opening tag if (tokens[idx].nesting === 1) { tokens[idx].attrJoin('class', tokens[idx].info); } return slf.renderToken(tokens, idx, _options); } // eslint-disable-next-line @typescript-eslint/no-explicit-any function renderSpoiler(tokens, idx, _options, _env, slf) { // add a class to the opening tag if (tokens[idx].nesting === 1) { let summary = tokens[idx].content; tokens[idx].content = ''; const re = /\{state\s*=\s*"open"\}/; if (summary.search(re) !== -1) { summary = summary.replace(re, ''); tokens[idx].attrJoin('open', 'open'); } return slf.renderToken(tokens, idx, _options) + '\n<summary>' + summary + '</summary>'; } return slf.renderToken(tokens, idx, _options); } const minMarkers = 3; const markerStr = ':'; const markerChar = markerStr.charCodeAt(0); const markerLen = markerStr.length; function rule(state, startLine, endLine, silent) { let pos, nextLine, token; let autoClosed = false; let start = state.bMarks[startLine] + state.tShift[startLine]; let max = state.eMarks[startLine]; // Check out the first character quickly, // this should filter out most of non-containers if (markerChar !== state.src.charCodeAt(start)) { return false; } // Check out the rest of the marker string for (pos = start + 1; pos <= max; pos++) { if (markerStr[(pos - start) % markerLen] !== state.src[pos]) { break; } } const markerCount = Math.floor((pos - start) / markerLen); if (markerCount < minMarkers) { return false; } pos -= (pos - start) % markerLen; const markup = state.src.slice(start, pos); const params = state.src.slice(pos, max); const parse = params.trim().split(' '); const name = (parse === null || parse === void 0 ? void 0 : parse.length) > 0 ? (parse[0] || '') : ''; const summary = parse.length > 1 ? parse.slice(1).join(' ') : ''; if (!names.includes(name)) { return false; } // Since start is found, we can report success here in validation mode if (silent) { return true; } // Search for the end of the block nextLine = startLine; for (;;) { nextLine++; if (nextLine >= endLine) { // unclosed block should be autoclosed by end of document. // also block seems to be autoclosed by end of parent break; } start = state.bMarks[nextLine] + state.tShift[nextLine]; max = state.eMarks[nextLine]; if (start < max && state.sCount[nextLine] < state.blkIndent) { // non-empty line with negative indent should stop the list: // - ``` // test break; } if (markerChar !== state.src.charCodeAt(start)) { continue; } if (state.sCount[nextLine] - state.blkIndent >= 4) { // closing fence should be indented less than 4 spaces continue; } for (pos = start + 1; pos <= max; pos++) { if (markerStr[(pos - start) % markerLen] !== state.src[pos]) { break; } } // closing code fence must be at least as long as the opening one if (Math.floor((pos - start) / markerLen) < markerCount) { continue; } // make sure tail has spaces only pos -= (pos - start) % markerLen; pos = state.skipSpaces(pos); if (pos < max) { continue; } // found! autoClosed = true; break; } const oldLineMax = state.lineMax; // this will prevent lazy continuations from ever going past our end marker state.lineMax = nextLine; // if (name === 'spoiler') { token = state.push(name === 'spoiler' ? 'spoiler_open' : 'container_open', name === 'spoiler' ? 'details' : 'div', 1); token.content = summary; token.info = name; token.markup = markup; token.block = true; token.map = [startLine, nextLine]; state.md.block.tokenize(state, startLine + 1, nextLine); token = state.push(name === 'spoiler' ? 'spoiler_close' : 'container_close', name === 'spoiler' ? 'details' : 'div', -1); token.markup = state.src.slice(start, pos); token.block = true; state.lineMax = oldLineMax; state.line = nextLine + (autoClosed ? 1 : 0); return true; } md.block.ruler.before('fence', 'container', rule, { alt: ['paragraph', 'reference', 'blockquote', 'list'] }); md.renderer.rules.container_open = renderContainer; md.renderer.rules.container_close = renderContainer; md.renderer.rules.spoiler_open = renderSpoiler; md.renderer.rules.spoiler_close = renderSpoiler; } //# sourceMappingURL=container.js.map