@braincrew-lab/langchain-canvas 0.2.0 → 0.4.9
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/dist/{ChartRenderer-AAWVGKV5.js → ChartRenderer-JGRJ23OB.js} +10 -20
- package/dist/{DocumentRenderer-NBRBPYU6.js → DocumentRenderer-ZQDQMX7X.js} +8 -4
- package/dist/FileRenderer-3ZHNORZJ.js +39 -0
- package/dist/SlidesRenderer-56R3TNWN.js +496 -0
- package/dist/{TableRenderer-VKDD3CB6.js → TableRenderer-3ESF577F.js} +49 -193
- package/dist/chunk-7T5DRR3F.js +109 -0
- package/dist/{chunk-S54GJDSJ.js → chunk-EHW446VF.js} +62 -47
- package/dist/chunk-FTNRRJ3K.js +13 -0
- package/dist/chunk-IFNRLN4Y.js +137 -0
- package/dist/{chunk-UL5F66PN.js → chunk-K2UZAYW2.js} +1 -1
- package/dist/chunk-SGOPRUQ4.js +182 -0
- package/dist/formula-27TCEZI5.js +2 -0
- package/dist/formula-cli.d.ts +2 -0
- package/dist/formula-cli.js +37 -0
- package/dist/index.d.ts +201 -289
- package/dist/index.js +393 -860
- package/dist/langgraph/index.d.ts +68 -0
- package/dist/langgraph/index.js +111 -0
- package/dist/styles.css +125 -100
- package/dist/types-BfGP9R2I.d.ts +324 -0
- package/package.json +40 -5
- package/dist/PdfRenderer-DPQT4E7O.js +0 -97
- package/dist/SlidesRenderer-6ZGHXTQX.js +0 -877
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// src/io/tableMerge.ts
|
|
2
|
+
var isFormula = (v) => typeof v === "string" && v.startsWith("=");
|
|
3
|
+
var VALUE_KEYS = ["v", "m", "ct", "f", "qp", "spl"];
|
|
4
|
+
function normalizedValue(value) {
|
|
5
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
6
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : null;
|
|
7
|
+
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
8
|
+
const text = String(value).trim();
|
|
9
|
+
if (text === "") return null;
|
|
10
|
+
const num = Number(text);
|
|
11
|
+
return Number.isNaN(num) ? text : String(num);
|
|
12
|
+
}
|
|
13
|
+
var normalizedFormula = (f) => typeof f === "string" && f.trim() ? f.trim().replace(/^=/, "") : null;
|
|
14
|
+
function sameCellContent(rowsValue, cellV) {
|
|
15
|
+
const cellFormula = cellV && typeof cellV === "object" ? normalizedFormula(cellV.f) : null;
|
|
16
|
+
if (isFormula(rowsValue) || cellFormula !== null) {
|
|
17
|
+
return normalizedFormula(rowsValue) === cellFormula;
|
|
18
|
+
}
|
|
19
|
+
const cellValue = cellV && typeof cellV === "object" ? cellV.v ?? cellV.m ?? null : cellV;
|
|
20
|
+
return normalizedValue(rowsValue) === normalizedValue(cellValue);
|
|
21
|
+
}
|
|
22
|
+
function cellMap(sheet) {
|
|
23
|
+
const map = /* @__PURE__ */ new Map();
|
|
24
|
+
if (sheet.celldata?.length) {
|
|
25
|
+
for (const cell of sheet.celldata) {
|
|
26
|
+
if (cell?.v != null) map.set(`${cell.r},${cell.c}`, cell.v);
|
|
27
|
+
}
|
|
28
|
+
return map;
|
|
29
|
+
}
|
|
30
|
+
(sheet.data ?? []).forEach(
|
|
31
|
+
(row, r) => (row ?? []).forEach((cell, c) => {
|
|
32
|
+
if (cell != null) map.set(`${r},${c}`, cell);
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
return map;
|
|
36
|
+
}
|
|
37
|
+
function projectedValue(cellV) {
|
|
38
|
+
if (cellV === null || cellV === void 0) return "";
|
|
39
|
+
if (typeof cellV !== "object") return cellV;
|
|
40
|
+
const f = normalizedFormula(cellV.f);
|
|
41
|
+
if (f !== null) return `=${f}`;
|
|
42
|
+
const v = cellV.v ?? cellV.m;
|
|
43
|
+
return v === null || v === void 0 ? "" : v;
|
|
44
|
+
}
|
|
45
|
+
function projectSheetIntoRows(columns, rows, sheet) {
|
|
46
|
+
const first = sheet?.[0];
|
|
47
|
+
if (!first || columns.length === 0) return rows;
|
|
48
|
+
const cells = cellMap(first);
|
|
49
|
+
let deepest = 0;
|
|
50
|
+
for (const key of cells.keys()) {
|
|
51
|
+
const [r, c] = key.split(",").map(Number);
|
|
52
|
+
if (r >= 1 && c < columns.length) deepest = Math.max(deepest, r);
|
|
53
|
+
}
|
|
54
|
+
const projected = [];
|
|
55
|
+
for (let i = 0; i < deepest; i++) {
|
|
56
|
+
const row = { ...rows[i] ?? {} };
|
|
57
|
+
columns.forEach((col, c) => {
|
|
58
|
+
row[col.key] = projectedValue(cells.get(`${i + 1},${c}`));
|
|
59
|
+
});
|
|
60
|
+
projected.push(row);
|
|
61
|
+
}
|
|
62
|
+
return projected;
|
|
63
|
+
}
|
|
64
|
+
function valueCell(rowsValue, dataIdx, col, formulas) {
|
|
65
|
+
if (rowsValue === null || rowsValue === void 0 || rowsValue === "") return null;
|
|
66
|
+
if (isFormula(rowsValue)) {
|
|
67
|
+
const out = { f: rowsValue };
|
|
68
|
+
const computed = formulas?.get(`${dataIdx + 1},${col}`);
|
|
69
|
+
if (computed !== void 0) {
|
|
70
|
+
out.v = computed;
|
|
71
|
+
out.m = String(computed);
|
|
72
|
+
if (typeof computed === "number") out.ct = { fa: "General", t: "n" };
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
const numeric = typeof rowsValue === "number";
|
|
77
|
+
return { v: rowsValue, m: String(rowsValue), ...numeric ? { ct: { fa: "General", t: "n" } } : {} };
|
|
78
|
+
}
|
|
79
|
+
function mergeRowsIntoSheet(columns, rows, sheet, formulas) {
|
|
80
|
+
const first = sheet?.[0];
|
|
81
|
+
if (!first || columns.length === 0) return sheet;
|
|
82
|
+
const cells = cellMap(first);
|
|
83
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
84
|
+
columns.forEach((col, c) => {
|
|
85
|
+
const label = col.label ?? col.key;
|
|
86
|
+
if (!sameCellContent(label, cells.get(`0,${c}`))) {
|
|
87
|
+
overrides.set(`0,${c}`, { v: label, m: String(label) });
|
|
88
|
+
}
|
|
89
|
+
rows.forEach((row, i) => {
|
|
90
|
+
const value = row[col.key];
|
|
91
|
+
if (!sameCellContent(value, cells.get(`${i + 1},${c}`))) {
|
|
92
|
+
overrides.set(`${i + 1},${c}`, valueCell(value, i, c, formulas));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
const inRectangle = (r, c) => c < columns.length && r >= 1;
|
|
97
|
+
const ghosts = [...cells.keys()].filter((key) => {
|
|
98
|
+
const [r, c] = key.split(",").map(Number);
|
|
99
|
+
return inRectangle(r, c) && r > rows.length;
|
|
100
|
+
});
|
|
101
|
+
if (overrides.size === 0 && ghosts.length === 0) return sheet;
|
|
102
|
+
const merged = [];
|
|
103
|
+
const seen = /* @__PURE__ */ new Set();
|
|
104
|
+
for (const [key, existing] of cells) {
|
|
105
|
+
const [r, c] = key.split(",").map(Number);
|
|
106
|
+
seen.add(key);
|
|
107
|
+
if (inRectangle(r, c) && r > rows.length) continue;
|
|
108
|
+
if (!overrides.has(key)) {
|
|
109
|
+
merged.push({ r, c, v: existing });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const next = overrides.get(key);
|
|
113
|
+
const style = existing && typeof existing === "object" ? Object.fromEntries(
|
|
114
|
+
Object.entries(existing).filter(
|
|
115
|
+
([k]) => !VALUE_KEYS.includes(k)
|
|
116
|
+
)
|
|
117
|
+
) : {};
|
|
118
|
+
const v = next === null ? style : { ...style, ...next };
|
|
119
|
+
if (Object.keys(v).length > 0) merged.push({ r, c, v });
|
|
120
|
+
}
|
|
121
|
+
for (const [key, next] of overrides) {
|
|
122
|
+
if (seen.has(key) || next === null) continue;
|
|
123
|
+
const [r, c] = key.split(",").map(Number);
|
|
124
|
+
merged.push({ r, c, v: next });
|
|
125
|
+
}
|
|
126
|
+
merged.sort((a, b) => a.r - b.r || a.c - b.c);
|
|
127
|
+
const { data: _data, ...rest } = first;
|
|
128
|
+
const mergedFirst = {
|
|
129
|
+
...rest,
|
|
130
|
+
celldata: merged,
|
|
131
|
+
row: Math.max(Number(first.row) || 0, rows.length + 40),
|
|
132
|
+
column: Math.max(Number(first.column) || 0, columns.length + 2)
|
|
133
|
+
};
|
|
134
|
+
return [mergedFirst, ...(sheet ?? []).slice(1)];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { mergeRowsIntoSheet, projectSheetIntoRows };
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { loadOptional } from './chunk-YZZSJJMQ.js';
|
|
2
|
+
|
|
3
|
+
// src/io/formulaFunctions.ts
|
|
4
|
+
var unwrap = (arg) => arg !== null && typeof arg === "object" && !Array.isArray(arg) && "value" in arg ? arg.value : arg;
|
|
5
|
+
var flat = (arg) => {
|
|
6
|
+
const value = unwrap(arg);
|
|
7
|
+
return Array.isArray(value) ? value.flat(Infinity) : [value];
|
|
8
|
+
};
|
|
9
|
+
var scalar = (arg) => flat(arg)[0] ?? null;
|
|
10
|
+
var numbers = (values) => values.flatMap(flat).filter((v) => typeof v === "number");
|
|
11
|
+
var ciEqual = (a, b) => String(a ?? "").toLowerCase() === b.toLowerCase();
|
|
12
|
+
var matchesCriteria = (value, criteria) => {
|
|
13
|
+
if (typeof criteria === "string") {
|
|
14
|
+
const m = /^(<>|>=|<=|=|>|<)(.*)$/.exec(criteria);
|
|
15
|
+
if (m) {
|
|
16
|
+
const [, op, rest] = m;
|
|
17
|
+
const num2 = rest.trim() === "" ? NaN : Number(rest);
|
|
18
|
+
if (!Number.isNaN(num2)) {
|
|
19
|
+
if (op === "=") return value === num2;
|
|
20
|
+
if (op === "<>") return value !== num2;
|
|
21
|
+
if (typeof value !== "number") return false;
|
|
22
|
+
return op === ">" ? value > num2 : op === "<" ? value < num2 : op === ">=" ? value >= num2 : value <= num2;
|
|
23
|
+
}
|
|
24
|
+
if (op === "=") return ciEqual(value, rest);
|
|
25
|
+
if (op === "<>") return !ciEqual(value, rest);
|
|
26
|
+
const a = String(value ?? "").toLowerCase();
|
|
27
|
+
const b = rest.toLowerCase();
|
|
28
|
+
return op === ">" ? a > b : op === "<" ? a < b : op === ">=" ? a >= b : a <= b;
|
|
29
|
+
}
|
|
30
|
+
const num = criteria.trim() === "" ? NaN : Number(criteria);
|
|
31
|
+
if (!Number.isNaN(num)) return value === num;
|
|
32
|
+
return typeof value === "string" && ciEqual(value, criteria);
|
|
33
|
+
}
|
|
34
|
+
return value === criteria;
|
|
35
|
+
};
|
|
36
|
+
var criteriaPairs = (args, length) => {
|
|
37
|
+
if (args.length === 0 || args.length % 2 !== 0) throw new Error("criteria come in range/criteria pairs");
|
|
38
|
+
const pairs = [];
|
|
39
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
40
|
+
const range = flat(args[i]);
|
|
41
|
+
if (range.length !== length) throw new Error("criteria ranges must match the first range's size");
|
|
42
|
+
pairs.push({ range, criteria: scalar(args[i + 1]) });
|
|
43
|
+
}
|
|
44
|
+
return pairs;
|
|
45
|
+
};
|
|
46
|
+
var matchingIndexes = (pairs, length) => {
|
|
47
|
+
const out = [];
|
|
48
|
+
for (let i = 0; i < length; i++) {
|
|
49
|
+
if (pairs.every(({ range, criteria }) => matchesCriteria(range[i], criteria))) out.push(i);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
};
|
|
53
|
+
var truthy = (v) => v === true || v === 1 || typeof v === "string" && v.toUpperCase() === "TRUE";
|
|
54
|
+
var text = (v) => typeof v === "boolean" ? v ? "TRUE" : "FALSE" : String(v ?? "");
|
|
55
|
+
function customFormulaFunctions() {
|
|
56
|
+
return {
|
|
57
|
+
SUMIFS: (sumRange, ...rest) => {
|
|
58
|
+
const sums = flat(sumRange);
|
|
59
|
+
const pairs = criteriaPairs(rest, sums.length);
|
|
60
|
+
return matchingIndexes(pairs, sums.length).reduce((acc, i) => {
|
|
61
|
+
const v = sums[i];
|
|
62
|
+
return typeof v === "number" ? acc + v : acc;
|
|
63
|
+
}, 0);
|
|
64
|
+
},
|
|
65
|
+
AVERAGEIFS: (avgRange, ...rest) => {
|
|
66
|
+
const values = flat(avgRange);
|
|
67
|
+
const pairs = criteriaPairs(rest, values.length);
|
|
68
|
+
const hits = matchingIndexes(pairs, values.length).map((i) => values[i]).filter((v) => typeof v === "number");
|
|
69
|
+
if (hits.length === 0) throw new Error("AVERAGEIFS matched no cells");
|
|
70
|
+
return hits.reduce((a, b) => a + b, 0) / hits.length;
|
|
71
|
+
},
|
|
72
|
+
COUNTIFS: (...rest) => {
|
|
73
|
+
const length = flat(rest[0]).length;
|
|
74
|
+
return matchingIndexes(criteriaPairs(rest, length), length).length;
|
|
75
|
+
},
|
|
76
|
+
MATCH: (lookup, range, matchType) => {
|
|
77
|
+
const values = flat(range);
|
|
78
|
+
const target = scalar(lookup);
|
|
79
|
+
const rawMode = matchType === void 0 ? null : scalar(matchType);
|
|
80
|
+
const mode = typeof rawMode === "number" ? rawMode : 1;
|
|
81
|
+
const equals = (v) => typeof target === "string" ? ciEqual(v, target) : v === target;
|
|
82
|
+
if (mode === 0) {
|
|
83
|
+
const idx = values.findIndex(equals);
|
|
84
|
+
if (idx === -1) throw new Error("MATCH found no exact match");
|
|
85
|
+
return idx + 1;
|
|
86
|
+
}
|
|
87
|
+
let found = -1;
|
|
88
|
+
for (let i = 0; i < values.length; i++) {
|
|
89
|
+
const v = values[i];
|
|
90
|
+
if (typeof v !== typeof target || v === null || target === null) continue;
|
|
91
|
+
if (mode === 1 ? v <= target : v >= target) found = i;
|
|
92
|
+
else break;
|
|
93
|
+
}
|
|
94
|
+
if (found === -1) throw new Error("MATCH found no match");
|
|
95
|
+
return found + 1;
|
|
96
|
+
},
|
|
97
|
+
MAX: (...args) => {
|
|
98
|
+
const nums = numbers(args);
|
|
99
|
+
return nums.length ? Math.max(...nums) : 0;
|
|
100
|
+
},
|
|
101
|
+
MIN: (...args) => {
|
|
102
|
+
const nums = numbers(args);
|
|
103
|
+
return nums.length ? Math.min(...nums) : 0;
|
|
104
|
+
},
|
|
105
|
+
TEXTJOIN: (delimiter, ignoreEmpty, ...parts) => {
|
|
106
|
+
const values = parts.flatMap(flat);
|
|
107
|
+
const kept = truthy(scalar(ignoreEmpty)) ? values.filter((v) => v !== null && v !== "") : values;
|
|
108
|
+
return kept.map(text).join(text(scalar(delimiter)));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/io/formula.ts
|
|
114
|
+
var EMPTY = /* @__PURE__ */ new Map();
|
|
115
|
+
async function computeFormulas(columns, rows) {
|
|
116
|
+
const formulaCells = [];
|
|
117
|
+
rows.forEach(
|
|
118
|
+
(row, dataIdx) => columns.forEach((col, c) => {
|
|
119
|
+
const v = row[col.key];
|
|
120
|
+
if (typeof v === "string" && v.startsWith("=")) formulaCells.push({ dataIdx, col: c, formula: v });
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
if (formulaCells.length === 0) return EMPTY;
|
|
124
|
+
const mod = await loadOptional("fast-formula-parser", () => import('fast-formula-parser'));
|
|
125
|
+
const FormulaParser = mod.default ?? mod;
|
|
126
|
+
const memo = /* @__PURE__ */ new Map();
|
|
127
|
+
const inProgress = /* @__PURE__ */ new Set();
|
|
128
|
+
const rawAt = (row, col) => {
|
|
129
|
+
const colIdx = col - 1;
|
|
130
|
+
if (row === 1) return columns[colIdx]?.label ?? columns[colIdx]?.key ?? null;
|
|
131
|
+
const dataRow = rows[row - 2];
|
|
132
|
+
const column = columns[colIdx];
|
|
133
|
+
if (!dataRow || !column) return null;
|
|
134
|
+
const v = dataRow[column.key];
|
|
135
|
+
return v ?? null;
|
|
136
|
+
};
|
|
137
|
+
const valueAt = (row, col) => {
|
|
138
|
+
const raw = rawAt(row, col);
|
|
139
|
+
if (typeof raw !== "string" || !raw.startsWith("=")) return raw ?? 0;
|
|
140
|
+
const key = `${row},${col}`;
|
|
141
|
+
const cached = memo.get(key);
|
|
142
|
+
if (cached !== void 0) return cached;
|
|
143
|
+
if (inProgress.has(key)) return 0;
|
|
144
|
+
inProgress.add(key);
|
|
145
|
+
const value = evaluate(raw, row, col);
|
|
146
|
+
inProgress.delete(key);
|
|
147
|
+
memo.set(key, value);
|
|
148
|
+
return value;
|
|
149
|
+
};
|
|
150
|
+
const parser = new FormulaParser({
|
|
151
|
+
// Overrides the library's empty classic-function stubs (SUMIFS, MATCH, …).
|
|
152
|
+
functions: customFormulaFunctions(),
|
|
153
|
+
onCell: ({ row, col }) => valueAt(row, col),
|
|
154
|
+
onRange: (ref) => {
|
|
155
|
+
const maxRow = Math.min(ref.to.row, rows.length + 1);
|
|
156
|
+
const maxCol = Math.min(ref.to.col, columns.length);
|
|
157
|
+
const grid = [];
|
|
158
|
+
for (let r = ref.from.row; r <= maxRow; r++) {
|
|
159
|
+
const line = [];
|
|
160
|
+
for (let c = ref.from.col; c <= maxCol; c++) line.push(valueAt(r, c));
|
|
161
|
+
grid.push(line);
|
|
162
|
+
}
|
|
163
|
+
return grid;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
const evaluate = (formula, row, col) => {
|
|
167
|
+
try {
|
|
168
|
+
const result = parser.parse(formula.slice(1), { row, col });
|
|
169
|
+
if (result != null && typeof result === "object") return "#ERR";
|
|
170
|
+
return result ?? 0;
|
|
171
|
+
} catch {
|
|
172
|
+
return "#ERR";
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const out = /* @__PURE__ */ new Map();
|
|
176
|
+
for (const { dataIdx, col, formula } of formulaCells) {
|
|
177
|
+
out.set(`${dataIdx + 1},${col}`, evaluate(formula, dataIdx + 2, col + 1));
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export { computeFormulas };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { computeFormulas } from './chunk-SGOPRUQ4.js';
|
|
2
|
+
import './chunk-YZZSJJMQ.js';
|
|
3
|
+
|
|
4
|
+
// src/io/formulaCli.ts
|
|
5
|
+
async function main() {
|
|
6
|
+
const chunks = [];
|
|
7
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
8
|
+
const input = new TextDecoder().decode(
|
|
9
|
+
chunks.reduce((acc, c) => {
|
|
10
|
+
const merged = new Uint8Array(acc.length + c.length);
|
|
11
|
+
merged.set(acc);
|
|
12
|
+
merged.set(c, acc.length);
|
|
13
|
+
return merged;
|
|
14
|
+
}, new Uint8Array())
|
|
15
|
+
);
|
|
16
|
+
const { columns, rows } = JSON.parse(input);
|
|
17
|
+
const values = await computeFormulas(columns ?? [], rows ?? []);
|
|
18
|
+
const results = [];
|
|
19
|
+
(rows ?? []).forEach(
|
|
20
|
+
(row, dataIdx) => (columns ?? []).forEach((col, colIdx) => {
|
|
21
|
+
const v = row[col.key];
|
|
22
|
+
if (typeof v !== "string" || !v.startsWith("=")) return;
|
|
23
|
+
results.push({
|
|
24
|
+
row: dataIdx,
|
|
25
|
+
col: colIdx,
|
|
26
|
+
key: col.key,
|
|
27
|
+
formula: v,
|
|
28
|
+
value: values.get(`${dataIdx + 1},${colIdx}`) ?? null
|
|
29
|
+
});
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
process.stdout.write(JSON.stringify({ results }));
|
|
33
|
+
}
|
|
34
|
+
main().catch((error) => {
|
|
35
|
+
process.stdout.write(JSON.stringify({ error: String(error) }));
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
});
|