logisheets-core 1.1.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/dist/craft-interactions/index.d.ts +140 -0
- package/dist/craft-interactions/index.js +462 -0
- package/dist/field/index.d.ts +51 -0
- package/dist/field/index.js +70 -0
- package/dist/format/index.d.ts +21 -0
- package/dist/format/index.js +454 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +17 -0
- package/dist/ops/index.d.ts +155 -0
- package/dist/ops/index.js +335 -0
- package/dist/permissions/index.d.ts +32 -0
- package/dist/permissions/index.js +74 -0
- package/dist/port.d.ts +9 -0
- package/dist/port.js +14 -0
- package/dist/selection/index.d.ts +1 -0
- package/dist/selection/index.js +1 -0
- package/dist/selection/model.d.ts +10 -0
- package/dist/selection/model.js +38 -0
- package/dist/strings/case.d.ts +2 -0
- package/dist/strings/case.js +6 -0
- package/dist/strings/char-code.d.ts +422 -0
- package/dist/strings/char-code.js +424 -0
- package/dist/strings/common_length.d.ts +4 -0
- package/dist/strings/common_length.js +28 -0
- package/dist/strings/contain.d.ts +4 -0
- package/dist/strings/contain.js +60 -0
- package/dist/strings/index.d.ts +5 -0
- package/dist/strings/index.js +5 -0
- package/dist/strings/judges.d.ts +3 -0
- package/dist/strings/judges.js +38 -0
- package/dist/strings/surrogate.d.ts +16 -0
- package/dist/strings/surrogate.js +30 -0
- package/dist/structured/index.d.ts +41 -0
- package/dist/structured/index.js +50 -0
- package/dist/transaction/index.d.ts +8 -0
- package/dist/transaction/index.js +11 -0
- package/dist/type-guard/index.d.ts +3 -0
- package/dist/type-guard/index.js +3 -0
- package/dist/type-guard/propterty.d.ts +1 -0
- package/dist/type-guard/propterty.js +3 -0
- package/dist/type-guard/string.d.ts +1 -0
- package/dist/type-guard/string.js +3 -0
- package/dist/type-guard/u8.d.ts +1 -0
- package/dist/type-guard/u8.js +3 -0
- package/dist/utils/a1notation.d.ts +18 -0
- package/dist/utils/a1notation.js +76 -0
- package/dist/utils/array.d.ts +2 -0
- package/dist/utils/array.js +12 -0
- package/dist/utils/clone.d.ts +2 -0
- package/dist/utils/clone.js +25 -0
- package/dist/utils/const.d.ts +7 -0
- package/dist/utils/const.js +8 -0
- package/dist/utils/equal.d.ts +1 -0
- package/dist/utils/equal.js +11 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/uuid.d.ts +1 -0
- package/dist/utils/uuid.js +4 -0
- package/dist/validation/index.d.ts +34 -0
- package/dist/validation/index.js +60 -0
- package/dist/value/index.d.ts +9 -0
- package/dist/value/index.js +49 -0
- package/package.json +54 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Value } from 'logisheets-web';
|
|
2
|
+
/** The slice of the engine that structured-data ops actually need. */
|
|
3
|
+
export interface EnginePort {
|
|
4
|
+
/** Apply a cell-input transaction. Returns the engine's status object. */
|
|
5
|
+
handleTransaction(tx: GatewayTransaction): {
|
|
6
|
+
status: {
|
|
7
|
+
type: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
/** Read a single cell's evaluated value. */
|
|
11
|
+
getValue(sheetIdx: number, row: number, col: number): Value;
|
|
12
|
+
}
|
|
13
|
+
export interface GatewayTransaction {
|
|
14
|
+
payloads: ReadonlyArray<{
|
|
15
|
+
type: 'cellInput';
|
|
16
|
+
value: {
|
|
17
|
+
sheetIdx: number;
|
|
18
|
+
row: number;
|
|
19
|
+
col: number;
|
|
20
|
+
content: string;
|
|
21
|
+
};
|
|
22
|
+
}>;
|
|
23
|
+
undoable: boolean;
|
|
24
|
+
temp: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface WriteTarget {
|
|
27
|
+
sheetIdx: number;
|
|
28
|
+
startRow: number;
|
|
29
|
+
startCol: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Import: write `records` (rows of string cells) into the sheet, anchored at
|
|
33
|
+
* (startRow, startCol). One transaction for the whole block. Returns true on
|
|
34
|
+
* an `ok` engine status.
|
|
35
|
+
*/
|
|
36
|
+
export declare function writeRecords(port: EnginePort, target: WriteTarget, records: ReadonlyArray<ReadonlyArray<string>>, undoable?: boolean): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Export: read a `rows` x `cols` rectangle of evaluated values back out as a
|
|
39
|
+
* 2-D array, anchored at (startRow, startCol).
|
|
40
|
+
*/
|
|
41
|
+
export declare function readRecords(port: EnginePort, target: WriteTarget, rows: number, cols: number): Value[][];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Structured-data primitives — the engine-facing core of data-gateway.
|
|
2
|
+
//
|
|
3
|
+
// These functions are the import/export building blocks: write a 2-D block of
|
|
4
|
+
// records into the workbook, and read a rectangle of records back out. They
|
|
5
|
+
// are PURE LOGIC: they never import a concrete engine. They talk to whatever
|
|
6
|
+
// engine the host injects through the minimal `EnginePort` seam below.
|
|
7
|
+
//
|
|
8
|
+
// - browser: wrap logisheets-engine's worker-backed client as an EnginePort
|
|
9
|
+
// - node: wrap logisheets' synchronous handle()/Workbook as an EnginePort
|
|
10
|
+
//
|
|
11
|
+
// The payload/value shapes are imported as TYPES from logisheets-web, so this
|
|
12
|
+
// file still carries no runtime dependency.
|
|
13
|
+
/**
|
|
14
|
+
* Import: write `records` (rows of string cells) into the sheet, anchored at
|
|
15
|
+
* (startRow, startCol). One transaction for the whole block. Returns true on
|
|
16
|
+
* an `ok` engine status.
|
|
17
|
+
*/
|
|
18
|
+
export function writeRecords(port, target, records, undoable = true) {
|
|
19
|
+
const payloads = [];
|
|
20
|
+
records.forEach((row, r) => {
|
|
21
|
+
row.forEach((content, c) => {
|
|
22
|
+
payloads.push({
|
|
23
|
+
type: 'cellInput',
|
|
24
|
+
value: {
|
|
25
|
+
sheetIdx: target.sheetIdx,
|
|
26
|
+
row: target.startRow + r,
|
|
27
|
+
col: target.startCol + c,
|
|
28
|
+
content,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
const effect = port.handleTransaction({ payloads, undoable, temp: false });
|
|
34
|
+
return effect.status.type === 'ok';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Export: read a `rows` x `cols` rectangle of evaluated values back out as a
|
|
38
|
+
* 2-D array, anchored at (startRow, startCol).
|
|
39
|
+
*/
|
|
40
|
+
export function readRecords(port, target, rows, cols) {
|
|
41
|
+
const out = [];
|
|
42
|
+
for (let r = 0; r < rows; r++) {
|
|
43
|
+
const line = [];
|
|
44
|
+
for (let c = 0; c < cols; c++) {
|
|
45
|
+
line.push(port.getValue(target.sheetIdx, target.startRow + r, target.startCol + c));
|
|
46
|
+
}
|
|
47
|
+
out.push(line);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Transaction, Payload } from 'logisheets-web';
|
|
2
|
+
export type { Transaction, Payload };
|
|
3
|
+
/**
|
|
4
|
+
* Build a {@link Transaction}. `temp` is explicit here — the host decides
|
|
5
|
+
* where it comes from (the App reads its global temp-mode toggle; a runtime
|
|
6
|
+
* passes false). This keeps the construction logic free of any store.
|
|
7
|
+
*/
|
|
8
|
+
export declare function makeTransaction(payloads: readonly Payload[], undoable: boolean, temp: boolean): Transaction;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Transaction construction — the engine-neutral core of building an edit
|
|
2
|
+
// transaction. The browser app wraps this with a store-bound `tx()` that
|
|
3
|
+
// supplies the temp-mode flag; the Node runtime builds transactions directly.
|
|
4
|
+
/**
|
|
5
|
+
* Build a {@link Transaction}. `temp` is explicit here — the host decides
|
|
6
|
+
* where it comes from (the App reads its global temp-mode toggle; a runtime
|
|
7
|
+
* passes false). This keeps the construction logic free of any store.
|
|
8
|
+
*/
|
|
9
|
+
export function makeTransaction(payloads, undoable, temp) {
|
|
10
|
+
return { payloads, undoable, temp };
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hasOwnProperty<T, K extends PropertyKey>(obj: T, prop: K): obj is T & Record<K, unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isString(value: unknown): value is string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isArrayBuffer(value: unknown): value is ArrayBuffer;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function isA1notation(value: unknown): boolean;
|
|
2
|
+
export declare function parseA1notation(value: string): {
|
|
3
|
+
cs: number;
|
|
4
|
+
rs: number;
|
|
5
|
+
ce?: number;
|
|
6
|
+
re?: number;
|
|
7
|
+
} | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Convert a 0-based column index to A1-notation, i.e., A, BC, etc..
|
|
10
|
+
*
|
|
11
|
+
* Note that the in Excel A1-notation, row indices are plain integers and don't
|
|
12
|
+
* need to be formatted to A1-notation.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toA1notation(index: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Convert a A1-notation to 0-based column index, i.e., A, BC, etc..
|
|
17
|
+
*/
|
|
18
|
+
export declare function toZeroBasedNotation(notation: string): number;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// https://github.com/FLighter7/a1-notation
|
|
2
|
+
import { upperCase } from '../strings/index.js';
|
|
3
|
+
import { isString } from '../type-guard/index.js';
|
|
4
|
+
const a1notationReg = /^(?<cs>[A-Z]+)(?<rs>\d+)(:(?<ce>[A-Z]+)(?<re>\d+))?$/i;
|
|
5
|
+
const notationReq = /^[A-Z]/;
|
|
6
|
+
export function isA1notation(value) {
|
|
7
|
+
if (!isString(value))
|
|
8
|
+
return false;
|
|
9
|
+
return a1notationReg.test(upperCase(value));
|
|
10
|
+
}
|
|
11
|
+
// zero-based
|
|
12
|
+
export function parseA1notation(value) {
|
|
13
|
+
const result = upperCase(value).match(a1notationReg);
|
|
14
|
+
if (!result?.groups)
|
|
15
|
+
return;
|
|
16
|
+
const { ce, re, cs, rs } = result.groups;
|
|
17
|
+
return {
|
|
18
|
+
cs: toZeroBasedNotation(cs),
|
|
19
|
+
rs: parseInt(rs) - 1,
|
|
20
|
+
ce: ce ? toZeroBasedNotation(ce) : undefined,
|
|
21
|
+
re: re ? parseInt(re) - 1 : undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Convert a 0-based column index to A1-notation, i.e., A, BC, etc..
|
|
26
|
+
*
|
|
27
|
+
* Note that the in Excel A1-notation, row indices are plain integers and don't
|
|
28
|
+
* need to be formatted to A1-notation.
|
|
29
|
+
*/
|
|
30
|
+
export function toA1notation(index) {
|
|
31
|
+
/**
|
|
32
|
+
* The algorithm employed here is the same as converting numbers between
|
|
33
|
+
* different bases, e.g., decimal vs. hexadecimal.
|
|
34
|
+
*
|
|
35
|
+
* The A1-notation uses A-Z as the basic letters. Therefore it is
|
|
36
|
+
* intrinsically a 26-based notation.
|
|
37
|
+
*/
|
|
38
|
+
if (!Number.isSafeInteger(index) || index < 0)
|
|
39
|
+
throw Error(`Invalid column index '${index}'. Must be a non-negative integer.`);
|
|
40
|
+
// Use 0-based index internally.
|
|
41
|
+
let n = index;
|
|
42
|
+
let ret = '';
|
|
43
|
+
while (n > -1) {
|
|
44
|
+
// 26 = number of letters from A to Z
|
|
45
|
+
// 0x41 = 65 = the code point of 'A'
|
|
46
|
+
const codePoint = (n % 26) + 0x41;
|
|
47
|
+
ret = String.fromCodePoint(codePoint) + ret;
|
|
48
|
+
n = Math.floor(n / 26) - 1;
|
|
49
|
+
}
|
|
50
|
+
return ret;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Convert a A1-notation to 0-based column index, i.e., A, BC, etc..
|
|
54
|
+
*/
|
|
55
|
+
export function toZeroBasedNotation(notation) {
|
|
56
|
+
const n = upperCase(notation);
|
|
57
|
+
if (!n.match(notationReq) || n === '')
|
|
58
|
+
throw Error(`Invalid notation ${n}. Must be a [A-Z] character.`);
|
|
59
|
+
let index = 0;
|
|
60
|
+
// Calculation method:
|
|
61
|
+
// Example:
|
|
62
|
+
//
|
|
63
|
+
// position: "ABC"
|
|
64
|
+
// char "A" "B" "C"
|
|
65
|
+
// charCode 65 66 67
|
|
66
|
+
// number 1 2 3
|
|
67
|
+
// powNumber 2 1 0
|
|
68
|
+
// sum=number*26^powNumber 1*26^2 2*26^1 3*26^0
|
|
69
|
+
// numberSum(one_based_index) = 1*26^2 + 2*26^1 + 3*26^0 = 731
|
|
70
|
+
// index(zero_based_index) = numSum - 1 = 730
|
|
71
|
+
for (let pos = 0; pos < n.length; pos += 1) {
|
|
72
|
+
const powNumber = n.length - 1 - pos;
|
|
73
|
+
index += Math.pow(26, powNumber) * (n.charCodeAt(pos) - 64);
|
|
74
|
+
}
|
|
75
|
+
return index - 1;
|
|
76
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MAX_LEN } from './const.js';
|
|
2
|
+
export function initArr(len, value) {
|
|
3
|
+
return new Array(len).fill(value);
|
|
4
|
+
}
|
|
5
|
+
export function initTable(initValue) {
|
|
6
|
+
const table = [];
|
|
7
|
+
for (let i = 0; i <= MAX_LEN; i += 1) {
|
|
8
|
+
const row = initArr(MAX_LEN, initValue);
|
|
9
|
+
table.push(row);
|
|
10
|
+
}
|
|
11
|
+
return table;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export function shallowCopy(curr, target) {
|
|
3
|
+
if (typeof curr !== 'object' || typeof target !== 'object')
|
|
4
|
+
return;
|
|
5
|
+
for (const key in curr) {
|
|
6
|
+
if (Object.prototype.hasOwnProperty.call(curr, key)) {
|
|
7
|
+
target[key] = curr[key];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
export function deepCopy(curr, target) {
|
|
13
|
+
if (typeof curr !== 'object' || typeof target !== 'object')
|
|
14
|
+
return;
|
|
15
|
+
for (const key in curr) {
|
|
16
|
+
const v = curr[key];
|
|
17
|
+
if (typeof v !== 'object') {
|
|
18
|
+
target[key] = v;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const value = Array.isArray(v) ? [] : {};
|
|
22
|
+
deepCopy(curr[key], value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const DEBUG_WEB = true;
|
|
2
|
+
export const DEBUG_ERR = true;
|
|
3
|
+
export const MAX_LEN = 128;
|
|
4
|
+
export var AttributeName;
|
|
5
|
+
(function (AttributeName) {
|
|
6
|
+
AttributeName["SELECTOR_DND_HANDLE"] = "data-selector-dnd-handle";
|
|
7
|
+
AttributeName["SELECTOR_DND_MASK"] = "data-selector-dnd-mask";
|
|
8
|
+
})(AttributeName || (AttributeName = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function equal(a: any, b: any): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function simpleUuid(): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Value } from 'logisheets-web';
|
|
2
|
+
/** One cell's validation rule. `formula` is an Excel expression (no leading
|
|
3
|
+
* `=`) that should reference the target cell(s) and evaluate to a boolean,
|
|
4
|
+
* e.g. `A1>0` or `LEN(B2)<=10`. */
|
|
5
|
+
export interface ValidationRule {
|
|
6
|
+
sheetIdx: number;
|
|
7
|
+
row: number;
|
|
8
|
+
col: number;
|
|
9
|
+
formula: string;
|
|
10
|
+
}
|
|
11
|
+
export type ViolationKind = 'failed' | 'error' | 'required' | 'duplicate' | 'membership';
|
|
12
|
+
export interface Violation {
|
|
13
|
+
sheetIdx: number;
|
|
14
|
+
row: number;
|
|
15
|
+
col: number;
|
|
16
|
+
formula?: string;
|
|
17
|
+
kind: ViolationKind;
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Interpret a single evaluated validation result. Mirrors the branch logic
|
|
22
|
+
* in the browser's ValidationCell:
|
|
23
|
+
* - empty -> valid (nothing to check)
|
|
24
|
+
* - bool false -> failed
|
|
25
|
+
* - error -> formula error
|
|
26
|
+
* - anything else -> unexpected, treated as error
|
|
27
|
+
*/
|
|
28
|
+
export declare function interpretValidation(rule: ValidationRule, value: Value): Violation | null;
|
|
29
|
+
/**
|
|
30
|
+
* Check every rule and return the cells that break their validation. Pure:
|
|
31
|
+
* the caller supplies `evalFormula` (WorkbookOps wraps the engine). `rules`
|
|
32
|
+
* are evaluated against the values already resolved by the caller.
|
|
33
|
+
*/
|
|
34
|
+
export declare function checkValidations(rules: readonly ValidationRule[], evalFormula: (sheetIdx: number, formula: string) => Value): Violation[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Validation — headless rule checking.
|
|
2
|
+
//
|
|
3
|
+
// A validation rule is just a formula that must evaluate to TRUE for the cell
|
|
4
|
+
// to be valid (this is exactly the model used by the browser's ValidationCell:
|
|
5
|
+
// it writes `=<formula>` into a shadow/ephemeral cell, lets the WASM engine
|
|
6
|
+
// evaluate it, and reads back a bool). The *evaluation* lives entirely in the
|
|
7
|
+
// engine, so it already runs on Node — this module is only the pure result
|
|
8
|
+
// interpretation. The engine access is supplied by the caller as a plain
|
|
9
|
+
// `evalFormula` function (WorkbookOps wraps the Client); see ../ops.
|
|
10
|
+
/**
|
|
11
|
+
* Interpret a single evaluated validation result. Mirrors the branch logic
|
|
12
|
+
* in the browser's ValidationCell:
|
|
13
|
+
* - empty -> valid (nothing to check)
|
|
14
|
+
* - bool false -> failed
|
|
15
|
+
* - error -> formula error
|
|
16
|
+
* - anything else -> unexpected, treated as error
|
|
17
|
+
*/
|
|
18
|
+
export function interpretValidation(rule, value) {
|
|
19
|
+
if (value === undefined)
|
|
20
|
+
return null;
|
|
21
|
+
// The engine represents an empty cell as the literal string 'empty'.
|
|
22
|
+
if (value === 'empty')
|
|
23
|
+
return null;
|
|
24
|
+
const v = value;
|
|
25
|
+
if (v.type === 'empty')
|
|
26
|
+
return null;
|
|
27
|
+
if (v.type === 'bool') {
|
|
28
|
+
if (v.value === false) {
|
|
29
|
+
return {
|
|
30
|
+
...rule,
|
|
31
|
+
kind: 'failed',
|
|
32
|
+
message: 'Value does not meet validation criteria',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (v.type === 'error') {
|
|
38
|
+
return {
|
|
39
|
+
...rule,
|
|
40
|
+
kind: 'error',
|
|
41
|
+
message: 'Validation formula error: ' + String(v.value),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return { ...rule, kind: 'error', message: 'Unexpected validation result' };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check every rule and return the cells that break their validation. Pure:
|
|
48
|
+
* the caller supplies `evalFormula` (WorkbookOps wraps the engine). `rules`
|
|
49
|
+
* are evaluated against the values already resolved by the caller.
|
|
50
|
+
*/
|
|
51
|
+
export function checkValidations(rules, evalFormula) {
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const rule of rules) {
|
|
54
|
+
const value = evalFormula(rule.sheetIdx, rule.formula);
|
|
55
|
+
const violation = interpretValidation(rule, value);
|
|
56
|
+
if (violation)
|
|
57
|
+
out.push(violation);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Value } from 'logisheets-web';
|
|
2
|
+
/** The engine represents an empty cell as the literal string 'empty'. */
|
|
3
|
+
export declare function isValueEmpty(v: Value): boolean;
|
|
4
|
+
/** Extract a string, or '' for non-string / empty values. */
|
|
5
|
+
export declare function valueToString(val: Value): string;
|
|
6
|
+
/** Extract a number, or null for non-number / empty values. */
|
|
7
|
+
export declare function valueToNumber(val: Value): number | null;
|
|
8
|
+
/** Coerce any Value to its display string (str / number / bool). */
|
|
9
|
+
export declare function valueToDisplayString(val: Value): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Pure Value helpers — parsing/formatting/emptiness of engine cell values.
|
|
2
|
+
//
|
|
3
|
+
// These are data transformations with no UI or engine dependency (the Value
|
|
4
|
+
// type is imported as a type only), so they are shared by the App's renderers
|
|
5
|
+
// and any Node-side logic.
|
|
6
|
+
/** The engine represents an empty cell as the literal string 'empty'. */
|
|
7
|
+
export function isValueEmpty(v) {
|
|
8
|
+
if (v === undefined)
|
|
9
|
+
return true;
|
|
10
|
+
if (v === 'empty')
|
|
11
|
+
return true;
|
|
12
|
+
const x = v;
|
|
13
|
+
if (x.type === 'empty')
|
|
14
|
+
return true;
|
|
15
|
+
if (x.type === 'str' && (x.value === '' || x.value === undefined))
|
|
16
|
+
return true;
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
/** Extract a string, or '' for non-string / empty values. */
|
|
20
|
+
export function valueToString(val) {
|
|
21
|
+
if (val === 'empty')
|
|
22
|
+
return '';
|
|
23
|
+
const x = val;
|
|
24
|
+
if (x.type === 'str')
|
|
25
|
+
return x.value;
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
/** Extract a number, or null for non-number / empty values. */
|
|
29
|
+
export function valueToNumber(val) {
|
|
30
|
+
if (val === 'empty')
|
|
31
|
+
return null;
|
|
32
|
+
const x = val;
|
|
33
|
+
if (x.type === 'number')
|
|
34
|
+
return x.value;
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/** Coerce any Value to its display string (str / number / bool). */
|
|
38
|
+
export function valueToDisplayString(val) {
|
|
39
|
+
if (val === 'empty')
|
|
40
|
+
return '';
|
|
41
|
+
const x = val;
|
|
42
|
+
if (x.type === 'str')
|
|
43
|
+
return x.value;
|
|
44
|
+
if (x.type === 'number')
|
|
45
|
+
return String(x.value);
|
|
46
|
+
if (x.type === 'bool')
|
|
47
|
+
return x.value ? 'TRUE' : 'FALSE';
|
|
48
|
+
return '';
|
|
49
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "logisheets-core",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "UI-free LogiSheets logic — runs in the browser or on Node. Depends on logisheets-web only for types; the engine Client is injected by the host.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./strings": {
|
|
15
|
+
"types": "./dist/strings/index.d.ts",
|
|
16
|
+
"default": "./dist/strings/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./type-guard": {
|
|
19
|
+
"types": "./dist/type-guard/index.d.ts",
|
|
20
|
+
"default": "./dist/type-guard/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./selection": {
|
|
23
|
+
"types": "./dist/selection/index.d.ts",
|
|
24
|
+
"default": "./dist/selection/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./utils": {
|
|
27
|
+
"types": "./dist/utils/index.d.ts",
|
|
28
|
+
"default": "./dist/utils/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./value": {
|
|
31
|
+
"types": "./dist/value/index.d.ts",
|
|
32
|
+
"default": "./dist/value/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -p tsconfig.build.json",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"prepack": "yarn build"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist"
|
|
43
|
+
],
|
|
44
|
+
"author": "Jeremy He",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"logisheets-web": "^1.1.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"logisheets-web": "workspace:*",
|
|
51
|
+
"typescript": "^5.5.0",
|
|
52
|
+
"vitest": "^2.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|