docxtemplater/es6/errors.js
2021-09-04 10:15:02 +05:00

395 lines
9.7 KiB
JavaScript

"use strict";
const { last, first } = require("./utils");
function XTError(message) {
this.name = "GenericError";
this.message = message;
this.stack = new Error(message).stack;
}
XTError.prototype = Error.prototype;
function XTTemplateError(message) {
this.name = "TemplateError";
this.message = message;
this.stack = new Error(message).stack;
}
XTTemplateError.prototype = new XTError();
function XTRenderingError(message) {
this.name = "RenderingError";
this.message = message;
this.stack = new Error(message).stack;
}
XTRenderingError.prototype = new XTError();
function XTScopeParserError(message) {
this.name = "ScopeParserError";
this.message = message;
this.stack = new Error(message).stack;
}
XTScopeParserError.prototype = new XTError();
function XTInternalError(message) {
this.name = "InternalError";
this.properties = { explanation: "InternalError" };
this.message = message;
this.stack = new Error(message).stack;
}
XTInternalError.prototype = new XTError();
function XTAPIVersionError(message) {
this.name = "APIVersionError";
this.properties = { explanation: "APIVersionError" };
this.message = message;
this.stack = new Error(message).stack;
}
XTAPIVersionError.prototype = new XTError();
function throwApiVersionError(msg, properties) {
const err = new XTAPIVersionError(msg);
err.properties = {
id: "api_version_error",
...properties,
};
throw err;
}
function throwMultiError(errors) {
const err = new XTTemplateError("Multi error");
err.properties = {
errors,
id: "multi_error",
explanation: "The template has multiple errors",
};
throw err;
}
function getUnopenedTagException(options) {
const err = new XTTemplateError("Unopened tag");
err.properties = {
xtag: last(options.xtag.split(" ")),
id: "unopened_tag",
context: options.xtag,
offset: options.offset,
lIndex: options.lIndex,
explanation: `The tag beginning with "${options.xtag.substr(
0,
10
)}" is unopened`,
};
return err;
}
function getDuplicateOpenTagException(options) {
const err = new XTTemplateError("Duplicate open tag, expected one open tag");
err.properties = {
xtag: first(options.xtag.split(" ")),
id: "duplicate_open_tag",
context: options.xtag,
offset: options.offset,
lIndex: options.lIndex,
explanation: `The tag beginning with "${options.xtag.substr(
0,
10
)}" has duplicate open tags`,
};
return err;
}
function getDuplicateCloseTagException(options) {
const err = new XTTemplateError(
"Duplicate close tag, expected one close tag"
);
err.properties = {
xtag: first(options.xtag.split(" ")),
id: "duplicate_close_tag",
context: options.xtag,
offset: options.offset,
lIndex: options.lIndex,
explanation: `The tag ending with "${options.xtag.substr(
0,
10
)}" has duplicate close tags`,
};
return err;
}
function getUnclosedTagException(options) {
const err = new XTTemplateError("Unclosed tag");
err.properties = {
xtag: first(options.xtag.split(" ")).substr(1),
id: "unclosed_tag",
context: options.xtag,
offset: options.offset,
lIndex: options.lIndex,
explanation: `The tag beginning with "${options.xtag.substr(
0,
10
)}" is unclosed`,
};
return err;
}
function throwXmlTagNotFound(options) {
const err = new XTTemplateError(
`No tag "${options.element}" was found at the ${options.position}`
);
const part = options.parsed[options.index];
err.properties = {
id: `no_xml_tag_found_at_${options.position}`,
explanation: `No tag "${options.element}" was found at the ${options.position}`,
offset: part.offset,
part,
parsed: options.parsed,
index: options.index,
element: options.element,
};
throw err;
}
function getCorruptCharactersException({ tag, value, offset }) {
const err = new XTRenderingError("There are some XML corrupt characters");
err.properties = {
id: "invalid_xml_characters",
xtag: tag,
value,
offset,
explanation: "There are some corrupt characters for the field ${tag}",
};
return err;
}
function throwContentMustBeString(type) {
const err = new XTInternalError("Content must be a string");
err.properties.id = "xmltemplater_content_must_be_string";
err.properties.type = type;
throw err;
}
function throwExpandNotFound(options) {
const {
part: { value, offset },
id = "raw_tag_outerxml_invalid",
message = "Raw tag not in paragraph",
} = options;
const { part } = options;
let {
explanation = `The tag "${value}" is not inside a paragraph`,
} = options;
if (typeof explanation === "function") {
explanation = explanation(part);
}
const err = new XTTemplateError(message);
err.properties = {
id,
explanation,
rootError: options.rootError,
xtag: value,
offset,
postparsed: options.postparsed,
expandTo: options.expandTo,
index: options.index,
};
throw err;
}
function throwRawTagShouldBeOnlyTextInParagraph(options) {
const err = new XTTemplateError(
"Raw tag should be the only text in paragraph"
);
const tag = options.part.value;
err.properties = {
id: "raw_xml_tag_should_be_only_text_in_paragraph",
explanation: `The raw tag "${tag}" should be the only text in this paragraph. This means that this tag should not be surrounded by any text or spaces.`,
xtag: tag,
offset: options.part.offset,
paragraphParts: options.paragraphParts,
};
throw err;
}
function getUnmatchedLoopException(options) {
const { location } = options;
const t = location === "start" ? "unclosed" : "unopened";
const T = location === "start" ? "Unclosed" : "Unopened";
const err = new XTTemplateError(`${T} loop`);
const tag = options.part.value;
err.properties = {
id: `${t}_loop`,
explanation: `The loop with tag "${tag}" is ${t}`,
xtag: tag,
offset: options.part.offset,
};
return err;
}
function getClosingTagNotMatchOpeningTag({ tags }) {
const err = new XTTemplateError("Closing tag does not match opening tag");
err.properties = {
id: "closing_tag_does_not_match_opening_tag",
explanation: `The tag "${tags[0].value}" is closed by the tag "${tags[1].value}"`,
openingtag: first(tags).value,
offset: [first(tags).offset, last(tags).offset],
closingtag: last(tags).value,
};
return err;
}
function getScopeCompilationError({ tag, rootError, offset }) {
const err = new XTScopeParserError("Scope parser compilation failed");
err.properties = {
id: "scopeparser_compilation_failed",
offset,
tag,
explanation: `The scope parser for the tag "${tag}" failed to compile`,
rootError,
};
return err;
}
function getScopeParserExecutionError({ tag, scope, error, offset }) {
const err = new XTScopeParserError("Scope parser execution failed");
err.properties = {
id: "scopeparser_execution_failed",
explanation: `The scope parser for the tag ${tag} failed to execute`,
scope,
offset,
tag,
rootError: error,
};
return err;
}
function getLoopPositionProducesInvalidXMLError({ tag, offset }) {
const err = new XTTemplateError(
`The position of the loop tags "${tag}" would produce invalid XML`
);
err.properties = {
tag,
id: "loop_position_invalid",
explanation: `The tags "${tag}" are misplaced in the document, for example one of them is in a table and the other one outside the table`,
offset,
};
return err;
}
function throwUnimplementedTagType(part, index) {
let errorMsg = `Unimplemented tag type "${part.type}"`;
if (part.module) {
errorMsg += ` "${part.module}"`;
}
const err = new XTTemplateError(errorMsg);
err.properties = {
part,
index,
id: "unimplemented_tag_type",
};
throw err;
}
function throwMalformedXml(part) {
const err = new XTInternalError("Malformed xml");
err.properties = {
part,
id: "malformed_xml",
};
throw err;
}
function throwLocationInvalid(part) {
throw new XTInternalError(
`Location should be one of "start" or "end" (given : ${part.location})`
);
}
function throwResolveBeforeCompile() {
const err = new XTInternalError(
"You must run `.compile()` before running `.resolveData()`"
);
err.properties = {
id: "resolve_before_compile",
};
throw err;
}
function throwRenderInvalidTemplate() {
const err = new XTInternalError(
"You should not call .render on a document that had compilation errors"
);
err.properties = {
id: "render_on_invalid_template",
};
throw err;
}
function throwFileTypeNotIdentified() {
const err = new XTInternalError(
"The filetype for this file could not be identified, is this file corrupted ?"
);
err.properties = {
id: "filetype_not_identified",
};
throw err;
}
function throwXmlInvalid(content, offset) {
const err = new XTTemplateError("An XML file has invalid xml");
err.properties = {
id: "file_has_invalid_xml",
content,
offset,
explanation: "The docx contains invalid XML, it is most likely corrupt",
};
throw err;
}
function throwFileTypeNotHandled(fileType) {
const err = new XTInternalError(
`The filetype "${fileType}" is not handled by docxtemplater`
);
err.properties = {
id: "filetype_not_handled",
explanation: `The file you are trying to generate is of type "${fileType}", but only docx and pptx formats are handled`,
fileType,
};
throw err;
}
module.exports = {
XTError,
XTTemplateError,
XTInternalError,
XTScopeParserError,
XTAPIVersionError,
// Remove this alias in v4
RenderingError: XTRenderingError,
XTRenderingError,
getClosingTagNotMatchOpeningTag,
getLoopPositionProducesInvalidXMLError,
getScopeCompilationError,
getScopeParserExecutionError,
getUnclosedTagException,
getUnopenedTagException,
getUnmatchedLoopException,
getDuplicateCloseTagException,
getDuplicateOpenTagException,
getCorruptCharactersException,
throwApiVersionError,
throwContentMustBeString,
throwFileTypeNotHandled,
throwFileTypeNotIdentified,
throwLocationInvalid,
throwMalformedXml,
throwMultiError,
throwExpandNotFound,
throwRawTagShouldBeOnlyTextInParagraph,
throwUnimplementedTagType,
throwXmlTagNotFound,
throwXmlInvalid,
throwResolveBeforeCompile,
throwRenderInvalidTemplate,
};