-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathcalcCanvasNodeSizeAndImg.ts
More file actions
120 lines (106 loc) · 3.35 KB
/
calcCanvasNodeSizeAndImg.ts
File metadata and controls
120 lines (106 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid";
import { OnloadArgs, TreeNode } from "roamjs-components/types";
import { DEFAULT_STYLE_PROPS, MAX_WIDTH } from "../components/tldraw/Tldraw";
import { measureCanvasNodeText } from "./measureCanvasNodeText";
import resolveQueryBuilderRef from "./resolveQueryBuilderRef";
import runQuery from "./runQuery";
import getDiscourseNodes from "./getDiscourseNodes";
import resolveRefs from "roamjs-components/dom/resolveRefs";
import { render as renderToast } from "roamjs-components/components/Toast";
import { loadImage } from "./loadImage";
import sendErrorEmail from "./sendErrorEmail";
const extractFirstImageUrl = (text: string): string | null => {
const regex = /!\[.*?\]\((https:\/\/[^)]+)\)/;
const result = text.match(regex) || resolveRefs(text).match(regex);
return result ? result[1] : null;
};
const getFirstImageByUid = (uid: string): string | null => {
const tree = getFullTreeByParentUid(uid);
const findFirstImage = (node: TreeNode): string | null => {
const imageUrl = extractFirstImageUrl(node.text);
if (imageUrl) return imageUrl;
if (node.children) {
for (const child of node.children) {
const childImageUrl = findFirstImage(child);
if (childImageUrl) return childImageUrl;
}
}
return null;
};
return findFirstImage(tree);
};
const calcCanvasNodeSizeAndImg = async ({
nodeText,
uid,
nodeType,
extensionAPI,
}: {
nodeText: string;
uid: string;
nodeType: string;
extensionAPI: OnloadArgs["extensionAPI"];
}) => {
const allNodes = getDiscourseNodes();
const canvasSettings = Object.fromEntries(
allNodes.map((n) => [n.type, { ...n.canvasSettings }])
);
const {
"query-builder-alias": qbAlias = "",
"key-image": isKeyImage = "",
"key-image-option": keyImageOption = "",
} = canvasSettings[nodeType] || {};
const { w, h } = measureCanvasNodeText({
...DEFAULT_STYLE_PROPS,
maxWidth: MAX_WIDTH,
text: nodeText,
});
if (!isKeyImage) return { w, h, imageUrl: "" };
let imageUrl;
if (keyImageOption === "query-builder") {
const parentUid = resolveQueryBuilderRef({
queryRef: qbAlias,
extensionAPI,
});
const results = await runQuery({
extensionAPI,
parentUid,
inputs: { NODETEXT: nodeText, NODEUID: uid },
});
const result = results.allProcessedResults[0]?.text || "";
imageUrl = extractFirstImageUrl(result);
} else {
imageUrl = getFirstImageByUid(uid);
}
if (!imageUrl) return { w, h, imageUrl: "" };
const padding = Number(DEFAULT_STYLE_PROPS.padding.replace("px", ""));
const maxWidth = Number(MAX_WIDTH.replace("px", ""));
const effectiveWidth = maxWidth - 2 * padding;
try {
const { width, height } = await loadImage(imageUrl);
const aspectRatio = width / height;
const nodeImageHeight = effectiveWidth / aspectRatio;
return {
w,
h: h + nodeImageHeight + padding * 2,
imageUrl,
};
} catch (e) {
const error = e as Error;
sendErrorEmail({
type: "Canvas Image Load Failed",
error,
data: {
uid,
nodeText,
imageUrl,
},
});
renderToast({
id: "tldraw-image-load-fail",
content: error.message,
intent: "warning",
});
return { w, h, imageUrl: "" };
}
};
export default calcCanvasNodeSizeAndImg;