140 lines
3.6 KiB
JavaScript
140 lines
3.6 KiB
JavaScript
const traitName = "expandPair";
|
|
const mergeSort = require("../mergesort");
|
|
const { getLeft, getRight } = require("../doc-utils");
|
|
|
|
const wrapper = require("../module-wrapper");
|
|
const { getExpandToDefault } = require("../traits");
|
|
const {
|
|
getUnmatchedLoopException,
|
|
getClosingTagNotMatchOpeningTag,
|
|
throwLocationInvalid,
|
|
} = require("../errors");
|
|
|
|
function getOpenCountChange(part) {
|
|
switch (part.location) {
|
|
case "start":
|
|
return 1;
|
|
case "end":
|
|
return -1;
|
|
default:
|
|
throwLocationInvalid(part);
|
|
}
|
|
}
|
|
|
|
function getPairs(traits) {
|
|
const errors = [];
|
|
let pairs = [];
|
|
if (traits.length === 0) {
|
|
return { pairs, errors };
|
|
}
|
|
let countOpen = 1;
|
|
const [firstTrait] = traits;
|
|
if (firstTrait.part.location === "start") {
|
|
for (let i = 1; i < traits.length; i++) {
|
|
const currentTrait = traits[i];
|
|
countOpen += getOpenCountChange(currentTrait.part);
|
|
if (countOpen === 0) {
|
|
const outer = getPairs(traits.slice(i + 1));
|
|
if (
|
|
currentTrait.part.value !== firstTrait.part.value &&
|
|
currentTrait.part.value !== ""
|
|
) {
|
|
errors.push(
|
|
getClosingTagNotMatchOpeningTag({
|
|
tags: [firstTrait.part, currentTrait.part],
|
|
})
|
|
);
|
|
} else {
|
|
pairs = [[firstTrait, currentTrait]];
|
|
}
|
|
return {
|
|
pairs: pairs.concat(outer.pairs),
|
|
errors: errors.concat(outer.errors),
|
|
};
|
|
}
|
|
}
|
|
}
|
|
const { part } = firstTrait;
|
|
errors.push(getUnmatchedLoopException({ part, location: part.location }));
|
|
const outer = getPairs(traits.slice(1));
|
|
return { pairs: outer.pairs, errors: errors.concat(outer.errors) };
|
|
}
|
|
|
|
const expandPairTrait = {
|
|
name: "ExpandPairTrait",
|
|
optionsTransformer(options, docxtemplater) {
|
|
this.expandTags = docxtemplater.fileTypeConfig.expandTags.concat(
|
|
docxtemplater.options.paragraphLoop
|
|
? docxtemplater.fileTypeConfig.onParagraphLoop
|
|
: []
|
|
);
|
|
return options;
|
|
},
|
|
postparse(postparsed, { getTraits, postparse }) {
|
|
let traits = getTraits(traitName, postparsed);
|
|
traits = traits.map(function (trait) {
|
|
return trait || [];
|
|
});
|
|
traits = mergeSort(traits);
|
|
const { pairs, errors } = getPairs(traits);
|
|
const expandedPairs = pairs.map((pair) => {
|
|
let { expandTo } = pair[0].part;
|
|
if (expandTo === "auto") {
|
|
const result = getExpandToDefault(postparsed, pair, this.expandTags);
|
|
if (result.error) {
|
|
errors.push(result.error);
|
|
}
|
|
expandTo = result.value;
|
|
}
|
|
if (!expandTo) {
|
|
return [pair[0].offset, pair[1].offset];
|
|
}
|
|
let left, right;
|
|
try {
|
|
left = getLeft(postparsed, expandTo, pair[0].offset);
|
|
} catch (e) {
|
|
errors.push(e);
|
|
}
|
|
try {
|
|
right = getRight(postparsed, expandTo, pair[1].offset);
|
|
} catch (e) {
|
|
errors.push(e);
|
|
}
|
|
return [left, right];
|
|
});
|
|
|
|
let currentPairIndex = 0;
|
|
let innerParts;
|
|
|
|
const newParsed = postparsed.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 = postparsed[pair[0].offset];
|
|
basePart.subparsed = postparse(innerParts, { basePart });
|
|
delete basePart.location;
|
|
delete basePart.expandTo;
|
|
newParsed.push(basePart);
|
|
currentPairIndex++;
|
|
}
|
|
return newParsed;
|
|
}, []);
|
|
return { postparsed: newParsed, errors };
|
|
},
|
|
};
|
|
|
|
module.exports = () => wrapper(expandPairTrait);
|