label-studio-converter 1.0.0
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/LICENSE.md +33 -0
- package/README.md +351 -0
- package/dist/bash-complete.cjs +1296 -0
- package/dist/bash-complete.cjs.map +1 -0
- package/dist/bash-complete.d.cts +1 -0
- package/dist/bash-complete.d.ts +1 -0
- package/dist/bash-complete.js +1279 -0
- package/dist/bash-complete.js.map +1 -0
- package/dist/cli.cjs +1281 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1264 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +418 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +309 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +377 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,1296 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
// node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
|
|
34
|
+
var init_cjs_shims = __esm({
|
|
35
|
+
"node_modules/.pnpm/tsup@8.5.1_jiti@2.4.2_postcss@8.5.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js"() {
|
|
36
|
+
"use strict";
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// src/constants.ts
|
|
41
|
+
var OUTPUT_BASE_DIR, DEFAULT_LABEL_NAME, DEFAULT_LABEL_STUDIO_FULL_JSON, DEFAULT_CREATE_FILE_PER_IMAGE, DEFAULT_CREATE_FILE_LIST_FOR_SERVING, DEFAULT_FILE_LIST_NAME, DEFAULT_BASE_SERVER_URL, DEFAULT_PPOCR_FILE_NAME, SORT_VERTICAL_NONE, SORT_VERTICAL_TOP_BOTTOM, SORT_VERTICAL_BOTTOM_TOP, DEFAULT_SORT_VERTICAL, SORT_HORIZONTAL_NONE, SORT_HORIZONTAL_LTR, SORT_HORIZONTAL_RTL, DEFAULT_SORT_HORIZONTAL;
|
|
42
|
+
var init_constants = __esm({
|
|
43
|
+
"src/constants.ts"() {
|
|
44
|
+
"use strict";
|
|
45
|
+
init_cjs_shims();
|
|
46
|
+
OUTPUT_BASE_DIR = "./output";
|
|
47
|
+
DEFAULT_LABEL_NAME = "Text";
|
|
48
|
+
DEFAULT_LABEL_STUDIO_FULL_JSON = true;
|
|
49
|
+
DEFAULT_CREATE_FILE_PER_IMAGE = false;
|
|
50
|
+
DEFAULT_CREATE_FILE_LIST_FOR_SERVING = true;
|
|
51
|
+
DEFAULT_FILE_LIST_NAME = "files.txt";
|
|
52
|
+
DEFAULT_BASE_SERVER_URL = "http://localhost:8081";
|
|
53
|
+
DEFAULT_PPOCR_FILE_NAME = "Label.txt";
|
|
54
|
+
SORT_VERTICAL_NONE = "none";
|
|
55
|
+
SORT_VERTICAL_TOP_BOTTOM = "top-bottom";
|
|
56
|
+
SORT_VERTICAL_BOTTOM_TOP = "bottom-top";
|
|
57
|
+
DEFAULT_SORT_VERTICAL = SORT_VERTICAL_NONE;
|
|
58
|
+
SORT_HORIZONTAL_NONE = "none";
|
|
59
|
+
SORT_HORIZONTAL_LTR = "ltr";
|
|
60
|
+
SORT_HORIZONTAL_RTL = "rtl";
|
|
61
|
+
DEFAULT_SORT_HORIZONTAL = SORT_HORIZONTAL_NONE;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// src/lib/ppocr-label.ts
|
|
66
|
+
var import_node_crypto, import_node_fs, import_node_path, import_image_size, ppocrToLabelStudio, ppocrToFullLabelStudio, ppocrToMinLabelStudio;
|
|
67
|
+
var init_ppocr_label = __esm({
|
|
68
|
+
"src/lib/ppocr-label.ts"() {
|
|
69
|
+
"use strict";
|
|
70
|
+
init_cjs_shims();
|
|
71
|
+
import_node_crypto = require("crypto");
|
|
72
|
+
import_node_fs = require("fs");
|
|
73
|
+
import_node_path = require("path");
|
|
74
|
+
import_image_size = __toESM(require("image-size"), 1);
|
|
75
|
+
init_constants();
|
|
76
|
+
ppocrToLabelStudio = async (data, options) => {
|
|
77
|
+
const {
|
|
78
|
+
imagePath,
|
|
79
|
+
baseServerUrl,
|
|
80
|
+
inputDir,
|
|
81
|
+
toFullJson = true,
|
|
82
|
+
taskId = 1,
|
|
83
|
+
labelName = DEFAULT_LABEL_NAME
|
|
84
|
+
} = options || {};
|
|
85
|
+
if (toFullJson) {
|
|
86
|
+
return ppocrToFullLabelStudio(
|
|
87
|
+
data,
|
|
88
|
+
imagePath,
|
|
89
|
+
baseServerUrl,
|
|
90
|
+
inputDir,
|
|
91
|
+
taskId,
|
|
92
|
+
labelName
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
return ppocrToMinLabelStudio(
|
|
96
|
+
data,
|
|
97
|
+
imagePath,
|
|
98
|
+
baseServerUrl,
|
|
99
|
+
inputDir,
|
|
100
|
+
labelName
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
ppocrToFullLabelStudio = (data, imagePath, baseServerUrl, inputDir, taskId = 1, labelName = DEFAULT_LABEL_NAME) => {
|
|
105
|
+
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
106
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
107
|
+
let original_width = 1920;
|
|
108
|
+
let original_height = 1080;
|
|
109
|
+
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
110
|
+
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
111
|
+
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
112
|
+
}
|
|
113
|
+
const buffer = (0, import_node_fs.readFileSync)(resolvedImagePath);
|
|
114
|
+
const dimensions = (0, import_image_size.default)(buffer);
|
|
115
|
+
if (!dimensions.width || !dimensions.height) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Failed to read image dimensions from: ${resolvedImagePath}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
original_width = dimensions.width;
|
|
121
|
+
original_height = dimensions.height;
|
|
122
|
+
const fileName = imagePath.split("/").pop() || imagePath;
|
|
123
|
+
const result = [
|
|
124
|
+
{
|
|
125
|
+
id: taskId,
|
|
126
|
+
annotations: [
|
|
127
|
+
{
|
|
128
|
+
id: taskId,
|
|
129
|
+
completed_by: 1,
|
|
130
|
+
result: data.map((item) => {
|
|
131
|
+
const { points } = item;
|
|
132
|
+
const annotationId = (0, import_node_crypto.randomUUID)().slice(0, 10);
|
|
133
|
+
const polygonPoints = points.map(([x, y]) => [
|
|
134
|
+
(x ?? 0) / original_width * 100,
|
|
135
|
+
(y ?? 0) / original_height * 100
|
|
136
|
+
]);
|
|
137
|
+
return [
|
|
138
|
+
// 1. Polygon geometry only
|
|
139
|
+
{
|
|
140
|
+
original_width,
|
|
141
|
+
original_height,
|
|
142
|
+
image_rotation: 0,
|
|
143
|
+
value: {
|
|
144
|
+
points: polygonPoints,
|
|
145
|
+
closed: true
|
|
146
|
+
},
|
|
147
|
+
id: annotationId,
|
|
148
|
+
from_name: "poly",
|
|
149
|
+
to_name: "image",
|
|
150
|
+
type: "polygon",
|
|
151
|
+
origin: "manual"
|
|
152
|
+
},
|
|
153
|
+
// 2. Labels with polygon geometry
|
|
154
|
+
{
|
|
155
|
+
original_width,
|
|
156
|
+
original_height,
|
|
157
|
+
image_rotation: 0,
|
|
158
|
+
value: {
|
|
159
|
+
points: polygonPoints,
|
|
160
|
+
closed: true,
|
|
161
|
+
labels: [labelName]
|
|
162
|
+
},
|
|
163
|
+
id: annotationId,
|
|
164
|
+
from_name: "label",
|
|
165
|
+
to_name: "image",
|
|
166
|
+
type: "labels",
|
|
167
|
+
origin: "manual"
|
|
168
|
+
},
|
|
169
|
+
// 3. Textarea with polygon geometry and text
|
|
170
|
+
{
|
|
171
|
+
original_width,
|
|
172
|
+
original_height,
|
|
173
|
+
image_rotation: 0,
|
|
174
|
+
value: {
|
|
175
|
+
points: polygonPoints,
|
|
176
|
+
closed: true,
|
|
177
|
+
text: [item.transcription]
|
|
178
|
+
},
|
|
179
|
+
id: annotationId,
|
|
180
|
+
from_name: "transcription",
|
|
181
|
+
to_name: "image",
|
|
182
|
+
type: "textarea",
|
|
183
|
+
origin: "manual"
|
|
184
|
+
}
|
|
185
|
+
];
|
|
186
|
+
}).flat(),
|
|
187
|
+
was_cancelled: false,
|
|
188
|
+
ground_truth: false,
|
|
189
|
+
created_at: now,
|
|
190
|
+
updated_at: now,
|
|
191
|
+
draft_created_at: now,
|
|
192
|
+
lead_time: 0,
|
|
193
|
+
prediction: {},
|
|
194
|
+
result_count: data.length * 3,
|
|
195
|
+
unique_id: (0, import_node_crypto.randomUUID)(),
|
|
196
|
+
import_id: null,
|
|
197
|
+
last_action: null,
|
|
198
|
+
bulk_created: false,
|
|
199
|
+
task: taskId,
|
|
200
|
+
project: 1,
|
|
201
|
+
updated_by: 1,
|
|
202
|
+
parent_prediction: null,
|
|
203
|
+
parent_annotation: null,
|
|
204
|
+
last_created_by: null
|
|
205
|
+
}
|
|
206
|
+
],
|
|
207
|
+
file_upload: fileName,
|
|
208
|
+
drafts: [],
|
|
209
|
+
predictions: [],
|
|
210
|
+
data: { ocr: `${newBaseServerUrl}${imagePath}` },
|
|
211
|
+
meta: {},
|
|
212
|
+
created_at: now,
|
|
213
|
+
updated_at: now,
|
|
214
|
+
allow_skip: false,
|
|
215
|
+
inner_id: taskId,
|
|
216
|
+
total_annotations: 1,
|
|
217
|
+
cancelled_annotations: 0,
|
|
218
|
+
total_predictions: 0,
|
|
219
|
+
comment_count: 0,
|
|
220
|
+
unresolved_comment_count: 0,
|
|
221
|
+
last_comment_updated_at: null,
|
|
222
|
+
project: 1,
|
|
223
|
+
updated_by: 1,
|
|
224
|
+
comment_authors: []
|
|
225
|
+
}
|
|
226
|
+
];
|
|
227
|
+
return result;
|
|
228
|
+
};
|
|
229
|
+
ppocrToMinLabelStudio = (data, imagePath, baseServerUrl, inputDir, labelName = "text") => {
|
|
230
|
+
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
231
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
232
|
+
let original_width = 1920;
|
|
233
|
+
let original_height = 1080;
|
|
234
|
+
const resolvedImagePath = inputDir ? (0, import_node_path.join)(inputDir, imagePath) : imagePath;
|
|
235
|
+
if (!(0, import_node_fs.existsSync)(resolvedImagePath)) {
|
|
236
|
+
throw new Error(`Image file not found: ${resolvedImagePath}`);
|
|
237
|
+
}
|
|
238
|
+
const buffer = (0, import_node_fs.readFileSync)(resolvedImagePath);
|
|
239
|
+
const dimensions = (0, import_image_size.default)(buffer);
|
|
240
|
+
if (!dimensions.width || !dimensions.height) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
`Failed to read image dimensions from: ${resolvedImagePath}`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
original_width = dimensions.width;
|
|
246
|
+
original_height = dimensions.height;
|
|
247
|
+
return data.map((item, index) => {
|
|
248
|
+
const { points } = item;
|
|
249
|
+
let minX = Infinity;
|
|
250
|
+
let minY = Infinity;
|
|
251
|
+
let maxX = -Infinity;
|
|
252
|
+
let maxY = -Infinity;
|
|
253
|
+
for (const point of points) {
|
|
254
|
+
const [x, y] = point;
|
|
255
|
+
if (x !== void 0 && y !== void 0) {
|
|
256
|
+
minX = Math.min(minX, x);
|
|
257
|
+
minY = Math.min(minY, y);
|
|
258
|
+
maxX = Math.max(maxX, x);
|
|
259
|
+
maxY = Math.max(maxY, y);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const width = maxX - minX;
|
|
263
|
+
const height = maxY - minY;
|
|
264
|
+
return {
|
|
265
|
+
ocr: encodeURI(`${newBaseServerUrl}${imagePath}`),
|
|
266
|
+
id: index + 1,
|
|
267
|
+
bbox: [
|
|
268
|
+
{
|
|
269
|
+
x: minX,
|
|
270
|
+
y: minY,
|
|
271
|
+
width,
|
|
272
|
+
height,
|
|
273
|
+
rotation: 0,
|
|
274
|
+
original_width,
|
|
275
|
+
original_height
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
label: [
|
|
279
|
+
{
|
|
280
|
+
points,
|
|
281
|
+
closed: true,
|
|
282
|
+
labels: [labelName],
|
|
283
|
+
original_width,
|
|
284
|
+
original_height
|
|
285
|
+
}
|
|
286
|
+
],
|
|
287
|
+
transcription: [item.transcription],
|
|
288
|
+
poly: [
|
|
289
|
+
{
|
|
290
|
+
points,
|
|
291
|
+
closed: true,
|
|
292
|
+
original_width,
|
|
293
|
+
original_height
|
|
294
|
+
}
|
|
295
|
+
],
|
|
296
|
+
annotator: 1,
|
|
297
|
+
annotation_id: index + 1,
|
|
298
|
+
created_at: now,
|
|
299
|
+
updated_at: now,
|
|
300
|
+
lead_time: 0
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// src/lib/schema.ts
|
|
308
|
+
var import_zod, FullOCRLabelStudioSchema, MinOCRLabelStudioSchema, PPOCRLabelSchema;
|
|
309
|
+
var init_schema = __esm({
|
|
310
|
+
"src/lib/schema.ts"() {
|
|
311
|
+
"use strict";
|
|
312
|
+
init_cjs_shims();
|
|
313
|
+
import_zod = __toESM(require("zod"), 1);
|
|
314
|
+
FullOCRLabelStudioSchema = import_zod.default.array(
|
|
315
|
+
import_zod.default.object({
|
|
316
|
+
id: import_zod.default.number(),
|
|
317
|
+
annotations: import_zod.default.array(
|
|
318
|
+
import_zod.default.object({
|
|
319
|
+
id: import_zod.default.number(),
|
|
320
|
+
completed_by: import_zod.default.number(),
|
|
321
|
+
result: import_zod.default.array(
|
|
322
|
+
import_zod.default.union([
|
|
323
|
+
import_zod.default.object({
|
|
324
|
+
original_width: import_zod.default.number(),
|
|
325
|
+
original_height: import_zod.default.number(),
|
|
326
|
+
image_rotation: import_zod.default.number(),
|
|
327
|
+
value: import_zod.default.object({
|
|
328
|
+
x: import_zod.default.number(),
|
|
329
|
+
y: import_zod.default.number(),
|
|
330
|
+
width: import_zod.default.number(),
|
|
331
|
+
height: import_zod.default.number(),
|
|
332
|
+
rotation: import_zod.default.number()
|
|
333
|
+
}),
|
|
334
|
+
id: import_zod.default.string(),
|
|
335
|
+
from_name: import_zod.default.string(),
|
|
336
|
+
to_name: import_zod.default.string(),
|
|
337
|
+
type: import_zod.default.string(),
|
|
338
|
+
origin: import_zod.default.string()
|
|
339
|
+
}),
|
|
340
|
+
import_zod.default.object({
|
|
341
|
+
original_width: import_zod.default.number(),
|
|
342
|
+
original_height: import_zod.default.number(),
|
|
343
|
+
image_rotation: import_zod.default.number(),
|
|
344
|
+
value: import_zod.default.object({
|
|
345
|
+
x: import_zod.default.number(),
|
|
346
|
+
y: import_zod.default.number(),
|
|
347
|
+
width: import_zod.default.number(),
|
|
348
|
+
height: import_zod.default.number(),
|
|
349
|
+
rotation: import_zod.default.number(),
|
|
350
|
+
labels: import_zod.default.array(import_zod.default.string())
|
|
351
|
+
}),
|
|
352
|
+
id: import_zod.default.string(),
|
|
353
|
+
from_name: import_zod.default.string(),
|
|
354
|
+
to_name: import_zod.default.string(),
|
|
355
|
+
type: import_zod.default.string(),
|
|
356
|
+
origin: import_zod.default.string()
|
|
357
|
+
}),
|
|
358
|
+
import_zod.default.object({
|
|
359
|
+
original_width: import_zod.default.number(),
|
|
360
|
+
original_height: import_zod.default.number(),
|
|
361
|
+
image_rotation: import_zod.default.number(),
|
|
362
|
+
value: import_zod.default.object({
|
|
363
|
+
x: import_zod.default.number(),
|
|
364
|
+
y: import_zod.default.number(),
|
|
365
|
+
width: import_zod.default.number(),
|
|
366
|
+
height: import_zod.default.number(),
|
|
367
|
+
rotation: import_zod.default.number(),
|
|
368
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
369
|
+
}),
|
|
370
|
+
id: import_zod.default.string(),
|
|
371
|
+
from_name: import_zod.default.string(),
|
|
372
|
+
to_name: import_zod.default.string(),
|
|
373
|
+
type: import_zod.default.string(),
|
|
374
|
+
origin: import_zod.default.string()
|
|
375
|
+
}),
|
|
376
|
+
import_zod.default.object({
|
|
377
|
+
original_width: import_zod.default.number(),
|
|
378
|
+
original_height: import_zod.default.number(),
|
|
379
|
+
image_rotation: import_zod.default.number(),
|
|
380
|
+
value: import_zod.default.object({
|
|
381
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
382
|
+
closed: import_zod.default.boolean()
|
|
383
|
+
}),
|
|
384
|
+
id: import_zod.default.string(),
|
|
385
|
+
from_name: import_zod.default.string(),
|
|
386
|
+
to_name: import_zod.default.string(),
|
|
387
|
+
type: import_zod.default.string(),
|
|
388
|
+
origin: import_zod.default.string()
|
|
389
|
+
}),
|
|
390
|
+
import_zod.default.object({
|
|
391
|
+
original_width: import_zod.default.number(),
|
|
392
|
+
original_height: import_zod.default.number(),
|
|
393
|
+
image_rotation: import_zod.default.number(),
|
|
394
|
+
value: import_zod.default.object({
|
|
395
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
396
|
+
closed: import_zod.default.boolean(),
|
|
397
|
+
labels: import_zod.default.array(import_zod.default.string())
|
|
398
|
+
}),
|
|
399
|
+
id: import_zod.default.string(),
|
|
400
|
+
from_name: import_zod.default.string(),
|
|
401
|
+
to_name: import_zod.default.string(),
|
|
402
|
+
type: import_zod.default.string(),
|
|
403
|
+
origin: import_zod.default.string()
|
|
404
|
+
}),
|
|
405
|
+
import_zod.default.object({
|
|
406
|
+
original_width: import_zod.default.number(),
|
|
407
|
+
original_height: import_zod.default.number(),
|
|
408
|
+
image_rotation: import_zod.default.number(),
|
|
409
|
+
value: import_zod.default.object({
|
|
410
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
411
|
+
closed: import_zod.default.boolean(),
|
|
412
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
413
|
+
}),
|
|
414
|
+
id: import_zod.default.string(),
|
|
415
|
+
from_name: import_zod.default.string(),
|
|
416
|
+
to_name: import_zod.default.string(),
|
|
417
|
+
type: import_zod.default.string(),
|
|
418
|
+
origin: import_zod.default.string()
|
|
419
|
+
})
|
|
420
|
+
])
|
|
421
|
+
),
|
|
422
|
+
was_cancelled: import_zod.default.boolean(),
|
|
423
|
+
ground_truth: import_zod.default.boolean(),
|
|
424
|
+
created_at: import_zod.default.string(),
|
|
425
|
+
updated_at: import_zod.default.string(),
|
|
426
|
+
draft_created_at: import_zod.default.string(),
|
|
427
|
+
lead_time: import_zod.default.number(),
|
|
428
|
+
prediction: import_zod.default.object({}),
|
|
429
|
+
result_count: import_zod.default.number(),
|
|
430
|
+
unique_id: import_zod.default.string(),
|
|
431
|
+
import_id: import_zod.default.null(),
|
|
432
|
+
last_action: import_zod.default.null(),
|
|
433
|
+
bulk_created: import_zod.default.boolean(),
|
|
434
|
+
task: import_zod.default.number(),
|
|
435
|
+
project: import_zod.default.number(),
|
|
436
|
+
updated_by: import_zod.default.number(),
|
|
437
|
+
parent_prediction: import_zod.default.null(),
|
|
438
|
+
parent_annotation: import_zod.default.null(),
|
|
439
|
+
last_created_by: import_zod.default.null()
|
|
440
|
+
})
|
|
441
|
+
),
|
|
442
|
+
file_upload: import_zod.default.string(),
|
|
443
|
+
drafts: import_zod.default.array(
|
|
444
|
+
import_zod.default.object({
|
|
445
|
+
id: import_zod.default.number(),
|
|
446
|
+
user: import_zod.default.string(),
|
|
447
|
+
created_username: import_zod.default.string(),
|
|
448
|
+
created_ago: import_zod.default.string(),
|
|
449
|
+
result: import_zod.default.array(
|
|
450
|
+
import_zod.default.union([
|
|
451
|
+
import_zod.default.object({
|
|
452
|
+
original_width: import_zod.default.number(),
|
|
453
|
+
original_height: import_zod.default.number(),
|
|
454
|
+
image_rotation: import_zod.default.number(),
|
|
455
|
+
value: import_zod.default.object({
|
|
456
|
+
x: import_zod.default.number(),
|
|
457
|
+
y: import_zod.default.number(),
|
|
458
|
+
width: import_zod.default.number(),
|
|
459
|
+
height: import_zod.default.number(),
|
|
460
|
+
rotation: import_zod.default.number()
|
|
461
|
+
}),
|
|
462
|
+
id: import_zod.default.string(),
|
|
463
|
+
from_name: import_zod.default.string(),
|
|
464
|
+
to_name: import_zod.default.string(),
|
|
465
|
+
type: import_zod.default.string(),
|
|
466
|
+
origin: import_zod.default.string()
|
|
467
|
+
}),
|
|
468
|
+
import_zod.default.object({
|
|
469
|
+
original_width: import_zod.default.number(),
|
|
470
|
+
original_height: import_zod.default.number(),
|
|
471
|
+
image_rotation: import_zod.default.number(),
|
|
472
|
+
value: import_zod.default.object({
|
|
473
|
+
x: import_zod.default.number(),
|
|
474
|
+
y: import_zod.default.number(),
|
|
475
|
+
width: import_zod.default.number(),
|
|
476
|
+
height: import_zod.default.number(),
|
|
477
|
+
rotation: import_zod.default.number(),
|
|
478
|
+
labels: import_zod.default.array(import_zod.default.string())
|
|
479
|
+
}),
|
|
480
|
+
id: import_zod.default.string(),
|
|
481
|
+
from_name: import_zod.default.string(),
|
|
482
|
+
to_name: import_zod.default.string(),
|
|
483
|
+
type: import_zod.default.string(),
|
|
484
|
+
origin: import_zod.default.string()
|
|
485
|
+
}),
|
|
486
|
+
import_zod.default.object({
|
|
487
|
+
original_width: import_zod.default.number(),
|
|
488
|
+
original_height: import_zod.default.number(),
|
|
489
|
+
image_rotation: import_zod.default.number(),
|
|
490
|
+
value: import_zod.default.object({
|
|
491
|
+
x: import_zod.default.number(),
|
|
492
|
+
y: import_zod.default.number(),
|
|
493
|
+
width: import_zod.default.number(),
|
|
494
|
+
height: import_zod.default.number(),
|
|
495
|
+
rotation: import_zod.default.number(),
|
|
496
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
497
|
+
}),
|
|
498
|
+
id: import_zod.default.string(),
|
|
499
|
+
from_name: import_zod.default.string(),
|
|
500
|
+
to_name: import_zod.default.string(),
|
|
501
|
+
type: import_zod.default.string(),
|
|
502
|
+
origin: import_zod.default.string()
|
|
503
|
+
}),
|
|
504
|
+
import_zod.default.object({
|
|
505
|
+
original_width: import_zod.default.number(),
|
|
506
|
+
original_height: import_zod.default.number(),
|
|
507
|
+
image_rotation: import_zod.default.number(),
|
|
508
|
+
value: import_zod.default.object({
|
|
509
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
510
|
+
closed: import_zod.default.boolean()
|
|
511
|
+
}),
|
|
512
|
+
id: import_zod.default.string(),
|
|
513
|
+
from_name: import_zod.default.string(),
|
|
514
|
+
to_name: import_zod.default.string(),
|
|
515
|
+
type: import_zod.default.string(),
|
|
516
|
+
origin: import_zod.default.string()
|
|
517
|
+
}),
|
|
518
|
+
import_zod.default.object({
|
|
519
|
+
original_width: import_zod.default.number(),
|
|
520
|
+
original_height: import_zod.default.number(),
|
|
521
|
+
image_rotation: import_zod.default.number(),
|
|
522
|
+
value: import_zod.default.object({
|
|
523
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
524
|
+
closed: import_zod.default.boolean(),
|
|
525
|
+
labels: import_zod.default.array(import_zod.default.string())
|
|
526
|
+
}),
|
|
527
|
+
id: import_zod.default.string(),
|
|
528
|
+
from_name: import_zod.default.string(),
|
|
529
|
+
to_name: import_zod.default.string(),
|
|
530
|
+
type: import_zod.default.string(),
|
|
531
|
+
origin: import_zod.default.string()
|
|
532
|
+
}),
|
|
533
|
+
import_zod.default.object({
|
|
534
|
+
original_width: import_zod.default.number(),
|
|
535
|
+
original_height: import_zod.default.number(),
|
|
536
|
+
image_rotation: import_zod.default.number(),
|
|
537
|
+
value: import_zod.default.object({
|
|
538
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
539
|
+
closed: import_zod.default.boolean(),
|
|
540
|
+
text: import_zod.default.array(import_zod.default.string())
|
|
541
|
+
}),
|
|
542
|
+
id: import_zod.default.string(),
|
|
543
|
+
from_name: import_zod.default.string(),
|
|
544
|
+
to_name: import_zod.default.string(),
|
|
545
|
+
type: import_zod.default.string(),
|
|
546
|
+
origin: import_zod.default.string()
|
|
547
|
+
})
|
|
548
|
+
])
|
|
549
|
+
),
|
|
550
|
+
lead_time: import_zod.default.number(),
|
|
551
|
+
was_postponed: import_zod.default.boolean(),
|
|
552
|
+
import_id: import_zod.default.null(),
|
|
553
|
+
created_at: import_zod.default.string(),
|
|
554
|
+
updated_at: import_zod.default.string(),
|
|
555
|
+
task: import_zod.default.number(),
|
|
556
|
+
annotation: import_zod.default.number()
|
|
557
|
+
})
|
|
558
|
+
),
|
|
559
|
+
predictions: import_zod.default.array(import_zod.default.unknown()),
|
|
560
|
+
data: import_zod.default.object({ ocr: import_zod.default.string() }),
|
|
561
|
+
meta: import_zod.default.object({}),
|
|
562
|
+
created_at: import_zod.default.string(),
|
|
563
|
+
updated_at: import_zod.default.string(),
|
|
564
|
+
allow_skip: import_zod.default.boolean(),
|
|
565
|
+
inner_id: import_zod.default.number(),
|
|
566
|
+
total_annotations: import_zod.default.number(),
|
|
567
|
+
cancelled_annotations: import_zod.default.number(),
|
|
568
|
+
total_predictions: import_zod.default.number(),
|
|
569
|
+
comment_count: import_zod.default.number(),
|
|
570
|
+
unresolved_comment_count: import_zod.default.number(),
|
|
571
|
+
last_comment_updated_at: import_zod.default.null(),
|
|
572
|
+
project: import_zod.default.number(),
|
|
573
|
+
updated_by: import_zod.default.number(),
|
|
574
|
+
comment_authors: import_zod.default.array(import_zod.default.unknown())
|
|
575
|
+
})
|
|
576
|
+
);
|
|
577
|
+
MinOCRLabelStudioSchema = import_zod.default.array(
|
|
578
|
+
import_zod.default.object({
|
|
579
|
+
ocr: import_zod.default.string(),
|
|
580
|
+
id: import_zod.default.number(),
|
|
581
|
+
bbox: import_zod.default.array(
|
|
582
|
+
import_zod.default.object({
|
|
583
|
+
x: import_zod.default.number(),
|
|
584
|
+
y: import_zod.default.number(),
|
|
585
|
+
width: import_zod.default.number(),
|
|
586
|
+
height: import_zod.default.number(),
|
|
587
|
+
rotation: import_zod.default.number(),
|
|
588
|
+
original_width: import_zod.default.number(),
|
|
589
|
+
original_height: import_zod.default.number()
|
|
590
|
+
})
|
|
591
|
+
),
|
|
592
|
+
label: import_zod.default.array(
|
|
593
|
+
import_zod.default.union([
|
|
594
|
+
import_zod.default.object({
|
|
595
|
+
x: import_zod.default.number(),
|
|
596
|
+
y: import_zod.default.number(),
|
|
597
|
+
width: import_zod.default.number(),
|
|
598
|
+
height: import_zod.default.number(),
|
|
599
|
+
rotation: import_zod.default.number(),
|
|
600
|
+
labels: import_zod.default.array(import_zod.default.string()),
|
|
601
|
+
original_width: import_zod.default.number(),
|
|
602
|
+
original_height: import_zod.default.number()
|
|
603
|
+
}),
|
|
604
|
+
import_zod.default.object({
|
|
605
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
606
|
+
closed: import_zod.default.boolean(),
|
|
607
|
+
labels: import_zod.default.array(import_zod.default.string()),
|
|
608
|
+
original_width: import_zod.default.number(),
|
|
609
|
+
original_height: import_zod.default.number()
|
|
610
|
+
})
|
|
611
|
+
])
|
|
612
|
+
),
|
|
613
|
+
transcription: import_zod.default.array(import_zod.default.string()),
|
|
614
|
+
poly: import_zod.default.array(
|
|
615
|
+
import_zod.default.object({
|
|
616
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
617
|
+
closed: import_zod.default.boolean(),
|
|
618
|
+
original_width: import_zod.default.number(),
|
|
619
|
+
original_height: import_zod.default.number()
|
|
620
|
+
})
|
|
621
|
+
),
|
|
622
|
+
annotator: import_zod.default.number(),
|
|
623
|
+
annotation_id: import_zod.default.number(),
|
|
624
|
+
created_at: import_zod.default.string(),
|
|
625
|
+
updated_at: import_zod.default.string(),
|
|
626
|
+
lead_time: import_zod.default.number()
|
|
627
|
+
})
|
|
628
|
+
);
|
|
629
|
+
PPOCRLabelSchema = import_zod.default.array(
|
|
630
|
+
import_zod.default.object({
|
|
631
|
+
transcription: import_zod.default.string(),
|
|
632
|
+
points: import_zod.default.array(import_zod.default.array(import_zod.default.number())),
|
|
633
|
+
dt_score: import_zod.default.number()
|
|
634
|
+
})
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// src/lib/sort.ts
|
|
640
|
+
function getBoundingBoxCenter(points) {
|
|
641
|
+
let minX = Infinity;
|
|
642
|
+
let minY = Infinity;
|
|
643
|
+
let maxX = -Infinity;
|
|
644
|
+
let maxY = -Infinity;
|
|
645
|
+
for (const [x, y] of points) {
|
|
646
|
+
if (x !== void 0 && y !== void 0) {
|
|
647
|
+
minX = Math.min(minX, x);
|
|
648
|
+
minY = Math.min(minY, y);
|
|
649
|
+
maxX = Math.max(maxX, x);
|
|
650
|
+
maxY = Math.max(maxY, y);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return {
|
|
654
|
+
x: (minX + maxX) / 2,
|
|
655
|
+
y: (minY + maxY) / 2,
|
|
656
|
+
width: maxX - minX,
|
|
657
|
+
height: maxY - minY
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
function sortBoundingBoxes(annotations, verticalSort, horizontalSort) {
|
|
661
|
+
if (verticalSort === SORT_VERTICAL_NONE && horizontalSort === SORT_HORIZONTAL_NONE) {
|
|
662
|
+
return annotations;
|
|
663
|
+
}
|
|
664
|
+
const sorted = [...annotations];
|
|
665
|
+
const isVerticalText = sorted.length > 0 && (() => {
|
|
666
|
+
const verticalCount = sorted.filter((ann) => {
|
|
667
|
+
const center = getBoundingBoxCenter(ann.points);
|
|
668
|
+
return center.height > center.width * 1.5;
|
|
669
|
+
}).length;
|
|
670
|
+
return verticalCount > sorted.length / 2;
|
|
671
|
+
})();
|
|
672
|
+
if (horizontalSort === SORT_HORIZONTAL_RTL && verticalSort !== SORT_VERTICAL_NONE && isVerticalText) {
|
|
673
|
+
const annotationsWithCenters = sorted.map((ann) => ({
|
|
674
|
+
annotation: ann,
|
|
675
|
+
center: getBoundingBoxCenter(ann.points)
|
|
676
|
+
}));
|
|
677
|
+
const columns = [];
|
|
678
|
+
for (const item of annotationsWithCenters) {
|
|
679
|
+
let addedToColumn = false;
|
|
680
|
+
for (const column of columns) {
|
|
681
|
+
const avgX = column.reduce((sum, c) => sum + c.center.x, 0) / column.length;
|
|
682
|
+
if (Math.abs(item.center.x - avgX) < GROUPING_TOLERANCE) {
|
|
683
|
+
column.push(item);
|
|
684
|
+
addedToColumn = true;
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (!addedToColumn) {
|
|
689
|
+
columns.push([item]);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
columns.sort((colA, colB) => {
|
|
693
|
+
const avgXA = colA.reduce((sum, c) => sum + c.center.x, 0) / colA.length;
|
|
694
|
+
const avgXB = colB.reduce((sum, c) => sum + c.center.x, 0) / colB.length;
|
|
695
|
+
return avgXB - avgXA;
|
|
696
|
+
});
|
|
697
|
+
for (const column of columns) {
|
|
698
|
+
column.sort((a, b) => {
|
|
699
|
+
return verticalSort === SORT_VERTICAL_TOP_BOTTOM ? a.center.y - b.center.y : b.center.y - a.center.y;
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
return columns.flat().map((item) => item.annotation);
|
|
703
|
+
}
|
|
704
|
+
sorted.sort((a, b) => {
|
|
705
|
+
const centerA = getBoundingBoxCenter(a.points);
|
|
706
|
+
const centerB = getBoundingBoxCenter(b.points);
|
|
707
|
+
if (verticalSort !== SORT_VERTICAL_NONE) {
|
|
708
|
+
const yDiff = verticalSort === SORT_VERTICAL_TOP_BOTTOM ? centerA.y - centerB.y : centerB.y - centerA.y;
|
|
709
|
+
if (Math.abs(yDiff) > GROUPING_TOLERANCE) {
|
|
710
|
+
return yDiff;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (horizontalSort !== SORT_HORIZONTAL_NONE) {
|
|
714
|
+
return horizontalSort === SORT_HORIZONTAL_LTR ? centerA.x - centerB.x : centerB.x - centerA.x;
|
|
715
|
+
}
|
|
716
|
+
return 0;
|
|
717
|
+
});
|
|
718
|
+
return sorted;
|
|
719
|
+
}
|
|
720
|
+
var GROUPING_TOLERANCE;
|
|
721
|
+
var init_sort = __esm({
|
|
722
|
+
"src/lib/sort.ts"() {
|
|
723
|
+
"use strict";
|
|
724
|
+
init_cjs_shims();
|
|
725
|
+
init_constants();
|
|
726
|
+
GROUPING_TOLERANCE = 50;
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// src/commands/toLabelStudio/impl.ts
|
|
731
|
+
var impl_exports = {};
|
|
732
|
+
__export(impl_exports, {
|
|
733
|
+
convertToLabelStudio: () => convertToLabelStudio
|
|
734
|
+
});
|
|
735
|
+
async function convertToLabelStudio(flags, ...inputDirs) {
|
|
736
|
+
const {
|
|
737
|
+
outDir = OUTPUT_BASE_DIR,
|
|
738
|
+
defaultLabelName = DEFAULT_LABEL_NAME,
|
|
739
|
+
toFullJson = DEFAULT_LABEL_STUDIO_FULL_JSON,
|
|
740
|
+
createFilePerImage = DEFAULT_CREATE_FILE_PER_IMAGE,
|
|
741
|
+
createFileListForServing = DEFAULT_CREATE_FILE_LIST_FOR_SERVING,
|
|
742
|
+
fileListName = DEFAULT_FILE_LIST_NAME,
|
|
743
|
+
baseServerUrl = DEFAULT_BASE_SERVER_URL,
|
|
744
|
+
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
745
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
746
|
+
} = flags;
|
|
747
|
+
const newBaseServerUrl = baseServerUrl.replace(/\/+$/, "") + (baseServerUrl === "" ? "" : "/");
|
|
748
|
+
await (0, import_promises.mkdir)(outDir, { recursive: true });
|
|
749
|
+
for (const inputDir of inputDirs) {
|
|
750
|
+
console.log(import_chalk.default.blue(`Processing input directory: ${inputDir}`));
|
|
751
|
+
const files = await (0, import_promises.readdir)(inputDir);
|
|
752
|
+
for (const file of files) {
|
|
753
|
+
if (!file.endsWith(".txt")) {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
const filePath = (0, import_path.join)(inputDir, file);
|
|
757
|
+
console.log(import_chalk.default.gray(`Processing file: ${file}`));
|
|
758
|
+
try {
|
|
759
|
+
const fileData = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
760
|
+
const lines = fileData.trim().split("\n");
|
|
761
|
+
const imageDataMap = /* @__PURE__ */ new Map();
|
|
762
|
+
for (const line of lines) {
|
|
763
|
+
const parts = line.split(" ");
|
|
764
|
+
if (parts.length !== 2) {
|
|
765
|
+
throw new Error(`Invalid PPOCRLabelV2 format in line: ${line}`);
|
|
766
|
+
}
|
|
767
|
+
const [imagePath, annotationsStr] = parts;
|
|
768
|
+
const annotations = JSON.parse(annotationsStr);
|
|
769
|
+
PPOCRLabelSchema.parse(annotations);
|
|
770
|
+
imageDataMap.set(imagePath, annotations);
|
|
771
|
+
}
|
|
772
|
+
const allLabelStudioData = [];
|
|
773
|
+
const fileList = [];
|
|
774
|
+
let taskId = 1;
|
|
775
|
+
for (const [imagePath, ppocrData] of imageDataMap.entries()) {
|
|
776
|
+
const sortedPpocrData = sortBoundingBoxes(
|
|
777
|
+
ppocrData,
|
|
778
|
+
sortVertical,
|
|
779
|
+
sortHorizontal
|
|
780
|
+
);
|
|
781
|
+
const finalImagePath = createFileListForServing ? encodeURI(`${newBaseServerUrl}${imagePath}`) : imagePath;
|
|
782
|
+
const labelStudioData = await ppocrToLabelStudio(sortedPpocrData, {
|
|
783
|
+
toFullJson,
|
|
784
|
+
imagePath,
|
|
785
|
+
baseServerUrl: newBaseServerUrl,
|
|
786
|
+
inputDir,
|
|
787
|
+
taskId,
|
|
788
|
+
labelName: defaultLabelName
|
|
789
|
+
});
|
|
790
|
+
if (toFullJson) {
|
|
791
|
+
allLabelStudioData.push(labelStudioData[0]);
|
|
792
|
+
} else {
|
|
793
|
+
allLabelStudioData.push(...labelStudioData);
|
|
794
|
+
}
|
|
795
|
+
if (createFilePerImage) {
|
|
796
|
+
const imageBaseName = imagePath.replace(/\//g, "_").replace(/\.[^.]+$/, "");
|
|
797
|
+
const individualOutputPath = (0, import_path.join)(
|
|
798
|
+
outDir,
|
|
799
|
+
`${imageBaseName}_${toFullJson ? "full" : "min"}.json`
|
|
800
|
+
);
|
|
801
|
+
await (0, import_promises.writeFile)(
|
|
802
|
+
individualOutputPath,
|
|
803
|
+
JSON.stringify(
|
|
804
|
+
toFullJson ? labelStudioData[0] : labelStudioData,
|
|
805
|
+
null,
|
|
806
|
+
2
|
|
807
|
+
),
|
|
808
|
+
"utf-8"
|
|
809
|
+
);
|
|
810
|
+
console.log(
|
|
811
|
+
import_chalk.default.gray(
|
|
812
|
+
` \u2713 Created individual file: ${individualOutputPath}`
|
|
813
|
+
)
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
if (createFileListForServing) {
|
|
817
|
+
fileList.push(finalImagePath);
|
|
818
|
+
}
|
|
819
|
+
taskId++;
|
|
820
|
+
}
|
|
821
|
+
const baseName = file.replace(".txt", "");
|
|
822
|
+
const outputPath = (0, import_path.join)(
|
|
823
|
+
outDir,
|
|
824
|
+
`${baseName}_${toFullJson ? "full" : "min"}.json`
|
|
825
|
+
);
|
|
826
|
+
await (0, import_promises.writeFile)(
|
|
827
|
+
outputPath,
|
|
828
|
+
JSON.stringify(allLabelStudioData, null, 2),
|
|
829
|
+
"utf-8"
|
|
830
|
+
);
|
|
831
|
+
console.log(import_chalk.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
|
|
832
|
+
if (createFileListForServing && fileList.length > 0) {
|
|
833
|
+
const fileListPath = (0, import_path.join)(outDir, fileListName);
|
|
834
|
+
await (0, import_promises.writeFile)(fileListPath, fileList.join("\n"), "utf-8");
|
|
835
|
+
console.log(
|
|
836
|
+
import_chalk.default.green(
|
|
837
|
+
`\u2713 Created file list: ${fileListPath} (${fileList.length} files)`
|
|
838
|
+
)
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
} catch (error) {
|
|
842
|
+
console.error(
|
|
843
|
+
import_chalk.default.red(`\u2717 Failed to process ${file}:`),
|
|
844
|
+
error instanceof Error ? error.message : error
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
console.log(import_chalk.default.green("\n\u2713 Conversion completed!"));
|
|
850
|
+
}
|
|
851
|
+
var import_promises, import_path, import_chalk;
|
|
852
|
+
var init_impl = __esm({
|
|
853
|
+
"src/commands/toLabelStudio/impl.ts"() {
|
|
854
|
+
"use strict";
|
|
855
|
+
init_cjs_shims();
|
|
856
|
+
import_promises = require("fs/promises");
|
|
857
|
+
import_path = require("path");
|
|
858
|
+
import_chalk = __toESM(require("chalk"), 1);
|
|
859
|
+
init_constants();
|
|
860
|
+
init_ppocr_label();
|
|
861
|
+
init_schema();
|
|
862
|
+
init_sort();
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// src/lib/label-studio.ts
|
|
867
|
+
var turf, labelStudioToPPOCR, minLabelStudioToPPOCR;
|
|
868
|
+
var init_label_studio = __esm({
|
|
869
|
+
"src/lib/label-studio.ts"() {
|
|
870
|
+
"use strict";
|
|
871
|
+
init_cjs_shims();
|
|
872
|
+
turf = __toESM(require("@turf/turf"), 1);
|
|
873
|
+
labelStudioToPPOCR = async (data, baseImageDir) => {
|
|
874
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
875
|
+
for (const task of data) {
|
|
876
|
+
let imagePath = task.file_upload || "";
|
|
877
|
+
if (task.data.ocr) {
|
|
878
|
+
const urlPath = task.data.ocr.replace(/^https?:\/\/[^/]+\//, "");
|
|
879
|
+
imagePath = decodeURIComponent(urlPath);
|
|
880
|
+
}
|
|
881
|
+
if (baseImageDir) {
|
|
882
|
+
imagePath = `${baseImageDir}/${task.file_upload || imagePath.split("/").pop() || imagePath}`;
|
|
883
|
+
}
|
|
884
|
+
const imageAnnotations = [];
|
|
885
|
+
for (const annotation of task.annotations) {
|
|
886
|
+
const groupedById = /* @__PURE__ */ new Map();
|
|
887
|
+
for (const resultItem of annotation.result) {
|
|
888
|
+
const { id } = resultItem;
|
|
889
|
+
if (!groupedById.has(id)) {
|
|
890
|
+
groupedById.set(id, []);
|
|
891
|
+
}
|
|
892
|
+
groupedById.get(id).push(resultItem);
|
|
893
|
+
}
|
|
894
|
+
for (const [_, resultItems] of groupedById) {
|
|
895
|
+
let points;
|
|
896
|
+
let transcription = "";
|
|
897
|
+
for (const resultItem of resultItems) {
|
|
898
|
+
if ("points" in resultItem.value && resultItem.value.points) {
|
|
899
|
+
const { points: valuePoints } = resultItem.value;
|
|
900
|
+
const { original_width, original_height } = resultItem;
|
|
901
|
+
points = valuePoints.map(([x, y]) => [
|
|
902
|
+
(x ?? 0) * original_width / 100,
|
|
903
|
+
(y ?? 0) * original_height / 100
|
|
904
|
+
]);
|
|
905
|
+
} else if ("x" in resultItem.value && "y" in resultItem.value && "width" in resultItem.value && "height" in resultItem.value) {
|
|
906
|
+
const { x, y, width, height } = resultItem.value;
|
|
907
|
+
const { original_width, original_height } = resultItem;
|
|
908
|
+
const absX = x * original_width / 100;
|
|
909
|
+
const absY = y * original_height / 100;
|
|
910
|
+
const absWidth = width * original_width / 100;
|
|
911
|
+
const absHeight = height * original_height / 100;
|
|
912
|
+
points = [
|
|
913
|
+
[absX, absY],
|
|
914
|
+
[absX + absWidth, absY],
|
|
915
|
+
[absX + absWidth, absY + absHeight],
|
|
916
|
+
[absX, absY + absHeight]
|
|
917
|
+
];
|
|
918
|
+
}
|
|
919
|
+
if ("text" in resultItem.value && Array.isArray(resultItem.value.text)) {
|
|
920
|
+
transcription = resultItem.value.text[0] || "";
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (points && points.length > 0) {
|
|
924
|
+
let dt_score = 1;
|
|
925
|
+
try {
|
|
926
|
+
const firstPoint = points[0];
|
|
927
|
+
if (firstPoint) {
|
|
928
|
+
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
929
|
+
const area2 = turf.area(polygon2);
|
|
930
|
+
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
931
|
+
}
|
|
932
|
+
} catch {
|
|
933
|
+
dt_score = 0.8;
|
|
934
|
+
}
|
|
935
|
+
imageAnnotations.push({
|
|
936
|
+
transcription,
|
|
937
|
+
points,
|
|
938
|
+
dt_score
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (imageAnnotations.length > 0) {
|
|
944
|
+
resultMap.set(imagePath, imageAnnotations);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
return resultMap;
|
|
948
|
+
};
|
|
949
|
+
minLabelStudioToPPOCR = async (data, baseImageDir) => {
|
|
950
|
+
const resultMap = /* @__PURE__ */ new Map();
|
|
951
|
+
for (const item of data) {
|
|
952
|
+
let imagePath = item.ocr || "";
|
|
953
|
+
if (imagePath) {
|
|
954
|
+
imagePath = decodeURIComponent(
|
|
955
|
+
imagePath.replace(/^https?:\/\/[^/]+\//, "")
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
if (baseImageDir) {
|
|
959
|
+
imagePath = `${baseImageDir}/${imagePath.split("/").pop() || imagePath}`;
|
|
960
|
+
}
|
|
961
|
+
let points;
|
|
962
|
+
if (item.poly.length > 0 && item.poly[0]) {
|
|
963
|
+
const { points: polyPoints } = item.poly[0];
|
|
964
|
+
points = polyPoints;
|
|
965
|
+
} else if (item.bbox.length > 0 && item.bbox[0]) {
|
|
966
|
+
const bbox = item.bbox[0];
|
|
967
|
+
const { x, y, width, height } = bbox;
|
|
968
|
+
points = [
|
|
969
|
+
[x, y],
|
|
970
|
+
[x + width, y],
|
|
971
|
+
[x + width, y + height],
|
|
972
|
+
[x, y + height]
|
|
973
|
+
];
|
|
974
|
+
} else {
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
const transcription = item.transcription.length > 0 ? item.transcription[0] : "";
|
|
978
|
+
let dt_score = 1;
|
|
979
|
+
try {
|
|
980
|
+
const firstPoint = points[0];
|
|
981
|
+
if (firstPoint) {
|
|
982
|
+
const polygon2 = turf.polygon([points.concat([firstPoint])]);
|
|
983
|
+
const area2 = turf.area(polygon2);
|
|
984
|
+
dt_score = Math.min(1, Math.max(0.5, area2 / 1e4));
|
|
985
|
+
}
|
|
986
|
+
} catch {
|
|
987
|
+
dt_score = 0.8;
|
|
988
|
+
}
|
|
989
|
+
const annotation = {
|
|
990
|
+
transcription: transcription ?? "",
|
|
991
|
+
points,
|
|
992
|
+
dt_score
|
|
993
|
+
};
|
|
994
|
+
if (!resultMap.has(imagePath)) {
|
|
995
|
+
resultMap.set(imagePath, []);
|
|
996
|
+
}
|
|
997
|
+
resultMap.get(imagePath).push(annotation);
|
|
998
|
+
}
|
|
999
|
+
return resultMap;
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// src/commands/toPPOCR/impl.ts
|
|
1005
|
+
var impl_exports2 = {};
|
|
1006
|
+
__export(impl_exports2, {
|
|
1007
|
+
convertToPPOCR: () => convertToPPOCR
|
|
1008
|
+
});
|
|
1009
|
+
async function convertToPPOCR(flags, ...inputDirs) {
|
|
1010
|
+
const {
|
|
1011
|
+
outDir = `${OUTPUT_BASE_DIR}`,
|
|
1012
|
+
fileName = DEFAULT_PPOCR_FILE_NAME,
|
|
1013
|
+
baseImageDir,
|
|
1014
|
+
sortVertical = DEFAULT_SORT_VERTICAL,
|
|
1015
|
+
sortHorizontal = DEFAULT_SORT_HORIZONTAL
|
|
1016
|
+
} = flags;
|
|
1017
|
+
await (0, import_promises2.mkdir)(outDir, { recursive: true });
|
|
1018
|
+
for (const inputDir of inputDirs) {
|
|
1019
|
+
console.log(import_chalk2.default.blue(`Processing input directory: ${inputDir}`));
|
|
1020
|
+
const files = await (0, import_promises2.readdir)(inputDir);
|
|
1021
|
+
for (const file of files) {
|
|
1022
|
+
if (!file.endsWith(".json")) {
|
|
1023
|
+
continue;
|
|
1024
|
+
}
|
|
1025
|
+
const filePath = (0, import_path2.join)(inputDir, file);
|
|
1026
|
+
console.log(import_chalk2.default.gray(`Processing file: ${file}`));
|
|
1027
|
+
try {
|
|
1028
|
+
const fileData = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
1029
|
+
const labelStudioData = JSON.parse(fileData);
|
|
1030
|
+
const { data, isFull } = isLabelStudioFullJSON(labelStudioData);
|
|
1031
|
+
const ppocrDataMap = isFull ? await labelStudioToPPOCR(data, baseImageDir) : await minLabelStudioToPPOCR(
|
|
1032
|
+
data,
|
|
1033
|
+
baseImageDir
|
|
1034
|
+
);
|
|
1035
|
+
const outputLines = [];
|
|
1036
|
+
for (const [imagePath, annotations] of ppocrDataMap.entries()) {
|
|
1037
|
+
const sortedAnnotations = sortBoundingBoxes(
|
|
1038
|
+
annotations,
|
|
1039
|
+
sortVertical,
|
|
1040
|
+
sortHorizontal
|
|
1041
|
+
);
|
|
1042
|
+
PPOCRLabelSchema.parse(sortedAnnotations);
|
|
1043
|
+
const jsonArray = JSON.stringify(sortedAnnotations);
|
|
1044
|
+
outputLines.push(`${imagePath} ${jsonArray}`);
|
|
1045
|
+
}
|
|
1046
|
+
const baseName = file.replace(".json", "");
|
|
1047
|
+
const outputPath = (0, import_path2.join)(outDir, `${baseName}_${fileName}`);
|
|
1048
|
+
await (0, import_promises2.writeFile)(outputPath, outputLines.join("\n"), "utf-8");
|
|
1049
|
+
console.log(import_chalk2.default.green(`\u2713 Converted ${file} -> ${outputPath}`));
|
|
1050
|
+
} catch (error) {
|
|
1051
|
+
console.error(
|
|
1052
|
+
import_chalk2.default.red(`\u2717 Failed to process ${file}:`),
|
|
1053
|
+
error instanceof Error ? error.message : error
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
console.log(import_chalk2.default.green("\n\u2713 Conversion completed!"));
|
|
1059
|
+
}
|
|
1060
|
+
var import_promises2, import_path2, import_chalk2, isLabelStudioFullJSON;
|
|
1061
|
+
var init_impl2 = __esm({
|
|
1062
|
+
"src/commands/toPPOCR/impl.ts"() {
|
|
1063
|
+
"use strict";
|
|
1064
|
+
init_cjs_shims();
|
|
1065
|
+
import_promises2 = require("fs/promises");
|
|
1066
|
+
import_path2 = require("path");
|
|
1067
|
+
import_chalk2 = __toESM(require("chalk"), 1);
|
|
1068
|
+
init_constants();
|
|
1069
|
+
init_label_studio();
|
|
1070
|
+
init_schema();
|
|
1071
|
+
init_sort();
|
|
1072
|
+
isLabelStudioFullJSON = (data) => {
|
|
1073
|
+
const parsedFull = FullOCRLabelStudioSchema.safeParse(data);
|
|
1074
|
+
if (parsedFull.success) {
|
|
1075
|
+
return { isFull: true, data: parsedFull.data };
|
|
1076
|
+
}
|
|
1077
|
+
if (!Array.isArray(data) && typeof data === "object" && data !== null) {
|
|
1078
|
+
const parsedSingleFull = FullOCRLabelStudioSchema.safeParse([data]);
|
|
1079
|
+
if (parsedSingleFull.success) {
|
|
1080
|
+
return { isFull: true, data: parsedSingleFull.data };
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
const parsedMin = MinOCRLabelStudioSchema.safeParse(data);
|
|
1084
|
+
if (parsedMin.success) {
|
|
1085
|
+
return { isFull: false, data: parsedMin.data };
|
|
1086
|
+
}
|
|
1087
|
+
throw new Error("Input data is not valid Label Studio JSON format.");
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1092
|
+
// src/bin/bash-complete.ts
|
|
1093
|
+
init_cjs_shims();
|
|
1094
|
+
var import_core4 = require("@stricli/core");
|
|
1095
|
+
|
|
1096
|
+
// src/app.ts
|
|
1097
|
+
init_cjs_shims();
|
|
1098
|
+
var import_auto_complete = require("@stricli/auto-complete");
|
|
1099
|
+
var import_core3 = require("@stricli/core");
|
|
1100
|
+
|
|
1101
|
+
// package.json
|
|
1102
|
+
var version = "1.0.0";
|
|
1103
|
+
var description = "Convert between Label Studio OCR format and PPOCRLabelv2 format";
|
|
1104
|
+
|
|
1105
|
+
// src/commands/toLabelStudio/command.ts
|
|
1106
|
+
init_cjs_shims();
|
|
1107
|
+
var import_core = require("@stricli/core");
|
|
1108
|
+
init_constants();
|
|
1109
|
+
var toLabelStudioCommand = (0, import_core.buildCommand)({
|
|
1110
|
+
loader: async () => {
|
|
1111
|
+
const { convertToLabelStudio: convertToLabelStudio2 } = await Promise.resolve().then(() => (init_impl(), impl_exports));
|
|
1112
|
+
return convertToLabelStudio2;
|
|
1113
|
+
},
|
|
1114
|
+
parameters: {
|
|
1115
|
+
positional: {
|
|
1116
|
+
kind: "array",
|
|
1117
|
+
parameter: {
|
|
1118
|
+
brief: "Input directories containing PPOCRLabel files",
|
|
1119
|
+
parse: String
|
|
1120
|
+
},
|
|
1121
|
+
minimum: 1
|
|
1122
|
+
},
|
|
1123
|
+
flags: {
|
|
1124
|
+
outDir: {
|
|
1125
|
+
kind: "parsed",
|
|
1126
|
+
brief: `Output directory. Default to "${OUTPUT_BASE_DIR}"`,
|
|
1127
|
+
parse: String,
|
|
1128
|
+
optional: true
|
|
1129
|
+
},
|
|
1130
|
+
defaultLabelName: {
|
|
1131
|
+
kind: "parsed",
|
|
1132
|
+
brief: `Default label name for text annotations. Default to "${DEFAULT_LABEL_NAME}"`,
|
|
1133
|
+
parse: String,
|
|
1134
|
+
optional: true
|
|
1135
|
+
},
|
|
1136
|
+
toFullJson: {
|
|
1137
|
+
kind: "boolean",
|
|
1138
|
+
brief: `Convert to Full OCR Label Studio format. Default to "${DEFAULT_LABEL_STUDIO_FULL_JSON}"`,
|
|
1139
|
+
optional: true
|
|
1140
|
+
},
|
|
1141
|
+
createFilePerImage: {
|
|
1142
|
+
kind: "boolean",
|
|
1143
|
+
brief: `Create a separate Label Studio JSON file for each image. Default to "${DEFAULT_CREATE_FILE_PER_IMAGE}"`,
|
|
1144
|
+
optional: true
|
|
1145
|
+
},
|
|
1146
|
+
createFileListForServing: {
|
|
1147
|
+
kind: "boolean",
|
|
1148
|
+
brief: `Create a file list for serving in Label Studio. Default to "${DEFAULT_CREATE_FILE_LIST_FOR_SERVING}"`,
|
|
1149
|
+
optional: true
|
|
1150
|
+
},
|
|
1151
|
+
fileListName: {
|
|
1152
|
+
kind: "parsed",
|
|
1153
|
+
brief: `Name of the file list for serving. Default to "${DEFAULT_FILE_LIST_NAME}"`,
|
|
1154
|
+
parse: String,
|
|
1155
|
+
optional: true
|
|
1156
|
+
},
|
|
1157
|
+
baseServerUrl: {
|
|
1158
|
+
kind: "parsed",
|
|
1159
|
+
brief: `Base server URL for constructing image URLs in the file list. Default to "${DEFAULT_BASE_SERVER_URL}"`,
|
|
1160
|
+
parse: String,
|
|
1161
|
+
optional: true
|
|
1162
|
+
},
|
|
1163
|
+
sortVertical: {
|
|
1164
|
+
kind: "parsed",
|
|
1165
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}" (default), "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}"`,
|
|
1166
|
+
parse: String,
|
|
1167
|
+
optional: true
|
|
1168
|
+
},
|
|
1169
|
+
sortHorizontal: {
|
|
1170
|
+
kind: "parsed",
|
|
1171
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}" (default), "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}"`,
|
|
1172
|
+
parse: String,
|
|
1173
|
+
optional: true
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
},
|
|
1177
|
+
docs: {
|
|
1178
|
+
brief: "Convert PPOCRLabel files to Label Studio format"
|
|
1179
|
+
}
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1182
|
+
// src/commands/toPPOCR/commands.ts
|
|
1183
|
+
init_cjs_shims();
|
|
1184
|
+
var import_core2 = require("@stricli/core");
|
|
1185
|
+
init_constants();
|
|
1186
|
+
var toPPOCRCommand = (0, import_core2.buildCommand)({
|
|
1187
|
+
loader: async () => {
|
|
1188
|
+
const { convertToPPOCR: convertToPPOCR2 } = await Promise.resolve().then(() => (init_impl2(), impl_exports2));
|
|
1189
|
+
return convertToPPOCR2;
|
|
1190
|
+
},
|
|
1191
|
+
parameters: {
|
|
1192
|
+
positional: {
|
|
1193
|
+
kind: "array",
|
|
1194
|
+
parameter: {
|
|
1195
|
+
brief: "Input directories containing Label Studio files",
|
|
1196
|
+
parse: String
|
|
1197
|
+
},
|
|
1198
|
+
minimum: 1
|
|
1199
|
+
},
|
|
1200
|
+
flags: {
|
|
1201
|
+
outDir: {
|
|
1202
|
+
kind: "parsed",
|
|
1203
|
+
brief: `Output directory. Default to "${OUTPUT_BASE_DIR}"`,
|
|
1204
|
+
parse: String,
|
|
1205
|
+
optional: true
|
|
1206
|
+
},
|
|
1207
|
+
fileName: {
|
|
1208
|
+
kind: "parsed",
|
|
1209
|
+
brief: `Output PPOCR file name. Default to "${DEFAULT_PPOCR_FILE_NAME}"`,
|
|
1210
|
+
parse: String,
|
|
1211
|
+
optional: true
|
|
1212
|
+
},
|
|
1213
|
+
baseImageDir: {
|
|
1214
|
+
kind: "parsed",
|
|
1215
|
+
brief: 'Base directory path to prepend to image filenames in output (e.g., "ch" or "images/ch")',
|
|
1216
|
+
parse: String,
|
|
1217
|
+
optional: true
|
|
1218
|
+
},
|
|
1219
|
+
sortVertical: {
|
|
1220
|
+
kind: "parsed",
|
|
1221
|
+
brief: `Sort bounding boxes vertically. Options: "${SORT_VERTICAL_NONE}" (default), "${SORT_VERTICAL_TOP_BOTTOM}", "${SORT_VERTICAL_BOTTOM_TOP}"`,
|
|
1222
|
+
parse: String,
|
|
1223
|
+
optional: true
|
|
1224
|
+
},
|
|
1225
|
+
sortHorizontal: {
|
|
1226
|
+
kind: "parsed",
|
|
1227
|
+
brief: `Sort bounding boxes horizontally. Options: "${SORT_HORIZONTAL_NONE}" (default), "${SORT_HORIZONTAL_LTR}", "${SORT_HORIZONTAL_RTL}"`,
|
|
1228
|
+
parse: String,
|
|
1229
|
+
optional: true
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
},
|
|
1233
|
+
docs: {
|
|
1234
|
+
brief: "Convert Label Studio files to PPOCRLabel format"
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
// src/app.ts
|
|
1239
|
+
var routes = (0, import_core3.buildRouteMap)({
|
|
1240
|
+
routes: {
|
|
1241
|
+
toLabelStudio: toLabelStudioCommand,
|
|
1242
|
+
toPPOCR: toPPOCRCommand,
|
|
1243
|
+
install: (0, import_auto_complete.buildInstallCommand)("label-studio-converter", {
|
|
1244
|
+
bash: "__label-studio-converter_bash_complete"
|
|
1245
|
+
}),
|
|
1246
|
+
uninstall: (0, import_auto_complete.buildUninstallCommand)("label-studio-converter", { bash: true })
|
|
1247
|
+
},
|
|
1248
|
+
docs: {
|
|
1249
|
+
brief: description,
|
|
1250
|
+
hideRoute: {
|
|
1251
|
+
install: true,
|
|
1252
|
+
uninstall: true
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
var app = (0, import_core3.buildApplication)(routes, {
|
|
1257
|
+
name: "label-studio-converter",
|
|
1258
|
+
versionInfo: {
|
|
1259
|
+
currentVersion: version
|
|
1260
|
+
}
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1263
|
+
// src/context.ts
|
|
1264
|
+
init_cjs_shims();
|
|
1265
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
1266
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
1267
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
1268
|
+
function buildContext(process2) {
|
|
1269
|
+
return {
|
|
1270
|
+
process: process2,
|
|
1271
|
+
os: import_node_os.default,
|
|
1272
|
+
fs: import_node_fs2.default,
|
|
1273
|
+
path: import_node_path2.default
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/bin/bash-complete.ts
|
|
1278
|
+
(async () => {
|
|
1279
|
+
const inputs = process.argv.slice(3);
|
|
1280
|
+
if (process.env.COMP_LINE?.endsWith(" ")) {
|
|
1281
|
+
inputs.push("");
|
|
1282
|
+
}
|
|
1283
|
+
await (0, import_core4.proposeCompletions)(app, inputs, buildContext(process));
|
|
1284
|
+
try {
|
|
1285
|
+
for (const { completion } of await (0, import_core4.proposeCompletions)(
|
|
1286
|
+
app,
|
|
1287
|
+
inputs,
|
|
1288
|
+
buildContext(process)
|
|
1289
|
+
)) {
|
|
1290
|
+
process.stdout.write(`${completion}
|
|
1291
|
+
`);
|
|
1292
|
+
}
|
|
1293
|
+
} catch {
|
|
1294
|
+
}
|
|
1295
|
+
})();
|
|
1296
|
+
//# sourceMappingURL=bash-complete.cjs.map
|