/home/bdqbpbxa/demo-subdomains/billine.goodface.com.ua/js/lib/prism-js-fold.js
// inspects code elements from prism during pre-render hook. if it's JS or JSON we try to insert details/summary tags to
// allow code folding
const lastLineWrapperOpen = "<span class='ll'>".split(); // wrap portion of last line preceding the closing symbol so we can conditionally hide it, needed to make non-square hidden regions collapse nicely.
const lastLineWrapperClose = "</span>".split();
const firstLineContentWrapperOpen = "<span class='fl'>".split(); // wrapper beginning at first **visible** character on first line where opening symbol is found. needed so we can align opening toggle nicely
const firstLineContentWrapperClose = "</span>".split();
const detailsOpenFragmentActive = "<details open><summary>".split();
const detailsOpenFragmentInactive = "<details><summary>".split();
const summaryCloseFragment = "</summary>".split();
const detailsCloseFragment = "</details>".split();
const symbolPairMap = {
"{": "}",
"[": "]",
};
// folding `context` type contains:
// - minimumDepth:int - depth value that must be met or exceeded for folding to occur
function insertFold(inputBuffer, depth, context) {
const output = [];
let remaining = inputBuffer;
let current;
function createFold(symbol) {
const [result, resultRemaining] = insertFold(remaining, depth + 1, context);
const currentLineEndIndex = result.indexOf("\n");
// only create fold if symbol pair crossed a '\n'. only insert fold if at required depth.
if (currentLineEndIndex >= 0 && depth >= context.minimumDepth) {
const currentLineStartIndex = output.lastIndexOf("\n");
const currentLineStart = output.splice(currentLineStartIndex + 1);
const currentLineCharacterStartIndex = currentLineStart.findIndex((c) =>
/[^\s]{1}/.test(c)
);
const currentLineStartWhiteSpace = currentLineStart.splice(
0,
currentLineCharacterStartIndex
);
const currentLineEnd = result.splice(0, currentLineEndIndex);
const resultLastLineIndex = result.lastIndexOf("\n");
const resultLastLine = result.splice(resultLastLineIndex + 1);
output.push(
...(context.lineCount >= 40
? detailsOpenFragmentInactive
: detailsOpenFragmentActive),
...currentLineStartWhiteSpace,
...firstLineContentWrapperOpen,
...currentLineStart,
...currentLineEnd,
...firstLineContentWrapperClose,
...summaryCloseFragment,
...result,
...detailsCloseFragment,
...lastLineWrapperOpen,
...resultLastLine,
...lastLineWrapperClose,
symbolPairMap[symbol]
);
remaining = resultRemaining;
} else {
output.push(...result, symbolPairMap[symbol]);
remaining = resultRemaining;
}
}
while ((current = remaining.shift()) !== undefined) {
switch (current) {
case "[":
case "{":
output.push(current);
createFold(current);
break;
case "]":
case "}":
return [output, remaining];
default:
output.push(current);
}
}
return [output, remaining];
}
// takes a code element and begins recursion if it's a parsable format
function insertFolds(codeElement) {
const parseable =
Array.from(codeElement.classList).find(
(cls) =>
cls.endsWith("json") ||
cls.endsWith("js") ||
cls.endsWith("javascript") ||
cls.endsWith("php")
) !== undefined;
if (parseable) {
const inputBuffer = codeElement.innerText.split("");
const [result] = insertFold(inputBuffer, 1, {
minimumDepth: 2,
lineCount: inputBuffer.filter((c) => c === "\n").length,
});
codeElement.innerHTML = result.join("");
}
}
if (Prism) {
Prism.hooks.add("before-all-elements-highlight", ({ elements }) =>
elements.forEach(insertFolds)
);
} else {
console.warn(
"prism-js-fold: Prism was not loaded so we could not add the Prism hook needed for code folding insertion."
);
}