Skip to content

Commit 9c42dab

Browse files
committed
Provide image metadata (size)
1 parent bd71a65 commit 9c42dab

File tree

4 files changed

+76
-11
lines changed

4 files changed

+76
-11
lines changed

bin/importGlossary.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ const setGlossary = async (metadata) => {
5353
answer?.UIID || "",
5454
definition,
5555
aliases,
56-
imageToUpdate
56+
imageToUpdate,
57+
shouldUpdateImage ? metadata.imageDimensions : undefined
5758
);
5859

5960
if (res.status === 429) {
@@ -131,11 +132,12 @@ async function main() {
131132
// Fetch Google Doc
132133
const gdocsClient = await getDocsClient();
133134
const doc = await getGoogleDoc({ docID: GLOSSARY_DOC }, gdocsClient);
134-
await replaceImages(doc.inlineObjects, GLOSSARY_DOC);
135+
const imageDimensions = await replaceImages(doc.inlineObjects, GLOSSARY_DOC);
135136
const documentContext = {
136137
footnotes: doc.footnotes || {},
137138
namedStyles: doc.namedStyles,
138139
inlineObjects: doc.inlineObjects,
140+
imageDimensions,
139141
};
140142

141143
const table = doc.body.content.filter(({ table }) => table)[0];
@@ -200,13 +202,19 @@ async function main() {
200202
const imgMatch = row.image?.match(/!\[\]\((.*?)\)/);
201203
const newImage = imgMatch?.[1];
202204

205+
// Get image dimensions if available
206+
const dimensions = newImage
207+
? documentContext.imageDimensions[newImage]
208+
: null;
209+
203210
// If no existing entry found, mark as new
204211
if (!existingEntry) {
205212
return {
206213
row,
207214
needsUpdate: true,
208215
existsInCoda: false,
209216
parsedImage: newImage,
217+
imageDimensions: dimensions,
210218
};
211219
}
212220

@@ -252,6 +260,7 @@ async function main() {
252260
existsInCoda: true,
253261
existingEntry,
254262
parsedImage: newImage,
263+
imageDimensions: dimensions,
255264
};
256265
});
257266

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"google-auth-library": "^8.7.0",
2828
"googleapis": "^105.0.0",
2929
"html-entities": "^2.4.0",
30+
"image-size": "^2.0.2",
3031
"markdown-table": "^3.0.4",
3132
"node-fetch": "^3.3.1",
3233
"prettier": "^2.8.8"

parser/cloudflare.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { randomUUID } from "crypto";
22
import { withRetry } from "./utils.js";
3+
import imageSize from "image-size";
34

45
const sendRequest = (endpoint, method, body) =>
56
withRetry(
@@ -30,6 +31,25 @@ const sendRequest = (endpoint, method, body) =>
3031
}
3132
);
3233

34+
const getImageDimensions = async (url) => {
35+
try {
36+
const response = await fetch(url);
37+
if (!response.ok) {
38+
console.warn(
39+
`Failed to fetch image for dimensions: ${response.statusText}`
40+
);
41+
return null;
42+
}
43+
44+
const buffer = Buffer.from(await response.arrayBuffer());
45+
const dimensions = imageSize(buffer);
46+
return { width: dimensions.width, height: dimensions.height };
47+
} catch (error) {
48+
console.warn(`Error getting image dimensions for ${url}:`, error.message);
49+
return null;
50+
}
51+
};
52+
3353
const uploadImage = async (url, metadata) => {
3454
const formData = new FormData();
3555
formData.append("url", url);
@@ -42,19 +62,37 @@ const uploadImage = async (url, metadata) => {
4262
};
4363

4464
export const replaceImages = async (objects, uiid) => {
45-
if (!process.env.CLOUDFLARE_ACCOUNT_ID) return null;
65+
if (!process.env.CLOUDFLARE_ACCOUNT_ID) return {};
4666

4767
const fingerprint = randomUUID();
68+
const imageDimensions = {};
69+
4870
const updates = Object.entries(objects || {}).map(async ([key, obj]) => {
4971
const img = obj?.inlineObjectProperties?.embeddedObject;
5072
if (img) {
51-
img.imageProperties.contentUri = await uploadImage(
52-
img.imageProperties.contentUri,
53-
{ title: img.title, UIID: uiid, fingerprint }
54-
);
73+
const originalUri = img.imageProperties.contentUri;
74+
75+
// Get dimensions before uploading
76+
const dimensions = await getImageDimensions(originalUri);
77+
78+
// Upload to Cloudflare
79+
const newUri = await uploadImage(originalUri, {
80+
title: img.title,
81+
UIID: uiid,
82+
fingerprint,
83+
});
84+
85+
img.imageProperties.contentUri = newUri;
86+
87+
// Store dimensions mapped by the final URI
88+
if (dimensions && newUri) {
89+
imageDimensions[newUri] = dimensions;
90+
}
5591
}
5692
});
93+
5794
await Promise.all(updates);
95+
return imageDimensions;
5896
};
5997

6098
export const questionImages = async () => {

parser/coda.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,25 @@ export const updateGlossary = async (
211211
questionUIId,
212212
md,
213213
aliases,
214-
image
215-
) =>
216-
codaUpsert(
214+
image,
215+
imageDimensions
216+
) => {
217+
// Require image dimensions if image is provided
218+
let imageData = undefined;
219+
if (image) {
220+
if (!imageDimensions) {
221+
throw new Error(
222+
`Image dimensions required for glossary entry: ${glossaryWord}`
223+
);
224+
}
225+
imageData = JSON.stringify({
226+
url: image,
227+
width: imageDimensions.width,
228+
height: imageDimensions.height,
229+
});
230+
}
231+
232+
return codaUpsert(
217233
`${glossaryTableURL}/rows/`,
218234
{
219235
glossaryWord,
@@ -222,7 +238,8 @@ export const updateGlossary = async (
222238
glossaryRichText: md,
223239
glossaryAliases: aliases,
224240
glossaryLastIngested: new Date().toISOString(),
225-
glossaryImage: image || undefined,
241+
glossaryImage: imageData,
226242
},
227243
["glossaryWord"]
228244
);
245+
};

0 commit comments

Comments
 (0)