all files / es6/modules/ expandPairTrait.js

100% Statements 65/65
100% Branches 30/30
100% Functions 6/6
100% Lines 65/65
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94                 681× 478×   203×   201× 201× 201× 325× 325× 325× 201× 201×           480× 480× 1901×   480× 480× 478× 201× 201× 68×   201× 55×   146× 146× 146×     478× 478× 478× 66532× 66532× 66532× 66532× 49066× 49066×   17466× 201×   17466× 17064×   17466× 201× 201× 201× 201× 201× 201× 201×   17265×          
const traitName = "expandPair";
const mergeSort = require("../mergesort");
const DocUtils = require("../docUtils");
const {getExpandToDefault} = require("../traits");
const Errors = require("../errors");
 
function throwUnmatchedLoopException(options) {
	const location = options.location;
	const t = location === "start" ? "unclosed" : "unopened";
	const T = location === "start" ? "Unclosed" : "Unopened";
 
	const err = new Errors.XTTemplateError(`${T} loop`);
	const tag = options.part.value;
	err.properties = {
		id: `${t}_loop`,
		explanation: `The loop with tag ${tag} is ${t}`,
		xtag: tag,
	};
	throw err;
}
 
function getPairs(traits) {
	if (traits.length === 0) {
		return [];
	}
	if (traits.length === 1) {
		const part = traits[0].part;
		throwUnmatchedLoopException({part, location: traits[0].part.location});
	}
	const trait = traits[0];
	let countOpen = 1;
	for (let i = 1; i < traits.length; i++) {
		const t = traits[i];
		countOpen += t.part.location === "start" ? 1 : -1;
		if (countOpen === 0) {
			const outer = getPairs(traits.slice(i + 1));
			return [[trait, t]].concat(outer);
		}
	}
}
 
const expandPairTrait = {
	postparse: function (parsed, {getTraits, postparse}) {
		let traits = getTraits(traitName, parsed);
		traits = traits.map(function (trait) {
			return trait || [];
		});
		traits = mergeSort(traits);
		const pairs = getPairs(traits);
		const expandedPairs = pairs.map(function (pair) {
			let expandTo = pair[0].part.expandTo;
			if (expandTo === "auto") {
				expandTo = getExpandToDefault(parsed.slice(pair[0].offset, pair[1].offset));
			}
			if (!expandTo) {
				return [pair[0].offset, pair[1].offset];
			}
			const left = DocUtils.getLeft(parsed, expandTo, pair[0].offset);
			const right = DocUtils.getRight(parsed, expandTo, pair[1].offset);
			return [left, right];
		});
 
		let currentPairIndex = 0;
		let innerParts;
		return parsed.reduce(function (newParsed, part, i) {
			const inPair = currentPairIndex < pairs.length && expandedPairs[currentPairIndex][0] <= i;
			const pair = pairs[currentPairIndex];
			const expandedPair = expandedPairs[currentPairIndex];
			if(!inPair) {
				newParsed.push(part);
				return newParsed;
			}
			if (expandedPair[0] === i) {
				innerParts = [];
			}
			if (pair[0].offset !== i && pair[1].offset !== i) {
				innerParts.push(part);
			}
			if (expandedPair[1] === i) {
				const basePart = parsed[pair[0].offset];
				delete basePart.location;
				delete basePart.expandTo;
				basePart.subparsed = postparse(innerParts);
				newParsed.push(basePart);
				currentPairIndex++;
				return newParsed;
			}
			return newParsed;
		}, []);
	},
};
 
module.exports = expandPairTrait;