@rpascene/shared 0.30.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/es/baseDB.mjs +109 -0
- package/dist/es/build/copy-static.mjs +29 -0
- package/dist/es/common.mjs +37 -0
- package/dist/es/constants/example-code.mjs +202 -0
- package/dist/es/constants/index.mjs +74 -0
- package/dist/es/env/basic.mjs +6 -0
- package/dist/es/env/constants.mjs +97 -0
- package/dist/es/env/decide-model-config.mjs +172 -0
- package/dist/es/env/global-config-manager.mjs +82 -0
- package/dist/es/env/helper.mjs +45 -0
- package/dist/es/env/index.mjs +5 -0
- package/dist/es/env/init-debug.mjs +18 -0
- package/dist/es/env/model-config-manager.mjs +99 -0
- package/dist/es/env/parse.mjs +69 -0
- package/dist/es/env/types.mjs +265 -0
- package/dist/es/env/utils.mjs +18 -0
- package/dist/es/extractor/constants.mjs +2 -0
- package/dist/es/extractor/cs_postmessage.mjs +61 -0
- package/dist/es/extractor/customLocator.mjs +646 -0
- package/dist/es/extractor/debug.mjs +6 -0
- package/dist/es/extractor/dom-util.mjs +92 -0
- package/dist/es/extractor/index.mjs +7 -0
- package/dist/es/extractor/locator.mjs +95 -0
- package/dist/es/extractor/tree.mjs +81 -0
- package/dist/es/extractor/util.mjs +244 -0
- package/dist/es/extractor/web-extractor.mjs +361 -0
- package/dist/es/img/box-select.mjs +184 -0
- package/dist/es/img/draw-box.mjs +42 -0
- package/dist/es/img/get-jimp.mjs +10 -0
- package/dist/es/img/get-photon.mjs +19 -0
- package/dist/es/img/get-sharp.mjs +11 -0
- package/dist/es/img/index.mjs +5 -0
- package/dist/es/img/info.mjs +32 -0
- package/dist/es/img/transform.mjs +192 -0
- package/dist/es/index.mjs +3 -0
- package/dist/es/logger.mjs +61 -0
- package/dist/es/node/fs.mjs +44 -0
- package/dist/es/node/index.mjs +1 -0
- package/dist/es/polyfills/async-hooks.mjs +2 -0
- package/dist/es/polyfills/index.mjs +1 -0
- package/dist/es/types/index.mjs +3 -0
- package/dist/es/us-keyboard-layout.mjs +1414 -0
- package/dist/es/us-keyboard-layout.mjs.LICENSE.txt +5 -0
- package/dist/es/utils.mjs +66 -0
- package/dist/lib/baseDB.js +149 -0
- package/dist/lib/build/copy-static.js +77 -0
- package/dist/lib/common.js +93 -0
- package/dist/lib/constants/example-code.js +239 -0
- package/dist/lib/constants/index.js +153 -0
- package/dist/lib/env/basic.js +40 -0
- package/dist/lib/env/constants.js +143 -0
- package/dist/lib/env/decide-model-config.js +212 -0
- package/dist/lib/env/global-config-manager.js +116 -0
- package/dist/lib/env/helper.js +85 -0
- package/dist/lib/env/index.js +94 -0
- package/dist/lib/env/init-debug.js +52 -0
- package/dist/lib/env/model-config-manager.js +133 -0
- package/dist/lib/env/parse.js +106 -0
- package/dist/lib/env/types.js +650 -0
- package/dist/lib/env/utils.js +61 -0
- package/dist/lib/extractor/constants.js +42 -0
- package/dist/lib/extractor/cs_postmessage.js +98 -0
- package/dist/lib/extractor/customLocator.js +698 -0
- package/dist/lib/extractor/debug.js +12 -0
- package/dist/lib/extractor/dom-util.js +150 -0
- package/dist/lib/extractor/index.js +153 -0
- package/dist/lib/extractor/locator.js +141 -0
- package/dist/lib/extractor/tree.js +127 -0
- package/dist/lib/extractor/util.js +335 -0
- package/dist/lib/extractor/web-extractor.js +407 -0
- package/dist/lib/img/box-select.js +232 -0
- package/dist/lib/img/draw-box.js +89 -0
- package/dist/lib/img/get-jimp.js +72 -0
- package/dist/lib/img/get-photon.js +76 -0
- package/dist/lib/img/get-sharp.js +63 -0
- package/dist/lib/img/index.js +102 -0
- package/dist/lib/img/info.js +86 -0
- package/dist/lib/img/transform.js +279 -0
- package/dist/lib/index.js +43 -0
- package/dist/lib/logger.js +114 -0
- package/dist/lib/node/fs.js +97 -0
- package/dist/lib/node/index.js +60 -0
- package/dist/lib/polyfills/async-hooks.js +36 -0
- package/dist/lib/polyfills/index.js +60 -0
- package/dist/lib/types/index.js +37 -0
- package/dist/lib/us-keyboard-layout.js +1457 -0
- package/dist/lib/us-keyboard-layout.js.LICENSE.txt +5 -0
- package/dist/lib/utils.js +136 -0
- package/dist/types/baseDB.d.ts +25 -0
- package/dist/types/build/copy-static.d.ts +31 -0
- package/dist/types/common.d.ts +12 -0
- package/dist/types/constants/example-code.d.ts +2 -0
- package/dist/types/constants/index.d.ts +23 -0
- package/dist/types/env/basic.d.ts +6 -0
- package/dist/types/env/constants.d.ts +40 -0
- package/dist/types/env/decide-model-config.d.ts +14 -0
- package/dist/types/env/global-config-manager.d.ts +32 -0
- package/dist/types/env/helper.d.ts +6 -0
- package/dist/types/env/index.d.ts +4 -0
- package/dist/types/env/init-debug.d.ts +1 -0
- package/dist/types/env/model-config-manager.d.ts +24 -0
- package/dist/types/env/parse.d.ts +12 -0
- package/dist/types/env/types.d.ts +295 -0
- package/dist/types/env/utils.d.ts +7 -0
- package/dist/types/extractor/constants.d.ts +1 -0
- package/dist/types/extractor/cs_postmessage.d.ts +2 -0
- package/dist/types/extractor/customLocator.d.ts +69 -0
- package/dist/types/extractor/debug.d.ts +1 -0
- package/dist/types/extractor/dom-util.d.ts +26 -0
- package/dist/types/extractor/index.d.ts +36 -0
- package/dist/types/extractor/locator.d.ts +7 -0
- package/dist/types/extractor/tree.d.ts +9 -0
- package/dist/types/extractor/util.d.ts +43 -0
- package/dist/types/extractor/web-extractor.d.ts +19 -0
- package/dist/types/img/box-select.d.ts +25 -0
- package/dist/types/img/draw-box.d.ts +15 -0
- package/dist/types/img/get-jimp.d.ts +2 -0
- package/dist/types/img/get-photon.d.ts +8 -0
- package/dist/types/img/get-sharp.d.ts +3 -0
- package/dist/types/img/index.d.ts +4 -0
- package/dist/types/img/info.d.ts +29 -0
- package/dist/types/img/transform.d.ts +88 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/logger.d.ts +4 -0
- package/dist/types/node/fs.d.ts +15 -0
- package/dist/types/node/index.d.ts +1 -0
- package/dist/types/polyfills/async-hooks.d.ts +6 -0
- package/dist/types/polyfills/index.d.ts +4 -0
- package/dist/types/types/index.d.ts +37 -0
- package/dist/types/us-keyboard-layout.d.ts +32 -0
- package/dist/types/utils.d.ts +22 -0
- package/package.json +102 -0
- package/src/baseDB.ts +158 -0
- package/src/build/copy-static.ts +62 -0
- package/src/common.ts +67 -0
- package/src/constants/example-code.ts +202 -0
- package/src/constants/index.ts +81 -0
- package/src/env/basic.ts +12 -0
- package/src/env/constants.ts +291 -0
- package/src/env/decide-model-config.ts +319 -0
- package/src/env/global-config-manager.ts +174 -0
- package/src/env/helper.ts +80 -0
- package/src/env/index.ts +4 -0
- package/src/env/init-debug.ts +29 -0
- package/src/env/model-config-manager.ts +145 -0
- package/src/env/parse.ts +131 -0
- package/src/env/types.ts +573 -0
- package/src/env/utils.ts +39 -0
- package/src/extractor/constants.ts +5 -0
- package/src/extractor/cs_postmessage.ts +101 -0
- package/src/extractor/customLocator.ts +1138 -0
- package/src/extractor/debug.ts +10 -0
- package/src/extractor/dom-util.ts +141 -0
- package/src/extractor/index.ts +54 -0
- package/src/extractor/locator.ts +179 -0
- package/src/extractor/tree.ts +179 -0
- package/src/extractor/util.ts +468 -0
- package/src/extractor/web-extractor.ts +559 -0
- package/src/img/box-select.ts +346 -0
- package/src/img/draw-box.ts +60 -0
- package/src/img/get-jimp.ts +12 -0
- package/src/img/get-photon.ts +48 -0
- package/src/img/get-sharp.ts +18 -0
- package/src/img/index.ts +24 -0
- package/src/img/info.ts +79 -0
- package/src/img/jimp.d.ts +4 -0
- package/src/img/transform.ts +396 -0
- package/src/index.ts +6 -0
- package/src/logger.ts +93 -0
- package/src/node/fs.ts +84 -0
- package/src/node/index.ts +1 -0
- package/src/polyfills/async-hooks.ts +6 -0
- package/src/polyfills/index.ts +4 -0
- package/src/types/index.ts +53 -0
- package/src/us-keyboard-layout.ts +723 -0
- package/src/utils.ts +127 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { CONTAINER_MINI_HEIGHT, CONTAINER_MINI_WIDTH, NodeType } from "../constants/index.mjs";
|
|
2
|
+
import { isAElement, isButtonElement, isContainerElement, isFormElement, isImgElement, isTextElement } from "./dom-util.mjs";
|
|
3
|
+
import { descriptionOfTree } from "./tree.mjs";
|
|
4
|
+
import { elementRect, getNodeAttributes, getPseudoElementContent, getRect, getTopDocument, logger, rpasceneGenerateHash, setDebugMode } from "./util.mjs";
|
|
5
|
+
import { onWindowMessage, postWindowMessage } from "./cs_postmessage.mjs";
|
|
6
|
+
import { getContainerPath, getLocators } from "./customLocator.mjs";
|
|
7
|
+
let indexId = 0;
|
|
8
|
+
function tagNameOfNode(node, currentWindow = globalThis) {
|
|
9
|
+
let tagName = '';
|
|
10
|
+
if (node instanceof currentWindow.HTMLElement) {
|
|
11
|
+
var _node_tagName;
|
|
12
|
+
tagName = null == (_node_tagName = node.tagName) ? void 0 : _node_tagName.toLowerCase();
|
|
13
|
+
} else {
|
|
14
|
+
const parentElement = node.parentElement;
|
|
15
|
+
if (parentElement && parentElement instanceof currentWindow.HTMLElement) {
|
|
16
|
+
var _parentElement_tagName;
|
|
17
|
+
tagName = null == (_parentElement_tagName = parentElement.tagName) ? void 0 : _parentElement_tagName.toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return tagName ? `<${tagName}>` : '';
|
|
21
|
+
}
|
|
22
|
+
function collectElementInfo(node, currentWindow, currentDocument, baseZoom = 1, basePoint = {
|
|
23
|
+
left: 0,
|
|
24
|
+
top: 0
|
|
25
|
+
}, isContainer = false) {
|
|
26
|
+
const rect = elementRect(node, currentWindow, currentDocument, baseZoom);
|
|
27
|
+
if (!rect) return null;
|
|
28
|
+
if (rect.width < CONTAINER_MINI_WIDTH || rect.height < CONTAINER_MINI_HEIGHT) return null;
|
|
29
|
+
if (0 !== basePoint.left || 0 !== basePoint.top) {
|
|
30
|
+
rect.left += basePoint.left;
|
|
31
|
+
rect.top += basePoint.top;
|
|
32
|
+
}
|
|
33
|
+
if (rect.height >= window.innerHeight && rect.width >= window.innerWidth) return null;
|
|
34
|
+
if (isFormElement(node, currentWindow)) {
|
|
35
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
36
|
+
let valueContent = attributes.value || attributes.placeholder || node.textContent || '';
|
|
37
|
+
const nodeHashId = rpasceneGenerateHash(node, valueContent, rect);
|
|
38
|
+
const tagName = node.tagName.toLowerCase();
|
|
39
|
+
if ('select' === node.tagName.toLowerCase()) {
|
|
40
|
+
const selectedOption = node.options[node.selectedIndex];
|
|
41
|
+
valueContent = (null == selectedOption ? void 0 : selectedOption.textContent) || '';
|
|
42
|
+
}
|
|
43
|
+
if (('input' === node.tagName.toLowerCase() || 'textarea' === node.tagName.toLowerCase()) && node.value) valueContent = node.value;
|
|
44
|
+
const elementInfo = {
|
|
45
|
+
id: nodeHashId,
|
|
46
|
+
nodeHashId,
|
|
47
|
+
nodeType: NodeType.FORM_ITEM,
|
|
48
|
+
indexId: indexId++,
|
|
49
|
+
attributes: {
|
|
50
|
+
...attributes,
|
|
51
|
+
htmlTagName: `<${tagName}>`,
|
|
52
|
+
nodeType: NodeType.FORM_ITEM
|
|
53
|
+
},
|
|
54
|
+
content: valueContent.trim(),
|
|
55
|
+
rect,
|
|
56
|
+
center: [
|
|
57
|
+
Math.round(rect.left + rect.width / 2),
|
|
58
|
+
Math.round(rect.top + rect.height / 2)
|
|
59
|
+
],
|
|
60
|
+
zoom: rect.zoom,
|
|
61
|
+
isVisible: rect.isVisible
|
|
62
|
+
};
|
|
63
|
+
return elementInfo;
|
|
64
|
+
}
|
|
65
|
+
if (isButtonElement(node, currentWindow)) {
|
|
66
|
+
const rect = mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom);
|
|
67
|
+
if (!rect) return null;
|
|
68
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
69
|
+
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
70
|
+
const content = node.innerText || pseudo.before || pseudo.after || '';
|
|
71
|
+
const nodeHashId = rpasceneGenerateHash(node, content, rect);
|
|
72
|
+
const elementInfo = {
|
|
73
|
+
id: nodeHashId,
|
|
74
|
+
indexId: indexId++,
|
|
75
|
+
nodeHashId,
|
|
76
|
+
nodeType: NodeType.BUTTON,
|
|
77
|
+
attributes: {
|
|
78
|
+
...attributes,
|
|
79
|
+
htmlTagName: tagNameOfNode(node, currentWindow),
|
|
80
|
+
nodeType: NodeType.BUTTON
|
|
81
|
+
},
|
|
82
|
+
content,
|
|
83
|
+
rect,
|
|
84
|
+
center: [
|
|
85
|
+
Math.round(rect.left + rect.width / 2),
|
|
86
|
+
Math.round(rect.top + rect.height / 2)
|
|
87
|
+
],
|
|
88
|
+
zoom: rect.zoom,
|
|
89
|
+
isVisible: rect.isVisible
|
|
90
|
+
};
|
|
91
|
+
return elementInfo;
|
|
92
|
+
}
|
|
93
|
+
if (isImgElement(node, currentWindow)) {
|
|
94
|
+
var _node_nodeName;
|
|
95
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
96
|
+
const nodeHashId = rpasceneGenerateHash(node, '', rect);
|
|
97
|
+
const elementInfo = {
|
|
98
|
+
id: nodeHashId,
|
|
99
|
+
indexId: indexId++,
|
|
100
|
+
nodeHashId,
|
|
101
|
+
attributes: {
|
|
102
|
+
...attributes,
|
|
103
|
+
...(null == (_node_nodeName = node.nodeName) ? void 0 : _node_nodeName.toLowerCase()) === 'svg' ? {
|
|
104
|
+
svgContent: 'true'
|
|
105
|
+
} : {},
|
|
106
|
+
nodeType: NodeType.IMG,
|
|
107
|
+
htmlTagName: tagNameOfNode(node, currentWindow)
|
|
108
|
+
},
|
|
109
|
+
nodeType: NodeType.IMG,
|
|
110
|
+
content: '',
|
|
111
|
+
rect,
|
|
112
|
+
center: [
|
|
113
|
+
Math.round(rect.left + rect.width / 2),
|
|
114
|
+
Math.round(rect.top + rect.height / 2)
|
|
115
|
+
],
|
|
116
|
+
zoom: rect.zoom,
|
|
117
|
+
isVisible: rect.isVisible
|
|
118
|
+
};
|
|
119
|
+
return elementInfo;
|
|
120
|
+
}
|
|
121
|
+
if (isTextElement(node, currentWindow)) {
|
|
122
|
+
var _node_textContent;
|
|
123
|
+
const text = null == (_node_textContent = node.textContent) ? void 0 : _node_textContent.trim().replace(/\n+/g, ' ');
|
|
124
|
+
if (!text) return null;
|
|
125
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
126
|
+
const attributeKeys = Object.keys(attributes);
|
|
127
|
+
if (!text.trim() && 0 === attributeKeys.length) return null;
|
|
128
|
+
const nodeHashId = rpasceneGenerateHash(node, text, rect);
|
|
129
|
+
const elementInfo = {
|
|
130
|
+
id: nodeHashId,
|
|
131
|
+
indexId: indexId++,
|
|
132
|
+
nodeHashId,
|
|
133
|
+
nodeType: NodeType.TEXT,
|
|
134
|
+
attributes: {
|
|
135
|
+
...attributes,
|
|
136
|
+
nodeType: NodeType.TEXT,
|
|
137
|
+
htmlTagName: tagNameOfNode(node, currentWindow)
|
|
138
|
+
},
|
|
139
|
+
center: [
|
|
140
|
+
Math.round(rect.left + rect.width / 2),
|
|
141
|
+
Math.round(rect.top + rect.height / 2)
|
|
142
|
+
],
|
|
143
|
+
content: text,
|
|
144
|
+
rect,
|
|
145
|
+
zoom: rect.zoom,
|
|
146
|
+
isVisible: rect.isVisible
|
|
147
|
+
};
|
|
148
|
+
return elementInfo;
|
|
149
|
+
}
|
|
150
|
+
if (isAElement(node, currentWindow)) {
|
|
151
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
152
|
+
const pseudo = getPseudoElementContent(node, currentWindow);
|
|
153
|
+
const content = node.innerText || pseudo.before || pseudo.after || '';
|
|
154
|
+
const nodeHashId = rpasceneGenerateHash(node, content, rect);
|
|
155
|
+
const elementInfo = {
|
|
156
|
+
id: nodeHashId,
|
|
157
|
+
indexId: indexId++,
|
|
158
|
+
nodeHashId,
|
|
159
|
+
nodeType: NodeType.A,
|
|
160
|
+
attributes: {
|
|
161
|
+
...attributes,
|
|
162
|
+
htmlTagName: tagNameOfNode(node, currentWindow),
|
|
163
|
+
nodeType: NodeType.A
|
|
164
|
+
},
|
|
165
|
+
content,
|
|
166
|
+
rect,
|
|
167
|
+
center: [
|
|
168
|
+
Math.round(rect.left + rect.width / 2),
|
|
169
|
+
Math.round(rect.top + rect.height / 2)
|
|
170
|
+
],
|
|
171
|
+
zoom: rect.zoom,
|
|
172
|
+
isVisible: rect.isVisible
|
|
173
|
+
};
|
|
174
|
+
return elementInfo;
|
|
175
|
+
}
|
|
176
|
+
if (isContainerElement(node, currentWindow) || isContainer) {
|
|
177
|
+
const attributes = getNodeAttributes(node, currentWindow);
|
|
178
|
+
const nodeHashId = rpasceneGenerateHash(node, '', rect);
|
|
179
|
+
const elementInfo = {
|
|
180
|
+
id: nodeHashId,
|
|
181
|
+
nodeHashId,
|
|
182
|
+
indexId: indexId++,
|
|
183
|
+
nodeType: NodeType.CONTAINER,
|
|
184
|
+
attributes: {
|
|
185
|
+
...attributes,
|
|
186
|
+
nodeType: NodeType.CONTAINER,
|
|
187
|
+
htmlTagName: tagNameOfNode(node, currentWindow)
|
|
188
|
+
},
|
|
189
|
+
content: '',
|
|
190
|
+
rect,
|
|
191
|
+
center: [
|
|
192
|
+
Math.round(rect.left + rect.width / 2),
|
|
193
|
+
Math.round(rect.top + rect.height / 2)
|
|
194
|
+
],
|
|
195
|
+
zoom: rect.zoom,
|
|
196
|
+
isVisible: rect.isVisible
|
|
197
|
+
};
|
|
198
|
+
return elementInfo;
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
async function extractTextWithPosition(initNode, debugMode = false) {
|
|
203
|
+
const elementNode = await extractTreeNode(initNode, debugMode);
|
|
204
|
+
const elementInfoArray = [];
|
|
205
|
+
function dfsTopChildren(node) {
|
|
206
|
+
if (node.node) elementInfoArray.push(node.node);
|
|
207
|
+
for(let i = 0; i < node.children.length; i++)dfsTopChildren(node.children[i]);
|
|
208
|
+
}
|
|
209
|
+
dfsTopChildren({
|
|
210
|
+
children: elementNode.children,
|
|
211
|
+
node: elementNode.node
|
|
212
|
+
});
|
|
213
|
+
console.log(elementInfoArray, 'elementInfoArray');
|
|
214
|
+
return elementInfoArray;
|
|
215
|
+
}
|
|
216
|
+
async function extractTreeNodeAsString(initNode, visibleOnly = false, debugMode = false) {
|
|
217
|
+
const elementNode = await extractTreeNode(initNode, debugMode);
|
|
218
|
+
return descriptionOfTree(elementNode, void 0, false, visibleOnly);
|
|
219
|
+
}
|
|
220
|
+
async function extractTreeNode(initNode, debugMode = false, basePoint = {
|
|
221
|
+
left: 0,
|
|
222
|
+
top: 0
|
|
223
|
+
}, baseZoom = 1, containerPaths = []) {
|
|
224
|
+
setDebugMode(debugMode);
|
|
225
|
+
indexId = 0;
|
|
226
|
+
let containerPathClone = [
|
|
227
|
+
...containerPaths
|
|
228
|
+
];
|
|
229
|
+
const topDocument = getTopDocument();
|
|
230
|
+
const startNode = initNode || topDocument;
|
|
231
|
+
const topChildren = [];
|
|
232
|
+
function dfs(node, currentWindow, currentDocument, baseZoom = 1, basePoint = {
|
|
233
|
+
left: 0,
|
|
234
|
+
top: 0
|
|
235
|
+
}) {
|
|
236
|
+
if (!node) return null;
|
|
237
|
+
if (node.nodeType && 10 === node.nodeType) return null;
|
|
238
|
+
const elementInfo = collectElementInfo(node, currentWindow, currentDocument, baseZoom, basePoint, false);
|
|
239
|
+
if (elementInfo) {
|
|
240
|
+
const allPaths = getLocators(node);
|
|
241
|
+
elementInfo.allPaths = allPaths;
|
|
242
|
+
elementInfo.containerPaths = containerPathClone;
|
|
243
|
+
}
|
|
244
|
+
if (node instanceof currentWindow.HTMLIFrameElement) {
|
|
245
|
+
if (node.contentWindow && node.contentWindow) return null;
|
|
246
|
+
}
|
|
247
|
+
const nodeInfo = {
|
|
248
|
+
node: elementInfo,
|
|
249
|
+
children: []
|
|
250
|
+
};
|
|
251
|
+
if ((null == elementInfo ? void 0 : elementInfo.nodeType) === NodeType.BUTTON || (null == elementInfo ? void 0 : elementInfo.nodeType) === NodeType.IMG || (null == elementInfo ? void 0 : elementInfo.nodeType) === NodeType.TEXT || (null == elementInfo ? void 0 : elementInfo.nodeType) === NodeType.FORM_ITEM || (null == elementInfo ? void 0 : elementInfo.nodeType) === NodeType.CONTAINER) return nodeInfo;
|
|
252
|
+
const rect = getRect(node, baseZoom, currentWindow);
|
|
253
|
+
for(let i = 0; i < node.childNodes.length; i++){
|
|
254
|
+
logger('will dfs', node.childNodes[i]);
|
|
255
|
+
const childNodeInfo = dfs(node.childNodes[i], currentWindow, currentDocument, rect.zoom, basePoint);
|
|
256
|
+
if (Array.isArray(childNodeInfo)) nodeInfo.children.push(...childNodeInfo);
|
|
257
|
+
else if (childNodeInfo) nodeInfo.children.push(childNodeInfo);
|
|
258
|
+
}
|
|
259
|
+
if (null === nodeInfo.node) {
|
|
260
|
+
if (0 === nodeInfo.children.length) return null;
|
|
261
|
+
return nodeInfo.children;
|
|
262
|
+
}
|
|
263
|
+
return nodeInfo;
|
|
264
|
+
}
|
|
265
|
+
function getCssScale(ele) {
|
|
266
|
+
try {
|
|
267
|
+
const { width, height } = ele.getBoundingClientRect();
|
|
268
|
+
return {
|
|
269
|
+
cssScaleX: Number((width / ele.offsetWidth).toFixed(1)),
|
|
270
|
+
cssScaleY: Number((height / ele.offsetHeight).toFixed(1))
|
|
271
|
+
};
|
|
272
|
+
} catch (error) {
|
|
273
|
+
return {
|
|
274
|
+
cssScaleX: 1,
|
|
275
|
+
cssScaleY: 1
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const rootNodeInfo = dfs(startNode, window, document, baseZoom, basePoint);
|
|
280
|
+
if (Array.isArray(rootNodeInfo)) topChildren.push(...rootNodeInfo);
|
|
281
|
+
else if (rootNodeInfo) topChildren.push(rootNodeInfo);
|
|
282
|
+
if (startNode === topDocument) {
|
|
283
|
+
const iframes = document.querySelectorAll('iframe');
|
|
284
|
+
for(let i = 0; i < iframes.length; i++){
|
|
285
|
+
const iframe = iframes[i];
|
|
286
|
+
const iframeInfo = collectElementInfo(iframe, window, document, 1);
|
|
287
|
+
const baseZoom = getCssScale(iframe).cssScaleX;
|
|
288
|
+
const containerPath = getContainerPath(iframe);
|
|
289
|
+
containerPathClone = containerPathClone.concat(containerPath);
|
|
290
|
+
if (iframeInfo) if (iframe.contentDocument && iframe.contentWindow) {
|
|
291
|
+
console.log("iframe\u540C\u57DF");
|
|
292
|
+
const iframeChildren = dfs(iframe.contentDocument.body, iframe.contentWindow, iframe.contentDocument, baseZoom, {
|
|
293
|
+
left: iframeInfo.rect.left,
|
|
294
|
+
top: iframeInfo.rect.top
|
|
295
|
+
});
|
|
296
|
+
if (Array.isArray(iframeChildren)) topChildren.push(...iframeChildren);
|
|
297
|
+
else if (iframeChildren) topChildren.push(iframeChildren);
|
|
298
|
+
} else {
|
|
299
|
+
console.log(iframeInfo, "iframe\u8DE8\u57DF\u4E86");
|
|
300
|
+
const iframeChildren = await postWindowMessage(iframe.contentWindow, window, {
|
|
301
|
+
action: 'extractTreeNode',
|
|
302
|
+
data: {
|
|
303
|
+
basePoint: {
|
|
304
|
+
left: iframeInfo.rect.left,
|
|
305
|
+
top: iframeInfo.rect.top
|
|
306
|
+
},
|
|
307
|
+
baseZoom,
|
|
308
|
+
containerPaths: containerPathClone
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
if (Array.isArray(iframeChildren)) topChildren.push(...iframeChildren);
|
|
312
|
+
else if (iframeChildren) topChildren.push(iframeChildren);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
node: null,
|
|
318
|
+
children: topChildren
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function mergeElementAndChildrenRects(node, currentWindow, currentDocument, baseZoom = 1) {
|
|
322
|
+
const selfRect = elementRect(node, currentWindow, currentDocument, baseZoom);
|
|
323
|
+
if (!selfRect) return null;
|
|
324
|
+
let minLeft = selfRect.left;
|
|
325
|
+
let minTop = selfRect.top;
|
|
326
|
+
let maxRight = selfRect.left + selfRect.width;
|
|
327
|
+
let maxBottom = selfRect.top + selfRect.height;
|
|
328
|
+
function traverse(child) {
|
|
329
|
+
for(let i = 0; i < child.childNodes.length; i++){
|
|
330
|
+
const sub = child.childNodes[i];
|
|
331
|
+
if (1 === sub.nodeType) {
|
|
332
|
+
const rect = elementRect(sub, currentWindow, currentDocument, baseZoom);
|
|
333
|
+
if (rect) {
|
|
334
|
+
minLeft = Math.min(minLeft, rect.left);
|
|
335
|
+
minTop = Math.min(minTop, rect.top);
|
|
336
|
+
maxRight = Math.max(maxRight, rect.left + rect.width);
|
|
337
|
+
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
|
338
|
+
}
|
|
339
|
+
traverse(sub);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
traverse(node);
|
|
344
|
+
return {
|
|
345
|
+
...selfRect,
|
|
346
|
+
left: minLeft,
|
|
347
|
+
top: minTop,
|
|
348
|
+
width: maxRight - minLeft,
|
|
349
|
+
height: maxBottom - minTop
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
if ('undefined' != typeof window) onWindowMessage(window, async ({ action, data }, { source })=>{
|
|
353
|
+
if ('extractTreeNode' === action) try {
|
|
354
|
+
return await extractTreeNode(document.body, false, data.basePoint, data.baseZoom, data.containerPaths);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
return {
|
|
357
|
+
error: 'error message'
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
export { collectElementInfo, extractTextWithPosition, extractTreeNode, extractTreeNodeAsString, mergeElementAndChildrenRects };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import node_assert from "node:assert";
|
|
2
|
+
import get_jimp from "./get-jimp.mjs";
|
|
3
|
+
import { bufferFromBase64, imageInfoOfBase64 } from "./index.mjs";
|
|
4
|
+
let cachedFont = null;
|
|
5
|
+
const loadFonts = async ()=>{
|
|
6
|
+
const Jimp = await get_jimp();
|
|
7
|
+
try {
|
|
8
|
+
const fonts = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE);
|
|
9
|
+
return fonts;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.warn('Error loading font, will try to load online fonts', error);
|
|
12
|
+
const onlineFonts = 'https://cdn.jsdelivr.net/npm/jimp-compact@0.16.1-2/fonts/open-sans/open-sans-16-white/open-sans-16-white.fnt';
|
|
13
|
+
const fonts = await Jimp.loadFont(onlineFonts);
|
|
14
|
+
return fonts;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const createSvgOverlay = async (elements, imageWidth, imageHeight, boxPadding = 5, borderThickness = 2, prompt)=>{
|
|
18
|
+
const Jimp = await get_jimp();
|
|
19
|
+
const image = new Jimp(imageWidth, imageHeight, 0x00000000);
|
|
20
|
+
const colors = [
|
|
21
|
+
{
|
|
22
|
+
rect: 0xc62300ff,
|
|
23
|
+
text: 0xffffffff
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
rect: 0x0000ffff,
|
|
27
|
+
text: 0xffffffff
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
rect: 0x8b4513ff,
|
|
31
|
+
text: 0xffffffff
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
rect: 0x3e7b27ff,
|
|
35
|
+
text: 0xffffffff
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
rect: 0x500073ff,
|
|
39
|
+
text: 0xffffffff
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
if (prompt) try {
|
|
43
|
+
cachedFont = cachedFont || await loadFonts();
|
|
44
|
+
const promptPadding = 10;
|
|
45
|
+
const promptMargin = 20;
|
|
46
|
+
const promptHeight = 30;
|
|
47
|
+
const promptY = imageHeight - promptHeight - promptMargin;
|
|
48
|
+
image.scan(0, promptY, imageWidth, promptHeight, (x, y, idx)=>{
|
|
49
|
+
image.bitmap.data[idx + 0] = 0x00;
|
|
50
|
+
image.bitmap.data[idx + 1] = 0x00;
|
|
51
|
+
image.bitmap.data[idx + 2] = 0x00;
|
|
52
|
+
image.bitmap.data[idx + 3] = 0xcc;
|
|
53
|
+
});
|
|
54
|
+
image.print(cachedFont, promptPadding, promptY, {
|
|
55
|
+
text: prompt,
|
|
56
|
+
alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT,
|
|
57
|
+
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
|
|
58
|
+
}, imageWidth - 2 * promptPadding, promptHeight);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Error drawing prompt text', error);
|
|
61
|
+
}
|
|
62
|
+
for(let index = 0; index < elements.length; index++){
|
|
63
|
+
const element = elements[index];
|
|
64
|
+
const color = colors[index % colors.length];
|
|
65
|
+
const paddedLeft = Math.max(0, element.rect.left - boxPadding);
|
|
66
|
+
const paddedTop = Math.max(0, element.rect.top - boxPadding);
|
|
67
|
+
const paddedWidth = Math.min(imageWidth - paddedLeft, element.rect.width + 2 * boxPadding);
|
|
68
|
+
const paddedHeight = Math.min(imageHeight - paddedTop, element.rect.height + 2 * boxPadding);
|
|
69
|
+
const paddedRect = {
|
|
70
|
+
left: paddedLeft,
|
|
71
|
+
top: paddedTop,
|
|
72
|
+
width: paddedWidth,
|
|
73
|
+
height: paddedHeight
|
|
74
|
+
};
|
|
75
|
+
image.scan(paddedRect.left, paddedRect.top, paddedRect.width, paddedRect.height, (x, y, idx)=>{
|
|
76
|
+
if (x >= paddedRect.left && x < paddedRect.left + borderThickness || x <= paddedRect.left + paddedRect.width - 1 && x > paddedRect.left + paddedRect.width - borderThickness || y >= paddedRect.top && y < paddedRect.top + borderThickness || y <= paddedRect.top + paddedRect.height - 1 && y > paddedRect.top + paddedRect.height - borderThickness) {
|
|
77
|
+
image.bitmap.data[idx + 0] = color.rect >> 24 & 0xff;
|
|
78
|
+
image.bitmap.data[idx + 1] = color.rect >> 16 & 0xff;
|
|
79
|
+
image.bitmap.data[idx + 2] = color.rect >> 8 & 0xff;
|
|
80
|
+
image.bitmap.data[idx + 3] = 0xff & color.rect;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
const indexId = element.indexId;
|
|
84
|
+
if ('number' != typeof indexId) continue;
|
|
85
|
+
const textWidth = 8 * indexId.toString().length;
|
|
86
|
+
const textHeight = 12;
|
|
87
|
+
const rectWidth = textWidth + 5;
|
|
88
|
+
const rectHeight = textHeight + 4;
|
|
89
|
+
let rectX = paddedRect.left - rectWidth;
|
|
90
|
+
let rectY = paddedRect.top + paddedRect.height / 2 - textHeight / 2 - 2;
|
|
91
|
+
const checkOverlap = (x, y)=>elements.slice(0, index).some((otherElement)=>x < otherElement.rect.left + otherElement.rect.width && x + rectWidth > otherElement.rect.left && y < otherElement.rect.top + otherElement.rect.height && y + rectHeight > otherElement.rect.top);
|
|
92
|
+
const isWithinBounds = (x, y)=>x >= 0 && x + rectWidth <= imageWidth && y >= 0 && y + rectHeight <= imageHeight;
|
|
93
|
+
if (checkOverlap(rectX, rectY) || !isWithinBounds(rectX, rectY)) if (!checkOverlap(paddedRect.left, paddedRect.top - rectHeight - 2) && isWithinBounds(paddedRect.left, paddedRect.top - rectHeight - 2)) {
|
|
94
|
+
rectX = paddedRect.left;
|
|
95
|
+
rectY = paddedRect.top - rectHeight - 2;
|
|
96
|
+
} else if (!checkOverlap(paddedRect.left, paddedRect.top + paddedRect.height + 2) && isWithinBounds(paddedRect.left, paddedRect.top + paddedRect.height + 2)) {
|
|
97
|
+
rectX = paddedRect.left;
|
|
98
|
+
rectY = paddedRect.top + paddedRect.height + 2;
|
|
99
|
+
} else if (!checkOverlap(paddedRect.left + paddedRect.width + 2, paddedRect.top) && isWithinBounds(paddedRect.left + paddedRect.width + 2, paddedRect.top)) {
|
|
100
|
+
rectX = paddedRect.left + paddedRect.width + 2;
|
|
101
|
+
rectY = paddedRect.top;
|
|
102
|
+
} else {
|
|
103
|
+
rectX = paddedRect.left;
|
|
104
|
+
rectY = paddedRect.top + 2;
|
|
105
|
+
}
|
|
106
|
+
image.scan(rectX, rectY, rectWidth, rectHeight, (x, y, idx)=>{
|
|
107
|
+
image.bitmap.data[idx + 0] = color.rect >> 24 & 0xff;
|
|
108
|
+
image.bitmap.data[idx + 1] = color.rect >> 16 & 0xff;
|
|
109
|
+
image.bitmap.data[idx + 2] = color.rect >> 8 & 0xff;
|
|
110
|
+
image.bitmap.data[idx + 3] = 0xff & color.rect;
|
|
111
|
+
});
|
|
112
|
+
try {
|
|
113
|
+
cachedFont = cachedFont || await loadFonts();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('Error loading font', error);
|
|
116
|
+
}
|
|
117
|
+
image.print(cachedFont, rectX, rectY, {
|
|
118
|
+
text: indexId.toString(),
|
|
119
|
+
alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
|
|
120
|
+
alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
|
|
121
|
+
}, rectWidth, rectHeight);
|
|
122
|
+
}
|
|
123
|
+
return image;
|
|
124
|
+
};
|
|
125
|
+
const compositeElementInfoImg = async (options)=>{
|
|
126
|
+
node_assert(options.inputImgBase64, 'inputImgBase64 is required');
|
|
127
|
+
let width = 0;
|
|
128
|
+
let height = 0;
|
|
129
|
+
let jimpImage;
|
|
130
|
+
const Jimp = await get_jimp();
|
|
131
|
+
if (options.size) {
|
|
132
|
+
width = options.size.width;
|
|
133
|
+
height = options.size.height;
|
|
134
|
+
}
|
|
135
|
+
if (width && height) {
|
|
136
|
+
const imageBuffer = await bufferFromBase64(options.inputImgBase64);
|
|
137
|
+
jimpImage = await Jimp.read(imageBuffer);
|
|
138
|
+
const imageBitmap = jimpImage.bitmap;
|
|
139
|
+
if (imageBitmap.width !== width || imageBitmap.height !== height) jimpImage.resize(width, height, Jimp.RESIZE_NEAREST_NEIGHBOR);
|
|
140
|
+
} else {
|
|
141
|
+
const info = await imageInfoOfBase64(options.inputImgBase64);
|
|
142
|
+
width = info.width;
|
|
143
|
+
height = info.height;
|
|
144
|
+
jimpImage = info.jimpImage;
|
|
145
|
+
}
|
|
146
|
+
if (!width || !height) throw Error('Image processing failed because width or height is undefined');
|
|
147
|
+
const { elementsPositionInfo, prompt } = options;
|
|
148
|
+
const result = await Promise.resolve(jimpImage).then(async (image)=>{
|
|
149
|
+
const svgOverlay = await createSvgOverlay(elementsPositionInfo, width, height, options.annotationPadding, options.borderThickness, prompt);
|
|
150
|
+
const svgImage = await Jimp.read(svgOverlay);
|
|
151
|
+
const compositeImage = await image.composite(svgImage, 0, 0, {
|
|
152
|
+
mode: Jimp.BLEND_SOURCE_OVER,
|
|
153
|
+
opacitySource: 1,
|
|
154
|
+
opacityDest: 1
|
|
155
|
+
});
|
|
156
|
+
return compositeImage;
|
|
157
|
+
}).then(async (compositeImage)=>{
|
|
158
|
+
compositeImage.quality(90);
|
|
159
|
+
const base64 = await compositeImage.getBase64Async(Jimp.MIME_JPEG);
|
|
160
|
+
return base64;
|
|
161
|
+
}).catch((error)=>{
|
|
162
|
+
throw error;
|
|
163
|
+
});
|
|
164
|
+
return result;
|
|
165
|
+
};
|
|
166
|
+
const processImageElementInfo = async (options)=>{
|
|
167
|
+
const base64Image = options.inputImgBase64.split(';base64,').pop();
|
|
168
|
+
node_assert(base64Image, 'base64Image is undefined');
|
|
169
|
+
const [compositeElementInfoImgBase64, compositeElementInfoImgWithoutTextBase64] = await Promise.all([
|
|
170
|
+
compositeElementInfoImg({
|
|
171
|
+
inputImgBase64: options.inputImgBase64,
|
|
172
|
+
elementsPositionInfo: options.elementsPositionInfo
|
|
173
|
+
}),
|
|
174
|
+
compositeElementInfoImg({
|
|
175
|
+
inputImgBase64: options.inputImgBase64,
|
|
176
|
+
elementsPositionInfo: options.elementsPositionInfoWithoutText
|
|
177
|
+
})
|
|
178
|
+
]);
|
|
179
|
+
return {
|
|
180
|
+
compositeElementInfoImgBase64,
|
|
181
|
+
compositeElementInfoImgWithoutTextBase64
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
export { compositeElementInfoImg, processImageElementInfo };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import get_jimp from "./get-jimp.mjs";
|
|
2
|
+
import { bufferFromBase64 } from "./info.mjs";
|
|
3
|
+
import { saveBase64Image } from "./transform.mjs";
|
|
4
|
+
async function drawBoxOnImage(options) {
|
|
5
|
+
const { inputImgBase64, rect } = options;
|
|
6
|
+
const color = {
|
|
7
|
+
r: 255,
|
|
8
|
+
g: 0,
|
|
9
|
+
b: 0,
|
|
10
|
+
a: 255
|
|
11
|
+
};
|
|
12
|
+
const Jimp = await get_jimp();
|
|
13
|
+
const imageBuffer = await bufferFromBase64(inputImgBase64);
|
|
14
|
+
const image = await Jimp.read(imageBuffer);
|
|
15
|
+
const centerX = rect.x;
|
|
16
|
+
const centerY = rect.y;
|
|
17
|
+
const radius = 5;
|
|
18
|
+
image.scan(Math.floor(centerX - radius), Math.floor(centerY - radius), 2 * radius, 2 * radius, (x, y, idx)=>{
|
|
19
|
+
const distance = Math.sqrt((x - centerX) ** 2 + (y - centerY) ** 2);
|
|
20
|
+
if (distance <= radius) {
|
|
21
|
+
image.bitmap.data[idx + 0] = color.r;
|
|
22
|
+
image.bitmap.data[idx + 1] = color.g;
|
|
23
|
+
image.bitmap.data[idx + 2] = color.b;
|
|
24
|
+
image.bitmap.data[idx + 3] = color.a;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
image.quality(90);
|
|
28
|
+
const resultBase64 = await image.getBase64Async(Jimp.MIME_JPEG);
|
|
29
|
+
return resultBase64;
|
|
30
|
+
}
|
|
31
|
+
async function savePositionImg(options) {
|
|
32
|
+
const { inputImgBase64, rect, outputPath } = options;
|
|
33
|
+
const imgBase64 = await drawBoxOnImage({
|
|
34
|
+
inputImgBase64,
|
|
35
|
+
rect
|
|
36
|
+
});
|
|
37
|
+
await saveBase64Image({
|
|
38
|
+
base64Data: imgBase64,
|
|
39
|
+
outputPath
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export { drawBoxOnImage, savePositionImg };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import jimp from "jimp";
|
|
2
|
+
import { ifInBrowser, ifInWorker } from "../utils.mjs";
|
|
3
|
+
async function getJimp() {
|
|
4
|
+
if (ifInBrowser || ifInWorker) {
|
|
5
|
+
await import("jimp/browser/lib/jimp.js");
|
|
6
|
+
return ('undefined' != typeof window ? window : self).Jimp;
|
|
7
|
+
}
|
|
8
|
+
return jimp;
|
|
9
|
+
}
|
|
10
|
+
export { getJimp as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ifInBrowser, ifInNode, ifInWorker } from "../utils.mjs";
|
|
2
|
+
let photonModule = null;
|
|
3
|
+
let isInitialized = false;
|
|
4
|
+
async function getPhoton() {
|
|
5
|
+
if (photonModule && isInitialized) return photonModule;
|
|
6
|
+
try {
|
|
7
|
+
if (ifInBrowser || ifInWorker) {
|
|
8
|
+
const photon = await import("@silvia-odwyer/photon");
|
|
9
|
+
if ('function' == typeof photon.default) await photon.default();
|
|
10
|
+
photonModule = photon;
|
|
11
|
+
} else if (ifInNode) photonModule = await import("@silvia-odwyer/photon-node");
|
|
12
|
+
if (!photonModule.PhotonImage || !photonModule.PhotonImage.new_from_byteslice) throw new Error('PhotonImage.new_from_byteslice is not available');
|
|
13
|
+
isInitialized = true;
|
|
14
|
+
return photonModule;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new Error(`Failed to load photon module: ${error instanceof Error ? error.message : String(error)}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export { getPhoton as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ifInNode } from "../utils.mjs";
|
|
2
|
+
async function getSharp() {
|
|
3
|
+
if (!ifInNode) throw new Error('Sharp is only available in Node.js environment');
|
|
4
|
+
try {
|
|
5
|
+
const sharp = await import("sharp");
|
|
6
|
+
return sharp.default;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
throw new Error(`Failed to load sharp module: ${error instanceof Error ? error.message : String(error)}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export { getSharp as default };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { bufferFromBase64, imageInfo, imageInfoOfBase64, isValidPNGImageBuffer } from "./info.mjs";
|
|
2
|
+
import { createImgBase64ByFormat, cropByRect, httpImg2Base64, jimpFromBase64, jimpToBase64, localImg2Base64, paddingToMatchBlock, paddingToMatchBlockByBase64, parseBase64, preProcessImageUrl, resizeAndConvertImgBuffer, resizeImgBase64, saveBase64Image, zoomForGPT4o } from "./transform.mjs";
|
|
3
|
+
import { compositeElementInfoImg, processImageElementInfo } from "./box-select.mjs";
|
|
4
|
+
import { drawBoxOnImage, savePositionImg } from "./draw-box.mjs";
|
|
5
|
+
export { bufferFromBase64, compositeElementInfoImg, createImgBase64ByFormat, cropByRect, drawBoxOnImage, httpImg2Base64, imageInfo, imageInfoOfBase64, isValidPNGImageBuffer, jimpFromBase64, jimpToBase64, localImg2Base64, paddingToMatchBlock, paddingToMatchBlockByBase64, parseBase64, preProcessImageUrl, processImageElementInfo, resizeAndConvertImgBuffer, resizeImgBase64, saveBase64Image, savePositionImg, zoomForGPT4o };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import node_assert from "node:assert";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import get_jimp from "./get-jimp.mjs";
|
|
4
|
+
async function imageInfo(image) {
|
|
5
|
+
const Jimp = await get_jimp();
|
|
6
|
+
let jimpImage;
|
|
7
|
+
if ('string' == typeof image) jimpImage = await Jimp.read(image);
|
|
8
|
+
else if (Buffer.isBuffer(image)) jimpImage = await Jimp.read(image);
|
|
9
|
+
else if (image instanceof Jimp) jimpImage = image;
|
|
10
|
+
else throw new Error('Invalid image input: must be a string path or a Buffer');
|
|
11
|
+
const { width, height } = jimpImage.bitmap;
|
|
12
|
+
node_assert(width && height, `Invalid image: ${'string' == typeof image ? image : 'Buffer'}`);
|
|
13
|
+
return {
|
|
14
|
+
width,
|
|
15
|
+
height,
|
|
16
|
+
jimpImage
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function imageInfoOfBase64(imageBase64) {
|
|
20
|
+
const buffer = await bufferFromBase64(imageBase64);
|
|
21
|
+
return imageInfo(buffer);
|
|
22
|
+
}
|
|
23
|
+
async function bufferFromBase64(imageBase64) {
|
|
24
|
+
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, '');
|
|
25
|
+
return Buffer.from(base64Data, 'base64');
|
|
26
|
+
}
|
|
27
|
+
function isValidPNGImageBuffer(buffer) {
|
|
28
|
+
if (!buffer || buffer.length < 8) return false;
|
|
29
|
+
const isPNG = 0x89 === buffer[0] && 0x50 === buffer[1] && 0x4e === buffer[2] && 0x47 === buffer[3];
|
|
30
|
+
return isPNG;
|
|
31
|
+
}
|
|
32
|
+
export { bufferFromBase64, imageInfo, imageInfoOfBase64, isValidPNGImageBuffer };
|