@kuzuma/colwork 0.0.0-stage → 0.2.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 +21 -0
- package/README.md +326 -2
- package/dist/colwork.css +1 -0
- package/dist/colwork.js +1928 -0
- package/dist/colwork.umd.cjs +7 -0
- package/dist/index.d.ts +324 -0
- package/dist/model-merges.d.cts +3 -0
- package/dist/model-merges.d.ts +3 -0
- package/dist/model-schema.d.cts +80 -0
- package/dist/model-schema.d.ts +80 -0
- package/dist/model-validation.d.cts +7 -0
- package/dist/model-validation.d.ts +7 -0
- package/dist/model.cjs +1 -0
- package/dist/model.d.cts +18 -0
- package/dist/model.d.ts +18 -0
- package/dist/model.js +259 -0
- package/dist/range.d.cts +15 -0
- package/dist/range.d.ts +15 -0
- package/dist/yjsArchive.d.cts +28 -0
- package/dist/yjsArchive.d.ts +28 -0
- package/dist/yjsRebuild.d.cts +2 -0
- package/dist/yjsRebuild.d.ts +2 -0
- package/package.json +90 -4
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CellRange } from './range.js';
|
|
2
|
+
import type * as Y from 'yjs';
|
|
3
|
+
/** The existing version-one wire format. Missing metadata is valid legacy data. */
|
|
4
|
+
export declare const COLWORK_SCHEMA_VERSION: 1;
|
|
5
|
+
export declare const COLWORK_MAP_NAMES: Readonly<{
|
|
6
|
+
readonly cells: "cells";
|
|
7
|
+
readonly styles: "styles";
|
|
8
|
+
readonly rowHeights: "rowHeights";
|
|
9
|
+
readonly columnWidths: "columnWidths";
|
|
10
|
+
readonly merges: "merges";
|
|
11
|
+
readonly locks: "locks";
|
|
12
|
+
readonly metadata: "colwork-metadata";
|
|
13
|
+
}>;
|
|
14
|
+
export type CellBorder = {
|
|
15
|
+
top?: boolean;
|
|
16
|
+
right?: boolean;
|
|
17
|
+
bottom?: boolean;
|
|
18
|
+
left?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type CellStyle = {
|
|
21
|
+
bold?: boolean;
|
|
22
|
+
italic?: boolean;
|
|
23
|
+
underline?: boolean;
|
|
24
|
+
strike?: boolean;
|
|
25
|
+
wrap?: boolean;
|
|
26
|
+
border?: CellBorder;
|
|
27
|
+
fontSize?: number;
|
|
28
|
+
color?: string;
|
|
29
|
+
background?: string;
|
|
30
|
+
align?: 'left' | 'center' | 'right';
|
|
31
|
+
format?: 'general' | 'number' | 'date' | 'percent';
|
|
32
|
+
};
|
|
33
|
+
export type PasswordLock = {
|
|
34
|
+
version: 1;
|
|
35
|
+
algorithm: 'PBKDF2-SHA-256';
|
|
36
|
+
iterations: 600000;
|
|
37
|
+
salt: string;
|
|
38
|
+
verifier: string;
|
|
39
|
+
};
|
|
40
|
+
export type CellLock = '1' | PasswordLock;
|
|
41
|
+
export type SheetMaps = {
|
|
42
|
+
cells: Y.Map<string>;
|
|
43
|
+
styles: Y.Map<string>;
|
|
44
|
+
rowHeights: Y.Map<number>;
|
|
45
|
+
columnWidths: Y.Map<number>;
|
|
46
|
+
merges: Y.Map<string>;
|
|
47
|
+
locks: Y.Map<string>;
|
|
48
|
+
};
|
|
49
|
+
/** Sparse, JSON-serializable logical sheet. Dimensions are derived from stored data. */
|
|
50
|
+
export type SheetSnapshot = {
|
|
51
|
+
schemaVersion: typeof COLWORK_SCHEMA_VERSION;
|
|
52
|
+
rowCount: number;
|
|
53
|
+
columnCount: number;
|
|
54
|
+
cells: Record<string, string>;
|
|
55
|
+
styles: Record<string, CellStyle>;
|
|
56
|
+
rowHeights: Record<string, number>;
|
|
57
|
+
columnWidths: Record<string, number>;
|
|
58
|
+
merges: CellRange[];
|
|
59
|
+
locks: Record<string, CellLock>;
|
|
60
|
+
};
|
|
61
|
+
export type SheetValidationIssue = {
|
|
62
|
+
path: string;
|
|
63
|
+
message: string;
|
|
64
|
+
};
|
|
65
|
+
export declare function parseCellKey(key: string): {
|
|
66
|
+
row: number;
|
|
67
|
+
column: number;
|
|
68
|
+
} | undefined;
|
|
69
|
+
export declare function mergeKey(range: CellRange): string;
|
|
70
|
+
export declare function parseMergeKey(key: string): CellRange | undefined;
|
|
71
|
+
/** Optional host policy. Omitted numeric limits impose no application-specific cap. */
|
|
72
|
+
export type SheetValidationLimits = {
|
|
73
|
+
maxRows?: number;
|
|
74
|
+
maxColumns?: number;
|
|
75
|
+
maxEntries?: number;
|
|
76
|
+
maxStringLength?: number;
|
|
77
|
+
maxMergeArea?: number;
|
|
78
|
+
maxMerges?: number;
|
|
79
|
+
allowUnknownRoots?: boolean;
|
|
80
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CellStyle, PasswordLock, SheetMaps, SheetValidationIssue, SheetValidationLimits } from './model-schema.cjs';
|
|
2
|
+
import * as Y from 'yjs';
|
|
3
|
+
export declare function isPasswordLock(value: unknown): value is PasswordLock;
|
|
4
|
+
export declare function isCellStyle(value: unknown): value is CellStyle;
|
|
5
|
+
/** Materializes named Y.Map roots, preserving the version-one encoding. */
|
|
6
|
+
export declare function getSheetMaps(document: Y.Doc): SheetMaps;
|
|
7
|
+
export declare function validateSheetDocument(document: Y.Doc, limits?: SheetValidationLimits): SheetValidationIssue[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CellStyle, PasswordLock, SheetMaps, SheetValidationIssue, SheetValidationLimits } from './model-schema.js';
|
|
2
|
+
import * as Y from 'yjs';
|
|
3
|
+
export declare function isPasswordLock(value: unknown): value is PasswordLock;
|
|
4
|
+
export declare function isCellStyle(value: unknown): value is CellStyle;
|
|
5
|
+
/** Materializes named Y.Map roots, preserving the version-one encoding. */
|
|
6
|
+
export declare function getSheetMaps(document: Y.Doc): SheetMaps;
|
|
7
|
+
export declare function validateSheetDocument(document: Y.Doc, limits?: SheetValidationLimits): SheetValidationIssue[];
|
package/dist/model.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("yjs");function _(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const g=_(I),y=1,p=Object.freeze({cells:"cells",styles:"styles",rowHeights:"rowHeights",columnWidths:"columnWidths",merges:"merges",locks:"locks",metadata:"colwork-metadata"});function S(e){if(!/^(0|[1-9]\d*):(0|[1-9]\d*)$/.test(e))return;const[t,r]=e.split(":").map(Number);return Number.isSafeInteger(t)&&Number.isSafeInteger(r)?{row:t,column:r}:void 0}function R(e){return`${e.start.row}:${e.start.column}-${e.end.row}:${e.end.column}`}function E(e){const t=e.split("-");if(t.length!==2)return;const r=S(t[0]),n=S(t[1]);if(!(!r||!n||r.row>n.row||r.column>n.column))return{start:r,end:n}}function z(e){for(const t of e){const r=t.codePointAt(0);if(r>=55296&&r<=57343)return!1}return!0}function U(e){if(e.length<2)return!1;const t=[...new Set(e.flatMap(i=>[i.start.column,i.end.column+1]))].sort((i,m)=>i-m),r=new Map(t.map((i,m)=>[i,m])),n=e.flatMap(i=>[{row:i.start.row,left:r.get(i.start.column),right:r.get(i.end.column+1)-1,delta:1},{row:i.end.row+1,left:r.get(i.start.column),right:r.get(i.end.column+1)-1,delta:-1}]).sort((i,m)=>i.row-m.row||i.delta-m.delta),f=new Int32Array(t.length*4),d=new Int32Array(t.length*4),u=(i,m,c,l,o,s)=>{if(l<=m&&c<=o){f[i]+=s,d[i]+=s;return}const a=Math.floor((m+c)/2);l<=a&&u(i*2,m,a,l,o,s),o>a&&u(i*2+1,a+1,c,l,o,s),f[i]=d[i]+Math.max(f[i*2],f[i*2+1])};for(const i of n)if(u(1,0,t.length-2,i.left,i.right,i.delta),f[1]>1)return!0;return!1}const x=e=>!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype,k=(e,t)=>Object.keys(e).every(r=>t.includes(r));function q(e){return x(e)&&k(e,["version","algorithm","iterations","salt","verifier"])&&e.version===1&&e.algorithm==="PBKDF2-SHA-256"&&e.iterations===6e5&&typeof e.salt=="string"&&/^[0-9a-f]{32}$/.test(e.salt)&&typeof e.verifier=="string"&&/^[0-9a-f]{64}$/.test(e.verifier)}function K(e){if(!x(e)||!k(e,["bold","italic","underline","strike","wrap","border","fontSize","color","background","align","format"]))return!1;for(const t of["bold","italic","underline","strike","wrap"])if(t in e&&typeof e[t]!="boolean")return!1;for(const t of["color","background"])if(t in e&&(typeof e[t]!="string"||!z(e[t])))return!1;if("fontSize"in e&&(typeof e.fontSize!="number"||!Number.isFinite(e.fontSize)||e.fontSize<=0)||"align"in e&&(typeof e.align!="string"||!["left","center","right"].includes(e.align))||"format"in e&&(typeof e.format!="string"||!["general","number","date","percent"].includes(e.format)))return!1;if("border"in e){if(!x(e.border)||!k(e.border,["top","right","bottom","left"]))return!1;for(const t of Object.keys(e.border))if(typeof e.border[t]!="boolean")return!1}return!0}function M(e){return{cells:e.getMap(p.cells),styles:e.getMap(p.styles),rowHeights:e.getMap(p.rowHeights),columnWidths:e.getMap(p.columnWidths),merges:e.getMap(p.merges),locks:e.getMap(p.locks)}}function O(e,t={}){for(const o of["maxRows","maxColumns","maxEntries","maxStringLength","maxMergeArea","maxMerges"]){const s=t[o];if(s!==void 0&&(!Number.isSafeInteger(s)||s<0))throw new RangeError(`${o} must be a non-negative safe integer`)}const r=[];(e.store.pendingStructs!==null||e.store.pendingDs!==null)&&r.push({path:"$",message:"Document contains unresolved Yjs update dependencies"});const n=(o,s)=>{r.push({path:o,message:s})};if(!t.allowUnknownRoots)for(const o of e.share.keys())Object.values(p).includes(o)||n(o,"Unknown document root");let f,d;try{f=M(e),d=e.getMap(p.metadata)}catch{return[...r,{path:"$",message:"Sheet roots must be Y.Map values"}]}for(const[o,s]of[...Object.entries(f),["metadata",d]])(!(s instanceof g.Map)||s._start!==null)&&n(o,"Expected map entries without sequence content");const u=Object.values(f).reduce((o,s)=>o+s.size,d.size);t.maxEntries!==void 0&&u>t.maxEntries&&n("$","Document exceeds maxEntries");const i=(o,s)=>o<Number.MAX_SAFE_INTEGER&&s<Number.MAX_SAFE_INTEGER&&(t.maxRows===void 0||o<t.maxRows)&&(t.maxColumns===void 0||s<t.maxColumns),m=(o,s)=>{if(typeof o!="string")return!1;try{return s(JSON.parse(o))}catch{return!1}},c=(o,s,a)=>{typeof a=="string"&&t.maxStringLength!==void 0&&a.length>t.maxStringLength&&n(`${o}.${s}`,"String exceeds maxStringLength")};for(const o of["cells","styles","locks"])f[o].forEach((s,a)=>{const h=S(a);(!h||!i(h.row,h.column))&&n(`${o}.${a}`,"Invalid or out-of-bounds row:column key"),c(o,a,s),o==="cells"&&(typeof s!="string"||!z(s))&&n(`${o}.${a}`,"Cell values must be strings"),o==="styles"&&!m(s,K)&&n(`${o}.${a}`,"Expected a JSON CellStyle object"),o==="locks"&&s!=="1"&&!m(s,q)&&n(`${o}.${a}`,"Expected a plain lock or version-one password verifier")});for(const o of["rowHeights","columnWidths"])f[o].forEach((s,a)=>{const h=Number(a),N=o==="rowHeights"?t.maxRows:t.maxColumns;(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(h)||h>=Number.MAX_SAFE_INTEGER||N!==void 0&&h>=N)&&n(`${o}.${a}`,"Invalid or out-of-bounds index"),(typeof s!="number"||!Number.isFinite(s)||s<=0)&&n(`${o}.${a}`,"Sizes must be finite positive numbers")});t.maxMerges!==void 0&&f.merges.size>t.maxMerges&&n("merges","Document exceeds maxMerges");const l=[];return f.merges.forEach((o,s)=>{const a=E(s);!a||o!=="1"||!i(a.end.row,a.end.column)?n(`merges.${s}`,"Invalid or out-of-bounds merge range"):(t.maxMergeArea!==void 0&&a.end.row-a.start.row+1>t.maxMergeArea/(a.end.column-a.start.column+1)&&n(`merges.${s}`,"Merge exceeds maxMergeArea"),l.push(a))}),U(l)&&n("merges","Merge ranges must not overlap"),d.forEach((o,s)=>{s==="schemaVersion"?o!==y&&n("metadata.schemaVersion","Unsupported schema version"):s==="initialized"?typeof o!="boolean"&&n("metadata.initialized","Expected a boolean"):n(`metadata.${s}`,"Unknown metadata field")}),r}function w(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}function $(e){const t=atob(e);return Uint8Array.from(t,r=>r.charCodeAt(0))}function j(e){if(e!=null&&e.trim())return JSON.parse(e)}function V(e){if(!(!e||e.format==="colwork.update-log"))return e.format==="colwork.archive"?e.snapshot:e}function A(e){return!e||e.format==="colwork.snapshot"?[]:e.updates??[]}function H(e,t){const r=j(e),n=j(t),f=V(r),d=[...A(r),...A(n)],u=new g.Doc;try{f!=null&&f.snapshot&&g.applyUpdate(u,$(f.snapshot));const i=Number((f==null?void 0:f.sequence)??0),m=new Set,c=new Set;let l=i;for(const o of d.sort((s,a)=>Number(s.seq)-Number(a.seq))){const s=Number(o.seq);!Number.isInteger(s)||typeof o.update!="string"||s<=i||m.has(s)||c.has(o.update)||(g.applyUpdate(u,$(o.update)),m.add(s),c.add(o.update),l=Math.max(l,s))}return{format:"colwork.snapshot",version:1,room:f==null?void 0:f.room,sequence:l,snapshot:w(g.encodeStateAsUpdate(u)),stateVector:w(g.encodeStateVector(u))}}finally{u.destroy()}}function W(e,t){const r=e.split(":").map(Number),n=t.split(":").map(Number);return r[0]-n[0]||(r[1]??0)-(n[1]??0)}function b(e){return[...e].sort(([t],[r])=>W(t,r))}function D(e){const t={};for(const r of["bold","italic","underline","strike","wrap","fontSize","color","background","align","format"])e[r]!==void 0&&(t[r]=e[r]);if(e.border!==void 0){const r={};for(const n of["top","right","bottom","left"])e.border[n]!==void 0&&(r[n]=e.border[n]);t.border=r}return t}function C(e,t){const r=O(e,t);if(r.length)throw new TypeError(`Invalid Colwork document at ${r[0].path}: ${r[0].message}`);const n=M(e),f=Object.fromEntries(b(n.styles).map(([c,l])=>[c,D(JSON.parse(l))])),d=Object.fromEntries(b(n.locks).map(([c,l])=>{if(l==="1")return[c,"1"];const o=JSON.parse(l);return[c,{version:o.version,algorithm:o.algorithm,iterations:o.iterations,salt:o.salt,verifier:o.verifier}]})),u=[...n.merges.keys()].map(c=>E(c)).sort((c,l)=>c.start.row-l.start.row||c.start.column-l.start.column||c.end.row-l.end.row||c.end.column-l.end.column);let i=1,m=1;for(const c of[...n.cells.keys(),...n.styles.keys(),...n.locks.keys()]){const l=S(c);i=Math.max(i,l.row+1),m=Math.max(m,l.column+1)}for(const c of u)i=Math.max(i,c.end.row+1),m=Math.max(m,c.end.column+1);for(const c of n.rowHeights.keys())i=Math.max(i,Number(c)+1);for(const c of n.columnWidths.keys())m=Math.max(m,Number(c)+1);return{schemaVersion:y,rowCount:i,columnCount:m,cells:Object.fromEntries(b(n.cells)),styles:f,rowHeights:Object.fromEntries(b(n.rowHeights)),columnWidths:Object.fromEntries(b(n.columnWidths)),merges:u,locks:d}}function L(e){const t=O(e);if(t.length)throw new TypeError(`Invalid Colwork document at ${t[0].path}: ${t[0].message}`);if(Object.values(M(e)).some(n=>n.size>0))throw new Error("Blank initialization requires an empty sheet");const r=e.getMap(p.metadata);e.transact(()=>{r.set("schemaVersion",y),r.set("initialized",!0)})}function P(e,t={}){const r=t.sequence??0;if(!Number.isSafeInteger(r)||r<0)throw new RangeError("sequence must be a non-negative safe integer");return{format:"colwork.snapshot",version:1,room:t.room,sequence:r,snapshot:w(g.encodeStateAsUpdate(e)),stateVector:w(g.encodeStateVector(e))}}function T(e,t){const r=new g.Doc;try{return g.applyUpdate(r,e),C(r,t)}finally{r.destroy()}}exports.COLWORK_MAP_NAMES=p;exports.COLWORK_SCHEMA_VERSION=y;exports.exportYjsSnapshot=P;exports.getSheetMaps=M;exports.initializeBlankSheet=L;exports.mergeKey=R;exports.parseCellKey=S;exports.parseMergeKey=E;exports.readSheetSnapshot=C;exports.readSheetSnapshotUpdate=T;exports.rebuildYjsSnapshot=H;exports.validateSheetDocument=O;
|
package/dist/model.d.cts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SheetSnapshot, SheetValidationLimits } from './model-schema.cjs';
|
|
2
|
+
import { YjsSnapshotFile } from './yjsArchive.cjs';
|
|
3
|
+
import * as Y from 'yjs';
|
|
4
|
+
export * from './model-schema.cjs';
|
|
5
|
+
export type { CellPosition, CellRange } from './range.cjs';
|
|
6
|
+
export { getSheetMaps, validateSheetDocument } from './model-validation.cjs';
|
|
7
|
+
export { rebuildYjsSnapshot } from './yjsRebuild.cjs';
|
|
8
|
+
export type { YjsArchiveFile, YjsSnapshotFile, YjsUpdateLogFile, YjsUpdateRecord } from './yjsArchive.cjs';
|
|
9
|
+
/** Reads a deterministic sparse sheet without loading a renderer, browser globals, or CSS. */
|
|
10
|
+
export declare function readSheetSnapshot(document: Y.Doc, limits?: SheetValidationLimits): SheetSnapshot;
|
|
11
|
+
/** Initializes an empty document without demo cells, headers, styles, or network access. */
|
|
12
|
+
export declare function initializeBlankSheet(document: Y.Doc): void;
|
|
13
|
+
export declare function exportYjsSnapshot(document: Y.Doc, options?: {
|
|
14
|
+
room?: string;
|
|
15
|
+
sequence?: number;
|
|
16
|
+
}): YjsSnapshotFile;
|
|
17
|
+
/** Decodes a Yjs state update and releases its temporary document after export. */
|
|
18
|
+
export declare function readSheetSnapshotUpdate(update: Uint8Array, limits?: SheetValidationLimits): SheetSnapshot;
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SheetSnapshot, SheetValidationLimits } from './model-schema.js';
|
|
2
|
+
import { YjsSnapshotFile } from './yjsArchive.js';
|
|
3
|
+
import * as Y from 'yjs';
|
|
4
|
+
export * from './model-schema.js';
|
|
5
|
+
export type { CellPosition, CellRange } from './range.js';
|
|
6
|
+
export { getSheetMaps, validateSheetDocument } from './model-validation.js';
|
|
7
|
+
export { rebuildYjsSnapshot } from './yjsRebuild.js';
|
|
8
|
+
export type { YjsArchiveFile, YjsSnapshotFile, YjsUpdateLogFile, YjsUpdateRecord } from './yjsArchive.js';
|
|
9
|
+
/** Reads a deterministic sparse sheet without loading a renderer, browser globals, or CSS. */
|
|
10
|
+
export declare function readSheetSnapshot(document: Y.Doc, limits?: SheetValidationLimits): SheetSnapshot;
|
|
11
|
+
/** Initializes an empty document without demo cells, headers, styles, or network access. */
|
|
12
|
+
export declare function initializeBlankSheet(document: Y.Doc): void;
|
|
13
|
+
export declare function exportYjsSnapshot(document: Y.Doc, options?: {
|
|
14
|
+
room?: string;
|
|
15
|
+
sequence?: number;
|
|
16
|
+
}): YjsSnapshotFile;
|
|
17
|
+
/** Decodes a Yjs state update and releases its temporary document after export. */
|
|
18
|
+
export declare function readSheetSnapshotUpdate(update: Uint8Array, limits?: SheetValidationLimits): SheetSnapshot;
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import * as p from "yjs";
|
|
2
|
+
const M = 1, g = Object.freeze({
|
|
3
|
+
cells: "cells",
|
|
4
|
+
styles: "styles",
|
|
5
|
+
rowHeights: "rowHeights",
|
|
6
|
+
columnWidths: "columnWidths",
|
|
7
|
+
merges: "merges",
|
|
8
|
+
locks: "locks",
|
|
9
|
+
metadata: "colwork-metadata"
|
|
10
|
+
});
|
|
11
|
+
function w(e) {
|
|
12
|
+
if (!/^(0|[1-9]\d*):(0|[1-9]\d*)$/.test(e)) return;
|
|
13
|
+
const [t, r] = e.split(":").map(Number);
|
|
14
|
+
return Number.isSafeInteger(t) && Number.isSafeInteger(r) ? { row: t, column: r } : void 0;
|
|
15
|
+
}
|
|
16
|
+
function _(e) {
|
|
17
|
+
return `${e.start.row}:${e.start.column}-${e.end.row}:${e.end.column}`;
|
|
18
|
+
}
|
|
19
|
+
function A(e) {
|
|
20
|
+
const t = e.split("-");
|
|
21
|
+
if (t.length !== 2) return;
|
|
22
|
+
const r = w(t[0]), n = w(t[1]);
|
|
23
|
+
if (!(!r || !n || r.row > n.row || r.column > n.column))
|
|
24
|
+
return { start: r, end: n };
|
|
25
|
+
}
|
|
26
|
+
function z(e) {
|
|
27
|
+
for (const t of e) {
|
|
28
|
+
const r = t.codePointAt(0);
|
|
29
|
+
if (r >= 55296 && r <= 57343) return !1;
|
|
30
|
+
}
|
|
31
|
+
return !0;
|
|
32
|
+
}
|
|
33
|
+
function I(e) {
|
|
34
|
+
if (e.length < 2) return !1;
|
|
35
|
+
const t = [...new Set(e.flatMap((i) => [i.start.column, i.end.column + 1]))].sort((i, m) => i - m), r = new Map(t.map((i, m) => [i, m])), n = e.flatMap((i) => [
|
|
36
|
+
{ row: i.start.row, left: r.get(i.start.column), right: r.get(i.end.column + 1) - 1, delta: 1 },
|
|
37
|
+
{ row: i.end.row + 1, left: r.get(i.start.column), right: r.get(i.end.column + 1) - 1, delta: -1 }
|
|
38
|
+
]).sort((i, m) => i.row - m.row || i.delta - m.delta), f = new Int32Array(t.length * 4), d = new Int32Array(t.length * 4), l = (i, m, c, u, o, s) => {
|
|
39
|
+
if (u <= m && c <= o) {
|
|
40
|
+
f[i] += s, d[i] += s;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const a = Math.floor((m + c) / 2);
|
|
44
|
+
u <= a && l(i * 2, m, a, u, o, s), o > a && l(i * 2 + 1, a + 1, c, u, o, s), f[i] = d[i] + Math.max(f[i * 2], f[i * 2 + 1]);
|
|
45
|
+
};
|
|
46
|
+
for (const i of n)
|
|
47
|
+
if (l(1, 0, t.length - 2, i.left, i.right, i.delta), f[1] > 1) return !0;
|
|
48
|
+
return !1;
|
|
49
|
+
}
|
|
50
|
+
const S = (e) => !!e && typeof e == "object" && !Array.isArray(e) && Object.getPrototypeOf(e) === Object.prototype, x = (e, t) => Object.keys(e).every((r) => t.includes(r));
|
|
51
|
+
function C(e) {
|
|
52
|
+
return S(e) && x(e, ["version", "algorithm", "iterations", "salt", "verifier"]) && e.version === 1 && e.algorithm === "PBKDF2-SHA-256" && e.iterations === 6e5 && typeof e.salt == "string" && /^[0-9a-f]{32}$/.test(e.salt) && typeof e.verifier == "string" && /^[0-9a-f]{64}$/.test(e.verifier);
|
|
53
|
+
}
|
|
54
|
+
function R(e) {
|
|
55
|
+
if (!S(e) || !x(e, ["bold", "italic", "underline", "strike", "wrap", "border", "fontSize", "color", "background", "align", "format"])) return !1;
|
|
56
|
+
for (const t of ["bold", "italic", "underline", "strike", "wrap"]) if (t in e && typeof e[t] != "boolean") return !1;
|
|
57
|
+
for (const t of ["color", "background"]) if (t in e && (typeof e[t] != "string" || !z(e[t]))) return !1;
|
|
58
|
+
if ("fontSize" in e && (typeof e.fontSize != "number" || !Number.isFinite(e.fontSize) || e.fontSize <= 0) || "align" in e && (typeof e.align != "string" || !["left", "center", "right"].includes(e.align)) || "format" in e && (typeof e.format != "string" || !["general", "number", "date", "percent"].includes(e.format))) return !1;
|
|
59
|
+
if ("border" in e) {
|
|
60
|
+
if (!S(e.border) || !x(e.border, ["top", "right", "bottom", "left"])) return !1;
|
|
61
|
+
for (const t of Object.keys(e.border)) if (typeof e.border[t] != "boolean") return !1;
|
|
62
|
+
}
|
|
63
|
+
return !0;
|
|
64
|
+
}
|
|
65
|
+
function k(e) {
|
|
66
|
+
return {
|
|
67
|
+
cells: e.getMap(g.cells),
|
|
68
|
+
styles: e.getMap(g.styles),
|
|
69
|
+
rowHeights: e.getMap(g.rowHeights),
|
|
70
|
+
columnWidths: e.getMap(g.columnWidths),
|
|
71
|
+
merges: e.getMap(g.merges),
|
|
72
|
+
locks: e.getMap(g.locks)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function j(e, t = {}) {
|
|
76
|
+
for (const o of ["maxRows", "maxColumns", "maxEntries", "maxStringLength", "maxMergeArea", "maxMerges"]) {
|
|
77
|
+
const s = t[o];
|
|
78
|
+
if (s !== void 0 && (!Number.isSafeInteger(s) || s < 0)) throw new RangeError(`${o} must be a non-negative safe integer`);
|
|
79
|
+
}
|
|
80
|
+
const r = [];
|
|
81
|
+
(e.store.pendingStructs !== null || e.store.pendingDs !== null) && r.push({ path: "$", message: "Document contains unresolved Yjs update dependencies" });
|
|
82
|
+
const n = (o, s) => {
|
|
83
|
+
r.push({ path: o, message: s });
|
|
84
|
+
};
|
|
85
|
+
if (!t.allowUnknownRoots)
|
|
86
|
+
for (const o of e.share.keys())
|
|
87
|
+
Object.values(g).includes(o) || n(o, "Unknown document root");
|
|
88
|
+
let f, d;
|
|
89
|
+
try {
|
|
90
|
+
f = k(e), d = e.getMap(g.metadata);
|
|
91
|
+
} catch {
|
|
92
|
+
return [...r, { path: "$", message: "Sheet roots must be Y.Map values" }];
|
|
93
|
+
}
|
|
94
|
+
for (const [o, s] of [...Object.entries(f), ["metadata", d]])
|
|
95
|
+
(!(s instanceof p.Map) || s._start !== null) && n(o, "Expected map entries without sequence content");
|
|
96
|
+
const l = Object.values(f).reduce((o, s) => o + s.size, d.size);
|
|
97
|
+
t.maxEntries !== void 0 && l > t.maxEntries && n("$", "Document exceeds maxEntries");
|
|
98
|
+
const i = (o, s) => o < Number.MAX_SAFE_INTEGER && s < Number.MAX_SAFE_INTEGER && (t.maxRows === void 0 || o < t.maxRows) && (t.maxColumns === void 0 || s < t.maxColumns), m = (o, s) => {
|
|
99
|
+
if (typeof o != "string") return !1;
|
|
100
|
+
try {
|
|
101
|
+
return s(JSON.parse(o));
|
|
102
|
+
} catch {
|
|
103
|
+
return !1;
|
|
104
|
+
}
|
|
105
|
+
}, c = (o, s, a) => {
|
|
106
|
+
typeof a == "string" && t.maxStringLength !== void 0 && a.length > t.maxStringLength && n(`${o}.${s}`, "String exceeds maxStringLength");
|
|
107
|
+
};
|
|
108
|
+
for (const o of ["cells", "styles", "locks"])
|
|
109
|
+
f[o].forEach((s, a) => {
|
|
110
|
+
const h = w(a);
|
|
111
|
+
(!h || !i(h.row, h.column)) && n(`${o}.${a}`, "Invalid or out-of-bounds row:column key"), c(o, a, s), o === "cells" && (typeof s != "string" || !z(s)) && n(`${o}.${a}`, "Cell values must be strings"), o === "styles" && !m(s, R) && n(`${o}.${a}`, "Expected a JSON CellStyle object"), o === "locks" && s !== "1" && !m(s, C) && n(`${o}.${a}`, "Expected a plain lock or version-one password verifier");
|
|
112
|
+
});
|
|
113
|
+
for (const o of ["rowHeights", "columnWidths"])
|
|
114
|
+
f[o].forEach((s, a) => {
|
|
115
|
+
const h = Number(a), E = o === "rowHeights" ? t.maxRows : t.maxColumns;
|
|
116
|
+
(!/^(0|[1-9]\d*)$/.test(a) || !Number.isSafeInteger(h) || h >= Number.MAX_SAFE_INTEGER || E !== void 0 && h >= E) && n(`${o}.${a}`, "Invalid or out-of-bounds index"), (typeof s != "number" || !Number.isFinite(s) || s <= 0) && n(`${o}.${a}`, "Sizes must be finite positive numbers");
|
|
117
|
+
});
|
|
118
|
+
t.maxMerges !== void 0 && f.merges.size > t.maxMerges && n("merges", "Document exceeds maxMerges");
|
|
119
|
+
const u = [];
|
|
120
|
+
return f.merges.forEach((o, s) => {
|
|
121
|
+
const a = A(s);
|
|
122
|
+
!a || o !== "1" || !i(a.end.row, a.end.column) ? n(`merges.${s}`, "Invalid or out-of-bounds merge range") : (t.maxMergeArea !== void 0 && a.end.row - a.start.row + 1 > t.maxMergeArea / (a.end.column - a.start.column + 1) && n(`merges.${s}`, "Merge exceeds maxMergeArea"), u.push(a));
|
|
123
|
+
}), I(u) && n("merges", "Merge ranges must not overlap"), d.forEach((o, s) => {
|
|
124
|
+
s === "schemaVersion" ? o !== M && n("metadata.schemaVersion", "Unsupported schema version") : s === "initialized" ? typeof o != "boolean" && n("metadata.initialized", "Expected a boolean") : n(`metadata.${s}`, "Unknown metadata field");
|
|
125
|
+
}), r;
|
|
126
|
+
}
|
|
127
|
+
function y(e) {
|
|
128
|
+
let t = "";
|
|
129
|
+
for (let n = 0; n < e.length; n += 32768)
|
|
130
|
+
t += String.fromCharCode(...e.subarray(n, n + 32768));
|
|
131
|
+
return btoa(t);
|
|
132
|
+
}
|
|
133
|
+
function $(e) {
|
|
134
|
+
const t = atob(e);
|
|
135
|
+
return Uint8Array.from(t, (r) => r.charCodeAt(0));
|
|
136
|
+
}
|
|
137
|
+
function N(e) {
|
|
138
|
+
if (e != null && e.trim())
|
|
139
|
+
return JSON.parse(e);
|
|
140
|
+
}
|
|
141
|
+
function U(e) {
|
|
142
|
+
if (!(!e || e.format === "colwork.update-log"))
|
|
143
|
+
return e.format === "colwork.archive" ? e.snapshot : e;
|
|
144
|
+
}
|
|
145
|
+
function O(e) {
|
|
146
|
+
return !e || e.format === "colwork.snapshot" ? [] : e.updates ?? [];
|
|
147
|
+
}
|
|
148
|
+
function W(e, t) {
|
|
149
|
+
const r = N(e), n = N(t), f = U(r), d = [...O(r), ...O(n)], l = new p.Doc();
|
|
150
|
+
try {
|
|
151
|
+
f != null && f.snapshot && p.applyUpdate(l, $(f.snapshot));
|
|
152
|
+
const i = Number((f == null ? void 0 : f.sequence) ?? 0), m = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set();
|
|
153
|
+
let u = i;
|
|
154
|
+
for (const o of d.sort((s, a) => Number(s.seq) - Number(a.seq))) {
|
|
155
|
+
const s = Number(o.seq);
|
|
156
|
+
!Number.isInteger(s) || typeof o.update != "string" || s <= i || m.has(s) || c.has(o.update) || (p.applyUpdate(l, $(o.update)), m.add(s), c.add(o.update), u = Math.max(u, s));
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
format: "colwork.snapshot",
|
|
160
|
+
version: 1,
|
|
161
|
+
room: f == null ? void 0 : f.room,
|
|
162
|
+
sequence: u,
|
|
163
|
+
snapshot: y(p.encodeStateAsUpdate(l)),
|
|
164
|
+
stateVector: y(p.encodeStateVector(l))
|
|
165
|
+
};
|
|
166
|
+
} finally {
|
|
167
|
+
l.destroy();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function q(e, t) {
|
|
171
|
+
const r = e.split(":").map(Number), n = t.split(":").map(Number);
|
|
172
|
+
return r[0] - n[0] || (r[1] ?? 0) - (n[1] ?? 0);
|
|
173
|
+
}
|
|
174
|
+
function b(e) {
|
|
175
|
+
return [...e].sort(([t], [r]) => q(t, r));
|
|
176
|
+
}
|
|
177
|
+
function V(e) {
|
|
178
|
+
const t = {};
|
|
179
|
+
for (const r of ["bold", "italic", "underline", "strike", "wrap", "fontSize", "color", "background", "align", "format"])
|
|
180
|
+
e[r] !== void 0 && (t[r] = e[r]);
|
|
181
|
+
if (e.border !== void 0) {
|
|
182
|
+
const r = {};
|
|
183
|
+
for (const n of ["top", "right", "bottom", "left"]) e.border[n] !== void 0 && (r[n] = e.border[n]);
|
|
184
|
+
t.border = r;
|
|
185
|
+
}
|
|
186
|
+
return t;
|
|
187
|
+
}
|
|
188
|
+
function H(e, t) {
|
|
189
|
+
const r = j(e, t);
|
|
190
|
+
if (r.length) throw new TypeError(`Invalid Colwork document at ${r[0].path}: ${r[0].message}`);
|
|
191
|
+
const n = k(e), f = Object.fromEntries(b(n.styles).map(([c, u]) => [c, V(JSON.parse(u))])), d = Object.fromEntries(b(n.locks).map(([c, u]) => {
|
|
192
|
+
if (u === "1") return [c, "1"];
|
|
193
|
+
const o = JSON.parse(u);
|
|
194
|
+
return [c, { version: o.version, algorithm: o.algorithm, iterations: o.iterations, salt: o.salt, verifier: o.verifier }];
|
|
195
|
+
})), l = [...n.merges.keys()].map((c) => A(c)).sort((c, u) => c.start.row - u.start.row || c.start.column - u.start.column || c.end.row - u.end.row || c.end.column - u.end.column);
|
|
196
|
+
let i = 1, m = 1;
|
|
197
|
+
for (const c of [...n.cells.keys(), ...n.styles.keys(), ...n.locks.keys()]) {
|
|
198
|
+
const u = w(c);
|
|
199
|
+
i = Math.max(i, u.row + 1), m = Math.max(m, u.column + 1);
|
|
200
|
+
}
|
|
201
|
+
for (const c of l)
|
|
202
|
+
i = Math.max(i, c.end.row + 1), m = Math.max(m, c.end.column + 1);
|
|
203
|
+
for (const c of n.rowHeights.keys()) i = Math.max(i, Number(c) + 1);
|
|
204
|
+
for (const c of n.columnWidths.keys()) m = Math.max(m, Number(c) + 1);
|
|
205
|
+
return {
|
|
206
|
+
schemaVersion: M,
|
|
207
|
+
rowCount: i,
|
|
208
|
+
columnCount: m,
|
|
209
|
+
cells: Object.fromEntries(b(n.cells)),
|
|
210
|
+
styles: f,
|
|
211
|
+
rowHeights: Object.fromEntries(b(n.rowHeights)),
|
|
212
|
+
columnWidths: Object.fromEntries(b(n.columnWidths)),
|
|
213
|
+
merges: l,
|
|
214
|
+
locks: d
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function D(e) {
|
|
218
|
+
const t = j(e);
|
|
219
|
+
if (t.length) throw new TypeError(`Invalid Colwork document at ${t[0].path}: ${t[0].message}`);
|
|
220
|
+
if (Object.values(k(e)).some((n) => n.size > 0)) throw new Error("Blank initialization requires an empty sheet");
|
|
221
|
+
const r = e.getMap(g.metadata);
|
|
222
|
+
e.transact(() => {
|
|
223
|
+
r.set("schemaVersion", M), r.set("initialized", !0);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function K(e, t = {}) {
|
|
227
|
+
const r = t.sequence ?? 0;
|
|
228
|
+
if (!Number.isSafeInteger(r) || r < 0) throw new RangeError("sequence must be a non-negative safe integer");
|
|
229
|
+
return {
|
|
230
|
+
format: "colwork.snapshot",
|
|
231
|
+
version: 1,
|
|
232
|
+
room: t.room,
|
|
233
|
+
sequence: r,
|
|
234
|
+
snapshot: y(p.encodeStateAsUpdate(e)),
|
|
235
|
+
stateVector: y(p.encodeStateVector(e))
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function L(e, t) {
|
|
239
|
+
const r = new p.Doc();
|
|
240
|
+
try {
|
|
241
|
+
return p.applyUpdate(r, e), H(r, t);
|
|
242
|
+
} finally {
|
|
243
|
+
r.destroy();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
export {
|
|
247
|
+
g as COLWORK_MAP_NAMES,
|
|
248
|
+
M as COLWORK_SCHEMA_VERSION,
|
|
249
|
+
K as exportYjsSnapshot,
|
|
250
|
+
k as getSheetMaps,
|
|
251
|
+
D as initializeBlankSheet,
|
|
252
|
+
_ as mergeKey,
|
|
253
|
+
w as parseCellKey,
|
|
254
|
+
A as parseMergeKey,
|
|
255
|
+
H as readSheetSnapshot,
|
|
256
|
+
L as readSheetSnapshotUpdate,
|
|
257
|
+
W as rebuildYjsSnapshot,
|
|
258
|
+
j as validateSheetDocument
|
|
259
|
+
};
|
package/dist/range.d.cts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type CellPosition = {
|
|
2
|
+
row: number;
|
|
3
|
+
column: number;
|
|
4
|
+
};
|
|
5
|
+
export type CellRange = {
|
|
6
|
+
start: CellPosition;
|
|
7
|
+
end: CellPosition;
|
|
8
|
+
};
|
|
9
|
+
export declare function normalizeRange(start: CellPosition, end: CellPosition): CellRange;
|
|
10
|
+
export declare function containsPosition(range: CellRange, position: CellPosition): boolean;
|
|
11
|
+
export declare function rangeSize(range: CellRange): {
|
|
12
|
+
rows: number;
|
|
13
|
+
columns: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function cellKey(position: CellPosition): string;
|
package/dist/range.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type CellPosition = {
|
|
2
|
+
row: number;
|
|
3
|
+
column: number;
|
|
4
|
+
};
|
|
5
|
+
export type CellRange = {
|
|
6
|
+
start: CellPosition;
|
|
7
|
+
end: CellPosition;
|
|
8
|
+
};
|
|
9
|
+
export declare function normalizeRange(start: CellPosition, end: CellPosition): CellRange;
|
|
10
|
+
export declare function containsPosition(range: CellRange, position: CellPosition): boolean;
|
|
11
|
+
export declare function rangeSize(range: CellRange): {
|
|
12
|
+
rows: number;
|
|
13
|
+
columns: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function cellKey(position: CellPosition): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type YjsUpdateRecord = {
|
|
2
|
+
seq: number;
|
|
3
|
+
update: string;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
};
|
|
6
|
+
export type YjsSnapshotFile = {
|
|
7
|
+
format: 'colwork.snapshot';
|
|
8
|
+
version: 1;
|
|
9
|
+
room?: string;
|
|
10
|
+
sequence: number;
|
|
11
|
+
snapshot: string;
|
|
12
|
+
stateVector: string;
|
|
13
|
+
};
|
|
14
|
+
export type YjsUpdateLogFile = {
|
|
15
|
+
format: 'colwork.update-log';
|
|
16
|
+
version: 1;
|
|
17
|
+
room?: string;
|
|
18
|
+
updates: YjsUpdateRecord[];
|
|
19
|
+
};
|
|
20
|
+
export type YjsArchiveFile = {
|
|
21
|
+
format: 'colwork.archive';
|
|
22
|
+
version: 1;
|
|
23
|
+
room?: string;
|
|
24
|
+
snapshot?: YjsSnapshotFile;
|
|
25
|
+
updates: YjsUpdateRecord[];
|
|
26
|
+
};
|
|
27
|
+
export declare function bytesToBase64(bytes: Uint8Array): string;
|
|
28
|
+
export declare function base64ToBytes(value: string): Uint8Array<ArrayBuffer>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type YjsUpdateRecord = {
|
|
2
|
+
seq: number;
|
|
3
|
+
update: string;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
};
|
|
6
|
+
export type YjsSnapshotFile = {
|
|
7
|
+
format: 'colwork.snapshot';
|
|
8
|
+
version: 1;
|
|
9
|
+
room?: string;
|
|
10
|
+
sequence: number;
|
|
11
|
+
snapshot: string;
|
|
12
|
+
stateVector: string;
|
|
13
|
+
};
|
|
14
|
+
export type YjsUpdateLogFile = {
|
|
15
|
+
format: 'colwork.update-log';
|
|
16
|
+
version: 1;
|
|
17
|
+
room?: string;
|
|
18
|
+
updates: YjsUpdateRecord[];
|
|
19
|
+
};
|
|
20
|
+
export type YjsArchiveFile = {
|
|
21
|
+
format: 'colwork.archive';
|
|
22
|
+
version: 1;
|
|
23
|
+
room?: string;
|
|
24
|
+
snapshot?: YjsSnapshotFile;
|
|
25
|
+
updates: YjsUpdateRecord[];
|
|
26
|
+
};
|
|
27
|
+
export declare function bytesToBase64(bytes: Uint8Array): string;
|
|
28
|
+
export declare function base64ToBytes(value: string): Uint8Array<ArrayBuffer>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,92 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuzuma/colwork",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "node script/demo.mjs dev",
|
|
8
|
+
"dev:test": "node script/demo.mjs dev",
|
|
9
|
+
"server": "node server/index.mjs",
|
|
10
|
+
"server:test": "node server/index.mjs --mode test",
|
|
11
|
+
"rebuild:yjs": "node script/rebuild-yjs.mjs",
|
|
12
|
+
"build": "npm run build:lib",
|
|
13
|
+
"build:lib": "tsc --noEmit && vite build --config vite.lib.config.ts && vite build --config vite.model.config.ts",
|
|
14
|
+
"test:e2e": "playwright test",
|
|
15
|
+
"build:site": "node script/demo.mjs build",
|
|
16
|
+
"dev:cloudflare": "npm run build:site && wrangler dev --config config/cloudflare/wrangler.dev.json --persist-to .wrangler/state",
|
|
17
|
+
"deploy:check": "node script/deploy-cloudflare.mjs --dry-run",
|
|
18
|
+
"deploy": "node script/deploy-cloudflare.mjs",
|
|
19
|
+
"test:cloudflare": "node --test test/cloudflare/*.test.mjs",
|
|
20
|
+
"prepublishOnly": "npm run build:lib",
|
|
21
|
+
"test:model": "node --test test/model/*.test.mjs"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"y-protocols": "^1.0.7",
|
|
25
|
+
"y-webrtc": "^10.3.0",
|
|
26
|
+
"y-websocket": "^2.1.0",
|
|
27
|
+
"yjs": "^13.6.27"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@playwright/test": "^1.63.0",
|
|
31
|
+
"@types/react": "^19.1.2",
|
|
32
|
+
"@types/react-dom": "^19.1.2",
|
|
33
|
+
"@vitejs/plugin-react": "^4.4.1",
|
|
34
|
+
"@vitejs/plugin-vue": "^5.2.3",
|
|
35
|
+
"lib0": "^0.2.119",
|
|
36
|
+
"react": "^19.1.0",
|
|
37
|
+
"react-dom": "^19.1.0",
|
|
38
|
+
"typescript": "^5.8.3",
|
|
39
|
+
"vite": "^6.3.5",
|
|
40
|
+
"vite-plugin-dts": "^4.5.4",
|
|
41
|
+
"vue": "^3.5.13",
|
|
42
|
+
"wrangler": "^4.145.0",
|
|
43
|
+
"ws": "^8.21.3"
|
|
44
|
+
},
|
|
45
|
+
"description": "A collaborative spreadsheet library powered by Yjs, with native DOM rendering, frozen panes, and password-protected ranges.",
|
|
46
|
+
"main": "./dist/colwork.umd.cjs",
|
|
47
|
+
"module": "./dist/colwork.js",
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"exports": {
|
|
50
|
+
".": {
|
|
51
|
+
"types": "./dist/index.d.ts",
|
|
52
|
+
"import": "./dist/colwork.js",
|
|
53
|
+
"require": "./dist/colwork.umd.cjs"
|
|
54
|
+
},
|
|
55
|
+
"./colwork.css": "./dist/colwork.css",
|
|
56
|
+
"./model": {
|
|
57
|
+
"import": {
|
|
58
|
+
"types": "./dist/model.d.ts",
|
|
59
|
+
"default": "./dist/model.js"
|
|
60
|
+
},
|
|
61
|
+
"require": {
|
|
62
|
+
"types": "./dist/model.d.cts",
|
|
63
|
+
"default": "./dist/model.cjs"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"files": [
|
|
68
|
+
"dist"
|
|
69
|
+
],
|
|
70
|
+
"sideEffects": [
|
|
71
|
+
"**/*.css"
|
|
72
|
+
],
|
|
73
|
+
"repository": {
|
|
74
|
+
"type": "git",
|
|
75
|
+
"url": "git+https://github.com/dlwm/colwork.git"
|
|
76
|
+
},
|
|
77
|
+
"homepage": "https://github.com/dlwm/colwork#readme",
|
|
78
|
+
"bugs": {
|
|
79
|
+
"url": "https://github.com/dlwm/colwork/issues"
|
|
80
|
+
},
|
|
81
|
+
"keywords": [
|
|
82
|
+
"spreadsheet",
|
|
83
|
+
"collaboration",
|
|
84
|
+
"yjs",
|
|
85
|
+
"vue",
|
|
86
|
+
"react"
|
|
87
|
+
],
|
|
88
|
+
"publishConfig": {
|
|
89
|
+
"access": "public",
|
|
90
|
+
"registry": "https://registry.npmjs.org/"
|
|
91
|
+
}
|
|
92
|
+
}
|