@tensorix/metahub 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/cli.js +124 -18
- package/dist/cli.js.map +9 -9
- package/dist/core/documents.d.ts +9 -6
- package/dist/core/documents.d.ts.map +1 -1
- package/dist/core/md/grammar.d.ts +37 -0
- package/dist/core/md/grammar.d.ts.map +1 -1
- package/dist/core/md/heal.d.ts.map +1 -1
- package/dist/core/sync/share-render.d.ts.map +1 -1
- package/dist/db-worker.js +2 -2
- package/dist/index.js +116 -15
- package/dist/index.js.map +7 -7
- package/dist/webui-fmt.js +1 -1
- package/dist/webui.js +108 -108
- package/package.json +1 -1
package/dist/core/documents.d.ts
CHANGED
|
@@ -76,13 +76,16 @@ export interface EditPair {
|
|
|
76
76
|
replaceAll?: boolean;
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
|
-
* Apply several anchored find/replaces in one
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
79
|
+
* Apply several anchored find/replaces in one single-versioned pass — the batch
|
|
80
|
+
* form of {@link editDocument}. Pairs fold left-to-right over the evolving body
|
|
81
|
+
* (a later `old` can match an earlier `new`), EVERY pair is validated before
|
|
82
|
+
* anything is written (validate-all-before-write), so any failing pair (empty/
|
|
83
|
+
* missing/ambiguous anchor) aborts with the document untouched. The writes then
|
|
84
|
+
* land in one oplog change-group (one revision, one version bump). `ifMatch` is
|
|
85
85
|
* checked once up front, so callers need only a single `doc read` for N deltas.
|
|
86
|
+
* NB: "one pass" here is validate-before-write + single-version, NOT a DB
|
|
87
|
+
* transaction — like every `grouped` mutator, there is no cross-process lock or
|
|
88
|
+
* rollback; concurrent writers reconcile via the block-level CRDT / LWW.
|
|
86
89
|
*/
|
|
87
90
|
export declare const editDocumentBatch: (db: DbDriver, id: string, opts: {
|
|
88
91
|
edits: EditPair[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,aAAa,0FAEhB,CAAC;AAqGX,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAShE;AAID,eAAO,MAAM,cAAc;WAEV,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM;iBAa9E,CAAC;AAEH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIxE;AAMD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,eAAe,EAAE,CAWnB;AAgFD,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,wBAOpC,CAAC;AAgDH;;;;GAIG;AACH,eAAO,MAAM,YAAY,iGAevB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;YAGZ,MAAM;eAAa,MAAM,GAAG,IAAI;6BAuBhD,CAAC;AAEH,eAAO,MAAM,cAAc;YAGP,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM,GAAG,IAAI;;cACtE,MAAM;6BAsBxB,CAAC;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;SAGV,MAAM;SAAO,MAAM;iBAAe,OAAO;cAAY,MAAM;
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/core/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,aAAa,0FAEhB,CAAC;AAqGX,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAShE;AAID,eAAO,MAAM,cAAc;WAEV,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM;iBAa9E,CAAC;AAEH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAIxE;AAMD,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,eAAe,EAAE,CAWnB;AAgFD,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,wBAOpC,CAAC;AAgDH;;;;GAIG;AACH,eAAO,MAAM,YAAY,iGAevB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;YAGZ,MAAM;eAAa,MAAM,GAAG,IAAI;6BAuBhD,CAAC;AAEH,eAAO,MAAM,cAAc;YAGP,MAAM;WAAS,MAAM;kBAAgB,MAAM;gBAAc,MAAM,GAAG,IAAI;;cACtE,MAAM;6BAsBxB,CAAC;AAEH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;SAGV,MAAM;SAAO,MAAM;iBAAe,OAAO;cAAY,MAAM;mBAiDxE,CAAC;AAEH,sGAAsG;AACtG,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB;WAGb,QAAQ,EAAE;cAAY,MAAM;mBAkC3C,CAAC;AAEH,eAAO,MAAM,cAAc,2DAczB,CAAC;AAEH,eAAO,MAAM,eAAe,2DAc1B,CAAC;AAEH,eAAO,MAAM,cAAc,uCAUzB,CAAC"}
|
|
@@ -10,6 +10,43 @@ export declare const RE: {
|
|
|
10
10
|
quote: RegExp;
|
|
11
11
|
divider: RegExp;
|
|
12
12
|
};
|
|
13
|
+
/** URL-scheme whitelist for rendered links/images — the single sanitizer every
|
|
14
|
+
* surface uses before emitting an `href`/`src` or calling `window.open`. Blocks
|
|
15
|
+
* the injection vectors (`javascript:`, `vbscript:`, and — for links — `data:`)
|
|
16
|
+
* while allowing normal web/mail/blob links, relative paths and `#anchors`.
|
|
17
|
+
* Returns "#" for anything rejected, so a hostile URL from synced or shared
|
|
18
|
+
* content can never execute. `allowData` is set for `<img>`, where `data:`
|
|
19
|
+
* image URIs are legitimate and non-executable. */
|
|
20
|
+
export declare function safeUrl(url: string, opts?: {
|
|
21
|
+
allowData?: boolean;
|
|
22
|
+
}): string;
|
|
23
|
+
/** A line that is solely a media/file embed is a block-level void on every
|
|
24
|
+
* surface. The classifier + its helpers live here so the same bytes are a block
|
|
25
|
+
* on all three (editor scan, `blocks.startsLeafBlock`, share renderer) — the
|
|
26
|
+
* divergence that let a media line fold into a paragraph on save only. */
|
|
27
|
+
export type MediaKind = "image" | "video" | "audio" | "file";
|
|
28
|
+
/** Lowercased file extension of a URL (no query/fragment), or "". */
|
|
29
|
+
export declare function extOf(url: string): string;
|
|
30
|
+
/** Which `` embed a media URL is, by extension. Image syntax never maps
|
|
31
|
+
* to "file": an unknown extension written as `![]()` is treated as an image. */
|
|
32
|
+
export declare function imageSyntaxKind(ext: string): "image" | "video" | "audio";
|
|
33
|
+
/** Split a media URL into its base src and an optional `w=` width, preserving any
|
|
34
|
+
* other query params / fragment (external images may carry signed tokens). */
|
|
35
|
+
export declare function parseMediaUrl(url: string): {
|
|
36
|
+
src: string;
|
|
37
|
+
width?: number;
|
|
38
|
+
};
|
|
39
|
+
export interface MediaLine {
|
|
40
|
+
kind: MediaKind;
|
|
41
|
+
src: string;
|
|
42
|
+
name: string;
|
|
43
|
+
width?: number;
|
|
44
|
+
size?: number;
|
|
45
|
+
}
|
|
46
|
+
/** A line that is solely one embed → its classified parts, else null. Media use
|
|
47
|
+
* `` (kind by extension); a file uses a `[name](/blob/..)` link so a
|
|
48
|
+
* plain standalone hyperlink stays a paragraph. */
|
|
49
|
+
export declare function matchMediaEmbed(line: string): MediaLine | null;
|
|
13
50
|
/** The single quote-line predicate for all consumers: quote content of `text`
|
|
14
51
|
* ("" for the serializer's empty form `> `), or null if the line is not a
|
|
15
52
|
* quote line. `text` must already be indent-stripped. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grammar.d.ts","sourceRoot":"","sources":["../../../src/core/md/grammar.ts"],"names":[],"mappings":"AAoBA;mFACmF;AACnF,eAAO,MAAM,UAAU,YAAY,CAAC;AAEpC,eAAO,MAAM,EAAE;;;;;;;;CAQd,CAAC;AAEF;;0DAE0D;AAC1D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG1D;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CA+B9E;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED;2DAC2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAO7E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAGD,eAAO,MAAM,aAAa,QAAmB,CAAC;AAE9C;8CAC8C;AAC9C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAUvF;AAED;kEACkE;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBpD"}
|
|
1
|
+
{"version":3,"file":"grammar.d.ts","sourceRoot":"","sources":["../../../src/core/md/grammar.ts"],"names":[],"mappings":"AAoBA;mFACmF;AACnF,eAAO,MAAM,UAAU,YAAY,CAAC;AAEpC,eAAO,MAAM,EAAE;;;;;;;;CAQd,CAAC;AAEF;;;;;;oDAMoD;AACpD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAa/E;AAID;;;2EAG2E;AAC3E,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAK7D,qEAAqE;AACrE,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKzC;AAED;iFACiF;AACjF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAIxE;AAED;+EAC+E;AAC/E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAe1E;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;oDAEoD;AACpD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAiB9D;AAED;;0DAE0D;AAC1D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG1D;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CA+B9E;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED;2DAC2D;AAC3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAO7E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAGD,eAAO,MAAM,aAAa,QAAmB,CAAC;AAE9C;8CAC8C;AAC9C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAUvF;AAED;kEACkE;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../../src/core/md/heal.ts"],"names":[],"mappings":"AAyDA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../../src/core/md/heal.ts"],"names":[],"mappings":"AAyDA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkCtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-render.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"share-render.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-render.ts"],"names":[],"mappings":"AA6BA,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED;;mCAEmC;AACnC,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CAuCvE;AAyBD,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CA+JxE"}
|
package/dist/db-worker.js
CHANGED
|
@@ -269,9 +269,9 @@ CREATE VIRTUAL TABLE IF NOT EXISTS search_fts USING fts5(
|
|
|
269
269
|
ORDER BY order_key DESC, id DESC LIMIT 1`).get(...G.args,...X?[X]:[])?.order_key??null}function rW($,J){let X=KJ(J);return $.query(`SELECT id, order_key FROM documents WHERE ${X.clause} AND __deleted = 0 ${o1}`).all(...X.args)}function CK($,J){let X=rW($,J),G=Xv(null,null,X.length);X.forEach((U,Q)=>{if(U.order_key!==G[Q])T$($,"documents",U.id,"order_key",G[Q])})}function oW($,J){let X=_K($),G=KJ(J),U=$.query(`SELECT id FROM documents WHERE ${G.clause} AND __deleted = 0 AND order_key IS NULL
|
|
270
270
|
ORDER BY created_hlc, id`).all(...G.args);if(!U.length)return;let Q=Xv(mW($,J),null,U.length);U.forEach((W,Y)=>{if(X)T$($,"documents",W.id,"order_key",Q[Y]);else $.query("UPDATE documents SET order_key = ? WHERE id = ?").run(Q[Y],W.id)})}var dW=d$(function(J){let X=J.query("SELECT DISTINCT parent_id FROM documents WHERE __deleted = 0 AND order_key IS NULL").all();for(let G of X)oW(J,G.parent_id)});function d1($,J,X,G){let U=X;while(U){if(U===J)throw new V$("invalid_input",`cannot set parent_id: would create a cycle (${J})`);U=z6($,U)?.parent_id??null}let Q=z6($,J);if(Q&&(Q.parent_id??null)!==X)T$($,"documents",J,"parent_id",X);let W;if(!G)W=b6(mW($,X,J),null);else{oW($,X);let Y=()=>{let A=rW($,X).filter((r)=>r.id!==J),M=A.findIndex((r)=>r.id===G.targetId);if(M<0)throw new V$("not_found",`no such target document: ${G.targetId}`);return G.where==="before"?[A[M-1]?.order_key??null,A[M].order_key]:[A[M].order_key,A[M+1]?.order_key??null]},[V,H]=Y();if(V!==null&&H!==null&&V>=H)CK($,X),[V,H]=Y();W=b6(V,H)}T$($,"documents",J,"order_key",W)}var DJ=d$(function(J,X,G,U){let Q=z6(J,X);if(!Q)throw new V$("not_found",`no such document: ${X}`);if(X===G)return Q;let W=z6(J,G);if(!W)throw new V$("not_found",`no such target document: ${G}`);if(U==="into")d1(J,X,G);else d1(J,X,W.parent_id,{targetId:G,where:U});return z6(J,X)}),pW=d$(function(J,X,G={}){let U=z6(J,X);if(!U)throw new V$("not_found",`no such document: ${X}`);sv(J,X);let Q=av(J,X),W=G.parentId!==void 0?G.parentId:U.parent_id,Y=YJ(J,{title:G.title??U.title,database_id:U.database_id??void 0,parent_id:W??void 0});if(Q.length)ev(J,Y.id,Q.map((V)=>({text:V.text,blankAfter:V.blank_after})),null,null);if(W===U.parent_id)DJ(J,Y.id,U.id,"after");return z6(J,Y.id)}),p1=d$(function(J,X,G,U={}){if(!z6(J,X))throw new V$("not_found",`no such document: ${X}`);if(U.ifMatch!==void 0&&R6(J,X)!==U.ifMatch)throw new V$("stale",`stale: document changed since ${U.ifMatch}; re-read first`);if(G.title!==void 0)T$(J,"documents",X,"title",G.title);if(G.database_id!==void 0)T$(J,"documents",X,"database_id",G.database_id);if(G.parent_id!==void 0){let Q=G.parent_id??null;if((z6(J,X).parent_id??null)!==Q)d1(J,X,Q)}if(G.body!==void 0)sv(J,X),jJ(J,X,G.body);return z6(J,X)}),eO=d$(function(J,X,G){if(!z6(J,X))throw new V$("not_found",`no such document: ${X}`);if(G.ifMatch!==void 0&&R6(J,X)!==G.ifMatch)throw new V$("stale",`stale: document changed since ${G.ifMatch}; re-read first`);if(G.old==="")throw new V$("invalid_input","--old must not be empty");sv(J,X);let U=av(J,X),Q=Cv(U.map((V)=>({text:V.text,blankAfter:V.blank_after}))),W=aW(Q,G.old);if(W===0)throw new V$("invalid_input","anchor not found: no match for --old");if(W>1&&!G.replaceAll)throw new V$("ambiguous",`${W} matches for --old; add surrounding context or use --replace-all`);if(!G.old.includes(`
|
|
271
271
|
|
|
272
|
-
`)){let V=U.filter((A)=>A.text.includes(G.old)),H=V.map((A)=>G.replaceAll?A.text.replaceAll(G.old,G.new):A.text.replace(G.old,G.new));if(H.every((A)=>A.length>0&&!A.includes(`
|
|
272
|
+
`)){let V=U.filter((A)=>A.text.includes(G.old)),H=V.map((A)=>G.replaceAll?A.text.replaceAll(G.old,()=>G.new):A.text.replace(G.old,()=>G.new));if(H.every((A)=>A.length>0&&!A.includes(`
|
|
273
273
|
|
|
274
|
-
`)))
|
|
274
|
+
`))){let A=G.replaceAll?V:V.slice(0,1),M=!1;return A.forEach((r,e)=>{if(H[e]!==r.text)T$(J,"doc_blocks",r.id,"text",H[e]),M=!0}),{id:X,changed:M,replaced:G.replaceAll?W:1,version:R6(J,X)}}}let Y=G.replaceAll?Q.replaceAll(G.old,()=>G.new):Q.replace(G.old,()=>G.new);return jJ(J,X,Y),{id:X,changed:Y!==Q,replaced:G.replaceAll?W:1,version:R6(J,X)}}),sO=d$(function(J,X,G){if(!z6(J,X))throw new V$("not_found",`no such document: ${X}`);if(G.edits.length===0)throw new V$("invalid_input","no edits given");if(G.ifMatch!==void 0&&R6(J,X)!==G.ifMatch)throw new V$("stale",`stale: document changed since ${G.ifMatch}; re-read first`);sv(J,X);let U=Cv(av(J,X).map((Y)=>({text:Y.text,blankAfter:Y.blank_after}))),Q=U,W=0;if(G.edits.forEach((Y,V)=>{if(Y.old==="")throw new V$("invalid_input",`edit[${V}]: old must not be empty`);let H=aW(Q,Y.old);if(H===0)throw new V$("invalid_input",`edit[${V}]: anchor not found: no match for old`);if(H>1&&!Y.replaceAll)throw new V$("ambiguous",`edit[${V}]: ${H} matches for old; add surrounding context or set replaceAll`);let A=Y.new??"";Q=Y.replaceAll?Q.replaceAll(Y.old,()=>A):Q.replace(Y.old,()=>A),W+=Y.replaceAll?H:1}),Q!==U)jJ(J,X,Q);return{id:X,changed:Q!==U,replaced:W,version:R6(J,X)}}),$L=d$(function(J,X,G){if(!z6(J,X))throw new V$("not_found",`no such document: ${X}`);sv(J,X);let U=pv(G);if(U.length){let Q=av(J,X),W=Q.length?Q[Q.length-1].order_key:null;ev(J,X,U,W,null)}return{id:X,changed:U.length>0,replaced:U.length,version:R6(J,X)}}),vL=d$(function(J,X,G){if(!z6(J,X))throw new V$("not_found",`no such document: ${X}`);sv(J,X);let U=pv(G);if(U.length){let Q=av(J,X),W=Q.length?Q[0].order_key:null;ev(J,X,U,null,W)}return{id:X,changed:U.length>0,replaced:U.length,version:R6(J,X)}}),tW=d$(function(J,X){if(!z6(J,X))return!1;T$(J,"documents",X,"__deleted",1);for(let G of cW(J,"doc_blocks","doc_id",X))T$(J,"doc_blocks",G,"__deleted",1);for(let G of cW(J,"documents","parent_id",X))T$(J,"documents",G,"parent_id",null);return!0});function cW($,J,X,G){return $.query(`SELECT id FROM ${J} WHERE ${X} = ? AND __deleted = 0`).all(G).map((U)=>U.id)}function aW($,J){if(J==="")return 0;let X=0,G=$.indexOf(J);while(G!==-1)X++,G=$.indexOf(J,G+J.length);return X}var IJ="default";function zJ($){let J=$.query("SELECT full_nodes, redundancy FROM blob_policy WHERE id = ? AND __deleted = 0").get(IJ),X=[];if(J?.full_nodes)try{let U=JSON.parse(J.full_nodes);if(Array.isArray(U))X=U.filter((Q)=>typeof Q==="string")}catch{}let G=J?.redundancy==="any"?"any":"all";return{fullNodes:X,redundancy:G}}var eW=($,J)=>{cU(null,()=>{let X=new Set,G=J.filter((Q)=>Q&&!X.has(Q)&&X.add(Q)!=null);if(T$($,"blob_policy",IJ,"full_nodes",G),zJ($).redundancy==null)T$($,"blob_policy",IJ,"redundancy","all")}),MK($)};function MK($){$.query("UPDATE blob_cache SET anchored = 0").run(),$.query("DELETE FROM meta WHERE key = ?").run(FK)}var FK="blob_verified_at";var uK=/\/blob\/([0-9a-f]{16,64})/g;function EK($){if(!$)return[];let J=[];for(let X of $.matchAll(uK))J.push(X[1]);return J}function sW($){let J=new Set,X=$.query("SELECT content FROM site_files WHERE encoding = 'blob' AND __deleted = 0").all();for(let U of X)if(U.content)J.add(U.content);let G=$.query("SELECT text FROM doc_blocks WHERE __deleted = 0 AND text LIKE '%/blob/%'").all();for(let U of G)for(let Q of EK(U.text))J.add(Q);return J}var SK={"https:":"443","http:":"80"};function $j($){try{let J=new URL($),X=J.port&&J.port!==SK[J.protocol]?`:${J.port}`:"";return J.hostname+X}catch{return $.trim().replace(/^[a-z]+:\/\//i,"").replace(/\/.*$/,"").replace(/:(80|443)$/,"")}}function $U($,J,X){let G=X?.trim()||"metahub";return`s3://${$j($)}/${J}/${G}`}function gK($){$.exec(WW);try{$.exec(jW)}catch{}}function vj($){return $.query("SELECT 1 AS ok FROM sqlite_master WHERE name = 'search_fts'").get()!=null}function i6($,J,X){return $.query(`PRAGMA table_info(${J})`).all().some((U)=>U.name===X)}function vU($,J){return $.query("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = ?").get(J)!=null}function wK($){if(!i6($,"records","data"))$.exec("ALTER TABLE records ADD COLUMN data TEXT NOT NULL DEFAULT '{}'");if(!i6($,"records","order_key"))$.exec("ALTER TABLE records ADD COLUMN order_key TEXT");if(!vU($,"record_values"))return;$.transaction(()=>{$.exec(`
|
|
275
275
|
UPDATE records SET data = coalesce((
|
|
276
276
|
SELECT json_group_object(rv.property_id, json(rv.value))
|
|
277
277
|
FROM record_values rv WHERE rv.record_id = records.id
|
package/dist/index.js
CHANGED
|
@@ -1392,16 +1392,22 @@ var init_documents = __esm(() => {
|
|
|
1392
1392
|
|
|
1393
1393
|
`)) {
|
|
1394
1394
|
const affected = blocks.filter((b) => b.text.includes(opts.old));
|
|
1395
|
-
const next = affected.map((b) => opts.replaceAll ? b.text.replaceAll(opts.old, opts.new) : b.text.replace(opts.old, opts.new));
|
|
1395
|
+
const next = affected.map((b) => opts.replaceAll ? b.text.replaceAll(opts.old, () => opts.new) : b.text.replace(opts.old, () => opts.new));
|
|
1396
1396
|
if (next.every((t) => t.length > 0 && !t.includes(`
|
|
1397
1397
|
|
|
1398
1398
|
`))) {
|
|
1399
1399
|
const targets = opts.replaceAll ? affected : affected.slice(0, 1);
|
|
1400
|
-
|
|
1401
|
-
|
|
1400
|
+
let wrote = false;
|
|
1401
|
+
targets.forEach((b, i) => {
|
|
1402
|
+
if (next[i] !== b.text) {
|
|
1403
|
+
emit(db, "doc_blocks", b.id, "text", next[i]);
|
|
1404
|
+
wrote = true;
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1407
|
+
return { id, changed: wrote, replaced: opts.replaceAll ? count : 1, version: documentVersion(db, id) };
|
|
1402
1408
|
}
|
|
1403
1409
|
}
|
|
1404
|
-
const newBody = opts.replaceAll ? body.replaceAll(opts.old, opts.new) : body.replace(opts.old, opts.new);
|
|
1410
|
+
const newBody = opts.replaceAll ? body.replaceAll(opts.old, () => opts.new) : body.replace(opts.old, () => opts.new);
|
|
1405
1411
|
reconcileBody(db, id, newBody);
|
|
1406
1412
|
return { id, changed: newBody !== body, replaced: opts.replaceAll ? count : 1, version: documentVersion(db, id) };
|
|
1407
1413
|
});
|
|
@@ -1425,7 +1431,7 @@ var init_documents = __esm(() => {
|
|
|
1425
1431
|
if (count > 1 && !e.replaceAll)
|
|
1426
1432
|
throw new MhError("ambiguous", `edit[${i}]: ${count} matches for old; add surrounding context or set replaceAll`);
|
|
1427
1433
|
const repl = e.new ?? "";
|
|
1428
|
-
body = e.replaceAll ? body.replaceAll(e.old, repl) : body.replace(e.old, repl);
|
|
1434
|
+
body = e.replaceAll ? body.replaceAll(e.old, () => repl) : body.replace(e.old, () => repl);
|
|
1429
1435
|
total += e.replaceAll ? count : 1;
|
|
1430
1436
|
});
|
|
1431
1437
|
if (body !== orig)
|
|
@@ -18803,6 +18809,70 @@ var init_shares = __esm(() => {
|
|
|
18803
18809
|
});
|
|
18804
18810
|
|
|
18805
18811
|
// src/core/md/grammar.ts
|
|
18812
|
+
function safeUrl(url2, opts = {}) {
|
|
18813
|
+
const probe = url2.replace(/[\u0000-\u0020]+/g, "");
|
|
18814
|
+
const m = /^([a-z][a-z0-9+.-]*):/i.exec(probe);
|
|
18815
|
+
if (!m)
|
|
18816
|
+
return url2;
|
|
18817
|
+
const scheme = m[1].toLowerCase();
|
|
18818
|
+
if (scheme === "http" || scheme === "https" || scheme === "mailto" || scheme === "blob")
|
|
18819
|
+
return url2;
|
|
18820
|
+
if (scheme === "data" && opts.allowData)
|
|
18821
|
+
return url2;
|
|
18822
|
+
return "#";
|
|
18823
|
+
}
|
|
18824
|
+
function extOf(url2) {
|
|
18825
|
+
const clean = url2.split(/[?#]/, 1)[0] ?? url2;
|
|
18826
|
+
const base = clean.slice(clean.lastIndexOf("/") + 1);
|
|
18827
|
+
const dot = base.lastIndexOf(".");
|
|
18828
|
+
return dot >= 0 ? base.slice(dot + 1).toLowerCase() : "";
|
|
18829
|
+
}
|
|
18830
|
+
function imageSyntaxKind(ext2) {
|
|
18831
|
+
if (VIDEO_EXTS.has(ext2))
|
|
18832
|
+
return "video";
|
|
18833
|
+
if (AUDIO_EXTS.has(ext2))
|
|
18834
|
+
return "audio";
|
|
18835
|
+
return "image";
|
|
18836
|
+
}
|
|
18837
|
+
function parseMediaUrl(url2) {
|
|
18838
|
+
const hash3 = url2.indexOf("#");
|
|
18839
|
+
const frag = hash3 >= 0 ? url2.slice(hash3) : "";
|
|
18840
|
+
const noFrag = hash3 >= 0 ? url2.slice(0, hash3) : url2;
|
|
18841
|
+
const q = noFrag.indexOf("?");
|
|
18842
|
+
if (q < 0)
|
|
18843
|
+
return { src: url2 };
|
|
18844
|
+
const base = noFrag.slice(0, q);
|
|
18845
|
+
let width;
|
|
18846
|
+
const kept = [];
|
|
18847
|
+
for (const p of noFrag.slice(q + 1).split("&").filter(Boolean)) {
|
|
18848
|
+
const m = p.match(/^w=(\d+)$/);
|
|
18849
|
+
if (m)
|
|
18850
|
+
width = parseInt(m[1], 10);
|
|
18851
|
+
else
|
|
18852
|
+
kept.push(p);
|
|
18853
|
+
}
|
|
18854
|
+
return { src: base + (kept.length ? "?" + kept.join("&") : "") + frag, width };
|
|
18855
|
+
}
|
|
18856
|
+
function matchMediaEmbed(line) {
|
|
18857
|
+
const t = line.trim();
|
|
18858
|
+
let m = t.match(/^!\[([^\]]*)\]\(([^\s)]+)\)$/);
|
|
18859
|
+
if (m) {
|
|
18860
|
+
const { src, width } = parseMediaUrl(m[2]);
|
|
18861
|
+
const kind = imageSyntaxKind(extOf(src));
|
|
18862
|
+
const r = { kind, src, name: m[1] };
|
|
18863
|
+
if (kind === "image" && width)
|
|
18864
|
+
r.width = width;
|
|
18865
|
+
return r;
|
|
18866
|
+
}
|
|
18867
|
+
m = t.match(/^\[([^\]]*)\]\(([^\s)]+)(?:\s+"([^"]*)")?\)$/);
|
|
18868
|
+
if (m && m[2].startsWith("/blob/")) {
|
|
18869
|
+
const r = { kind: "file", src: m[2], name: m[1] };
|
|
18870
|
+
if (m[3] != null && /^\d+$/.test(m[3]))
|
|
18871
|
+
r.size = parseInt(m[3], 10);
|
|
18872
|
+
return r;
|
|
18873
|
+
}
|
|
18874
|
+
return null;
|
|
18875
|
+
}
|
|
18806
18876
|
function matchQuoteLine(text) {
|
|
18807
18877
|
const m = text.match(RE.quote);
|
|
18808
18878
|
return m ? m[1] : null;
|
|
@@ -18906,7 +18976,7 @@ function splitTableRow(line) {
|
|
|
18906
18976
|
cells.pop();
|
|
18907
18977
|
return cells.map((c) => c.trim());
|
|
18908
18978
|
}
|
|
18909
|
-
var HTML_FENCE = "mh-html", RE, RE_DELIM_CELL;
|
|
18979
|
+
var HTML_FENCE = "mh-html", RE, VIDEO_EXTS, AUDIO_EXTS, RE_DELIM_CELL;
|
|
18910
18980
|
var init_grammar = __esm(() => {
|
|
18911
18981
|
RE = {
|
|
18912
18982
|
fenceOpen: /^\s*(`{3,}|~{3,})\s*([^\s`]*)?.*$/,
|
|
@@ -18917,6 +18987,8 @@ var init_grammar = __esm(() => {
|
|
|
18917
18987
|
quote: /^>[ \t](.*)$/,
|
|
18918
18988
|
divider: /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/
|
|
18919
18989
|
};
|
|
18990
|
+
VIDEO_EXTS = new Set(["mp4", "webm", "mov", "m4v", "ogv", "mkv", "ogg"]);
|
|
18991
|
+
AUDIO_EXTS = new Set(["mp3", "wav", "m4a", "aac", "flac", "opus", "oga", "weba"]);
|
|
18920
18992
|
RE_DELIM_CELL = /^\s*:?-+:?\s*$/;
|
|
18921
18993
|
});
|
|
18922
18994
|
|
|
@@ -19030,6 +19102,15 @@ function healLegacyMarkdown(src) {
|
|
|
19030
19102
|
changed = true;
|
|
19031
19103
|
}
|
|
19032
19104
|
}
|
|
19105
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
19106
|
+
if (inFence[i])
|
|
19107
|
+
continue;
|
|
19108
|
+
const line = lines[i];
|
|
19109
|
+
if (BARE_QUOTE.test(line) && (quoteish(i - 1) || quoteish(i + 1))) {
|
|
19110
|
+
lines[i] = line + " ";
|
|
19111
|
+
changed = true;
|
|
19112
|
+
}
|
|
19113
|
+
}
|
|
19033
19114
|
return changed ? lines.join(`
|
|
19034
19115
|
`) : src;
|
|
19035
19116
|
}
|
|
@@ -19052,7 +19133,7 @@ function renderInline(src, opts = {}) {
|
|
|
19052
19133
|
for (const t of tokens) {
|
|
19053
19134
|
out += escapeHtml(src.slice(pos, t.start));
|
|
19054
19135
|
const inner = src.slice(t.innerFrom, t.innerTo);
|
|
19055
|
-
const
|
|
19136
|
+
const rawUrl = rewrite(t.url ?? "", opts);
|
|
19056
19137
|
switch (t.kind) {
|
|
19057
19138
|
case "code":
|
|
19058
19139
|
out += `<code>${escapeHtml(inner)}</code>`;
|
|
@@ -19066,12 +19147,16 @@ function renderInline(src, opts = {}) {
|
|
|
19066
19147
|
case "del":
|
|
19067
19148
|
out += `<del>${escapeHtml(inner)}</del>`;
|
|
19068
19149
|
break;
|
|
19069
|
-
case "link":
|
|
19070
|
-
|
|
19150
|
+
case "link": {
|
|
19151
|
+
const href = escapeHtml(safeUrl(rawUrl));
|
|
19152
|
+
out += `<a href="${href}" target="_blank" rel="noreferrer noopener">${escapeHtml(inner)}</a>`;
|
|
19071
19153
|
break;
|
|
19072
|
-
|
|
19073
|
-
|
|
19154
|
+
}
|
|
19155
|
+
case "image": {
|
|
19156
|
+
const imgSrc = escapeHtml(safeUrl(rawUrl, { allowData: true }));
|
|
19157
|
+
out += `<img src="${imgSrc}" alt="${escapeHtml(t.alt ?? "")}" loading="lazy">`;
|
|
19074
19158
|
break;
|
|
19159
|
+
}
|
|
19075
19160
|
}
|
|
19076
19161
|
pos = t.end;
|
|
19077
19162
|
}
|
|
@@ -19082,6 +19167,19 @@ function rewrite(url2, opts) {
|
|
|
19082
19167
|
return opts.rewriteBlob(url2);
|
|
19083
19168
|
return url2;
|
|
19084
19169
|
}
|
|
19170
|
+
function renderMedia(m, opts) {
|
|
19171
|
+
const raw = rewrite(m.src, opts);
|
|
19172
|
+
if (m.kind === "video") {
|
|
19173
|
+
const src = escapeHtml(safeUrl(raw, { allowData: true }));
|
|
19174
|
+
return `<p class="mh-media"><video src="${src}" controls preload="metadata"></video></p>`;
|
|
19175
|
+
}
|
|
19176
|
+
if (m.kind === "audio") {
|
|
19177
|
+
const src = escapeHtml(safeUrl(raw, { allowData: true }));
|
|
19178
|
+
return `<p class="mh-media"><audio src="${src}" controls preload="metadata"></audio></p>`;
|
|
19179
|
+
}
|
|
19180
|
+
const href = escapeHtml(safeUrl(raw));
|
|
19181
|
+
return `<p class="mh-file"><a href="${href}" download>${escapeHtml(m.name || "file")}</a></p>`;
|
|
19182
|
+
}
|
|
19085
19183
|
function renderMarkdown(md, opts = {}) {
|
|
19086
19184
|
const healed = healLegacyMarkdown((md ?? "").replace(/\r\n?/g, `
|
|
19087
19185
|
`));
|
|
@@ -19193,9 +19291,10 @@ function renderMarkdown(md, opts = {}) {
|
|
|
19193
19291
|
out.push(ordered ? `<ol>${lis.join("")}</ol>` : `<ul>${lis.join("")}</ul>`);
|
|
19194
19292
|
continue;
|
|
19195
19293
|
}
|
|
19196
|
-
|
|
19294
|
+
const media = matchMediaEmbed(line);
|
|
19295
|
+
if (media) {
|
|
19197
19296
|
flushPara();
|
|
19198
|
-
out.push(`<p class="mh-img">${renderInline(line.trim(), opts)}</p>`);
|
|
19297
|
+
out.push(media.kind === "image" ? `<p class="mh-img">${renderInline(line.trim(), opts)}</p>` : renderMedia(media, opts));
|
|
19199
19298
|
i++;
|
|
19200
19299
|
continue;
|
|
19201
19300
|
}
|
|
@@ -19630,6 +19729,8 @@ function pageShell(title, inner, opts = {}) {
|
|
|
19630
19729
|
td[contenteditable]{outline:none} td.saving{opacity:.5} td.saved{background:rgba(46,160,67,.18)}
|
|
19631
19730
|
.tag{display:inline-block;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:1px 9px;font-size:12px}
|
|
19632
19731
|
.muted{color:var(--muted)} .mh-img{text-align:center}
|
|
19732
|
+
.mh-media{text-align:center} .mh-media video,.mh-media audio{max-width:100%}
|
|
19733
|
+
.mh-file a{display:inline-block;background:var(--card);border:1px solid var(--line);border-radius:8px;padding:8px 14px;color:var(--accent);text-decoration:none}
|
|
19633
19734
|
iframe.mh-embed{width:100%;border:1px solid var(--line);border-radius:8px;min-height:240px}
|
|
19634
19735
|
textarea.mh-raw{width:100%;min-height:60vh;font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;padding:14px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--fg)}
|
|
19635
19736
|
ul.files{list-style:none;padding:0} ul.files li{padding:4px 0} button.file{background:none;border:0;color:var(--accent);cursor:pointer;font-size:15px;padding:0}
|
|
@@ -20348,7 +20449,7 @@ init_config();
|
|
|
20348
20449
|
// package.json
|
|
20349
20450
|
var package_default = {
|
|
20350
20451
|
name: "@tensorix/metahub",
|
|
20351
|
-
version: "0.3.
|
|
20452
|
+
version: "0.3.2",
|
|
20352
20453
|
description: "Metahub core library and CLI",
|
|
20353
20454
|
license: "AGPL-3.0-only",
|
|
20354
20455
|
type: "module",
|
|
@@ -25262,4 +25363,4 @@ export {
|
|
|
25262
25363
|
BLOB_HASH_HEX
|
|
25263
25364
|
};
|
|
25264
25365
|
|
|
25265
|
-
//# debugId=
|
|
25366
|
+
//# debugId=6391E3807369E20264756E2164756E21
|