All files / src/processors fragmentProcessor.ts

97.05% Statements 33/34
91.66% Branches 11/12
100% Functions 6/6
96.87% Lines 31/32

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 715x     5x   71x 71x 71x     71x       71x     71x         71x     953x   28x 28x     925x 925x 28x     897x 9x   888x       71x       9x   9x       9x 9x 9x 9x   9x       9x 9x 9x   9x 9x      
import { CommentParser } from '../comment';
import { Options } from '../options';
 
export class FragmentProcessor {
	private parser: CommentParser;
	private fragmentCounter = 1;
	private orderedListRegex = /^\d\) /g;
	private codeBlockRegex = /```[^\n]*(?:\n[^`]*\n)```/g;
 
	constructor() {
		this.parser = new CommentParser();
	}
 
	process(markdown: string, options: Options) {
		const separatorRegexp = new RegExp(`${options.separator}|${options.verticalSeparator}`, 'gmi');
 
		// Detect line ranges containing Markdown code blocks so we can ignore them
		const codeBlockLines = Array.from(markdown.matchAll(this.codeBlockRegex)).map(({ 0: match, index }) => ({
			from: markdown.substring(0, index).split('\n').length - 1,
			to: markdown.substring(0, index + match.length).split('\n').length - 1,
		}));
 
		const output = markdown
			.split('\n')
			.map((line, lineNumber) => {
				if (`\n${line}\n`.match(separatorRegexp)) {
					// Reset counter when encountered slide separator
					this.fragmentCounter = 1;
					return line;
				}
 
				const isCodeblockLine = codeBlockLines.some(({ from, to }) => lineNumber >= from && lineNumber <= to);
				if (isCodeblockLine) {
					return line;
				}
 
				if (line.trim().startsWith('+ ') || this.orderedListRegex.test(line.trim())) {
					return this.transformLine(line);
				}
				return line;
			})
			.join('\n');
 
		return output;
	}
 
	transformLine(line: string) {
		const comment = this.parser.parseLine(line) ?? this.parser.buildComment('element');
 
		Iif (line.includes('<!--')) {
			line = line.substring(0, line.indexOf('<!--'));
		}
 
		if (!comment.hasAttribute('data-fragment-index')) {
			comment.addAttribute('data-fragment-index', this.fragmentCounter.toString());
			if (!comment.hasClass('fragment')) {
				comment.addClass('fragment');
			}
			this.fragmentCounter++;
		}
		
		// See here: https://github.com/hakimel/reveal.js/issues/1848. This makes sure that reveals work when dealing with formatting in the list (e.g. bold / italic / code, etc.)
		const extra_replacement = "&shy;" + this.parser.commentToString(comment);
		line = line.replace("+ ", "- " + extra_replacement);
		line = line.replaceAll(this.orderedListRegex, "1. " + extra_replacement);
 
		const output = line;
		return output;
	}
}