Skip to content

Commit

Permalink
Fix for #144 and #190: find the highest image ID that is already in u…
Browse files Browse the repository at this point in the history
…se in the template before rendering to ensure that image IDs are globally unique.
  • Loading branch information
jjhbw committed Jun 3, 2021
1 parent 6a7b7cd commit f139c02
Show file tree
Hide file tree
Showing 6 changed files with 325 additions and 25 deletions.
258 changes: 258 additions & 0 deletions src/__tests__/__snapshots__/images.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2375,3 +2375,261 @@ Object {
"_tag": "w:document",
}
`;

exports[`007: can inject an image in a document that already contains images (regression test for #144) 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" standalone=\\"yes\\"?>
<w:document xmlns:wpc=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\\" xmlns:cx=\\"http://schemas.microsoft.com/office/drawing/2014/chartex\\" xmlns:cx1=\\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\\" xmlns:cx2=\\"http://schemas.microsoft.com/office/drawing/2015/10/21/chartex\\" xmlns:cx3=\\"http://schemas.microsoft.com/office/drawing/2016/5/9/chartex\\" xmlns:cx4=\\"http://schemas.microsoft.com/office/drawing/2016/5/10/chartex\\" xmlns:cx5=\\"http://schemas.microsoft.com/office/drawing/2016/5/11/chartex\\" xmlns:cx6=\\"http://schemas.microsoft.com/office/drawing/2016/5/12/chartex\\" xmlns:cx7=\\"http://schemas.microsoft.com/office/drawing/2016/5/13/chartex\\" xmlns:cx8=\\"http://schemas.microsoft.com/office/drawing/2016/5/14/chartex\\" xmlns:mc=\\"http://schemas.openxmlformats.org/markup-compatibility/2006\\" xmlns:aink=\\"http://schemas.microsoft.com/office/drawing/2016/ink\\" xmlns:am3d=\\"http://schemas.microsoft.com/office/drawing/2017/model3d\\" xmlns:o=\\"urn:schemas-microsoft-com:office:office\\" xmlns:r=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\\" xmlns:m=\\"http://schemas.openxmlformats.org/officeDocument/2006/math\\" xmlns:v=\\"urn:schemas-microsoft-com:vml\\" xmlns:wp14=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\\" xmlns:wp=\\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\\" xmlns:w10=\\"urn:schemas-microsoft-com:office:word\\" xmlns:w=\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\" xmlns:w14=\\"http://schemas.microsoft.com/office/word/2010/wordml\\" xmlns:w15=\\"http://schemas.microsoft.com/office/word/2012/wordml\\" xmlns:w16cex=\\"http://schemas.microsoft.com/office/word/2018/wordml/cex\\" xmlns:w16cid=\\"http://schemas.microsoft.com/office/word/2016/wordml/cid\\" xmlns:w16=\\"http://schemas.microsoft.com/office/word/2018/wordml\\" xmlns:w16se=\\"http://schemas.microsoft.com/office/word/2015/wordml/symex\\" xmlns:wpg=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\\" xmlns:wpi=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\\" xmlns:wne=\\"http://schemas.microsoft.com/office/word/2006/wordml\\" xmlns:wps=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\\" mc:Ignorable=\\"w14 w15 w16se w16cid w16 w16cex wp14\\">
<w:body>
<w:p w14:paraId=\\"1903E9CC\\" w14:textId=\\"36A0822C\\" w:rsidR=\\"00816AFF\\" w:rsidRDefault=\\"00DA0F71\\">
<w:r w:rsidRPr=\\"007575DC\\">
<w:rPr>
<w:rFonts w:ascii=\\"Tahoma\\" w:hAnsi=\\"Tahoma\\" w:cs=\\"Tahoma\\"/>
<w:b/>
<w:bCs/>
<w:noProof/>
<w:sz w:val=\\"20\\"/>
<w:szCs w:val=\\"20\\"/>
<w:lang w:val=\\"de-DE\\" w:eastAsia=\\"de-DE\\"/>
</w:rPr>
<mc:AlternateContent>
<mc:Choice Requires=\\"wps\\">
<w:drawing>
<wp:anchor distT=\\"0\\" distB=\\"0\\" distL=\\"114300\\" distR=\\"114300\\" simplePos=\\"0\\" relativeHeight=\\"251659264\\" behindDoc=\\"1\\" locked=\\"0\\" layoutInCell=\\"1\\" allowOverlap=\\"1\\" wp14:anchorId=\\"46AE926C\\" wp14:editId=\\"32341B2B\\">
<wp:simplePos x=\\"0\\" y=\\"0\\"/>
<wp:positionH relativeFrom=\\"column\\">
<wp:posOffset>0</wp:posOffset>
</wp:positionH>
<wp:positionV relativeFrom=\\"paragraph\\">
<wp:posOffset>197485</wp:posOffset>
</wp:positionV>
<wp:extent cx=\\"1714500\\" cy=\\"1942465\\"/>
<wp:effectExtent l=\\"12700\\" t=\\"12700\\" r=\\"12700\\" b=\\"13335\\"/>
<wp:wrapThrough wrapText=\\"bothSides\\">
<wp:wrapPolygon edited=\\"0\\">
<wp:start x=\\"-160\\" y=\\"-141\\"/>
<wp:lineTo x=\\"-160\\" y=\\"21607\\"/>
<wp:lineTo x=\\"21600\\" y=\\"21607\\"/>
<wp:lineTo x=\\"21600\\" y=\\"-141\\"/>
<wp:lineTo x=\\"-160\\" y=\\"-141\\"/>
</wp:wrapPolygon>
</wp:wrapThrough>
<wp:docPr id=\\"1\\" name=\\"Rechteck 1\\"/>
<wp:cNvGraphicFramePr/>
<a:graphic xmlns:a=\\"http://schemas.openxmlformats.org/drawingml/2006/main\\">
<a:graphicData uri=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\\">
<wps:wsp>
<wps:cNvSpPr/>
<wps:spPr>
<a:xfrm>
<a:off x=\\"0\\" y=\\"0\\"/>
<a:ext cx=\\"1714500\\" cy=\\"1942465\\"/>
</a:xfrm>
<a:prstGeom prst=\\"rect\\">
<a:avLst/>
</a:prstGeom>
</wps:spPr>
<wps:style>
<a:lnRef idx=\\"2\\">
<a:schemeClr val=\\"dk1\\"/>
</a:lnRef>
<a:fillRef idx=\\"1\\">
<a:schemeClr val=\\"lt1\\"/>
</a:fillRef>
<a:effectRef idx=\\"0\\">
<a:schemeClr val=\\"dk1\\"/>
</a:effectRef>
<a:fontRef idx=\\"minor\\">
<a:schemeClr val=\\"dk1\\"/>
</a:fontRef>
</wps:style>
<wps:txbx>
<w:txbxContent>
<w:p w14:paraId=\\"3CB353F0\\" w14:textId=\\"77777777\\" w:rsidR=\\"00DA0F71\\" w:rsidRPr=\\"00F07369\\" w:rsidRDefault=\\"00DA0F71\\" w:rsidP=\\"00DA0F71\\">
<w:pPr>
<w:rPr>
<w:lang w:val=\\"en-US\\"/>
</w:rPr>
</w:pPr>
<w:r w:rsidRPr=\\"008C273F\\">
<w:rPr>
<w:lang w:val=\\"en-US\\"/>
</w:rPr>
<w:drawing>
<wp:inline distT=\\"0\\" distB=\\"0\\" distL=\\"0\\" distR=\\"0\\">
<wp:extent cx=\\"2160000\\" cy=\\"2160000\\"/>
<wp:docPr id=\\"2\\" name=\\"Picture 2\\" descr=\\"desc\\"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks xmlns:a=\\"http://schemas.openxmlformats.org/drawingml/2006/main\\" noChangeAspect=\\"1\\"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a=\\"http://schemas.openxmlformats.org/drawingml/2006/main\\">
<a:graphicData uri=\\"http://schemas.openxmlformats.org/drawingml/2006/picture\\">
<pic:pic xmlns:pic=\\"http://schemas.openxmlformats.org/drawingml/2006/picture\\">
<pic:nvPicPr>
<pic:cNvPr id=\\"0\\" name=\\"Picture 2\\" descr=\\"desc\\"/>
<pic:cNvPicPr>
<a:picLocks noChangeAspect=\\"1\\" noChangeArrowheads=\\"1\\"/>
</pic:cNvPicPr>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed=\\"img2\\" cstate=\\"print\\">
<a:extLst>
<a:ext uri=\\"{28A0092B-C50C-407E-A947-70E740481C1C}\\">
<a14:useLocalDpi xmlns:a14=\\"http://schemas.microsoft.com/office/drawing/2010/main\\" val=\\"0\\"/>
</a:ext>
</a:extLst>
</a:blip>
<a:srcRect/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr bwMode=\\"auto\\">
<a:xfrm>
<a:off x=\\"0\\" y=\\"0\\"/>
<a:ext cx=\\"2160000\\" cy=\\"2160000\\"/>
</a:xfrm>
<a:prstGeom prst=\\"rect\\">
<a:avLst/>
</a:prstGeom>
<a:noFill/>
<a:ln>
<a:noFill/>
</a:ln>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>
</w:txbxContent>
</wps:txbx>
<wps:bodyPr rot=\\"0\\" spcFirstLastPara=\\"0\\" vertOverflow=\\"overflow\\" horzOverflow=\\"overflow\\" vert=\\"horz\\" wrap=\\"square\\" lIns=\\"91440\\" tIns=\\"45720\\" rIns=\\"91440\\" bIns=\\"45720\\" numCol=\\"1\\" spcCol=\\"0\\" rtlCol=\\"0\\" fromWordArt=\\"0\\" anchor=\\"ctr\\" anchorCtr=\\"0\\" forceAA=\\"0\\" compatLnSpc=\\"1\\">
<a:prstTxWarp prst=\\"textNoShape\\">
<a:avLst/>
</a:prstTxWarp>
<a:noAutofit/>
</wps:bodyPr>
</wps:wsp>
</a:graphicData>
</a:graphic>
<wp14:sizeRelV relativeFrom=\\"margin\\">
<wp14:pctHeight>0</wp14:pctHeight>
</wp14:sizeRelV>
</wp:anchor>
</w:drawing>
</mc:Choice>
<mc:Fallback>
<w:pict>
<v:rect w14:anchorId=\\"46AE926C\\" id=\\"Rechteck 1\\" o:spid=\\"_x0000_s1026\\" style=\\"position:absolute;margin-left:0;margin-top:15.55pt;width:135pt;height:152.95pt;z-index:-251657216;visibility:visible;mso-wrap-style:square;mso-height-percent:0;mso-wrap-distance-left:9pt;mso-wrap-distance-top:0;mso-wrap-distance-right:9pt;mso-wrap-distance-bottom:0;mso-position-horizontal:absolute;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:text;mso-height-percent:0;mso-height-relative:margin;v-text-anchor:middle\\" o:gfxdata=\\"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
\\" fillcolor=\\"white [3201]\\" strokecolor=\\"black [3200]\\" strokeweight=\\"1pt\\">
<v:textbox>
<w:txbxContent>
<w:p w14:paraId=\\"3CB353F0\\" w14:textId=\\"77777777\\" w:rsidR=\\"00DA0F71\\" w:rsidRPr=\\"00F07369\\" w:rsidRDefault=\\"00DA0F71\\" w:rsidP=\\"00DA0F71\\">
<w:pPr>
<w:rPr>
<w:lang w:val=\\"en-US\\"/>
</w:rPr>
</w:pPr>
<w:r w:rsidRPr=\\"008C273F\\">
<w:rPr>
<w:lang w:val=\\"en-US\\"/>
</w:rPr>
<w:drawing>
<wp:inline distT=\\"0\\" distB=\\"0\\" distL=\\"0\\" distR=\\"0\\">
<wp:extent cx=\\"2160000\\" cy=\\"2160000\\"/>
<wp:docPr id=\\"3\\" name=\\"Picture 3\\" descr=\\"desc\\"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks xmlns:a=\\"http://schemas.openxmlformats.org/drawingml/2006/main\\" noChangeAspect=\\"1\\"/>
</wp:cNvGraphicFramePr>
<a:graphic xmlns:a=\\"http://schemas.openxmlformats.org/drawingml/2006/main\\">
<a:graphicData uri=\\"http://schemas.openxmlformats.org/drawingml/2006/picture\\">
<pic:pic xmlns:pic=\\"http://schemas.openxmlformats.org/drawingml/2006/picture\\">
<pic:nvPicPr>
<pic:cNvPr id=\\"0\\" name=\\"Picture 3\\" descr=\\"desc\\"/>
<pic:cNvPicPr>
<a:picLocks noChangeAspect=\\"1\\" noChangeArrowheads=\\"1\\"/>
</pic:cNvPicPr>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed=\\"img3\\" cstate=\\"print\\">
<a:extLst>
<a:ext uri=\\"{28A0092B-C50C-407E-A947-70E740481C1C}\\">
<a14:useLocalDpi xmlns:a14=\\"http://schemas.microsoft.com/office/drawing/2010/main\\" val=\\"0\\"/>
</a:ext>
</a:extLst>
</a:blip>
<a:srcRect/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr bwMode=\\"auto\\">
<a:xfrm>
<a:off x=\\"0\\" y=\\"0\\"/>
<a:ext cx=\\"2160000\\" cy=\\"2160000\\"/>
</a:xfrm>
<a:prstGeom prst=\\"rect\\">
<a:avLst/>
</a:prstGeom>
<a:noFill/>
<a:ln>
<a:noFill/>
</a:ln>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>
</w:txbxContent>
</v:textbox>
<w10:wrap type=\\"through\\"/>
</v:rect>
</w:pict>
</mc:Fallback>
</mc:AlternateContent>
</w:r>
</w:p>
<w:sectPr w:rsidR=\\"00816AFF\\" w:rsidSect=\\"0088060A\\">
<w:pgSz w:w=\\"12240\\" w:h=\\"15840\\"/>
<w:pgMar w:top=\\"1440\\" w:right=\\"1440\\" w:bottom=\\"1440\\" w:left=\\"1440\\" w:header=\\"720\\" w:footer=\\"720\\" w:gutter=\\"0\\"/>
<w:cols w:space=\\"720\\"/>
<w:docGrid w:linePitch=\\"360\\"/>
</w:sectPr>
</w:body>
</w:document>"
`;
Binary file not shown.
36 changes: 19 additions & 17 deletions src/__tests__/images.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,21 +271,23 @@ it('007: can inject an image in a document that already contains images (regress
const buff = await fs.promises.readFile(
path.join(__dirname, 'fixtures', 'sample.png')
);
const report = await createReport({
template,
data: {
cv: { ProfilePicture: { url: 'abc' } },
},
additionalJsContext: {
getImage: () => ({
width: 6,
height: 6,
data: buff,
extension: '.png',
}),
},
});
// TODO: can only be tested by loading the result into MS Word. It will show a file corruption warning.
fs.writeFileSync('test.docx', report);
expect(report).toBeInstanceOf(Uint8Array);
expect(
await createReport(
{
template,
data: {
cv: { ProfilePicture: { url: 'abc' } },
},
additionalJsContext: {
getImage: () => ({
width: 6,
height: 6,
data: buff,
extension: '.png',
}),
},
},
'XML'
)
).toMatchSnapshot();
});
18 changes: 17 additions & 1 deletion src/__tests__/unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import path from 'path';
import { zipLoad } from '../zip';
import { readContentTypes, getMainDoc, getMetadata } from '../main';
import {
readContentTypes,
getMainDoc,
getMetadata,
parseTemplate,
} from '../main';
import fs from 'fs';
import { setDebugLogSink } from '../debug';
import { findHighestImgId } from '../processTemplate';

if (process.env.DEBUG) setDebugLogSink(console.log);

Expand Down Expand Up @@ -69,3 +75,13 @@ describe('getMetadata', () => {
}
});
});

describe('findHighestImgId', () => {
it('returns 0 when doc contains no images', async () => {
const template = await fs.promises.readFile(
path.join(__dirname, 'fixtures', 'imageExistingMultiple.docx')
);
const { jsTemplate } = await parseTemplate(template);
expect(findHighestImgId(jsTemplate)).toBe(3);
});
});
Loading

0 comments on commit f139c02

Please sign in to comment.