Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ability to provide captions for images #286

Merged
merged 1 commit into from
Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ The JS snippet must return an _image object_ or a Promise of an _image object_,
* `thumbnail` _[optional]_: when injecting an SVG image, a fallback non-SVG (png/jpg/gif, etc.) image can be provided. This thumbnail is used when SVG images are not supported (e.g. older versions of Word) or when the document is previewed by e.g. Windows Explorer. See usage example below.
* `alt` _[optional]_: optional alt text.
* `rotation` _[optional]_: optional rotation in degrees, with positive angles moving clockwise.
* `caption` _[optional]_: optional caption displayed below the image

In the .docx template:
```
Expand Down
2 changes: 1 addition & 1 deletion examples/example-node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ createReport({
qr: contents => {
const dataUrl = qrcode(contents, { size: 500 });
const data = dataUrl.slice('data:image/gif;base64,'.length);
return { width: 6, height: 6, data, extension: '.gif' };
return { width: 6, height: 6, data, extension: '.gif', caption: 'QR Code caption' };
},
},
}).then(
Expand Down
18 changes: 14 additions & 4 deletions src/processTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,16 @@ export async function walkTemplate(
!nodeOut._fTextNode &&
nodeOut._tag === 'w:t'
) {
const imgNode = ctx.pendingImageNode;
const imgNode = ctx.pendingImageNode.image;
const captionNodes = ctx.pendingImageNode.caption;
const parent = nodeOut._parent;
if (parent) {
imgNode._parent = parent;
parent._children.pop();
parent._children.push(imgNode);
if (captionNodes) {
parent._children.push(...captionNodes);
}
// Prevent containing paragraph or table row from being removed
ctx.buffers['w:p'].fInsertedText = true;
ctx.buffers['w:tr'].fInsertedText = true;
Expand Down Expand Up @@ -575,7 +579,7 @@ const processCmd: CommandProcessor = async (
);
if (img != null) {
try {
await processImage(ctx, img);
processImage(ctx, img);
} catch (e) {
if (!(e instanceof Error)) throw e;
throw new ImageError(e, cmd);
Expand Down Expand Up @@ -813,7 +817,7 @@ function validateImagePars(pars: ImagePars) {
if (pars.thumbnail) validateImage(pars.thumbnail);
}

const processImage = async (ctx: Context, imagePars: ImagePars) => {
const processImage = (ctx: Context, imagePars: ImagePars) => {
validateImagePars(imagePars);
const cx = (imagePars.width * 360e3).toFixed(0);
const cy = (imagePars.height * 360e3).toFixed(0);
Expand Down Expand Up @@ -913,7 +917,13 @@ const processImage = async (ctx: Context, imagePars: ImagePars) => {
),
]),
]);
ctx.pendingImageNode = drawing;
ctx.pendingImageNode = { image: drawing };
if (imagePars.caption) {
ctx.pendingImageNode.caption = [
node('w:br'),
node('w:t', {}, [newTextNode(imagePars.caption)]),
];
}
};

function getImageData(imagePars: ImagePars): Image {
Expand Down
7 changes: 6 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export type Context = {
'w:p': BufferStatus;
'w:tr': BufferStatus;
};
pendingImageNode?: NonTextNode;
pendingImageNode?: { image: NonTextNode; caption?: NonTextNode[] };
imageId: number;
images: Images;
pendingLinkNode?: NonTextNode;
Expand Down Expand Up @@ -223,6 +223,11 @@ export type ImagePars = {
* Optional rotation in degrees, with positive angles moving clockwise.
*/
rotation?: number;

/**
* Optional caption
*/
caption?: string;
};

export type LinkPars = {
Expand Down