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
71
72
73
|
import hljs from 'highlight.js/lib/core';
import languageLoader from '~/content_editor/services/highlight_js_language_loader';
import { registerPlugins } from '../plugins/index';
import { LINES_PER_CHUNK, NEWLINE, ROUGE_TO_HLJS_LANGUAGE_MAP } from '../constants';
const loadLanguage = async (language) => {
const languageDefinition = await languageLoader[language]();
hljs.registerLanguage(language, languageDefinition.default);
};
const loadSubLanguages = async (languageDefinition) => {
// Some files can contain sub-languages (i.e., Svelte); this ensures that sub-languages are also loaded
if (!languageDefinition?.contains) return;
// generate list of languages to load
const languages = new Set(
languageDefinition.contains
.filter((component) => Boolean(component.subLanguage))
.map((component) => component.subLanguage),
);
if (languageDefinition.subLanguage) {
languages.add(languageDefinition.subLanguage);
}
await Promise.all([...languages].map(loadLanguage));
};
const initHighlightJs = async (fileType, content, language) => {
registerPlugins(hljs, fileType, content, true);
await loadLanguage(language);
await loadSubLanguages(hljs.getLanguage(language));
};
const splitByLineBreaks = (content = '') => content.split(/\r?\n/);
const createChunk = (language, rawChunkLines, highlightedChunkLines = [], startingFrom = 0) => ({
highlightedContent: highlightedChunkLines.join(NEWLINE),
rawContent: rawChunkLines.join(NEWLINE),
totalLines: rawChunkLines.length,
startingFrom,
language,
});
const splitIntoChunks = (language, rawContent, highlightedContent) => {
const result = [];
const splitRawContent = splitByLineBreaks(rawContent);
const splitHighlightedContent = splitByLineBreaks(highlightedContent);
for (let i = 0; i < splitRawContent.length; i += LINES_PER_CHUNK) {
const chunkIndex = Math.floor(i / LINES_PER_CHUNK);
const highlightedChunk = splitHighlightedContent.slice(i, i + LINES_PER_CHUNK);
const rawChunk = splitRawContent.slice(i, i + LINES_PER_CHUNK);
result[chunkIndex] = createChunk(language, rawChunk, highlightedChunk, i);
}
return result;
};
const highlight = async (fileType, rawContent, lang) => {
const language = ROUGE_TO_HLJS_LANGUAGE_MAP[lang.toLowerCase()];
let result;
if (language) {
await initHighlightJs(fileType, rawContent, language);
const highlightedContent = hljs.highlight(rawContent, { language }).value;
result = splitIntoChunks(language, rawContent, highlightedContent);
}
return result;
};
export { highlight, splitIntoChunks };
|