docx-templates
Advanced tools
Comparing version
@@ -0,1 +1,7 @@ | ||
## 4.10.0 (2023-02-03) | ||
- [Issue #194](https://github.com/guigrpa/docx-templates/issues/194): add ability to provide captions for images ([MR #286](https://github.com/guigrpa/docx-templates/pull/286)). | ||
- Ensure XMLs are processed in a deterministic order (mainly relevant for `listCommands()`), see commit 8b2ba5526df78da675eaf59f88cb76035ffac5bd. | ||
- Various minor code quality and typing improvements. | ||
- Bumped dependencies. | ||
## 4.9.2 (2022-04-04) | ||
@@ -2,0 +8,0 @@ - [PR 266](https://github.com/guigrpa/docx-templates/pull/266) Fix types for Deno bundle (by @mathe42). |
@@ -1,2 +0,2 @@ | ||
declare type LogSink = (message?: any, ...optionalParams: any[]) => void; | ||
declare type LogSink = (message?: string, ...optionalParams: unknown[]) => void; | ||
export declare const logger: { | ||
@@ -3,0 +3,0 @@ debug: LogSink; |
@@ -119,3 +119,3 @@ "use strict"; | ||
ctx.jsSandbox = (0, timm_1.omit)(context, ['__code__', '__result__']); | ||
debug_1.logger.debug('JS result', { attach: result }); | ||
debug_1.logger.debug('Command returned: ', result); | ||
return [2 /*return*/, result]; | ||
@@ -122,0 +122,0 @@ } |
@@ -66,3 +66,3 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var zip, contentTypes, mainDocument, templateXml, tic, parseResult, jsTemplate, tac; | ||
var zip, contentTypes, mainDocument, main_template_path, templateXml, tic, parseResult, jsTemplate, tac; | ||
return __generator(this, function (_a) { | ||
@@ -81,4 +81,5 @@ switch (_a.label) { | ||
mainDocument = getMainDoc(contentTypes); | ||
debug_1.logger.debug('Reading template...'); | ||
return [4 /*yield*/, (0, zip_1.zipGetText)(zip, "".concat(TEMPLATE_PATH, "/").concat(mainDocument))]; | ||
main_template_path = "".concat(TEMPLATE_PATH, "/").concat(mainDocument); | ||
debug_1.logger.debug("Reading ".concat(main_template_path, "...")); | ||
return [4 /*yield*/, (0, zip_1.zipGetText)(zip, main_template_path)]; | ||
case 3: | ||
@@ -88,4 +89,4 @@ templateXml = _a.sent(); | ||
throw new errors_1.TemplateParseError("".concat(mainDocument, " could not be found")); | ||
debug_1.logger.debug("Template file length: ".concat(templateXml.length)); | ||
debug_1.logger.debug('Parsing XML...'); | ||
debug_1.logger.debug("".concat(main_template_path, " file length: ").concat(templateXml.length)); | ||
debug_1.logger.debug("Parsing ".concat(main_template_path, " XML...")); | ||
tic = new Date().getTime(); | ||
@@ -97,6 +98,3 @@ return [4 /*yield*/, (0, xml_1.parseXml)(templateXml)]; | ||
tac = new Date().getTime(); | ||
debug_1.logger.debug("File parsed in ".concat(tac - tic, " ms"), { | ||
attach: jsTemplate, | ||
attachLevel: 'trace', | ||
}); | ||
debug_1.logger.debug("".concat(main_template_path, " parsed in ").concat(tac - tic, " ms")); | ||
return [2 /*return*/, { jsTemplate: jsTemplate, mainDocument: mainDocument, zip: zip, contentTypes: contentTypes }]; | ||
@@ -126,2 +124,4 @@ } | ||
}); }); | ||
// Sort to ensure deterministic processing. | ||
secondary_xml_files.sort(); | ||
prepped_secondaries = []; | ||
@@ -133,2 +133,3 @@ _i = 0, secondary_xml_files_1 = secondary_xml_files; | ||
f = secondary_xml_files_1[_i]; | ||
debug_1.logger.debug("Reading ".concat(f, "...")); | ||
return [4 /*yield*/, (0, zip_1.zipGetText)(zip, f)]; | ||
@@ -139,2 +140,4 @@ case 2: | ||
throw new errors_1.TemplateParseError("".concat(f, " could not be read")); | ||
debug_1.logger.debug("".concat(f, " file length: ").concat(raw.length)); | ||
debug_1.logger.debug("Parsing ".concat(f, " XML...")); | ||
return [4 /*yield*/, (0, xml_1.parseXml)(raw)]; | ||
@@ -272,2 +275,3 @@ case 3: | ||
debug_1.logger.debug('Completing [Content_Types].xml...'); | ||
debug_1.logger.debug('Content types', { attach: contentTypes }); | ||
ensureContentType = function (extension, contentType) { | ||
@@ -274,0 +278,0 @@ var children = contentTypes._children; |
@@ -25,3 +25,3 @@ "use strict"; | ||
node._parent && | ||
!node._parent._fTextNode && // Flow, don't complain | ||
!node._parent._fTextNode && | ||
node._parent._tag === 'w:t') { | ||
@@ -28,0 +28,0 @@ if (openNode == null) |
@@ -108,3 +108,3 @@ "use strict"; | ||
parent_2 && | ||
!parent_2._fTextNode && // Flow, don't complain | ||
!parent_2._fTextNode && | ||
parent_2._tag === 'w:t')) return [3 /*break*/, 3]; | ||
@@ -161,7 +161,22 @@ return [4 /*yield*/, processText(null, nodeIn, ctx, processCmd)]; | ||
exports.findHighestImgId = findHighestImgId; | ||
var debugPrintNode = function (node) { | ||
return JSON.stringify(node._fTextNode | ||
? { | ||
_ifName: node._ifName, | ||
_fTextNode: node._fTextNode, | ||
_text: node === null || node === void 0 ? void 0 : node._text, | ||
} | ||
: { | ||
_ifName: node._ifName, | ||
_fTextNode: node._fTextNode, | ||
_tag: node === null || node === void 0 ? void 0 : node._tag, | ||
_attrs: node === null || node === void 0 ? void 0 : node._attrs, | ||
}); | ||
}; | ||
function walkTemplate(data, template, ctx, processor) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var out, nodeIn, nodeOut, move, deltaJump, errors, curLoop, nextSibling, refNode, refNodeLevel, parent_3, tag, fRemoveNode, buffers, nodeOutParent, imgNode, parent_4, linkNode, parent_5, htmlNode, parent_6, tag, newNode, parent_7, result, newNodeAsTextNode; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var out, nodeIn, nodeOut, move, deltaJump, errors, curLoop, nextSibling, parent_3, tag, fRemoveNode, buffers, nodeOutParent, imgNode, captionNodes, parent_4, linkNode, parent_5, htmlNode, parent_6, tag, newNode, parent_7, result; | ||
var _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
@@ -173,7 +188,7 @@ out = (0, reportUtils_1.cloneNodeWithoutChildren)(template); | ||
errors = []; | ||
_a.label = 1; | ||
_b.label = 1; | ||
case 1: | ||
if (!true) return [3 /*break*/, 5]; | ||
curLoop = (0, reportUtils_1.getCurLoop)(ctx); | ||
nextSibling = void 0; | ||
nextSibling = null; | ||
// ============================================= | ||
@@ -185,10 +200,7 @@ // Move input node pointer | ||
throw new errors_1.InternalError('jumping while curLoop is null'); | ||
refNode = curLoop.refNode, refNodeLevel = curLoop.refNodeLevel; | ||
// | ||
// logger.debug(`Jumping to level ${refNodeLevel}...`, { | ||
// attach: cloneNodeForLogging(refNode), | ||
// }); | ||
deltaJump = ctx.level - refNodeLevel; | ||
nodeIn = refNode; | ||
ctx.level = refNodeLevel; | ||
// TODO: comment debug statements back out, as creating the debug string creates overhead. | ||
debug_1.logger.debug("Jumping to level ".concat(curLoop.refNodeLevel, "..."), debugPrintNode(curLoop.refNode)); | ||
deltaJump = ctx.level - curLoop.refNodeLevel; | ||
nodeIn = curLoop.refNode; | ||
ctx.level = curLoop.refNodeLevel; | ||
ctx.fJump = false; | ||
@@ -217,7 +229,3 @@ move = 'JUMP'; | ||
} | ||
// | ||
// logger.debug( | ||
// `Next node [${chalk.green.bold(move)}, level ${chalk.dim(ctx.level)}]`, | ||
// { attach: cloneNodeForLogging(nodeIn) } | ||
// ); | ||
debug_1.logger.debug("Next node [".concat(move, ", level ").concat(ctx.level, "]"), debugPrintNode(nodeIn)); | ||
// ============================================= | ||
@@ -254,10 +262,7 @@ // Process input node | ||
if ((0, reportUtils_1.isLoopExploring)(ctx) && | ||
curLoop && // Flow, don't complain | ||
curLoop && | ||
nodeIn === curLoop.refNode._parent) { | ||
curLoop.refNode = nodeIn; | ||
curLoop.refNodeLevel -= 1; | ||
// | ||
// logger.debug(`Updated loop '${curLoop.varName}' refNode:`, { | ||
// attach: cloneNodeForLogging(nodeIn), | ||
// }); | ||
debug_1.logger.debug("Updated loop '".concat(curLoop.varName, "' refNode: ") + debugPrintNode(nodeIn)); | ||
} | ||
@@ -272,5 +277,6 @@ nodeOutParent = nodeOut._parent; | ||
if (ctx.pendingImageNode && | ||
!nodeOut._fTextNode && // Flow-prevention | ||
!nodeOut._fTextNode && | ||
nodeOut._tag === 'w:t') { | ||
imgNode = ctx.pendingImageNode; | ||
imgNode = ctx.pendingImageNode.image; | ||
captionNodes = ctx.pendingImageNode.caption; | ||
parent_4 = nodeOut._parent; | ||
@@ -281,2 +287,5 @@ if (parent_4) { | ||
parent_4._children.push(imgNode); | ||
if (captionNodes) { | ||
(_a = parent_4._children).push.apply(_a, captionNodes); | ||
} | ||
// Prevent containing paragraph or table row from being removed | ||
@@ -291,3 +300,3 @@ ctx.buffers['w:p'].fInsertedText = true; | ||
if (ctx.pendingLinkNode && | ||
!nodeOut._fTextNode && // Flow-prevention | ||
!nodeOut._fTextNode && | ||
nodeOut._tag === 'w:r') { | ||
@@ -309,3 +318,3 @@ linkNode = ctx.pendingLinkNode; | ||
if (ctx.pendingHtmlNode && | ||
!nodeOut._fTextNode && // Flow-prevention | ||
!nodeOut._fTextNode && | ||
nodeOut._tag === 'w:p') { | ||
@@ -326,3 +335,3 @@ htmlNode = ctx.pendingHtmlNode; | ||
// case, add an empty `w:p` inside | ||
if (!nodeOut._fTextNode && // Flow-prevention | ||
if (!nodeOut._fTextNode && | ||
nodeOut._tag === 'w:tc' && | ||
@@ -367,6 +376,8 @@ !nodeOut._children.filter(function (o) { return !o._fTextNode && (o._tag === 'w:p' || o._tag === 'w:altChunk'); }).length) { | ||
case 2: | ||
result = _a.sent(); | ||
result = _b.sent(); | ||
if (typeof result === 'string') { | ||
newNodeAsTextNode = newNode; | ||
newNodeAsTextNode._text = result; | ||
// TODO: improve typesafety of conversion Node to TextNode. | ||
newNode._text = result; | ||
debug_1.logger.debug("Inserted command result string into node. Updated node: " + | ||
debugPrintNode(newNode)); | ||
} | ||
@@ -376,9 +387,9 @@ else { | ||
} | ||
_a.label = 3; | ||
_b.label = 3; | ||
case 3: | ||
// Execute the move in the output tree | ||
nodeOut = newNode; | ||
_a.label = 4; | ||
_b.label = 4; | ||
case 4: | ||
// Correct output tree level in case of a JUMP | ||
// JUMP to the target level of the tree. | ||
// ------------------------------------------- | ||
@@ -478,3 +489,3 @@ if (move === 'JUMP') { | ||
var processCmd = function (data, node, ctx) { return __awaiter(void 0, void 0, void 0, function () { | ||
var cmd, _a, cmdName, cmdRest, aliasMatch, aliasName, fullCmd, result, nerr, str, literalXmlDelimiter, img, e_1, pars, html, err_1; | ||
var cmd, _a, cmdName, cmdRest, aliasMatch, aliasName, fullCmd, result, nerr, str, literalXmlDelimiter, img, pars, html, err_1; | ||
return __generator(this, function (_b) { | ||
@@ -485,7 +496,8 @@ switch (_b.label) { | ||
ctx.cmd = ''; // flush the context | ||
debug_1.logger.debug("Processing cmd: ".concat(cmd)); | ||
_b.label = 1; | ||
case 1: | ||
_b.trys.push([1, 31, , 32]); | ||
_b.trys.push([1, 28, , 29]); | ||
_a = splitCommand(cmd), cmdName = _a.cmdName, cmdRest = _a.cmdRest; | ||
if (cmdName !== 'CMD_NODE') | ||
debug_1.logger.debug("Processing cmd: ".concat(cmd)); | ||
// Seeking query? | ||
@@ -498,3 +510,3 @@ if (ctx.fSeekQuery) { | ||
if (!(cmdName === 'QUERY' || cmdName === 'CMD_NODE')) return [3 /*break*/, 2]; | ||
return [3 /*break*/, 30]; | ||
return [3 /*break*/, 27]; | ||
case 2: | ||
@@ -509,3 +521,3 @@ if (!(cmdName === 'ALIAS')) return [3 /*break*/, 3]; | ||
debug_1.logger.debug("Defined alias '".concat(aliasName, "' for: ").concat(fullCmd)); | ||
return [3 /*break*/, 30]; | ||
return [3 /*break*/, 27]; | ||
case 3: | ||
@@ -516,7 +528,7 @@ if (!(cmdName === 'FOR' || cmdName === 'IF')) return [3 /*break*/, 5]; | ||
_b.sent(); | ||
return [3 /*break*/, 30]; | ||
return [3 /*break*/, 27]; | ||
case 5: | ||
if (!(cmdName === 'END-FOR' || cmdName === 'END-IF')) return [3 /*break*/, 6]; | ||
processEndForIf(node, ctx, cmd, cmdName, cmdRest); | ||
return [3 /*break*/, 30]; | ||
return [3 /*break*/, 27]; | ||
case 6: | ||
@@ -546,3 +558,3 @@ if (!(cmdName === 'INS')) return [3 /*break*/, 12]; | ||
return [2 /*return*/, str]; | ||
case 11: return [3 /*break*/, 30]; | ||
case 11: return [3 /*break*/, 27]; | ||
case 12: | ||
@@ -555,50 +567,48 @@ if (!(cmdName === 'EXEC')) return [3 /*break*/, 15]; | ||
_b.label = 14; | ||
case 14: return [3 /*break*/, 30]; | ||
case 14: return [3 /*break*/, 27]; | ||
case 15: | ||
if (!(cmdName === 'IMAGE')) return [3 /*break*/, 21]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 20]; | ||
if (!(cmdName === 'IMAGE')) return [3 /*break*/, 18]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 17]; | ||
return [4 /*yield*/, (0, jsSandbox_1.runUserJsAndGetRaw)(data, cmdRest, ctx)]; | ||
case 16: | ||
img = _b.sent(); | ||
if (!(img != null)) return [3 /*break*/, 20]; | ||
if (img != null) { | ||
try { | ||
processImage(ctx, img); | ||
} | ||
catch (e) { | ||
if (!(e instanceof Error)) | ||
throw e; | ||
throw new errors_1.ImageError(e, cmd); | ||
} | ||
} | ||
_b.label = 17; | ||
case 17: | ||
_b.trys.push([17, 19, , 20]); | ||
return [4 /*yield*/, processImage(ctx, img)]; | ||
case 17: return [3 /*break*/, 27]; | ||
case 18: | ||
_b.sent(); | ||
return [3 /*break*/, 20]; | ||
if (!(cmdName === 'LINK')) return [3 /*break*/, 22]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 21]; | ||
return [4 /*yield*/, (0, jsSandbox_1.runUserJsAndGetRaw)(data, cmdRest, ctx)]; | ||
case 19: | ||
e_1 = _b.sent(); | ||
if (!(e_1 instanceof Error)) | ||
throw e_1; | ||
throw new errors_1.ImageError(e_1, cmd); | ||
case 20: return [3 /*break*/, 30]; | ||
case 21: | ||
if (!(cmdName === 'LINK')) return [3 /*break*/, 25]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 24]; | ||
return [4 /*yield*/, (0, jsSandbox_1.runUserJsAndGetRaw)(data, cmdRest, ctx)]; | ||
case 22: | ||
pars = _b.sent(); | ||
if (!(pars != null)) return [3 /*break*/, 24]; | ||
if (!(pars != null)) return [3 /*break*/, 21]; | ||
return [4 /*yield*/, processLink(ctx, pars)]; | ||
case 23: | ||
case 20: | ||
_b.sent(); | ||
_b.label = 24; | ||
case 24: return [3 /*break*/, 30]; | ||
case 25: | ||
if (!(cmdName === 'HTML')) return [3 /*break*/, 29]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 28]; | ||
_b.label = 21; | ||
case 21: return [3 /*break*/, 27]; | ||
case 22: | ||
if (!(cmdName === 'HTML')) return [3 /*break*/, 26]; | ||
if (!!(0, reportUtils_1.isLoopExploring)(ctx)) return [3 /*break*/, 25]; | ||
return [4 /*yield*/, (0, jsSandbox_1.runUserJsAndGetRaw)(data, cmdRest, ctx)]; | ||
case 26: | ||
case 23: | ||
html = _b.sent(); | ||
if (!(html != null)) return [3 /*break*/, 28]; | ||
if (!(html != null)) return [3 /*break*/, 25]; | ||
return [4 /*yield*/, processHtml(ctx, html)]; | ||
case 27: | ||
case 24: | ||
_b.sent(); | ||
_b.label = 28; | ||
case 28: return [3 /*break*/, 30]; | ||
case 29: throw new errors_1.CommandSyntaxError(cmd); | ||
case 30: return [2 /*return*/]; | ||
case 31: | ||
_b.label = 25; | ||
case 25: return [3 /*break*/, 27]; | ||
case 26: throw new errors_1.CommandSyntaxError(cmd); | ||
case 27: return [2 /*return*/]; | ||
case 28: | ||
err_1 = _b.sent(); | ||
@@ -611,3 +621,3 @@ if (!(err_1 instanceof Error)) | ||
return [2 /*return*/, err_1]; | ||
case 32: return [2 /*return*/]; | ||
case 29: return [2 /*return*/]; | ||
} | ||
@@ -669,2 +679,4 @@ }); | ||
isIf = cmdName === 'IF'; | ||
forMatch = null; | ||
varName = undefined; | ||
if (isIf) { | ||
@@ -747,4 +759,5 @@ if (!node._ifName) { | ||
} | ||
var loopOver = curLoop.loopOver, idx = curLoop.idx; | ||
var _a = getNextItem(loopOver, idx), nextItem = _a.nextItem, curIdx = _a.curIdx; | ||
// Get the next item in the loop | ||
var nextIdx = curLoop.idx + 1; | ||
var nextItem = curLoop.loopOver[nextIdx]; | ||
if (nextItem != null) { | ||
@@ -754,3 +767,3 @@ // next iteration | ||
ctx.fJump = true; | ||
curLoop.idx = curIdx; | ||
curLoop.idx = nextIdx; | ||
} | ||
@@ -789,81 +802,87 @@ else { | ||
} | ||
var processImage = function (ctx, imagePars) { return __awaiter(void 0, void 0, void 0, function () { | ||
var cx, cy, imgRelId, id, alt, node, extNodes, rot, thumbnail, thumbRelId, pic, drawing; | ||
var processImage = function (ctx, imagePars) { | ||
var _a; | ||
return __generator(this, function (_b) { | ||
validateImagePars(imagePars); | ||
cx = (imagePars.width * 360e3).toFixed(0); | ||
cy = (imagePars.height * 360e3).toFixed(0); | ||
imgRelId = imageToContext(ctx, getImageData(imagePars)); | ||
id = String(ctx.imageId); | ||
alt = imagePars.alt || 'desc'; | ||
node = reportUtils_1.newNonTextNode; | ||
extNodes = []; | ||
extNodes.push(node('a:ext', { uri: '{28A0092B-C50C-407E-A947-70E740481C1C}' }, [ | ||
node('a14:useLocalDpi', { | ||
'xmlns:a14': 'http://schemas.microsoft.com/office/drawing/2010/main', | ||
val: '0', | ||
validateImagePars(imagePars); | ||
var cx = (imagePars.width * 360e3).toFixed(0); | ||
var cy = (imagePars.height * 360e3).toFixed(0); | ||
var imgRelId = imageToContext(ctx, getImageData(imagePars)); | ||
var id = String(ctx.imageId); | ||
var alt = imagePars.alt || 'desc'; | ||
var node = reportUtils_1.newNonTextNode; | ||
var extNodes = []; | ||
extNodes.push(node('a:ext', { uri: '{28A0092B-C50C-407E-A947-70E740481C1C}' }, [ | ||
node('a14:useLocalDpi', { | ||
'xmlns:a14': 'http://schemas.microsoft.com/office/drawing/2010/main', | ||
val: '0', | ||
}), | ||
])); | ||
// http://officeopenxml.com/drwSp-rotate.php | ||
// Values are in 60,000ths of a degree, with positive angles moving clockwise or towards the positive y-axis. | ||
var rot = imagePars.rotation | ||
? (imagePars.rotation * 60e3).toString() | ||
: undefined; | ||
if (ctx.images[imgRelId].extension === '.svg') { | ||
// Default to an empty thumbnail, as it is not critical and just part of the docx standard's scaffolding. | ||
// Without a thumbnail, the svg won't render (even in newer versions of Word that don't need the thumbnail). | ||
var thumbnail = (_a = imagePars.thumbnail) !== null && _a !== void 0 ? _a : { | ||
data: 'bm90aGluZwo=', | ||
extension: '.png', | ||
}; | ||
var thumbRelId = imageToContext(ctx, thumbnail); | ||
extNodes.push(node('a:ext', { uri: '{96DAC541-7B7A-43D3-8B79-37D633B846F1}' }, [ | ||
node('asvg:svgBlip', { | ||
'xmlns:asvg': 'http://schemas.microsoft.com/office/drawing/2016/SVG/main', | ||
'r:embed': imgRelId, | ||
}), | ||
])); | ||
rot = imagePars.rotation | ||
? (imagePars.rotation * 60e3).toString() | ||
: undefined; | ||
if (ctx.images[imgRelId].extension === '.svg') { | ||
thumbnail = (_a = imagePars.thumbnail) !== null && _a !== void 0 ? _a : { | ||
data: 'bm90aGluZwo=', | ||
extension: '.png', | ||
}; | ||
thumbRelId = imageToContext(ctx, thumbnail); | ||
extNodes.push(node('a:ext', { uri: '{96DAC541-7B7A-43D3-8B79-37D633B846F1}' }, [ | ||
node('asvg:svgBlip', { | ||
'xmlns:asvg': 'http://schemas.microsoft.com/office/drawing/2016/SVG/main', | ||
'r:embed': imgRelId, | ||
}), | ||
])); | ||
// For SVG the thumb is placed where the image normally goes. | ||
imgRelId = thumbRelId; | ||
} | ||
pic = node('pic:pic', { 'xmlns:pic': 'http://schemas.openxmlformats.org/drawingml/2006/picture' }, [ | ||
node('pic:nvPicPr', {}, [ | ||
node('pic:cNvPr', { id: '0', name: "Picture ".concat(id), descr: alt }), | ||
node('pic:cNvPicPr', {}, [ | ||
node('a:picLocks', { noChangeAspect: '1', noChangeArrowheads: '1' }), | ||
]), | ||
// For SVG the thumb is placed where the image normally goes. | ||
imgRelId = thumbRelId; | ||
} | ||
var pic = node('pic:pic', { 'xmlns:pic': 'http://schemas.openxmlformats.org/drawingml/2006/picture' }, [ | ||
node('pic:nvPicPr', {}, [ | ||
node('pic:cNvPr', { id: '0', name: "Picture ".concat(id), descr: alt }), | ||
node('pic:cNvPicPr', {}, [ | ||
node('a:picLocks', { noChangeAspect: '1', noChangeArrowheads: '1' }), | ||
]), | ||
node('pic:blipFill', {}, [ | ||
node('a:blip', { 'r:embed': imgRelId, cstate: 'print' }, [ | ||
node('a:extLst', {}, extNodes), | ||
]), | ||
node('a:srcRect'), | ||
node('a:stretch', {}, [node('a:fillRect')]), | ||
]), | ||
node('pic:blipFill', {}, [ | ||
node('a:blip', { 'r:embed': imgRelId, cstate: 'print' }, [ | ||
node('a:extLst', {}, extNodes), | ||
]), | ||
node('pic:spPr', { bwMode: 'auto' }, [ | ||
node('a:xfrm', rot ? { rot: rot } : {}, [ | ||
node('a:off', { x: '0', y: '0' }), | ||
node('a:ext', { cx: cx, cy: cy }), | ||
]), | ||
node('a:prstGeom', { prst: 'rect' }, [node('a:avLst')]), | ||
node('a:noFill'), | ||
node('a:ln', {}, [node('a:noFill')]), | ||
node('a:srcRect'), | ||
node('a:stretch', {}, [node('a:fillRect')]), | ||
]), | ||
node('pic:spPr', { bwMode: 'auto' }, [ | ||
node('a:xfrm', rot ? { rot: rot } : {}, [ | ||
node('a:off', { x: '0', y: '0' }), | ||
node('a:ext', { cx: cx, cy: cy }), | ||
]), | ||
]); | ||
drawing = node('w:drawing', {}, [ | ||
node('wp:inline', { distT: '0', distB: '0', distL: '0', distR: '0' }, [ | ||
node('wp:extent', { cx: cx, cy: cy }), | ||
node('wp:docPr', { id: id, name: "Picture ".concat(id), descr: alt }), | ||
node('wp:cNvGraphicFramePr', {}, [ | ||
node('a:graphicFrameLocks', { | ||
'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main', | ||
noChangeAspect: '1', | ||
}), | ||
]), | ||
node('a:graphic', { 'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main' }, [ | ||
node('a:graphicData', { uri: 'http://schemas.openxmlformats.org/drawingml/2006/picture' }, [pic]), | ||
]), | ||
node('a:prstGeom', { prst: 'rect' }, [node('a:avLst')]), | ||
node('a:noFill'), | ||
node('a:ln', {}, [node('a:noFill')]), | ||
]), | ||
]); | ||
var drawing = node('w:drawing', {}, [ | ||
node('wp:inline', { distT: '0', distB: '0', distL: '0', distR: '0' }, [ | ||
node('wp:extent', { cx: cx, cy: cy }), | ||
node('wp:docPr', { id: id, name: "Picture ".concat(id), descr: alt }), | ||
node('wp:cNvGraphicFramePr', {}, [ | ||
node('a:graphicFrameLocks', { | ||
'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main', | ||
noChangeAspect: '1', | ||
}), | ||
]), | ||
]); | ||
ctx.pendingImageNode = drawing; | ||
return [2 /*return*/]; | ||
}); | ||
}); }; | ||
node('a:graphic', { 'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main' }, [ | ||
node('a:graphicData', { uri: 'http://schemas.openxmlformats.org/drawingml/2006/picture' }, [pic]), | ||
]), | ||
]), | ||
]); | ||
ctx.pendingImageNode = { image: drawing }; | ||
if (imagePars.caption) { | ||
ctx.pendingImageNode.caption = [ | ||
node('w:br'), | ||
node('w:t', {}, [(0, reportUtils_1.newTextNode)(imagePars.caption)]), | ||
]; | ||
} | ||
}; | ||
function getImageData(imagePars) { | ||
@@ -926,15 +945,1 @@ var data = imagePars.data, extension = imagePars.extension; | ||
}; | ||
var getNextItem = function (items, curIdx0) { | ||
var nextItem = null; | ||
var curIdx = curIdx0 != null ? curIdx0 : -1; | ||
while (nextItem == null) { | ||
curIdx += 1; | ||
if (curIdx >= items.length) | ||
break; | ||
var tempItem = items[curIdx]; | ||
if (typeof tempItem === 'object' && tempItem.isDeleted) | ||
continue; | ||
nextItem = tempItem; | ||
} | ||
return { nextItem: nextItem, curIdx: curIdx }; | ||
}; |
@@ -124,3 +124,6 @@ /// <reference types="node" /> | ||
}; | ||
pendingImageNode?: NonTextNode; | ||
pendingImageNode?: { | ||
image: NonTextNode; | ||
caption?: NonTextNode[]; | ||
}; | ||
imageId: number; | ||
@@ -207,2 +210,6 @@ images: Images; | ||
rotation?: number; | ||
/** | ||
* Optional caption | ||
*/ | ||
caption?: string; | ||
}; | ||
@@ -209,0 +216,0 @@ export declare type LinkPars = { |
{ | ||
"name": "docx-templates", | ||
"version": "4.9.2", | ||
"version": "4.10.0", | ||
"description": "Template-based docx report creation", | ||
@@ -26,5 +26,5 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"prepare": "yarn compile", | ||
"compile": "rimraf ./lib && tsc && yarn rollup", | ||
"rollup": "rollup -c", | ||
"prepack": "yarn compile", | ||
"travis": "yarn compile && yarn test", | ||
@@ -31,0 +31,0 @@ "jest": "jest --watch --coverage", |
@@ -24,3 +24,31 @@ # Docx-templates [](https://travis-ci.org/guigrpa/docx-templates) [](https://coveralls.io/github/guigrpa/docx-templates?branch=master) [](https://www.npmjs.com/package/docx-templates) | ||
# Table of contents | ||
- [Installation](#installation) | ||
- [Node usage](#node-usage) | ||
- [Deno usage](#deno-usage) | ||
- [Browser usage](#browser-usage) | ||
- [Polyfilled browser-ready bundle](#polyfilled-browser-ready-bundle) | ||
- [Browser template compatibility caveat](#browser-template-compatibility-caveat) | ||
- [Running within a Web Worker](#running-within-a-web-worker) | ||
- [Writing templates](#writing-templates) | ||
- [Custom command delimiters](#custom-command-delimiters) | ||
- [Supported commands](#supported-commands) | ||
- [`QUERY`](#query) | ||
- [`INS` (`=`, or nothing at all)](#ins--or-nothing-at-all) | ||
- [`EXEC` (`!`)](#exec-) | ||
- [`IMAGE`](#image) | ||
- [`LINK`](#link) | ||
- [`HTML`](#html) | ||
- [`FOR` and `END-FOR`](#for-and-end-for) | ||
- [`IF` and `END-IF`](#if-and-end-if) | ||
- [`ALIAS` (and alias resolution with `*`)](#alias-and-alias-resolution-with-) | ||
- [Error handling](#error-handling) | ||
- [Error types](#error-types) | ||
- [Custom error handler](#custom-error-handler) | ||
- [Inspecting templates](#inspecting-templates) | ||
- [Performance & security](#performance--security) | ||
- [Similar projects](#similar-projects) | ||
- [License (MIT)](#license-mit) | ||
# Installation | ||
@@ -186,2 +214,5 @@ | ||
## Running within a Web Worker | ||
Note that you need to disable the sandbox mode using the `noSandbox: true` option to be able to run `createReport` from within a web worker. This is because the default sandbox mode browser polyfills require access to the `iframe` API, which is not available from a web worker context. Make sure you are aware of the security implications of disabling the sandbox. | ||
# Writing templates | ||
@@ -348,2 +379,3 @@ | ||
* `rotation` _[optional]_: optional rotation in degrees, with positive angles moving clockwise. | ||
* `caption` _[optional]_: optional caption displayed below the image | ||
@@ -355,2 +387,4 @@ In the .docx template: | ||
Note that you can center the image by centering the IMAGE command in the template. | ||
In the `createReport` call: | ||
@@ -386,4 +420,6 @@ ```js | ||
Takes the HTML resulting from evaluating a JavaScript snippet and converts it to Word contents (using [altchunk](https://blogs.msdn.microsoft.com/ericwhite/2008/10/26/how-to-use-altchunk-for-document-assembly/)): | ||
Takes the HTML resulting from evaluating a JavaScript snippet and converts it to Word contents. | ||
**Important:** This uses [altchunk](https://blogs.msdn.microsoft.com/ericwhite/2008/10/26/how-to-use-altchunk-for-document-assembly/), which is only supported in Microsoft Word, and not in e.g. LibreOffice or Google Docs. | ||
``` | ||
@@ -412,2 +448,4 @@ +++HTML ` | ||
Note that inside the loop, the variable relative to the current element being processed must be prefixed with `$`. | ||
Since JavaScript expressions are supported, you can for example filter the loop domain: | ||
@@ -597,7 +635,4 @@ | ||
## [Changelog](https://github.com/guigrpa/docx-templates/blob/master/CHANGELOG.md) | ||
# Similar projects | ||
## Similar projects | ||
* [docxtemplater](https://github.com/open-xml-templating/docxtemplater) (believe it or not, I just discovered this very similarly-named project after brushing up my old CS code for `docx-templates` and publishing it for the first time!). It provides lots of goodies, but doesn't allow (AFAIK) embedding queries or JS snippets. | ||
@@ -608,3 +643,3 @@ | ||
## License (MIT) | ||
# License (MIT) | ||
@@ -611,0 +646,0 @@ Copyright (c) [Guillermo Grau Panea](https://github.com/guigrpa) 2016-now |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
1454760
0.47%3617
0.53%645
5.74%4
33.33%