125 lines
3.3 KiB
JavaScript
125 lines
3.3 KiB
JavaScript
/* eslint-disable no-continue */
|
|
|
|
// a constant to hold the abc string
|
|
const abc = [];
|
|
// the callBack given from abcNotationExtension.js
|
|
// to pass the abc string up to a point
|
|
// where the DOM is already rendered
|
|
let callbackFunc;
|
|
|
|
function abcNotation(state, startLine, endLine, silent) {
|
|
const validateParams = params => params.trim().match(/^abc$/);
|
|
let nextLine;
|
|
let autoClosed = false;
|
|
|
|
let start = state.bMarks[startLine] + state.tShift[startLine];
|
|
let max = state.eMarks[startLine];
|
|
|
|
// Check out the first character quickly,
|
|
// this filters out all non-codeblocks
|
|
const marker = state.src.charCodeAt(start);
|
|
if (marker !== 0x7e /* ~ */ && marker !== 0x60 /* ` */) {
|
|
return false;
|
|
}
|
|
|
|
// Check out the rest of the marker string
|
|
const markerStart = start;
|
|
start = state.skipChars(start, marker);
|
|
const markerLength = start - markerStart;
|
|
if (markerLength < 3) {
|
|
return false;
|
|
}
|
|
|
|
const markup = state.src.slice(markerLength, start);
|
|
const params = state.src.slice(start, max);
|
|
if (!validateParams(params)) {
|
|
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 += 1;
|
|
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 (marker !== state.src.charCodeAt(start)) {
|
|
continue;
|
|
}
|
|
|
|
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
|
// closing fence should be indented less than 4 spaces
|
|
continue;
|
|
}
|
|
|
|
start = state.skipChars(start, marker);
|
|
// closing fence must be at least as long as the opening one
|
|
if (start - markerStart < markerLength) {
|
|
continue;
|
|
}
|
|
|
|
// make sure tail has spaces only
|
|
start = state.skipSpaces(start);
|
|
if (start < max) {
|
|
continue;
|
|
}
|
|
|
|
autoClosed = true;
|
|
// found!
|
|
break;
|
|
}
|
|
|
|
const oldParent = state.parentType;
|
|
const oldLineMax = state.lineMax;
|
|
state.parentType = 'container';
|
|
|
|
// If a fence has heading spaces, they should be removed from its inner block
|
|
// markerLength = state.sCount[startLine];
|
|
|
|
// this will prevent lazy continuations from ever going past our end marker
|
|
state.lineMax = nextLine;
|
|
|
|
const token = state.push('fence_abc_open', 'div', 1);
|
|
token.info = params;
|
|
token.markup = markup;
|
|
token.block = true;
|
|
token.map = [startLine, nextLine];
|
|
|
|
abc.push(state.getLines(startLine + 1, nextLine, markerLength, true));
|
|
|
|
state.parentType = oldParent;
|
|
state.lineMax = oldLineMax;
|
|
state.line = nextLine + (autoClosed ? 1 : 0);
|
|
|
|
callbackFunc(abc[0]);
|
|
return true;
|
|
}
|
|
|
|
export default (md, callback) => {
|
|
callbackFunc = callback;
|
|
md.block.ruler.before('fence', 'fence_abc', abcNotation);
|
|
md.renderer.rules.fence_abc_open = (tokens, idx, _options, env, self) => {
|
|
tokens[idx].attrPush(['id', 'abcSheetPaper']);
|
|
return self.renderToken(tokens, idx, _options, env, self);
|
|
};
|
|
};
|