apple-notes-mcp 2.8.36 → 2.8.38
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 +95 -2
- package/build/index.js +1773 -240
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -417,11 +417,11 @@ var require_codegen = __commonJS({
|
|
|
417
417
|
const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
|
|
418
418
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
419
419
|
}
|
|
420
|
-
optimizeNames(names,
|
|
420
|
+
optimizeNames(names, constants6) {
|
|
421
421
|
if (!names[this.name.str])
|
|
422
422
|
return;
|
|
423
423
|
if (this.rhs)
|
|
424
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
424
|
+
this.rhs = optimizeExpr(this.rhs, names, constants6);
|
|
425
425
|
return this;
|
|
426
426
|
}
|
|
427
427
|
get names() {
|
|
@@ -438,10 +438,10 @@ var require_codegen = __commonJS({
|
|
|
438
438
|
render({ _n }) {
|
|
439
439
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
440
440
|
}
|
|
441
|
-
optimizeNames(names,
|
|
441
|
+
optimizeNames(names, constants6) {
|
|
442
442
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
443
443
|
return;
|
|
444
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
444
|
+
this.rhs = optimizeExpr(this.rhs, names, constants6);
|
|
445
445
|
return this;
|
|
446
446
|
}
|
|
447
447
|
get names() {
|
|
@@ -502,8 +502,8 @@ var require_codegen = __commonJS({
|
|
|
502
502
|
optimizeNodes() {
|
|
503
503
|
return `${this.code}` ? this : void 0;
|
|
504
504
|
}
|
|
505
|
-
optimizeNames(names,
|
|
506
|
-
this.code = optimizeExpr(this.code, names,
|
|
505
|
+
optimizeNames(names, constants6) {
|
|
506
|
+
this.code = optimizeExpr(this.code, names, constants6);
|
|
507
507
|
return this;
|
|
508
508
|
}
|
|
509
509
|
get names() {
|
|
@@ -532,12 +532,12 @@ var require_codegen = __commonJS({
|
|
|
532
532
|
}
|
|
533
533
|
return nodes.length > 0 ? this : void 0;
|
|
534
534
|
}
|
|
535
|
-
optimizeNames(names,
|
|
535
|
+
optimizeNames(names, constants6) {
|
|
536
536
|
const { nodes } = this;
|
|
537
537
|
let i = nodes.length;
|
|
538
538
|
while (i--) {
|
|
539
539
|
const n = nodes[i];
|
|
540
|
-
if (n.optimizeNames(names,
|
|
540
|
+
if (n.optimizeNames(names, constants6))
|
|
541
541
|
continue;
|
|
542
542
|
subtractNames(names, n.names);
|
|
543
543
|
nodes.splice(i, 1);
|
|
@@ -590,12 +590,12 @@ var require_codegen = __commonJS({
|
|
|
590
590
|
return void 0;
|
|
591
591
|
return this;
|
|
592
592
|
}
|
|
593
|
-
optimizeNames(names,
|
|
593
|
+
optimizeNames(names, constants6) {
|
|
594
594
|
var _a;
|
|
595
|
-
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
596
|
-
if (!(super.optimizeNames(names,
|
|
595
|
+
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants6);
|
|
596
|
+
if (!(super.optimizeNames(names, constants6) || this.else))
|
|
597
597
|
return;
|
|
598
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
598
|
+
this.condition = optimizeExpr(this.condition, names, constants6);
|
|
599
599
|
return this;
|
|
600
600
|
}
|
|
601
601
|
get names() {
|
|
@@ -618,10 +618,10 @@ var require_codegen = __commonJS({
|
|
|
618
618
|
render(opts) {
|
|
619
619
|
return `for(${this.iteration})` + super.render(opts);
|
|
620
620
|
}
|
|
621
|
-
optimizeNames(names,
|
|
622
|
-
if (!super.optimizeNames(names,
|
|
621
|
+
optimizeNames(names, constants6) {
|
|
622
|
+
if (!super.optimizeNames(names, constants6))
|
|
623
623
|
return;
|
|
624
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
624
|
+
this.iteration = optimizeExpr(this.iteration, names, constants6);
|
|
625
625
|
return this;
|
|
626
626
|
}
|
|
627
627
|
get names() {
|
|
@@ -657,10 +657,10 @@ var require_codegen = __commonJS({
|
|
|
657
657
|
render(opts) {
|
|
658
658
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
659
659
|
}
|
|
660
|
-
optimizeNames(names,
|
|
661
|
-
if (!super.optimizeNames(names,
|
|
660
|
+
optimizeNames(names, constants6) {
|
|
661
|
+
if (!super.optimizeNames(names, constants6))
|
|
662
662
|
return;
|
|
663
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
663
|
+
this.iterable = optimizeExpr(this.iterable, names, constants6);
|
|
664
664
|
return this;
|
|
665
665
|
}
|
|
666
666
|
get names() {
|
|
@@ -702,11 +702,11 @@ var require_codegen = __commonJS({
|
|
|
702
702
|
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
|
|
703
703
|
return this;
|
|
704
704
|
}
|
|
705
|
-
optimizeNames(names,
|
|
705
|
+
optimizeNames(names, constants6) {
|
|
706
706
|
var _a, _b;
|
|
707
|
-
super.optimizeNames(names,
|
|
708
|
-
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
709
|
-
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names,
|
|
707
|
+
super.optimizeNames(names, constants6);
|
|
708
|
+
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants6);
|
|
709
|
+
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants6);
|
|
710
710
|
return this;
|
|
711
711
|
}
|
|
712
712
|
get names() {
|
|
@@ -1007,7 +1007,7 @@ var require_codegen = __commonJS({
|
|
|
1007
1007
|
function addExprNames(names, from) {
|
|
1008
1008
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
1009
1009
|
}
|
|
1010
|
-
function optimizeExpr(expr, names,
|
|
1010
|
+
function optimizeExpr(expr, names, constants6) {
|
|
1011
1011
|
if (expr instanceof code_1.Name)
|
|
1012
1012
|
return replaceName(expr);
|
|
1013
1013
|
if (!canOptimize(expr))
|
|
@@ -1022,14 +1022,14 @@ var require_codegen = __commonJS({
|
|
|
1022
1022
|
return items;
|
|
1023
1023
|
}, []));
|
|
1024
1024
|
function replaceName(n) {
|
|
1025
|
-
const c =
|
|
1025
|
+
const c = constants6[n.str];
|
|
1026
1026
|
if (c === void 0 || names[n.str] !== 1)
|
|
1027
1027
|
return n;
|
|
1028
1028
|
delete names[n.str];
|
|
1029
1029
|
return c;
|
|
1030
1030
|
}
|
|
1031
1031
|
function canOptimize(e) {
|
|
1032
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
1032
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants6[c.str] !== void 0);
|
|
1033
1033
|
}
|
|
1034
1034
|
}
|
|
1035
1035
|
function subtractNames(names, from) {
|
|
@@ -2991,7 +2991,7 @@ var require_compile = __commonJS({
|
|
|
2991
2991
|
const schOrFunc = root.refs[ref];
|
|
2992
2992
|
if (schOrFunc)
|
|
2993
2993
|
return schOrFunc;
|
|
2994
|
-
let _sch =
|
|
2994
|
+
let _sch = resolve5.call(this, root, ref);
|
|
2995
2995
|
if (_sch === void 0) {
|
|
2996
2996
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2997
2997
|
const { schemaId } = this.opts;
|
|
@@ -3018,7 +3018,7 @@ var require_compile = __commonJS({
|
|
|
3018
3018
|
function sameSchemaEnv(s1, s2) {
|
|
3019
3019
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3020
3020
|
}
|
|
3021
|
-
function
|
|
3021
|
+
function resolve5(root, ref) {
|
|
3022
3022
|
let sch;
|
|
3023
3023
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3024
3024
|
ref = sch;
|
|
@@ -3843,7 +3843,7 @@ var require_fast_uri = __commonJS({
|
|
|
3843
3843
|
}
|
|
3844
3844
|
return uri;
|
|
3845
3845
|
}
|
|
3846
|
-
function
|
|
3846
|
+
function resolve5(baseURI, relativeURI, options) {
|
|
3847
3847
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3848
3848
|
const {
|
|
3849
3849
|
parsed: baseParsed,
|
|
@@ -3876,49 +3876,49 @@ var require_fast_uri = __commonJS({
|
|
|
3876
3876
|
schemelessOptions.skipEscape = true;
|
|
3877
3877
|
return serialize(resolved, schemelessOptions);
|
|
3878
3878
|
}
|
|
3879
|
-
function resolveComponent(base,
|
|
3879
|
+
function resolveComponent(base, relative4, options, skipNormalization) {
|
|
3880
3880
|
const target = {};
|
|
3881
3881
|
if (!skipNormalization) {
|
|
3882
3882
|
base = parse3(serialize(base, options), options);
|
|
3883
|
-
|
|
3883
|
+
relative4 = parse3(serialize(relative4, options), options);
|
|
3884
3884
|
}
|
|
3885
3885
|
options = options || {};
|
|
3886
|
-
if (!options.tolerant &&
|
|
3887
|
-
target.scheme =
|
|
3888
|
-
target.userinfo =
|
|
3889
|
-
target.host =
|
|
3890
|
-
target.port =
|
|
3891
|
-
target.path = removeDotSegments(
|
|
3892
|
-
target.query =
|
|
3886
|
+
if (!options.tolerant && relative4.scheme) {
|
|
3887
|
+
target.scheme = relative4.scheme;
|
|
3888
|
+
target.userinfo = relative4.userinfo;
|
|
3889
|
+
target.host = relative4.host;
|
|
3890
|
+
target.port = relative4.port;
|
|
3891
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
3892
|
+
target.query = relative4.query;
|
|
3893
3893
|
} else {
|
|
3894
|
-
if (
|
|
3895
|
-
target.userinfo =
|
|
3896
|
-
target.host =
|
|
3897
|
-
target.port =
|
|
3898
|
-
target.path = removeDotSegments(
|
|
3899
|
-
target.query =
|
|
3894
|
+
if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
|
|
3895
|
+
target.userinfo = relative4.userinfo;
|
|
3896
|
+
target.host = relative4.host;
|
|
3897
|
+
target.port = relative4.port;
|
|
3898
|
+
target.path = removeDotSegments(relative4.path || "");
|
|
3899
|
+
target.query = relative4.query;
|
|
3900
3900
|
} else {
|
|
3901
|
-
if (!
|
|
3901
|
+
if (!relative4.path) {
|
|
3902
3902
|
target.path = base.path;
|
|
3903
|
-
if (
|
|
3904
|
-
target.query =
|
|
3903
|
+
if (relative4.query !== void 0) {
|
|
3904
|
+
target.query = relative4.query;
|
|
3905
3905
|
} else {
|
|
3906
3906
|
target.query = base.query;
|
|
3907
3907
|
}
|
|
3908
3908
|
} else {
|
|
3909
|
-
if (
|
|
3910
|
-
target.path = removeDotSegments(
|
|
3909
|
+
if (relative4.path[0] === "/") {
|
|
3910
|
+
target.path = removeDotSegments(relative4.path);
|
|
3911
3911
|
} else {
|
|
3912
3912
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3913
|
-
target.path = "/" +
|
|
3913
|
+
target.path = "/" + relative4.path;
|
|
3914
3914
|
} else if (!base.path) {
|
|
3915
|
-
target.path =
|
|
3915
|
+
target.path = relative4.path;
|
|
3916
3916
|
} else {
|
|
3917
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3917
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
|
|
3918
3918
|
}
|
|
3919
3919
|
target.path = removeDotSegments(target.path);
|
|
3920
3920
|
}
|
|
3921
|
-
target.query =
|
|
3921
|
+
target.query = relative4.query;
|
|
3922
3922
|
}
|
|
3923
3923
|
target.userinfo = base.userinfo;
|
|
3924
3924
|
target.host = base.host;
|
|
@@ -3926,7 +3926,7 @@ var require_fast_uri = __commonJS({
|
|
|
3926
3926
|
}
|
|
3927
3927
|
target.scheme = base.scheme;
|
|
3928
3928
|
}
|
|
3929
|
-
target.fragment =
|
|
3929
|
+
target.fragment = relative4.fragment;
|
|
3930
3930
|
return target;
|
|
3931
3931
|
}
|
|
3932
3932
|
function equal(uriA, uriB, options) {
|
|
@@ -4205,7 +4205,7 @@ var require_fast_uri = __commonJS({
|
|
|
4205
4205
|
var fastUri = {
|
|
4206
4206
|
SCHEMES,
|
|
4207
4207
|
normalize,
|
|
4208
|
-
resolve:
|
|
4208
|
+
resolve: resolve5,
|
|
4209
4209
|
resolveComponent,
|
|
4210
4210
|
equal,
|
|
4211
4211
|
serialize,
|
|
@@ -4620,7 +4620,7 @@ var require_core = __commonJS({
|
|
|
4620
4620
|
errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
|
|
4621
4621
|
if (!errors || errors.length === 0)
|
|
4622
4622
|
return "No errors";
|
|
4623
|
-
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((
|
|
4623
|
+
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
|
|
4624
4624
|
}
|
|
4625
4625
|
$dataMetaSchema(metaSchema, keywordsJsonPointers) {
|
|
4626
4626
|
const rules = this.RULES.all;
|
|
@@ -7422,7 +7422,7 @@ var require_DOMException = __commonJS({
|
|
|
7422
7422
|
"INVALID_NODE_TYPE_ERR (24): the supplied node is invalid or has an invalid ancestor for this operation",
|
|
7423
7423
|
"DATA_CLONE_ERR (25): the object can not be cloned."
|
|
7424
7424
|
];
|
|
7425
|
-
var
|
|
7425
|
+
var constants6 = {
|
|
7426
7426
|
INDEX_SIZE_ERR,
|
|
7427
7427
|
DOMSTRING_SIZE_ERR: 2,
|
|
7428
7428
|
// historical
|
|
@@ -7461,8 +7461,8 @@ var require_DOMException = __commonJS({
|
|
|
7461
7461
|
this.name = names[code];
|
|
7462
7462
|
}
|
|
7463
7463
|
DOMException.prototype.__proto__ = Error.prototype;
|
|
7464
|
-
for (c in
|
|
7465
|
-
v = { value:
|
|
7464
|
+
for (c in constants6) {
|
|
7465
|
+
v = { value: constants6[c] };
|
|
7466
7466
|
Object.defineProperty(DOMException, c, v);
|
|
7467
7467
|
Object.defineProperty(DOMException.prototype, c, v);
|
|
7468
7468
|
}
|
|
@@ -9621,8 +9621,8 @@ var require_select = __commonJS({
|
|
|
9621
9621
|
// Non-standard, for compatibility purposes.
|
|
9622
9622
|
":contains": function(param) {
|
|
9623
9623
|
return function(el) {
|
|
9624
|
-
var
|
|
9625
|
-
return
|
|
9624
|
+
var text2 = el.innerText || el.textContent || el.value || "";
|
|
9625
|
+
return text2.indexOf(param) !== -1;
|
|
9626
9626
|
};
|
|
9627
9627
|
},
|
|
9628
9628
|
":has": function(param) {
|
|
@@ -10289,9 +10289,9 @@ var require_Element = __commonJS({
|
|
|
10289
10289
|
position = utils.toASCIILowerCase(String(position));
|
|
10290
10290
|
this._insertAdjacent(position, textNode);
|
|
10291
10291
|
} },
|
|
10292
|
-
insertAdjacentHTML: { value: function insertAdjacentHTML(position,
|
|
10292
|
+
insertAdjacentHTML: { value: function insertAdjacentHTML(position, text2) {
|
|
10293
10293
|
position = utils.toASCIILowerCase(String(position));
|
|
10294
|
-
|
|
10294
|
+
text2 = String(text2);
|
|
10295
10295
|
var context;
|
|
10296
10296
|
switch (position) {
|
|
10297
10297
|
case "beforebegin":
|
|
@@ -10315,7 +10315,7 @@ var require_Element = __commonJS({
|
|
|
10315
10315
|
this.ownerDocument._address,
|
|
10316
10316
|
context
|
|
10317
10317
|
);
|
|
10318
|
-
parser.parse(
|
|
10318
|
+
parser.parse(text2, true);
|
|
10319
10319
|
this._insertAdjacent(position, parser._asDocumentFragment());
|
|
10320
10320
|
} },
|
|
10321
10321
|
children: { get: function() {
|
|
@@ -12184,9 +12184,9 @@ var require_URL = __commonJS({
|
|
|
12184
12184
|
},
|
|
12185
12185
|
// See: http://tools.ietf.org/html/rfc3986#section-5.2
|
|
12186
12186
|
// and https://url.spec.whatwg.org/#constructors
|
|
12187
|
-
resolve: function(
|
|
12187
|
+
resolve: function(relative4) {
|
|
12188
12188
|
var base = this;
|
|
12189
|
-
var r = new URL2(
|
|
12189
|
+
var r = new URL2(relative4);
|
|
12190
12190
|
var t = new URL2();
|
|
12191
12191
|
if (r.scheme !== void 0) {
|
|
12192
12192
|
t.scheme = r.scheme;
|
|
@@ -12434,9 +12434,9 @@ var require_CSSStyleDeclaration = __commonJS({
|
|
|
12434
12434
|
// Note that the styles don't get parsed until they're actually needed
|
|
12435
12435
|
_parsed: { get: function() {
|
|
12436
12436
|
if (!this._parsedStyles || this.cssText !== this._lastParsedText) {
|
|
12437
|
-
var
|
|
12438
|
-
this._parsedStyles = parseStyles(
|
|
12439
|
-
this._lastParsedText =
|
|
12437
|
+
var text2 = this.cssText;
|
|
12438
|
+
this._parsedStyles = parseStyles(text2);
|
|
12439
|
+
this._lastParsedText = text2;
|
|
12440
12440
|
delete this._names;
|
|
12441
12441
|
}
|
|
12442
12442
|
return this._parsedStyles;
|
|
@@ -23907,7 +23907,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
23907
23907
|
});
|
|
23908
23908
|
}
|
|
23909
23909
|
var markdownEscapes = [[/\\/g, "\\\\"], [/\*/g, "\\*"], [/^-/g, "\\-"], [/^\+ /g, "\\+ "], [/^(=+)/g, "\\$1"], [/^(#{1,6}) /g, "\\$1 "], [/`/g, "\\`"], [/^~~~/g, "\\~~~"], [/\[/g, "\\["], [/\]/g, "\\]"], [/^>/g, "\\>"], [/_/g, "\\_"], [/^(\d+)\. /g, "$1\\. "]];
|
|
23910
|
-
function
|
|
23910
|
+
function escapeMarkdown2(string3) {
|
|
23911
23911
|
return markdownEscapes.reduce(function(accumulator, escape3) {
|
|
23912
23912
|
return accumulator.replace(escape3[0], escape3[1]);
|
|
23913
23913
|
}, string3);
|
|
@@ -24087,7 +24087,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
24087
24087
|
rules.image = {
|
|
24088
24088
|
filter: "img",
|
|
24089
24089
|
replacement: function(content, node) {
|
|
24090
|
-
var alt =
|
|
24090
|
+
var alt = escapeMarkdown2(cleanAttribute(node.getAttribute("alt")));
|
|
24091
24091
|
var src = escapeLinkDestination(node.getAttribute("src") || "");
|
|
24092
24092
|
var title = cleanAttribute(node.getAttribute("title"));
|
|
24093
24093
|
var titlePart = title ? ' "' + escapeLinkTitle(title) + '"' : "";
|
|
@@ -24181,15 +24181,15 @@ var require_turndown_cjs = __commonJS({
|
|
|
24181
24181
|
var node = next(prev, element, isPre);
|
|
24182
24182
|
while (node !== element) {
|
|
24183
24183
|
if (node.nodeType === 3 || node.nodeType === 4) {
|
|
24184
|
-
var
|
|
24185
|
-
if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs &&
|
|
24186
|
-
|
|
24184
|
+
var text2 = node.data.replace(/[ \r\n\t]+/g, " ");
|
|
24185
|
+
if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs && text2[0] === " ") {
|
|
24186
|
+
text2 = text2.substr(1);
|
|
24187
24187
|
}
|
|
24188
|
-
if (!
|
|
24188
|
+
if (!text2) {
|
|
24189
24189
|
node = remove(node);
|
|
24190
24190
|
continue;
|
|
24191
24191
|
}
|
|
24192
|
-
node.data =
|
|
24192
|
+
node.data = text2;
|
|
24193
24193
|
prevText = node;
|
|
24194
24194
|
} else if (node.nodeType === 1) {
|
|
24195
24195
|
if (isBlock2(node) || node.nodeName === "BR") {
|
|
@@ -24452,7 +24452,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
24452
24452
|
* @type String
|
|
24453
24453
|
*/
|
|
24454
24454
|
escape: function(string3) {
|
|
24455
|
-
return
|
|
24455
|
+
return escapeMarkdown2(string3);
|
|
24456
24456
|
}
|
|
24457
24457
|
};
|
|
24458
24458
|
function process3(parentNode) {
|
|
@@ -24465,14 +24465,14 @@ var require_turndown_cjs = __commonJS({
|
|
|
24465
24465
|
} else if (node.nodeType === 1) {
|
|
24466
24466
|
replacement = replacementForNode.call(self, node);
|
|
24467
24467
|
}
|
|
24468
|
-
return
|
|
24468
|
+
return join22(output, replacement);
|
|
24469
24469
|
}, "");
|
|
24470
24470
|
}
|
|
24471
24471
|
function postProcess(output) {
|
|
24472
24472
|
var self = this;
|
|
24473
24473
|
this.rules.forEach(function(rule) {
|
|
24474
24474
|
if (typeof rule.append === "function") {
|
|
24475
|
-
output =
|
|
24475
|
+
output = join22(output, rule.append(self.options));
|
|
24476
24476
|
}
|
|
24477
24477
|
});
|
|
24478
24478
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -24484,7 +24484,7 @@ var require_turndown_cjs = __commonJS({
|
|
|
24484
24484
|
if (whitespace.leading || whitespace.trailing) content = content.trim();
|
|
24485
24485
|
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
24486
24486
|
}
|
|
24487
|
-
function
|
|
24487
|
+
function join22(output, replacement) {
|
|
24488
24488
|
var s1 = trimTrailingNewlines(output);
|
|
24489
24489
|
var s2 = trimLeadingNewlines(replacement);
|
|
24490
24490
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -36608,7 +36608,7 @@ var Protocol = class {
|
|
|
36608
36608
|
return;
|
|
36609
36609
|
}
|
|
36610
36610
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
36611
|
-
await new Promise((
|
|
36611
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
36612
36612
|
options?.signal?.throwIfAborted();
|
|
36613
36613
|
}
|
|
36614
36614
|
} catch (error2) {
|
|
@@ -36625,7 +36625,7 @@ var Protocol = class {
|
|
|
36625
36625
|
*/
|
|
36626
36626
|
request(request, resultSchema, options) {
|
|
36627
36627
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
36628
|
-
return new Promise((
|
|
36628
|
+
return new Promise((resolve5, reject) => {
|
|
36629
36629
|
const earlyReject = (error2) => {
|
|
36630
36630
|
reject(error2);
|
|
36631
36631
|
};
|
|
@@ -36703,7 +36703,7 @@ var Protocol = class {
|
|
|
36703
36703
|
if (!parseResult.success) {
|
|
36704
36704
|
reject(parseResult.error);
|
|
36705
36705
|
} else {
|
|
36706
|
-
|
|
36706
|
+
resolve5(parseResult.data);
|
|
36707
36707
|
}
|
|
36708
36708
|
} catch (error2) {
|
|
36709
36709
|
reject(error2);
|
|
@@ -36964,12 +36964,12 @@ var Protocol = class {
|
|
|
36964
36964
|
}
|
|
36965
36965
|
} catch {
|
|
36966
36966
|
}
|
|
36967
|
-
return new Promise((
|
|
36967
|
+
return new Promise((resolve5, reject) => {
|
|
36968
36968
|
if (signal.aborted) {
|
|
36969
36969
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
36970
36970
|
return;
|
|
36971
36971
|
}
|
|
36972
|
-
const timeoutId = setTimeout(
|
|
36972
|
+
const timeoutId = setTimeout(resolve5, interval);
|
|
36973
36973
|
signal.addEventListener("abort", () => {
|
|
36974
36974
|
clearTimeout(timeoutId);
|
|
36975
36975
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -38282,7 +38282,7 @@ var McpServer = class {
|
|
|
38282
38282
|
let task = createTaskResult.task;
|
|
38283
38283
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
38284
38284
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
38285
|
-
await new Promise((
|
|
38285
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
38286
38286
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
38287
38287
|
if (!updatedTask) {
|
|
38288
38288
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -38970,12 +38970,12 @@ var StdioServerTransport = class {
|
|
|
38970
38970
|
this.onclose?.();
|
|
38971
38971
|
}
|
|
38972
38972
|
send(message) {
|
|
38973
|
-
return new Promise((
|
|
38973
|
+
return new Promise((resolve5) => {
|
|
38974
38974
|
const json2 = serializeMessage(message);
|
|
38975
38975
|
if (this._stdout.write(json2)) {
|
|
38976
|
-
|
|
38976
|
+
resolve5();
|
|
38977
38977
|
} else {
|
|
38978
|
-
this._stdout.once("drain",
|
|
38978
|
+
this._stdout.once("drain", resolve5);
|
|
38979
38979
|
}
|
|
38980
38980
|
});
|
|
38981
38981
|
}
|
|
@@ -39418,12 +39418,12 @@ function fixed32Float(field) {
|
|
|
39418
39418
|
}
|
|
39419
39419
|
|
|
39420
39420
|
// src/utils/checklistRuns.ts
|
|
39421
|
-
function checklistRunLineStart(
|
|
39421
|
+
function checklistRunLineStart(text2, position, length) {
|
|
39422
39422
|
const end = position + length;
|
|
39423
39423
|
let anchor = position;
|
|
39424
|
-
while (anchor < end &&
|
|
39424
|
+
while (anchor < end && text2[anchor] === "\n") anchor++;
|
|
39425
39425
|
if (anchor === end) anchor = position;
|
|
39426
|
-
return anchor === 0 ? 0 :
|
|
39426
|
+
return anchor === 0 ? 0 : text2.lastIndexOf("\n", anchor - 1) + 1;
|
|
39427
39427
|
}
|
|
39428
39428
|
|
|
39429
39429
|
// src/utils/checklistParser.ts
|
|
@@ -39625,8 +39625,8 @@ import { join as join2 } from "node:path";
|
|
|
39625
39625
|
import { gunzipSync as gunzipSync2 } from "node:zlib";
|
|
39626
39626
|
var dbPath = join2(homedir2(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
|
|
39627
39627
|
var safeUrl = (url) => /^(?:https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) && !Array.from(url).some((char) => char.charCodeAt(0) < 32);
|
|
39628
|
-
var escapeAttribute = (
|
|
39629
|
-
var normalized = (
|
|
39628
|
+
var escapeAttribute = (text2) => text2.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
39629
|
+
var normalized = (text2) => text2.replace(/[\s\ufffc]/gu, "");
|
|
39630
39630
|
function styleValue(field) {
|
|
39631
39631
|
if (!(field.value instanceof Uint8Array)) return field.value;
|
|
39632
39632
|
if (field.fieldNumber === 2) {
|
|
@@ -39659,8 +39659,8 @@ function parseRichNote(data, nativeTags = []) {
|
|
|
39659
39659
|
const doc = decodeMessage(data);
|
|
39660
39660
|
const wrapper = embeddedMessage(getField(doc, 2));
|
|
39661
39661
|
const body = wrapper && embeddedMessage(getField(wrapper, 3));
|
|
39662
|
-
const
|
|
39663
|
-
if (!body ||
|
|
39662
|
+
const text2 = body && stringValue(getField(body, 2));
|
|
39663
|
+
if (!body || text2 === void 0) throw new Error("Unsupported Notes document structure");
|
|
39664
39664
|
const links = [];
|
|
39665
39665
|
const nativeObjectIds = [];
|
|
39666
39666
|
const objects = [];
|
|
@@ -39673,7 +39673,7 @@ function parseRichNote(data, nativeTags = []) {
|
|
|
39673
39673
|
const fields = embeddedMessage(run);
|
|
39674
39674
|
if (!fields) throw new Error("Invalid Notes attribute run");
|
|
39675
39675
|
const length = varintValue(getField(fields, 1));
|
|
39676
|
-
if (length === void 0 || length < 0 || position + length >
|
|
39676
|
+
if (length === void 0 || length < 0 || position + length > text2.length)
|
|
39677
39677
|
throw new Error("Invalid Notes run length");
|
|
39678
39678
|
const paragraph = embeddedMessage(getField(fields, 2));
|
|
39679
39679
|
styleRuns.push({
|
|
@@ -39692,9 +39692,9 @@ function parseRichNote(data, nativeTags = []) {
|
|
|
39692
39692
|
const previous = links.at(-1);
|
|
39693
39693
|
if (previous?.url === url && previous.start + previous.length === position) {
|
|
39694
39694
|
previous.length += length;
|
|
39695
|
-
previous.text +=
|
|
39695
|
+
previous.text += text2.slice(position, position + length);
|
|
39696
39696
|
} else
|
|
39697
|
-
links.push({ start: position, length, text:
|
|
39697
|
+
links.push({ start: position, length, text: text2.slice(position, position + length), url });
|
|
39698
39698
|
}
|
|
39699
39699
|
hasNativeObjects ||= Boolean(getField(fields, 12));
|
|
39700
39700
|
const attachment = embeddedMessage(getField(fields, 12));
|
|
@@ -39712,23 +39712,23 @@ function parseRichNote(data, nativeTags = []) {
|
|
|
39712
39712
|
const checklist = embeddedMessage(getField(paragraph, 5));
|
|
39713
39713
|
const rawId = checklist && getField(checklist, 1)?.value;
|
|
39714
39714
|
const itemId = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : "";
|
|
39715
|
-
const start = checklistRunLineStart(
|
|
39715
|
+
const start = checklistRunLineStart(text2, position, length);
|
|
39716
39716
|
if (itemId && !checklistItems.some((item) => item.id === itemId))
|
|
39717
39717
|
checklistItems.push({
|
|
39718
39718
|
id: itemId,
|
|
39719
39719
|
start,
|
|
39720
|
-
text:
|
|
39720
|
+
text: text2.slice(
|
|
39721
39721
|
start,
|
|
39722
|
-
|
|
39722
|
+
text2.indexOf("\n", start) === -1 ? text2.length : text2.indexOf("\n", start)
|
|
39723
39723
|
),
|
|
39724
39724
|
done: checklist ? varintValue(getField(checklist, 2)) === 1 : false
|
|
39725
39725
|
});
|
|
39726
39726
|
}
|
|
39727
39727
|
position += length;
|
|
39728
39728
|
}
|
|
39729
|
-
if (position !==
|
|
39729
|
+
if (position !== text2.length) throw new Error("Incomplete Notes attribute runs");
|
|
39730
39730
|
return {
|
|
39731
|
-
text,
|
|
39731
|
+
text: text2,
|
|
39732
39732
|
links,
|
|
39733
39733
|
nativeTags: hasNativeObjects ? nativeTags : [],
|
|
39734
39734
|
nativeObjectIds,
|
|
@@ -40014,8 +40014,8 @@ function parseAudioRecording(data) {
|
|
|
40014
40014
|
const registerNoteText = (id2) => {
|
|
40015
40015
|
const target = registerTarget(id2);
|
|
40016
40016
|
const note = target && sub(target, 10);
|
|
40017
|
-
const
|
|
40018
|
-
return
|
|
40017
|
+
const text2 = note && stringValue(getField(note, 2));
|
|
40018
|
+
return text2?.replace(/\n+$/u, "") || void 0;
|
|
40019
40019
|
};
|
|
40020
40020
|
const recordings = entries2.map((e) => customMap(e)).filter((m) => m?.type === "com.apple.notes.ICTTAudioRecording");
|
|
40021
40021
|
if (recordings.length !== 1) throw new Error("Expected exactly one audio recording object");
|
|
@@ -40054,13 +40054,13 @@ function parseAudioRecording(data) {
|
|
|
40054
40054
|
const segment = customMap(entry(segmentIndex));
|
|
40055
40055
|
if (segment?.type !== "com.apple.notes.ICTTTranscriptSegment")
|
|
40056
40056
|
throw new Error("Unexpected segment type");
|
|
40057
|
-
const
|
|
40058
|
-
if (typeof
|
|
40057
|
+
const text2 = registerPrimitive(segment.values.get("text"));
|
|
40058
|
+
if (typeof text2 !== "string") throw new Error("Segment without text");
|
|
40059
40059
|
const start = registerPrimitive(segment.values.get("timestamp"));
|
|
40060
40060
|
const duration3 = registerPrimitive(segment.values.get("duration"));
|
|
40061
40061
|
const speaker = registerPrimitive(segment.values.get("speaker"));
|
|
40062
40062
|
segments.push({
|
|
40063
|
-
text,
|
|
40063
|
+
text: text2,
|
|
40064
40064
|
...typeof start === "number" ? { start } : {},
|
|
40065
40065
|
...typeof duration3 === "number" ? { duration: duration3 } : {},
|
|
40066
40066
|
...typeof speaker === "string" && speaker ? { speaker } : {}
|
|
@@ -40080,10 +40080,10 @@ function parseAudioRecording(data) {
|
|
|
40080
40080
|
}
|
|
40081
40081
|
function joinSegments(segments) {
|
|
40082
40082
|
let out = "";
|
|
40083
|
-
for (const { text } of segments) {
|
|
40084
|
-
if (!
|
|
40085
|
-
const glue = !out || /\s$/u.test(out) || /^\s/u.test(
|
|
40086
|
-
out += glue +
|
|
40083
|
+
for (const { text: text2 } of segments) {
|
|
40084
|
+
if (!text2) continue;
|
|
40085
|
+
const glue = !out || /\s$/u.test(out) || /^\s/u.test(text2) || /^[.,!?;:%)\]}…'’]/u.test(text2) ? "" : " ";
|
|
40086
|
+
out += glue + text2;
|
|
40087
40087
|
}
|
|
40088
40088
|
return out.trim();
|
|
40089
40089
|
}
|
|
@@ -40217,14 +40217,14 @@ function describeRow(row, store, options, maxSegments) {
|
|
|
40217
40217
|
const all = recording.fragments.flatMap(
|
|
40218
40218
|
(fragment, i) => fragment.segments.map((s) => multi ? { ...s, fragment: i } : s)
|
|
40219
40219
|
);
|
|
40220
|
-
const
|
|
40220
|
+
const text2 = recording.fragments.map((f) => joinSegments(f.segments)).filter(Boolean).join("\n\n");
|
|
40221
40221
|
const speakers = [...new Set(all.flatMap((s) => s.speaker ? [s.speaker] : []))];
|
|
40222
40222
|
return {
|
|
40223
40223
|
...base,
|
|
40224
40224
|
status: all.length ? "ok" : "none",
|
|
40225
40225
|
fragmentCount: recording.fragments.length,
|
|
40226
40226
|
wordCount: all.length,
|
|
40227
|
-
...
|
|
40227
|
+
...text2 ? { text: text2 } : {},
|
|
40228
40228
|
...speakers.length ? { speakers } : {},
|
|
40229
40229
|
...recording.summary ? { summary: recording.summary } : {},
|
|
40230
40230
|
...recording.topLineSummary ? { topLineSummary: recording.topLineSummary } : {},
|
|
@@ -40378,18 +40378,18 @@ function decodeTable(compressed, strict) {
|
|
|
40378
40378
|
const ri = rows.map.get(uuidIndex(num(sub2(row, 1), 6)));
|
|
40379
40379
|
if (ri === void 0 || ci === void 0) continue;
|
|
40380
40380
|
const note = sub2(entry(num(sub2(row, 2), 6)), 10);
|
|
40381
|
-
const
|
|
40382
|
-
if (
|
|
40381
|
+
const text2 = stringValue(getField(note, 2));
|
|
40382
|
+
if (text2 === void 0 || text2.includes("\uFFFC")) {
|
|
40383
40383
|
if (strict) throw new Error("Embedded or unsupported table cell");
|
|
40384
40384
|
values[ri][ci] = null;
|
|
40385
40385
|
incomplete.push({
|
|
40386
40386
|
ri,
|
|
40387
40387
|
ci,
|
|
40388
|
-
reason:
|
|
40388
|
+
reason: text2 === void 0 ? "Cell text is missing" : "Cell contains an embedded object"
|
|
40389
40389
|
});
|
|
40390
40390
|
continue;
|
|
40391
40391
|
}
|
|
40392
|
-
values[ri][ci] =
|
|
40392
|
+
values[ri][ci] = text2.replace(/\n$/u, "");
|
|
40393
40393
|
}
|
|
40394
40394
|
}
|
|
40395
40395
|
const rtl = entries2.some((e) => {
|
|
@@ -40409,8 +40409,8 @@ function decodeTable(compressed, strict) {
|
|
|
40409
40409
|
|
|
40410
40410
|
// src/utils/tableMarkdown.ts
|
|
40411
40411
|
var UNDECODED_CELL_MARKER = "[undecoded cell]";
|
|
40412
|
-
function escapeMarkdownTableCell(
|
|
40413
|
-
return
|
|
40412
|
+
function escapeMarkdownTableCell(text2) {
|
|
40413
|
+
return text2.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r\n|[\r\n\u2028\u2029]/g, "<br>");
|
|
40414
40414
|
}
|
|
40415
40415
|
function renderMarkdownTable(rows) {
|
|
40416
40416
|
const width = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
@@ -40550,8 +40550,8 @@ var Decoder = class {
|
|
|
40550
40550
|
}
|
|
40551
40551
|
/** Mark a positively described leaf as an Exclude rule. */
|
|
40552
40552
|
negate(filter) {
|
|
40553
|
-
const
|
|
40554
|
-
const negated =
|
|
40553
|
+
const text2 = filter.description;
|
|
40554
|
+
const negated = text2.startsWith("has ") ? text2.replace(/^has /, "does not have ") : text2.startsWith("is ") ? text2.replace(/^is /, "is not ") : text2.startsWith("mentions ") ? text2.replace(/^mentions /, "does not mention ") : `not ${text2}`;
|
|
40555
40555
|
return { ...filter, excluded: true, description: negated };
|
|
40556
40556
|
}
|
|
40557
40557
|
clause(clause, excluded, depth) {
|
|
@@ -42003,11 +42003,11 @@ function fitExportNoteToBudget(note, maxBytes) {
|
|
|
42003
42003
|
function executeMutationAppleScript(script) {
|
|
42004
42004
|
return executeAppleScript(script, { maxRetries: 1 });
|
|
42005
42005
|
}
|
|
42006
|
-
function escapeForAppleScript(
|
|
42007
|
-
if (!
|
|
42006
|
+
function escapeForAppleScript(text2) {
|
|
42007
|
+
if (!text2) {
|
|
42008
42008
|
return "";
|
|
42009
42009
|
}
|
|
42010
|
-
let escaped =
|
|
42010
|
+
let escaped = text2.replace(/&/g, "&");
|
|
42011
42011
|
escaped = escaped.replace(/\\/g, "\");
|
|
42012
42012
|
escaped = escaped.replace(/"/g, '\\"');
|
|
42013
42013
|
escaped = escaped.replace(/\n/g, "<br>");
|
|
@@ -42020,9 +42020,9 @@ function escapeHtmlForAppleScript(htmlContent) {
|
|
|
42020
42020
|
}
|
|
42021
42021
|
return htmlContent.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
42022
42022
|
}
|
|
42023
|
-
function escapePlainStringForAppleScript(
|
|
42024
|
-
if (!
|
|
42025
|
-
return
|
|
42023
|
+
function escapePlainStringForAppleScript(text2) {
|
|
42024
|
+
if (!text2) return "";
|
|
42025
|
+
return text2.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
42026
42026
|
}
|
|
42027
42027
|
var MAX_TITLE_LENGTH = 2e3;
|
|
42028
42028
|
var MAX_CONTENT_LENGTH = 5 * 1024 * 1024;
|
|
@@ -44319,13 +44319,13 @@ var AppleNotesManager = class {
|
|
|
44319
44319
|
* Simple HTML to plaintext conversion for export.
|
|
44320
44320
|
*/
|
|
44321
44321
|
htmlToPlaintext(html) {
|
|
44322
|
-
let
|
|
44322
|
+
let text2 = html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/div>/gi, "\n").replace(/<\/p>/gi, "\n");
|
|
44323
44323
|
let prev;
|
|
44324
44324
|
do {
|
|
44325
|
-
prev =
|
|
44326
|
-
|
|
44327
|
-
} while (
|
|
44328
|
-
return
|
|
44325
|
+
prev = text2;
|
|
44326
|
+
text2 = text2.replace(/<[^>]*>/g, "");
|
|
44327
|
+
} while (text2 !== prev);
|
|
44328
|
+
return text2.replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/\/g, "\\").replace(/&/g, "&").replace(/\n{3,}/g, "\n\n").trim();
|
|
44329
44329
|
}
|
|
44330
44330
|
/**
|
|
44331
44331
|
* Exports notes as a JSON structure for backup/migration, one page at a time.
|
|
@@ -44501,11 +44501,11 @@ var AppleNotesManager = class {
|
|
|
44501
44501
|
const enriched = lines.map((line) => {
|
|
44502
44502
|
const listMatch = line.match(/^(\s*[-*])\s+(.+)$/);
|
|
44503
44503
|
if (!listMatch) return line;
|
|
44504
|
-
const [, prefix,
|
|
44505
|
-
const done = checklistMap.get(
|
|
44504
|
+
const [, prefix, text2] = listMatch;
|
|
44505
|
+
const done = checklistMap.get(text2.trim());
|
|
44506
44506
|
if (done === void 0) return line;
|
|
44507
|
-
checklistMap.delete(
|
|
44508
|
-
return `${prefix} ${done ? "[x]" : "[ ]"} ${
|
|
44507
|
+
checklistMap.delete(text2.trim());
|
|
44508
|
+
return `${prefix} ${done ? "[x]" : "[ ]"} ${text2}`;
|
|
44509
44509
|
});
|
|
44510
44510
|
return enriched.join("\n");
|
|
44511
44511
|
}
|
|
@@ -45095,7 +45095,7 @@ function buildTagInventorySql(columns, scoped) {
|
|
|
45095
45095
|
"COMMIT;"
|
|
45096
45096
|
].join(" ");
|
|
45097
45097
|
}
|
|
45098
|
-
var bareTag = (
|
|
45098
|
+
var bareTag = (text2) => text2.replace(/^#/, "").trim();
|
|
45099
45099
|
function referencedObjects(hex3) {
|
|
45100
45100
|
if (!hex3 || !/^[0-9a-f]+$/i.test(hex3)) return null;
|
|
45101
45101
|
try {
|
|
@@ -45133,11 +45133,11 @@ function assembleInventory(rows, accounts, scope2) {
|
|
|
45133
45133
|
const bodies = /* @__PURE__ */ new Map();
|
|
45134
45134
|
for (const row of rows) if (row.k === "body") bodies.set(row.note, referencedObjects(row.data));
|
|
45135
45135
|
const groups = /* @__PURE__ */ new Map();
|
|
45136
|
-
const group = (
|
|
45137
|
-
const key =
|
|
45136
|
+
const group = (text2, weight) => {
|
|
45137
|
+
const key = text2.toLocaleLowerCase();
|
|
45138
45138
|
let found = groups.get(key);
|
|
45139
45139
|
if (!found) groups.set(key, found = { spellings: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Map() });
|
|
45140
|
-
found.spellings.set(
|
|
45140
|
+
found.spellings.set(text2, (found.spellings.get(text2) ?? 0) + weight);
|
|
45141
45141
|
return found;
|
|
45142
45142
|
};
|
|
45143
45143
|
const unverified = /* @__PURE__ */ new Set();
|
|
@@ -45163,7 +45163,7 @@ function assembleInventory(rows, accounts, scope2) {
|
|
|
45163
45163
|
noteCount: entry.notes.size,
|
|
45164
45164
|
accounts: perAccount
|
|
45165
45165
|
};
|
|
45166
|
-
if (spellings.length > 1) result.spellings = spellings.slice(1).map(([
|
|
45166
|
+
if (spellings.length > 1) result.spellings = spellings.slice(1).map(([text2]) => text2);
|
|
45167
45167
|
return result;
|
|
45168
45168
|
});
|
|
45169
45169
|
inventory.sort((a, b) => b.noteCount - a.noteCount || a.tag.localeCompare(b.tag));
|
|
@@ -45431,10 +45431,10 @@ function htmlToText(html) {
|
|
|
45431
45431
|
var HASHTAG_RE = new RegExp("(?<![\\p{L}\\p{N}_])#([\\p{L}\\p{N}_]*\\p{L}[\\p{L}\\p{N}_]*)", "gu");
|
|
45432
45432
|
function parseHashtags(body) {
|
|
45433
45433
|
if (!body) return [];
|
|
45434
|
-
const
|
|
45434
|
+
const text2 = htmlToText(body);
|
|
45435
45435
|
const seen = /* @__PURE__ */ new Set();
|
|
45436
45436
|
const result = [];
|
|
45437
|
-
for (const match of
|
|
45437
|
+
for (const match of text2.matchAll(HASHTAG_RE)) {
|
|
45438
45438
|
const tag = match[1];
|
|
45439
45439
|
const key = tag.toLowerCase();
|
|
45440
45440
|
if (!seen.has(key)) {
|
|
@@ -45450,7 +45450,7 @@ var BLOCK_END_RE = /<\/(?:div|h[1-6]|p|li)>/gi;
|
|
|
45450
45450
|
var BREAK_RE = /<br\s*\/?\s*>/gi;
|
|
45451
45451
|
var TAG_RE = /<[^>]*>/g;
|
|
45452
45452
|
var NON_RENDERED_BLOCK_RE = /<(script|style)\b[^>]*>[\s\S]*?(?:<\/\1>|$)/gi;
|
|
45453
|
-
function decodeHtmlEntities(
|
|
45453
|
+
function decodeHtmlEntities(text2) {
|
|
45454
45454
|
const decodeCodePoint = (match, value, radix) => {
|
|
45455
45455
|
const codePoint = Number.parseInt(value, radix);
|
|
45456
45456
|
if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) {
|
|
@@ -45458,21 +45458,21 @@ function decodeHtmlEntities(text) {
|
|
|
45458
45458
|
}
|
|
45459
45459
|
return String.fromCodePoint(codePoint);
|
|
45460
45460
|
};
|
|
45461
|
-
return
|
|
45461
|
+
return text2.replace(/&#x([0-9a-f]+);?/gi, (match, hex3) => decodeCodePoint(match, hex3, 16)).replace(/&#([0-9]+);?/g, (match, decimal) => decodeCodePoint(match, decimal, 10)).replace(/ (?:;|(?![0-9a-z]))/gi, " ").replace(/"(?:;|(?![0-9a-z]))/gi, '"').replace(/&apos(?:;|(?![0-9a-z]))/gi, "'").replace(/<(?:;|(?![0-9a-z]))/gi, "<").replace(/>(?:;|(?![0-9a-z]))/gi, ">").replace(/&(?:;|(?![0-9a-z]))/gi, "&");
|
|
45462
45462
|
}
|
|
45463
45463
|
function firstVisibleHtmlLine(html) {
|
|
45464
|
-
let
|
|
45464
|
+
let text2 = html;
|
|
45465
45465
|
let previous;
|
|
45466
45466
|
do {
|
|
45467
|
-
previous =
|
|
45468
|
-
|
|
45469
|
-
} while (
|
|
45470
|
-
|
|
45467
|
+
previous = text2;
|
|
45468
|
+
text2 = text2.replace(NON_RENDERED_BLOCK_RE, "");
|
|
45469
|
+
} while (text2 !== previous);
|
|
45470
|
+
text2 = text2.replace(BREAK_RE, "\n").replace(BLOCK_END_RE, "\n");
|
|
45471
45471
|
do {
|
|
45472
|
-
previous =
|
|
45473
|
-
|
|
45474
|
-
} while (
|
|
45475
|
-
return decodeHtmlEntities(
|
|
45472
|
+
previous = text2;
|
|
45473
|
+
text2 = text2.replace(TAG_RE, "");
|
|
45474
|
+
} while (text2 !== previous);
|
|
45475
|
+
return decodeHtmlEntities(text2).split(/[\r\n\u2028\u2029]+/).map((line) => line.replace(/\s+/g, " ").trim()).find(Boolean);
|
|
45476
45476
|
}
|
|
45477
45477
|
function resolveUpdateResponseTitle(currentTitle, newTitle, format, newContent) {
|
|
45478
45478
|
if (format === "html") return firstVisibleHtmlLine(newContent) ?? currentTitle;
|
|
@@ -45637,15 +45637,15 @@ function splitComparison(value) {
|
|
|
45637
45637
|
const match = COMPARE_RE.exec(value);
|
|
45638
45638
|
return [match[1] ?? "=", match[2]];
|
|
45639
45639
|
}
|
|
45640
|
-
function parseLocalDate(
|
|
45641
|
-
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(
|
|
45640
|
+
function parseLocalDate(text2, pos) {
|
|
45641
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text2);
|
|
45642
45642
|
if (!match) {
|
|
45643
|
-
throw new NoteQueryError(`Expected a date as YYYY-MM-DD, got "${
|
|
45643
|
+
throw new NoteQueryError(`Expected a date as YYYY-MM-DD, got "${text2}"`, pos);
|
|
45644
45644
|
}
|
|
45645
45645
|
const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
45646
45646
|
const start = new Date(year, month - 1, day);
|
|
45647
45647
|
if (start.getFullYear() !== year || start.getMonth() !== month - 1 || start.getDate() !== day) {
|
|
45648
|
-
throw new NoteQueryError(`"${
|
|
45648
|
+
throw new NoteQueryError(`"${text2}" is not a valid calendar date`, pos);
|
|
45649
45649
|
}
|
|
45650
45650
|
return { start: start.getTime(), end: new Date(year, month - 1, day + 1).getTime() };
|
|
45651
45651
|
}
|
|
@@ -45819,8 +45819,8 @@ var Parser = class {
|
|
|
45819
45819
|
function parseNoteQuery(input) {
|
|
45820
45820
|
return new Parser(tokenize(input), input.length).parse();
|
|
45821
45821
|
}
|
|
45822
|
-
function normalizeForMatch(
|
|
45823
|
-
return
|
|
45822
|
+
function normalizeForMatch(text2) {
|
|
45823
|
+
return text2.normalize("NFC").replace(/[\ufffc\u00a0]/gu, " ").toLowerCase();
|
|
45824
45824
|
}
|
|
45825
45825
|
function needsContent(node) {
|
|
45826
45826
|
switch (node.type) {
|
|
@@ -45999,8 +45999,8 @@ var CHECKLIST_STYLE = 103;
|
|
|
45999
45999
|
function decodeNoteBody(data) {
|
|
46000
46000
|
const wrapper = embeddedMessage(getField(decodeMessage(data), 2));
|
|
46001
46001
|
const body = wrapper && embeddedMessage(getField(wrapper, 3));
|
|
46002
|
-
const
|
|
46003
|
-
if (!body ||
|
|
46002
|
+
const text2 = body && stringValue(getField(body, 2));
|
|
46003
|
+
if (!body || text2 === void 0) return null;
|
|
46004
46004
|
const facets = /* @__PURE__ */ new Set();
|
|
46005
46005
|
const objectIds = /* @__PURE__ */ new Set();
|
|
46006
46006
|
const checklist = /* @__PURE__ */ new Map();
|
|
@@ -46021,7 +46021,7 @@ function decodeNoteBody(data) {
|
|
|
46021
46021
|
if (paragraph && varintValue(getField(paragraph, 1)) === CHECKLIST_STYLE) {
|
|
46022
46022
|
const item = embeddedMessage(getField(paragraph, 5));
|
|
46023
46023
|
const rawId = item && getField(item, 1)?.value;
|
|
46024
|
-
const key = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : `line:${
|
|
46024
|
+
const key = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : `line:${text2.lastIndexOf("\n", position - 1) + 1}`;
|
|
46025
46025
|
checklist.set(key, (item && varintValue(getField(item, 2))) === 1);
|
|
46026
46026
|
}
|
|
46027
46027
|
position += length;
|
|
@@ -46029,15 +46029,15 @@ function decodeNoteBody(data) {
|
|
|
46029
46029
|
if (checklist.size > 0) facets.add("checklist");
|
|
46030
46030
|
const done = [...checklist.values()].filter(Boolean).length;
|
|
46031
46031
|
return {
|
|
46032
|
-
text,
|
|
46032
|
+
text: text2,
|
|
46033
46033
|
facets,
|
|
46034
46034
|
checklist: { total: checklist.size, open: checklist.size - done },
|
|
46035
46035
|
objectIds
|
|
46036
46036
|
};
|
|
46037
46037
|
}
|
|
46038
|
-
function countWords(
|
|
46038
|
+
function countWords(text2) {
|
|
46039
46039
|
let count = 0;
|
|
46040
|
-
for (const word of
|
|
46040
|
+
for (const word of text2.replace(/\ufffc/gu, " ").split(/\s+/u)) {
|
|
46041
46041
|
if (/[\p{L}\p{N}]/u.test(word)) count++;
|
|
46042
46042
|
}
|
|
46043
46043
|
return count;
|
|
@@ -46109,13 +46109,13 @@ var escapeSegment = escapeFolderName;
|
|
|
46109
46109
|
function resolveFolders(rows) {
|
|
46110
46110
|
const byPk = new Map(rows.map((row) => [row.pk, row]));
|
|
46111
46111
|
const resolved = /* @__PURE__ */ new Map();
|
|
46112
|
-
const
|
|
46112
|
+
const resolve5 = (pk, seen) => {
|
|
46113
46113
|
const cached2 = resolved.get(pk);
|
|
46114
46114
|
if (cached2) return cached2;
|
|
46115
46115
|
const row = byPk.get(pk);
|
|
46116
46116
|
if (!row || seen.has(pk)) return void 0;
|
|
46117
46117
|
seen.add(pk);
|
|
46118
|
-
const parent = row.parent !== null ?
|
|
46118
|
+
const parent = row.parent !== null ? resolve5(row.parent, seen) : void 0;
|
|
46119
46119
|
const name = row.name ?? "";
|
|
46120
46120
|
const path8 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
|
|
46121
46121
|
const plainPath = parent ? `${parent.plainPath}/${name}` : name;
|
|
@@ -46129,12 +46129,12 @@ function resolveFolders(rows) {
|
|
|
46129
46129
|
resolved.set(pk, info);
|
|
46130
46130
|
return info;
|
|
46131
46131
|
};
|
|
46132
|
-
for (const row of rows)
|
|
46132
|
+
for (const row of rows) resolve5(row.pk, /* @__PURE__ */ new Set());
|
|
46133
46133
|
return resolved;
|
|
46134
46134
|
}
|
|
46135
46135
|
var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS2 + seconds * 1e3;
|
|
46136
|
-
function buildSnippet(
|
|
46137
|
-
const clean =
|
|
46136
|
+
function buildSnippet(text2, terms) {
|
|
46137
|
+
const clean = text2.replace(/\ufffc/gu, " ");
|
|
46138
46138
|
const firstBreak = clean.indexOf("\n");
|
|
46139
46139
|
const body = firstBreak === -1 ? clean : clean.slice(firstBreak + 1);
|
|
46140
46140
|
const lower = normalizeForMatch(body);
|
|
@@ -46237,8 +46237,8 @@ function queryNotes(expression, options = {}) {
|
|
|
46237
46237
|
if (content !== void 0) return content;
|
|
46238
46238
|
const body2 = decode2();
|
|
46239
46239
|
if (!body2) return content = null;
|
|
46240
|
-
const
|
|
46241
|
-
const firstBreak =
|
|
46240
|
+
const text2 = body2.text;
|
|
46241
|
+
const firstBreak = text2.indexOf("\n");
|
|
46242
46242
|
const tags = /* @__PURE__ */ new Set();
|
|
46243
46243
|
for (const [id2, alt] of row.tags ?? []) {
|
|
46244
46244
|
if (id2 && alt && body2.objectIds.has(id2))
|
|
@@ -46247,9 +46247,9 @@ function queryNotes(expression, options = {}) {
|
|
|
46247
46247
|
const facets = new Set(body2.facets);
|
|
46248
46248
|
if (tags.size) facets.add("tag");
|
|
46249
46249
|
content = {
|
|
46250
|
-
textLower: normalizeForMatch(
|
|
46251
|
-
bodyLower: normalizeForMatch(firstBreak === -1 ? "" :
|
|
46252
|
-
words: countWords(
|
|
46250
|
+
textLower: normalizeForMatch(text2),
|
|
46251
|
+
bodyLower: normalizeForMatch(firstBreak === -1 ? "" : text2.slice(firstBreak + 1)),
|
|
46252
|
+
words: countWords(text2),
|
|
46253
46253
|
facets,
|
|
46254
46254
|
checklist: body2.checklist,
|
|
46255
46255
|
tags: [...tags]
|
|
@@ -46347,12 +46347,12 @@ function addNativeTags(request, deps) {
|
|
|
46347
46347
|
}
|
|
46348
46348
|
const after = deps.read(request.id);
|
|
46349
46349
|
const allTags = [.../* @__PURE__ */ new Set([...before.rich.nativeTags, ...tags])];
|
|
46350
|
-
const textWithoutTags = (
|
|
46350
|
+
const textWithoutTags = (text2) => {
|
|
46351
46351
|
for (const tag of [...allTags].sort((a, b) => b.length - a.length)) {
|
|
46352
46352
|
const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
46353
|
-
|
|
46353
|
+
text2 = text2.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
|
|
46354
46354
|
}
|
|
46355
|
-
return
|
|
46355
|
+
return text2.replace(/[\s\ufffc]/gu, "");
|
|
46356
46356
|
};
|
|
46357
46357
|
if (after.title !== before.title || allTags.some((tag) => !after.rich.nativeTags.includes(tag)) || textWithoutTags(before.rich.text) !== textWithoutTags(after.rich.text) || linkSignature(before.rich.links) !== linkSignature(after.rich.links) || before.rich.nativeObjectIds.some((id2) => !after.rich.nativeObjectIds.includes(id2)) || before.rich.hasChecklist !== after.rich.hasChecklist) {
|
|
46358
46358
|
throw new Error(
|
|
@@ -46473,9 +46473,9 @@ function renderMarkdown(markdown, options = {}) {
|
|
|
46473
46473
|
dividers: 0,
|
|
46474
46474
|
highlights: []
|
|
46475
46475
|
};
|
|
46476
|
-
const inline = (
|
|
46476
|
+
const inline = (text2) => {
|
|
46477
46477
|
const spans = [];
|
|
46478
|
-
let value =
|
|
46478
|
+
let value = text2;
|
|
46479
46479
|
if (blocks)
|
|
46480
46480
|
value = value.replace(/`([^`\n]+)`/g, (_s, code2) => {
|
|
46481
46481
|
if (/^\s|\s$/.test(code2)) throw new Error("Inline code cannot start or end with a space");
|
|
@@ -46497,13 +46497,13 @@ function renderMarkdown(markdown, options = {}) {
|
|
|
46497
46497
|
return value.replace(/(\d+)/g, (_s, i) => links[Number(i)]).replace(/(\d+)/g, (_s, i) => spans[Number(i)]);
|
|
46498
46498
|
};
|
|
46499
46499
|
const withoutTags = (html2) => {
|
|
46500
|
-
let
|
|
46500
|
+
let text2 = "", inTag = false;
|
|
46501
46501
|
for (const ch of html2) {
|
|
46502
46502
|
if (ch === "<") inTag = true;
|
|
46503
46503
|
else if (ch === ">" && inTag) inTag = false;
|
|
46504
|
-
else if (!inTag)
|
|
46504
|
+
else if (!inTag) text2 += ch;
|
|
46505
46505
|
}
|
|
46506
|
-
return
|
|
46506
|
+
return text2;
|
|
46507
46507
|
};
|
|
46508
46508
|
const visible = (html2) => withoutTags(html2).replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
46509
46509
|
let html = "", list, quote = false, code, previousBlank = true;
|
|
@@ -46540,9 +46540,9 @@ function renderMarkdown(markdown, options = {}) {
|
|
|
46540
46540
|
continue;
|
|
46541
46541
|
}
|
|
46542
46542
|
if (line.startsWith(">")) {
|
|
46543
|
-
const
|
|
46544
|
-
if (!
|
|
46545
|
-
if (/^(?:#|[-+*][ \t]|\d+[.)][ \t]|>|```)/.test(
|
|
46543
|
+
const text2 = line.replace(/^> ?/, "");
|
|
46544
|
+
if (!text2.trim()) throw new Error("Empty block quote lines are unsupported");
|
|
46545
|
+
if (/^(?:#|[-+*][ \t]|\d+[.)][ \t]|>|```)/.test(text2))
|
|
46546
46546
|
throw new Error("Block quotes support text and inline formatting only");
|
|
46547
46547
|
if (!quote) {
|
|
46548
46548
|
close();
|
|
@@ -46550,7 +46550,7 @@ function renderMarkdown(markdown, options = {}) {
|
|
|
46550
46550
|
quote = true;
|
|
46551
46551
|
expect.quotes.push("");
|
|
46552
46552
|
}
|
|
46553
|
-
const rendered = inline(
|
|
46553
|
+
const rendered = inline(text2);
|
|
46554
46554
|
html += `<div>${rendered}</div>`;
|
|
46555
46555
|
expect.quotes[expect.quotes.length - 1] += ` ${visible(rendered)}`;
|
|
46556
46556
|
previousBlank = false;
|
|
@@ -46911,11 +46911,11 @@ function appendNative(manager, request) {
|
|
|
46911
46911
|
throw new Error("Use create-table for verified native table insertion");
|
|
46912
46912
|
const markdownHtml = request.format === "markdown" ? appendMarkdownHtml(request.content) : null;
|
|
46913
46913
|
const op = request.format === "plaintext" ? "append-text" : request.format === "markdown" ? "append-markdown" : "append-html";
|
|
46914
|
-
const
|
|
46914
|
+
const text2 = request.format === "html" ? "<div><br></div>" + request.content : "\n\n" + request.content;
|
|
46915
46915
|
return mutateBackground(
|
|
46916
46916
|
request,
|
|
46917
46917
|
op,
|
|
46918
|
-
{ text },
|
|
46918
|
+
{ text: text2 },
|
|
46919
46919
|
(before, after) => {
|
|
46920
46920
|
assertPreserved(before, after, { append: true });
|
|
46921
46921
|
const verifyHtml = markdownHtml ?? request.content;
|
|
@@ -46955,7 +46955,7 @@ function setNativeTag(manager, request) {
|
|
|
46955
46955
|
deps
|
|
46956
46956
|
);
|
|
46957
46957
|
}
|
|
46958
|
-
var literalMarkdown = (
|
|
46958
|
+
var literalMarkdown = (text2) => text2.replace(/[!-/:-@[-`{-~]/g, "\\$&");
|
|
46959
46959
|
function headingLevels(html) {
|
|
46960
46960
|
return [...html.matchAll(/<h([1-3])\b[^>]*>([\s\S]*?)<\/h\1>/gi)].filter((match) => comparableVisibleText(match[2])).map((match) => Number(match[1]));
|
|
46961
46961
|
}
|
|
@@ -47712,18 +47712,18 @@ var NOTHING_WRITTEN = /nothing (?:was )?(?:changed|created|written)|no replaceme
|
|
|
47712
47712
|
var WRITE_ACCEPTED = /\baccepted (?:the|an) \w+, but/i;
|
|
47713
47713
|
function classifyError(message, cause) {
|
|
47714
47714
|
if (cause instanceof CodedError) return { ...cause.envelope };
|
|
47715
|
-
const
|
|
47715
|
+
const text2 = cause instanceof Error && cause.message && !message.includes(cause.message) ? `${message}
|
|
47716
47716
|
${cause.message}` : message;
|
|
47717
47717
|
const timeoutCause = typeof cause === "object" && cause !== null && cause.code === "ETIMEDOUT";
|
|
47718
47718
|
let code = "operation_failed";
|
|
47719
47719
|
if (timeoutCause) code = "timeout_indeterminate";
|
|
47720
|
-
else if (isPermissionDenied(
|
|
47721
|
-
else code = RULES.find((rule) => rule.pattern.test(
|
|
47720
|
+
else if (isPermissionDenied(text2)) code = "permission_denied";
|
|
47721
|
+
else code = RULES.find((rule) => rule.pattern.test(text2))?.code ?? "operation_failed";
|
|
47722
47722
|
const envelope = { code };
|
|
47723
47723
|
if (code === "timeout_indeterminate" || code === "verification_failed") {
|
|
47724
47724
|
envelope.indeterminate = true;
|
|
47725
|
-
if (WRITE_ACCEPTED.test(
|
|
47726
|
-
} else if (code === "revision_conflict" || NOTHING_WRITTEN.test(
|
|
47725
|
+
if (WRITE_ACCEPTED.test(text2)) envelope.committed = true;
|
|
47726
|
+
} else if (code === "revision_conflict" || NOTHING_WRITTEN.test(text2)) {
|
|
47727
47727
|
envelope.committed = false;
|
|
47728
47728
|
envelope.indeterminate = false;
|
|
47729
47729
|
}
|
|
@@ -47913,7 +47913,7 @@ function decodeNoteBlocks(data) {
|
|
|
47913
47913
|
const textBytes = note && bytesOf(note, 2);
|
|
47914
47914
|
if (!note || !textBytes)
|
|
47915
47915
|
throw new NoteBlocksError("unsupported-structure", "Unsupported Notes document structure");
|
|
47916
|
-
const
|
|
47916
|
+
const text2 = utf8.decode(textBytes);
|
|
47917
47917
|
const runTally = /* @__PURE__ */ new Map();
|
|
47918
47918
|
const paragraphTally = /* @__PURE__ */ new Map();
|
|
47919
47919
|
const runs = [];
|
|
@@ -47924,7 +47924,7 @@ function decodeNoteBlocks(data) {
|
|
|
47924
47924
|
throw new NoteBlocksError("invalid-runs", "Invalid Notes attribute run");
|
|
47925
47925
|
const fields = decodeWireFields(field.bytes);
|
|
47926
47926
|
const length = varintOf(fields, 1);
|
|
47927
|
-
if (length === void 0 || length < 0 || position + length >
|
|
47927
|
+
if (length === void 0 || length < 0 || position + length > text2.length)
|
|
47928
47928
|
throw new NoteBlocksError("invalid-runs", "Invalid Notes run length");
|
|
47929
47929
|
for (const n of new Set(fields.map((f) => f.fieldNumber)))
|
|
47930
47930
|
if (!KNOWN_RUN_FIELDS.has(n)) runTally.set(n, (runTally.get(n) || 0) + 1);
|
|
@@ -47939,15 +47939,15 @@ function decodeNoteBlocks(data) {
|
|
|
47939
47939
|
} catch (error2) {
|
|
47940
47940
|
wrap(error2);
|
|
47941
47941
|
}
|
|
47942
|
-
if (position !==
|
|
47942
|
+
if (position !== text2.length)
|
|
47943
47943
|
throw new NoteBlocksError("invalid-runs", "Incomplete Notes attribute runs");
|
|
47944
47944
|
const blocks = [];
|
|
47945
47945
|
const attachments = [];
|
|
47946
47946
|
let runIndex = 0;
|
|
47947
47947
|
let paragraphStart = 0;
|
|
47948
|
-
while (paragraphStart <
|
|
47949
|
-
const newline =
|
|
47950
|
-
const end = newline === -1 ?
|
|
47948
|
+
while (paragraphStart < text2.length) {
|
|
47949
|
+
const newline = text2.indexOf("\n", paragraphStart);
|
|
47950
|
+
const end = newline === -1 ? text2.length : newline;
|
|
47951
47951
|
while (runIndex < runs.length - 1 && runs[runIndex].start + runs[runIndex].length <= paragraphStart)
|
|
47952
47952
|
runIndex++;
|
|
47953
47953
|
const attrs = runs[runIndex]?.paragraph ?? DEFAULT_PARAGRAPH;
|
|
@@ -47957,7 +47957,7 @@ function decodeNoteBlocks(data) {
|
|
|
47957
47957
|
index: blocks.length,
|
|
47958
47958
|
start: paragraphStart,
|
|
47959
47959
|
length: end - paragraphStart,
|
|
47960
|
-
text:
|
|
47960
|
+
text: text2.slice(paragraphStart, end),
|
|
47961
47961
|
style,
|
|
47962
47962
|
styleType: attrs.styleType,
|
|
47963
47963
|
indent: attrs.indent,
|
|
@@ -47977,11 +47977,11 @@ function decodeNoteBlocks(data) {
|
|
|
47977
47977
|
block.runs.push({
|
|
47978
47978
|
start,
|
|
47979
47979
|
length: stop - start,
|
|
47980
|
-
text:
|
|
47980
|
+
text: text2.slice(start, stop),
|
|
47981
47981
|
...run.inline
|
|
47982
47982
|
});
|
|
47983
47983
|
if (run.inline.attachment)
|
|
47984
|
-
for (let at =
|
|
47984
|
+
for (let at = text2.indexOf("\uFFFC", start); at !== -1 && at < stop; at = text2.indexOf("\uFFFC", at + 1)) {
|
|
47985
47985
|
const marker = { ...run.inline.attachment, start: at, blockIndex: block.index };
|
|
47986
47986
|
block.attachments.push(marker);
|
|
47987
47987
|
attachments.push(marker);
|
|
@@ -47991,8 +47991,8 @@ function decodeNoteBlocks(data) {
|
|
|
47991
47991
|
paragraphStart = end + 1;
|
|
47992
47992
|
}
|
|
47993
47993
|
return {
|
|
47994
|
-
text,
|
|
47995
|
-
textLength:
|
|
47994
|
+
text: text2,
|
|
47995
|
+
textLength: text2.length,
|
|
47996
47996
|
blocks,
|
|
47997
47997
|
attachments,
|
|
47998
47998
|
undecodedFields: {
|
|
@@ -48182,7 +48182,7 @@ function validateLinkLabel(label) {
|
|
|
48182
48182
|
throw new Error("Hyperlink label must be one line without control characters");
|
|
48183
48183
|
return label;
|
|
48184
48184
|
}
|
|
48185
|
-
var escapeText = (
|
|
48185
|
+
var escapeText = (text2) => text2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
48186
48186
|
var escapeHref = (url) => escapeText(url).replace(/"/g, """);
|
|
48187
48187
|
function buildLinkInsertion(request) {
|
|
48188
48188
|
const url = validateLinkUrl(request.url);
|
|
@@ -48272,20 +48272,1441 @@ function insertLink(request, deps) {
|
|
|
48272
48272
|
};
|
|
48273
48273
|
}
|
|
48274
48274
|
|
|
48275
|
-
// src/
|
|
48276
|
-
import {
|
|
48275
|
+
// src/services/notesExport.ts
|
|
48276
|
+
import { mkdirSync as mkdirSync5 } from "node:fs";
|
|
48277
|
+
import { basename as basename4, dirname as dirname4, extname as extname4, join as join20 } from "node:path";
|
|
48278
|
+
|
|
48279
|
+
// src/utils/exportAssets.ts
|
|
48277
48280
|
import {
|
|
48278
48281
|
closeSync as closeSync4,
|
|
48279
48282
|
constants as constants4,
|
|
48280
48283
|
fstatSync as fstatSync4,
|
|
48281
|
-
|
|
48284
|
+
mkdirSync as mkdirSync4,
|
|
48282
48285
|
openSync as openSync4,
|
|
48286
|
+
readdirSync as readdirSync3,
|
|
48287
|
+
readSync as readSync3,
|
|
48288
|
+
realpathSync as realpathSync3,
|
|
48289
|
+
statSync as statSync3,
|
|
48290
|
+
writeSync as writeSync3
|
|
48291
|
+
} from "node:fs";
|
|
48292
|
+
import { homedir as homedir15 } from "node:os";
|
|
48293
|
+
import { basename as basename3, extname as extname3, join as join18, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
|
|
48294
|
+
var NOTES_CONTAINER = join18(homedir15(), "Library/Group Containers/group.com.apple.notes");
|
|
48295
|
+
var MAX_EMBED_BYTES = 10 * 1024 * 1024;
|
|
48296
|
+
var MAX_EMBED_TOTAL_BYTES = 256 * 1024 * 1024;
|
|
48297
|
+
var MAX_DIRECTORY_ENTRIES = 2e4;
|
|
48298
|
+
var MAX_BUNDLE_ENTRIES2 = 64;
|
|
48299
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".heic", ".gif", ".tiff", ".webp"]);
|
|
48300
|
+
function safeComponent2(value) {
|
|
48301
|
+
if (!value || value.length > 255) return void 0;
|
|
48302
|
+
if (value === "." || value === ".." || /[/\\\0]/.test(value)) return void 0;
|
|
48303
|
+
return value;
|
|
48304
|
+
}
|
|
48305
|
+
function confine(candidate, root) {
|
|
48306
|
+
try {
|
|
48307
|
+
const real = realpathSync3.native(candidate);
|
|
48308
|
+
return real.startsWith(root + sep3) ? real : void 0;
|
|
48309
|
+
} catch {
|
|
48310
|
+
return void 0;
|
|
48311
|
+
}
|
|
48312
|
+
}
|
|
48313
|
+
function listDirectory(dir, limit) {
|
|
48314
|
+
try {
|
|
48315
|
+
const names = readdirSync3(dir);
|
|
48316
|
+
return names.length > limit ? [] : names.sort();
|
|
48317
|
+
} catch {
|
|
48318
|
+
return [];
|
|
48319
|
+
}
|
|
48320
|
+
}
|
|
48321
|
+
function isFile(path8) {
|
|
48322
|
+
let fd;
|
|
48323
|
+
try {
|
|
48324
|
+
fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
48325
|
+
return fstatSync4(fd).isFile();
|
|
48326
|
+
} catch {
|
|
48327
|
+
return false;
|
|
48328
|
+
} finally {
|
|
48329
|
+
if (fd !== void 0) closeSync4(fd);
|
|
48330
|
+
}
|
|
48331
|
+
}
|
|
48332
|
+
function isDirectory2(path8) {
|
|
48333
|
+
try {
|
|
48334
|
+
return statSync3(path8).isDirectory();
|
|
48335
|
+
} catch {
|
|
48336
|
+
return false;
|
|
48337
|
+
}
|
|
48338
|
+
}
|
|
48339
|
+
function previewArea(name) {
|
|
48340
|
+
const sizes = [...name.matchAll(/-(\d{1,5})x(\d{1,5})(?=-|\.|$)/g)];
|
|
48341
|
+
const last = sizes[sizes.length - 1];
|
|
48342
|
+
return last ? Number(last[1]) * Number(last[2]) : 0;
|
|
48343
|
+
}
|
|
48344
|
+
var AssetLocator = class {
|
|
48345
|
+
accounts;
|
|
48346
|
+
previewIndex = /* @__PURE__ */ new Map();
|
|
48347
|
+
constructor(container = NOTES_CONTAINER) {
|
|
48348
|
+
let accountsRoot = "";
|
|
48349
|
+
try {
|
|
48350
|
+
accountsRoot = realpathSync3.native(join18(container, "Accounts"));
|
|
48351
|
+
} catch {
|
|
48352
|
+
}
|
|
48353
|
+
this.accounts = accountsRoot ? listDirectory(accountsRoot, 1e3).flatMap((name) => {
|
|
48354
|
+
const dir = safeComponent2(name) && confine(join18(accountsRoot, name), accountsRoot);
|
|
48355
|
+
return dir && isDirectory2(dir) ? [dir] : [];
|
|
48356
|
+
}) : [];
|
|
48357
|
+
}
|
|
48358
|
+
/** Canonical account directories found in the container. */
|
|
48359
|
+
get accountDirs() {
|
|
48360
|
+
return [...this.accounts];
|
|
48361
|
+
}
|
|
48362
|
+
/** The attachment's own file and its best preview, when present. */
|
|
48363
|
+
locate(source) {
|
|
48364
|
+
const id2 = safeComponent2(source.id);
|
|
48365
|
+
if (!id2) return {};
|
|
48366
|
+
for (const account of this.accounts) {
|
|
48367
|
+
const files = this.locateIn(account, id2, source);
|
|
48368
|
+
if (files.primary || files.preview) return files;
|
|
48369
|
+
}
|
|
48370
|
+
return {};
|
|
48371
|
+
}
|
|
48372
|
+
locateIn(account, id2, source) {
|
|
48373
|
+
const preview = this.preview(account, id2);
|
|
48374
|
+
const media = this.media(account, source);
|
|
48375
|
+
switch (source.kind) {
|
|
48376
|
+
case "drawing":
|
|
48377
|
+
case "paper": {
|
|
48378
|
+
const fallback = this.fallback(
|
|
48379
|
+
account,
|
|
48380
|
+
"FallbackImages",
|
|
48381
|
+
id2,
|
|
48382
|
+
source.fallbackImageGeneration,
|
|
48383
|
+
["FallbackImage.png", "FallbackImage.jpg"]
|
|
48384
|
+
);
|
|
48385
|
+
if (fallback)
|
|
48386
|
+
return { primary: { path: fallback, name: `${source.kind}.png`, role: "fallback" } };
|
|
48387
|
+
return preview ? { primary: preview } : {};
|
|
48388
|
+
}
|
|
48389
|
+
case "scan": {
|
|
48390
|
+
const pdf = this.fallback(account, "FallbackPDFs", id2, source.fallbackPdfGeneration, [
|
|
48391
|
+
"FallbackPDF.pdf"
|
|
48392
|
+
]);
|
|
48393
|
+
return {
|
|
48394
|
+
...pdf ? { primary: { path: pdf, name: "scan.pdf", role: "fallback" } } : {},
|
|
48395
|
+
...preview ? { preview } : {}
|
|
48396
|
+
};
|
|
48397
|
+
}
|
|
48398
|
+
case "link":
|
|
48399
|
+
return preview ? { preview } : {};
|
|
48400
|
+
default:
|
|
48401
|
+
return {
|
|
48402
|
+
...media ? { primary: media } : {},
|
|
48403
|
+
...preview ? { preview } : {}
|
|
48404
|
+
};
|
|
48405
|
+
}
|
|
48406
|
+
}
|
|
48407
|
+
/** Media/<media-id>/<generation>/<filename>, then without the generation. */
|
|
48408
|
+
media(account, source) {
|
|
48409
|
+
const mediaId = safeComponent2(source.mediaId);
|
|
48410
|
+
const filename = safeComponent2(source.mediaFilename);
|
|
48411
|
+
if (!mediaId || !filename) return void 0;
|
|
48412
|
+
const generation = safeComponent2(source.mediaGeneration);
|
|
48413
|
+
const candidates = [
|
|
48414
|
+
...generation ? [join18(account, "Media", mediaId, generation, filename)] : [],
|
|
48415
|
+
join18(account, "Media", mediaId, filename)
|
|
48416
|
+
];
|
|
48417
|
+
for (const candidate of candidates) {
|
|
48418
|
+
const path8 = confine(candidate, account);
|
|
48419
|
+
if (path8 && isFile(path8)) return { path: path8, name: filename, role: "original" };
|
|
48420
|
+
}
|
|
48421
|
+
return void 0;
|
|
48422
|
+
}
|
|
48423
|
+
/** <dir>/<id>/<generation>/<name>, <dir>/<id>/<name>, then any generation. */
|
|
48424
|
+
fallback(account, dir, id2, generation, names) {
|
|
48425
|
+
const base = join18(account, dir, id2);
|
|
48426
|
+
const gen = safeComponent2(generation);
|
|
48427
|
+
const generations = [
|
|
48428
|
+
...gen ? [gen] : [],
|
|
48429
|
+
"",
|
|
48430
|
+
...listDirectory(base, MAX_BUNDLE_ENTRIES2).filter((name) => name !== gen && safeComponent2(name)).reverse()
|
|
48431
|
+
];
|
|
48432
|
+
for (const g of generations)
|
|
48433
|
+
for (const name of names) {
|
|
48434
|
+
const path8 = confine(g ? join18(base, g, name) : join18(base, name), account);
|
|
48435
|
+
if (path8 && isFile(path8)) return path8;
|
|
48436
|
+
}
|
|
48437
|
+
return void 0;
|
|
48438
|
+
}
|
|
48439
|
+
/** The largest rendered preview image for an attachment. */
|
|
48440
|
+
preview(account, id2) {
|
|
48441
|
+
let index = this.previewIndex.get(account);
|
|
48442
|
+
if (!index) {
|
|
48443
|
+
index = /* @__PURE__ */ new Map();
|
|
48444
|
+
for (const name of listDirectory(join18(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
|
|
48445
|
+
const key = name.slice(0, 36).toUpperCase();
|
|
48446
|
+
const entries3 = index.get(key) ?? [];
|
|
48447
|
+
entries3.push(name);
|
|
48448
|
+
index.set(key, entries3);
|
|
48449
|
+
}
|
|
48450
|
+
this.previewIndex.set(account, index);
|
|
48451
|
+
}
|
|
48452
|
+
const entries2 = (index.get(id2.toUpperCase()) ?? []).filter((name) => name.slice(36, 37) === "-" || name.length === 36).filter((name) => {
|
|
48453
|
+
const ext = extname3(name).toLowerCase();
|
|
48454
|
+
return !ext || IMAGE_EXTENSIONS.has(ext) || /^\.\d+$/.test(ext);
|
|
48455
|
+
}).sort((a, b) => previewArea(b) - previewArea(a) || a.localeCompare(b));
|
|
48456
|
+
for (const name of entries2) {
|
|
48457
|
+
const entry = confine(join18(account, "Previews", name), account);
|
|
48458
|
+
if (!entry) continue;
|
|
48459
|
+
const file = isFile(entry) ? entry : this.bundleImage(entry, account);
|
|
48460
|
+
if (file) return { path: file, name: "preview", role: "preview" };
|
|
48461
|
+
}
|
|
48462
|
+
return void 0;
|
|
48463
|
+
}
|
|
48464
|
+
/** Preview.png (or another image) at most two levels inside a bundle. */
|
|
48465
|
+
bundleImage(bundle, account) {
|
|
48466
|
+
const found = [];
|
|
48467
|
+
for (const child of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
|
|
48468
|
+
const path8 = confine(join18(bundle, child), account);
|
|
48469
|
+
if (!path8) continue;
|
|
48470
|
+
if (isFile(path8)) found.push(path8);
|
|
48471
|
+
else
|
|
48472
|
+
for (const grandchild of listDirectory(path8, MAX_BUNDLE_ENTRIES2)) {
|
|
48473
|
+
const inner = confine(join18(path8, grandchild), account);
|
|
48474
|
+
if (inner && isFile(inner)) found.push(inner);
|
|
48475
|
+
}
|
|
48476
|
+
}
|
|
48477
|
+
return found.find((path8) => basename3(path8) === "Preview.png") ?? found.find((path8) => IMAGE_EXTENSIONS.has(extname3(path8).toLowerCase()));
|
|
48478
|
+
}
|
|
48479
|
+
};
|
|
48480
|
+
function sniffMime(head, name) {
|
|
48481
|
+
const ascii = Buffer.from(head).toString("latin1");
|
|
48482
|
+
if (ascii.startsWith("\x89PNG")) return "image/png";
|
|
48483
|
+
if (head[0] === 255 && head[1] === 216) return "image/jpeg";
|
|
48484
|
+
if (ascii.startsWith("GIF8")) return "image/gif";
|
|
48485
|
+
if (ascii.startsWith("%PDF")) return "application/pdf";
|
|
48486
|
+
if (ascii.slice(4, 12) === "ftypheic" || ascii.slice(4, 12) === "ftypmif1") return "image/heic";
|
|
48487
|
+
if (ascii.startsWith("RIFF") && ascii.slice(8, 12) === "WEBP") return "image/webp";
|
|
48488
|
+
const byExtension = {
|
|
48489
|
+
".png": "image/png",
|
|
48490
|
+
".jpg": "image/jpeg",
|
|
48491
|
+
".jpeg": "image/jpeg",
|
|
48492
|
+
".gif": "image/gif",
|
|
48493
|
+
".heic": "image/heic",
|
|
48494
|
+
".tiff": "image/tiff",
|
|
48495
|
+
".webp": "image/webp",
|
|
48496
|
+
".pdf": "application/pdf",
|
|
48497
|
+
".m4a": "audio/mp4",
|
|
48498
|
+
".mp3": "audio/mpeg",
|
|
48499
|
+
".wav": "audio/wav",
|
|
48500
|
+
".mov": "video/quicktime",
|
|
48501
|
+
".mp4": "video/mp4",
|
|
48502
|
+
".txt": "text/plain"
|
|
48503
|
+
};
|
|
48504
|
+
return byExtension[extname3(name).toLowerCase()] ?? "application/octet-stream";
|
|
48505
|
+
}
|
|
48506
|
+
function extensionFor(mime) {
|
|
48507
|
+
const map = {
|
|
48508
|
+
"image/png": ".png",
|
|
48509
|
+
"image/jpeg": ".jpg",
|
|
48510
|
+
"image/gif": ".gif",
|
|
48511
|
+
"image/heic": ".heic",
|
|
48512
|
+
"image/webp": ".webp",
|
|
48513
|
+
"application/pdf": ".pdf"
|
|
48514
|
+
};
|
|
48515
|
+
return map[mime] ?? "";
|
|
48516
|
+
}
|
|
48517
|
+
function safeAssetName(name, mime) {
|
|
48518
|
+
let clean = basename3(name).normalize("NFC").replace(/[^\p{L}\p{N}._ -]+/gu, "_").replace(/^[.\s]+/, "").trim();
|
|
48519
|
+
if (!clean) clean = "attachment";
|
|
48520
|
+
if (!extname3(clean)) clean += extensionFor(mime);
|
|
48521
|
+
const ext = extname3(clean);
|
|
48522
|
+
if (clean.length > 120) clean = clean.slice(0, 120 - ext.length) + ext;
|
|
48523
|
+
return clean;
|
|
48524
|
+
}
|
|
48525
|
+
function encodePathUrl(path8) {
|
|
48526
|
+
return path8.split("/").map(encodeURIComponent).join("/");
|
|
48527
|
+
}
|
|
48528
|
+
function canonicalForm(abs) {
|
|
48529
|
+
let current = abs;
|
|
48530
|
+
let rest = "";
|
|
48531
|
+
for (; ; ) {
|
|
48532
|
+
try {
|
|
48533
|
+
const real = realpathSync3.native(current);
|
|
48534
|
+
return rest ? join18(real, rest) : real;
|
|
48535
|
+
} catch {
|
|
48536
|
+
const parent = resolve3(current, "..");
|
|
48537
|
+
if (parent === current) return abs;
|
|
48538
|
+
rest = rest ? join18(basename3(current), rest) : basename3(current);
|
|
48539
|
+
current = parent;
|
|
48540
|
+
}
|
|
48541
|
+
}
|
|
48542
|
+
}
|
|
48543
|
+
function assertExportPath(p, container = NOTES_CONTAINER) {
|
|
48544
|
+
const abs = assertSafeSavePath(p);
|
|
48545
|
+
const within = (path8, root) => path8 === root || path8.startsWith(root + sep3);
|
|
48546
|
+
const roots = [resolve3(container), canonicalForm(resolve3(container))];
|
|
48547
|
+
const forms = [abs, canonicalForm(abs)];
|
|
48548
|
+
if (forms.some((form) => roots.some((root) => within(form, root))))
|
|
48549
|
+
throw new Error("Refusing to write inside the Notes library container.");
|
|
48550
|
+
return abs;
|
|
48551
|
+
}
|
|
48552
|
+
var CREATE_FLAGS = constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW;
|
|
48553
|
+
var OutputExistsError = class extends Error {
|
|
48554
|
+
code = "output_exists";
|
|
48555
|
+
constructor(path8) {
|
|
48556
|
+
super(`Output file already exists: ${path8}. Choose a new path or remove the old file first.`);
|
|
48557
|
+
this.name = "OutputExistsError";
|
|
48558
|
+
}
|
|
48559
|
+
};
|
|
48560
|
+
function openCreateOnly(path8) {
|
|
48561
|
+
try {
|
|
48562
|
+
return openSync4(path8, CREATE_FLAGS, 420);
|
|
48563
|
+
} catch (error2) {
|
|
48564
|
+
if (error2.code === "EEXIST") throw new OutputExistsError(path8);
|
|
48565
|
+
throw error2;
|
|
48566
|
+
}
|
|
48567
|
+
}
|
|
48568
|
+
function writeAllAndClose(fd, content) {
|
|
48569
|
+
try {
|
|
48570
|
+
const data = Buffer.from(content, "utf8");
|
|
48571
|
+
let written = 0;
|
|
48572
|
+
while (written < data.length) written += writeSync3(fd, data, written);
|
|
48573
|
+
return data.length;
|
|
48574
|
+
} finally {
|
|
48575
|
+
closeSync4(fd);
|
|
48576
|
+
}
|
|
48577
|
+
}
|
|
48578
|
+
function openSource(path8) {
|
|
48579
|
+
const fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
|
|
48580
|
+
const stat = fstatSync4(fd);
|
|
48581
|
+
if (!stat.isFile()) {
|
|
48582
|
+
closeSync4(fd);
|
|
48583
|
+
throw new Error("Asset is not a regular file");
|
|
48584
|
+
}
|
|
48585
|
+
return { fd, size: stat.size };
|
|
48586
|
+
}
|
|
48587
|
+
function readHead(fd) {
|
|
48588
|
+
const head = Buffer.alloc(16);
|
|
48589
|
+
const n = readSync3(fd, head, 0, 16, 0);
|
|
48590
|
+
return head.subarray(0, n);
|
|
48591
|
+
}
|
|
48592
|
+
var SidecarWriter = class {
|
|
48593
|
+
constructor(dir, linkBase) {
|
|
48594
|
+
this.dir = dir;
|
|
48595
|
+
this.linkBase = linkBase;
|
|
48596
|
+
}
|
|
48597
|
+
dir;
|
|
48598
|
+
linkBase;
|
|
48599
|
+
placed = /* @__PURE__ */ new Map();
|
|
48600
|
+
created = false;
|
|
48601
|
+
count = 0;
|
|
48602
|
+
place(asset) {
|
|
48603
|
+
const done = this.placed.get(asset.path);
|
|
48604
|
+
if (done) return done;
|
|
48605
|
+
let source;
|
|
48606
|
+
try {
|
|
48607
|
+
source = openSource(asset.path);
|
|
48608
|
+
} catch {
|
|
48609
|
+
return { error: "unreadable" };
|
|
48610
|
+
}
|
|
48611
|
+
try {
|
|
48612
|
+
const mime = sniffMime(readHead(source.fd), asset.name);
|
|
48613
|
+
if (!this.created) {
|
|
48614
|
+
assertExportPath(this.dir);
|
|
48615
|
+
mkdirSync4(this.dir, { recursive: true });
|
|
48616
|
+
this.created = true;
|
|
48617
|
+
}
|
|
48618
|
+
const name = safeAssetName(asset.name, mime);
|
|
48619
|
+
const ext = extname3(name);
|
|
48620
|
+
const stem = name.slice(0, name.length - ext.length);
|
|
48621
|
+
let target;
|
|
48622
|
+
let out;
|
|
48623
|
+
for (let n = 1; n <= 1e3 && out === void 0; n++) {
|
|
48624
|
+
target = join18(this.dir, n === 1 ? name : `${stem}-${n}${ext}`);
|
|
48625
|
+
try {
|
|
48626
|
+
out = openSync4(target, CREATE_FLAGS, 420);
|
|
48627
|
+
} catch (error2) {
|
|
48628
|
+
if (error2.code !== "EEXIST") throw error2;
|
|
48629
|
+
}
|
|
48630
|
+
}
|
|
48631
|
+
if (out === void 0 || !target) return { error: "no-free-name" };
|
|
48632
|
+
try {
|
|
48633
|
+
const chunk = Buffer.alloc(1024 * 1024);
|
|
48634
|
+
for (let position = 0; ; ) {
|
|
48635
|
+
const n = readSync3(source.fd, chunk, 0, chunk.length, position);
|
|
48636
|
+
if (n <= 0) break;
|
|
48637
|
+
let written = 0;
|
|
48638
|
+
while (written < n) written += writeSync3(out, chunk, written, n - written);
|
|
48639
|
+
position += n;
|
|
48640
|
+
}
|
|
48641
|
+
} finally {
|
|
48642
|
+
closeSync4(out);
|
|
48643
|
+
}
|
|
48644
|
+
this.count++;
|
|
48645
|
+
const url = this.linkBase ? encodePathUrl(relative3(this.linkBase, target).split(sep3).join("/")) : target;
|
|
48646
|
+
const result = { url, mime };
|
|
48647
|
+
this.placed.set(asset.path, result);
|
|
48648
|
+
return result;
|
|
48649
|
+
} catch (error2) {
|
|
48650
|
+
return { error: error2 instanceof Error ? error2.message : String(error2) };
|
|
48651
|
+
} finally {
|
|
48652
|
+
closeSync4(source.fd);
|
|
48653
|
+
}
|
|
48654
|
+
}
|
|
48655
|
+
};
|
|
48656
|
+
var DataUrlWriter = class {
|
|
48657
|
+
constructor(maxBytes = MAX_EMBED_BYTES, totalBytes = MAX_EMBED_TOTAL_BYTES) {
|
|
48658
|
+
this.maxBytes = maxBytes;
|
|
48659
|
+
this.totalBytes = totalBytes;
|
|
48660
|
+
}
|
|
48661
|
+
maxBytes;
|
|
48662
|
+
totalBytes;
|
|
48663
|
+
placed = /* @__PURE__ */ new Map();
|
|
48664
|
+
embeddedBytes = 0;
|
|
48665
|
+
count = 0;
|
|
48666
|
+
place(asset) {
|
|
48667
|
+
const done = this.placed.get(asset.path);
|
|
48668
|
+
if (done) return done;
|
|
48669
|
+
let source;
|
|
48670
|
+
try {
|
|
48671
|
+
source = openSource(asset.path);
|
|
48672
|
+
} catch {
|
|
48673
|
+
return { error: "unreadable" };
|
|
48674
|
+
}
|
|
48675
|
+
try {
|
|
48676
|
+
if (source.size > this.maxBytes || this.embeddedBytes + source.size > this.totalBytes)
|
|
48677
|
+
return { error: "too-large" };
|
|
48678
|
+
const data = Buffer.alloc(source.size);
|
|
48679
|
+
let read = 0;
|
|
48680
|
+
while (read < source.size) {
|
|
48681
|
+
const n = readSync3(source.fd, data, read, source.size - read, read);
|
|
48682
|
+
if (n <= 0) break;
|
|
48683
|
+
read += n;
|
|
48684
|
+
}
|
|
48685
|
+
const mime = sniffMime(data.subarray(0, 16), asset.name);
|
|
48686
|
+
const result = {
|
|
48687
|
+
url: `data:${mime};base64,${data.subarray(0, read).toString("base64")}`,
|
|
48688
|
+
mime
|
|
48689
|
+
};
|
|
48690
|
+
this.count++;
|
|
48691
|
+
this.embeddedBytes += read;
|
|
48692
|
+
this.placed.set(asset.path, result);
|
|
48693
|
+
return result;
|
|
48694
|
+
} finally {
|
|
48695
|
+
closeSync4(source.fd);
|
|
48696
|
+
}
|
|
48697
|
+
}
|
|
48698
|
+
};
|
|
48699
|
+
|
|
48700
|
+
// src/utils/exportRender.ts
|
|
48701
|
+
var emptyStats = () => ({
|
|
48702
|
+
attachments: 0,
|
|
48703
|
+
placed: 0,
|
|
48704
|
+
placeholders: 0,
|
|
48705
|
+
unavailable: 0,
|
|
48706
|
+
tables: 0,
|
|
48707
|
+
unreadableTables: 0,
|
|
48708
|
+
unreferenced: 0
|
|
48709
|
+
});
|
|
48710
|
+
var isSafeHref = (url) => /^(?:https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) && !Array.from(url).some((char) => char.charCodeAt(0) < 32);
|
|
48711
|
+
var LABELS = {
|
|
48712
|
+
table: "Table",
|
|
48713
|
+
image: "Image",
|
|
48714
|
+
drawing: "Drawing",
|
|
48715
|
+
paper: "Drawing",
|
|
48716
|
+
scan: "Scanned document",
|
|
48717
|
+
pdf: "PDF",
|
|
48718
|
+
audio: "Audio",
|
|
48719
|
+
video: "Video",
|
|
48720
|
+
link: "Link",
|
|
48721
|
+
gallery: "Gallery",
|
|
48722
|
+
divider: "Divider",
|
|
48723
|
+
inline: "Inline attachment",
|
|
48724
|
+
file: "File"
|
|
48725
|
+
};
|
|
48726
|
+
var attachmentLabel = (kind) => LABELS[kind];
|
|
48727
|
+
function fmtOf(run) {
|
|
48728
|
+
const fmt = {};
|
|
48729
|
+
if (run.bold) fmt.bold = true;
|
|
48730
|
+
if (run.italic) fmt.italic = true;
|
|
48731
|
+
if (run.underline) fmt.underline = true;
|
|
48732
|
+
if (run.strikethrough) fmt.strikethrough = true;
|
|
48733
|
+
if (run.superscript) fmt.superscript = true;
|
|
48734
|
+
if (run.subscript) fmt.subscript = true;
|
|
48735
|
+
if (run.highlight) fmt.highlight = run.highlight;
|
|
48736
|
+
if (run.color) fmt.color = run.color;
|
|
48737
|
+
if (run.link && run.linkSafe) fmt.link = run.link;
|
|
48738
|
+
return fmt;
|
|
48739
|
+
}
|
|
48740
|
+
var sameFmt = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
48741
|
+
function blockPieces(block, plan) {
|
|
48742
|
+
const pieces = [];
|
|
48743
|
+
const pushText = (text2, fmt) => {
|
|
48744
|
+
if (!text2) return;
|
|
48745
|
+
const last = pieces[pieces.length - 1];
|
|
48746
|
+
if (last?.type === "text" && sameFmt(last.fmt, fmt)) last.text += text2;
|
|
48747
|
+
else pieces.push({ type: "text", text: text2, fmt });
|
|
48748
|
+
};
|
|
48749
|
+
for (const run of block.runs) {
|
|
48750
|
+
const fmt = fmtOf(run);
|
|
48751
|
+
const parts = run.text.split("\uFFFC");
|
|
48752
|
+
parts.forEach((part, i) => {
|
|
48753
|
+
if (i > 0 && run.attachment)
|
|
48754
|
+
pieces.push({ type: "attachment", id: run.attachment.id, plan: plan(run.attachment.id) });
|
|
48755
|
+
pushText(part, fmt);
|
|
48756
|
+
});
|
|
48757
|
+
}
|
|
48758
|
+
return pieces;
|
|
48759
|
+
}
|
|
48760
|
+
var isBlockPlan = (plan) => plan.type === "table" || plan.type === "divider" || plan.type === "gallery";
|
|
48761
|
+
function titleBlockIndex(note) {
|
|
48762
|
+
const first2 = note.doc.blocks.find((block) => block.text.trim());
|
|
48763
|
+
if (!first2) return -1;
|
|
48764
|
+
if (first2.style === "title") return first2.index;
|
|
48765
|
+
return first2.text.trim() === note.title.trim() && first2.style !== "monospaced" ? first2.index : -1;
|
|
48766
|
+
}
|
|
48767
|
+
function place(ctx, asset) {
|
|
48768
|
+
return asset && ctx.writer ? ctx.writer.place(asset) : void 0;
|
|
48769
|
+
}
|
|
48770
|
+
function planAttachment(attachment, ctx) {
|
|
48771
|
+
ctx.stats.attachments++;
|
|
48772
|
+
const unavailable = (label2, reason, name2) => {
|
|
48773
|
+
ctx.stats.unavailable++;
|
|
48774
|
+
return { type: "unavailable", label: label2, reason, ...name2 ? { name: name2 } : {} };
|
|
48775
|
+
};
|
|
48776
|
+
if (!attachment) return unavailable("Attachment", "missing");
|
|
48777
|
+
const label = attachmentLabel(attachment.kind);
|
|
48778
|
+
const name = attachment.title;
|
|
48779
|
+
switch (attachment.kind) {
|
|
48780
|
+
case "inline": {
|
|
48781
|
+
const link = attachment.uti.endsWith(".link") && attachment.tokenId && isSafeHref(attachment.tokenId) ? attachment.tokenId : void 0;
|
|
48782
|
+
return { type: "inline", text: attachment.altText ?? "", ...link ? { link } : {} };
|
|
48783
|
+
}
|
|
48784
|
+
case "divider":
|
|
48785
|
+
return { type: "divider" };
|
|
48786
|
+
case "table": {
|
|
48787
|
+
ctx.stats.tables++;
|
|
48788
|
+
try {
|
|
48789
|
+
if (!attachment.tableData) throw new Error("no table data");
|
|
48790
|
+
return {
|
|
48791
|
+
type: "table",
|
|
48792
|
+
rows: parseNoteTable(Buffer.from(attachment.tableData, "hex")).rows
|
|
48793
|
+
};
|
|
48794
|
+
} catch {
|
|
48795
|
+
ctx.stats.unreadableTables++;
|
|
48796
|
+
return unavailable(label, "undecodable");
|
|
48797
|
+
}
|
|
48798
|
+
}
|
|
48799
|
+
case "gallery": {
|
|
48800
|
+
ctx.stats.attachments--;
|
|
48801
|
+
return {
|
|
48802
|
+
type: "gallery",
|
|
48803
|
+
items: attachment.children.map((child) => planAttachment(child, ctx))
|
|
48804
|
+
};
|
|
48805
|
+
}
|
|
48806
|
+
case "link": {
|
|
48807
|
+
const url = attachment.url ?? "";
|
|
48808
|
+
const preview = ctx.locator ? place(ctx, ctx.locator.locate(attachment).preview) : void 0;
|
|
48809
|
+
if (preview && "url" in preview) ctx.stats.placed++;
|
|
48810
|
+
return {
|
|
48811
|
+
type: "card",
|
|
48812
|
+
title: name ?? url,
|
|
48813
|
+
displayUrl: url,
|
|
48814
|
+
...isSafeHref(url) ? { url } : {},
|
|
48815
|
+
...preview && "url" in preview ? { previewUrl: preview.url } : {}
|
|
48816
|
+
};
|
|
48817
|
+
}
|
|
48818
|
+
default: {
|
|
48819
|
+
if (!ctx.writer) {
|
|
48820
|
+
ctx.stats.placeholders++;
|
|
48821
|
+
return { type: "placeholder", label, ...name ? { name } : {} };
|
|
48822
|
+
}
|
|
48823
|
+
const files = ctx.locator?.locate(attachment) ?? {};
|
|
48824
|
+
const primary = place(ctx, files.primary);
|
|
48825
|
+
const visual = ["image", "drawing", "paper"].includes(attachment.kind);
|
|
48826
|
+
const wantsPreview = attachment.kind === "scan" || attachment.kind === "pdf";
|
|
48827
|
+
const preview = files.preview && (wantsPreview || visual && !(primary && "url" in primary)) ? place(ctx, files.preview) : void 0;
|
|
48828
|
+
const previewUrl = preview && "url" in preview ? preview.url : void 0;
|
|
48829
|
+
if (primary && "url" in primary) {
|
|
48830
|
+
ctx.stats.placed++;
|
|
48831
|
+
const display = visual ? "image" : attachment.kind === "audio" ? "audio" : attachment.kind === "video" ? "video" : "link";
|
|
48832
|
+
return {
|
|
48833
|
+
type: "asset",
|
|
48834
|
+
label,
|
|
48835
|
+
...name ? { name } : {},
|
|
48836
|
+
display,
|
|
48837
|
+
url: primary.url,
|
|
48838
|
+
mime: primary.mime,
|
|
48839
|
+
...previewUrl ? { previewUrl } : {}
|
|
48840
|
+
};
|
|
48841
|
+
}
|
|
48842
|
+
if (visual && previewUrl) {
|
|
48843
|
+
ctx.stats.placed++;
|
|
48844
|
+
return {
|
|
48845
|
+
type: "asset",
|
|
48846
|
+
label,
|
|
48847
|
+
...name ? { name } : {},
|
|
48848
|
+
display: "image",
|
|
48849
|
+
url: previewUrl,
|
|
48850
|
+
mime: preview.mime
|
|
48851
|
+
};
|
|
48852
|
+
}
|
|
48853
|
+
const reason = primary && "error" in primary ? primary.error : "missing";
|
|
48854
|
+
return unavailable(label, reason, name);
|
|
48855
|
+
}
|
|
48856
|
+
}
|
|
48857
|
+
}
|
|
48858
|
+
function unreferencedAttachments(note) {
|
|
48859
|
+
const referenced = new Set(note.doc.attachments.map((marker) => marker.id));
|
|
48860
|
+
return note.ordered.filter(
|
|
48861
|
+
(attachment) => !referenced.has(attachment.id) && attachment.kind !== "table" && attachment.kind !== "inline" && attachment.kind !== "divider"
|
|
48862
|
+
);
|
|
48863
|
+
}
|
|
48864
|
+
|
|
48865
|
+
// src/utils/htmlExport.ts
|
|
48866
|
+
function escapeHtml(text2) {
|
|
48867
|
+
return text2.replace(
|
|
48868
|
+
/[&<>"']/g,
|
|
48869
|
+
(char) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[char]
|
|
48870
|
+
);
|
|
48871
|
+
}
|
|
48872
|
+
var HIGHLIGHT_CLASSES = /* @__PURE__ */ new Set(["purple", "pink", "orange", "mint", "blue"]);
|
|
48873
|
+
var ALIGN = /* @__PURE__ */ new Set(["center", "right", "justify"]);
|
|
48874
|
+
var REASONS = {
|
|
48875
|
+
"too-large": " (too large to embed; export with embedAssets false)",
|
|
48876
|
+
unreadable: " (unreadable)",
|
|
48877
|
+
undecodable: " (could not be decoded)"
|
|
48878
|
+
};
|
|
48879
|
+
function wrapText(text2, fmt) {
|
|
48880
|
+
let out = escapeHtml(text2).replace(/\n/g, "<br>");
|
|
48881
|
+
if (fmt.subscript) out = `<sub>${out}</sub>`;
|
|
48882
|
+
if (fmt.superscript) out = `<sup>${out}</sup>`;
|
|
48883
|
+
if (fmt.highlight)
|
|
48884
|
+
out = `<mark class="hl-${HIGHLIGHT_CLASSES.has(fmt.highlight) ? fmt.highlight : "other"}">${out}</mark>`;
|
|
48885
|
+
if (fmt.strikethrough) out = `<s>${out}</s>`;
|
|
48886
|
+
if (fmt.underline) out = `<u>${out}</u>`;
|
|
48887
|
+
if (fmt.italic) out = `<em>${out}</em>`;
|
|
48888
|
+
if (fmt.bold) out = `<strong>${out}</strong>`;
|
|
48889
|
+
if (fmt.color && /^#[0-9A-F]{6}(?:[0-9A-F]{2})?$/i.test(fmt.color))
|
|
48890
|
+
out = `<span style="color:${fmt.color}">${out}</span>`;
|
|
48891
|
+
return out;
|
|
48892
|
+
}
|
|
48893
|
+
var bracket = (label, name) => escapeHtml(`[${name ? `${label}: ${name}` : label}]`);
|
|
48894
|
+
function domainOf(url) {
|
|
48895
|
+
try {
|
|
48896
|
+
return new URL(url).hostname;
|
|
48897
|
+
} catch {
|
|
48898
|
+
return url;
|
|
48899
|
+
}
|
|
48900
|
+
}
|
|
48901
|
+
function isHtmlBlockPlan(plan) {
|
|
48902
|
+
switch (plan.type) {
|
|
48903
|
+
case "table":
|
|
48904
|
+
case "divider":
|
|
48905
|
+
case "gallery":
|
|
48906
|
+
case "card":
|
|
48907
|
+
return true;
|
|
48908
|
+
case "asset":
|
|
48909
|
+
return plan.display !== "link" || !!plan.previewUrl;
|
|
48910
|
+
default:
|
|
48911
|
+
return false;
|
|
48912
|
+
}
|
|
48913
|
+
}
|
|
48914
|
+
function inlinePlanHtml(plan) {
|
|
48915
|
+
switch (plan.type) {
|
|
48916
|
+
case "inline":
|
|
48917
|
+
return plan.link ? `<a href="${escapeHtml(plan.link)}">${escapeHtml(plan.text)}</a>` : escapeHtml(plan.text);
|
|
48918
|
+
case "placeholder":
|
|
48919
|
+
return `<span class="attachment-placeholder">${bracket(plan.label, plan.name)}</span>`;
|
|
48920
|
+
case "unavailable":
|
|
48921
|
+
return `<span class="attachment-unavailable" role="note">${bracket(
|
|
48922
|
+
`${plan.label} unavailable${REASONS[plan.reason] ?? ""}`,
|
|
48923
|
+
plan.name
|
|
48924
|
+
)}</span>`;
|
|
48925
|
+
case "asset":
|
|
48926
|
+
return `<a class="attachment attachment-file" href="${escapeHtml(plan.url)}">${escapeHtml(
|
|
48927
|
+
plan.name ?? plan.label
|
|
48928
|
+
)}</a>`;
|
|
48929
|
+
default:
|
|
48930
|
+
return blockPlanHtml(plan);
|
|
48931
|
+
}
|
|
48932
|
+
}
|
|
48933
|
+
function blockPlanHtml(plan) {
|
|
48934
|
+
switch (plan.type) {
|
|
48935
|
+
case "table":
|
|
48936
|
+
return tableHtml(plan.rows);
|
|
48937
|
+
case "divider":
|
|
48938
|
+
return "<hr>";
|
|
48939
|
+
case "gallery":
|
|
48940
|
+
return `<div class="attachment-gallery">${plan.items.map((item) => isHtmlBlockPlan(item) ? blockPlanHtml(item) : inlinePlanHtml(item)).join("")}</div>`;
|
|
48941
|
+
case "card": {
|
|
48942
|
+
const image = plan.previewUrl ? `<img src="${escapeHtml(plan.previewUrl)}" alt="" loading="lazy">` : "";
|
|
48943
|
+
const text2 = `<span class="link-card-text"><span class="link-card-title">${escapeHtml(plan.title)}</span><span class="link-card-domain">${escapeHtml(domainOf(plan.displayUrl))}</span></span>`;
|
|
48944
|
+
return plan.url ? `<a class="link-card" href="${escapeHtml(plan.url)}">${image}${text2}</a>` : `<div class="link-card">${image}${text2}</div>`;
|
|
48945
|
+
}
|
|
48946
|
+
case "asset": {
|
|
48947
|
+
const name = escapeHtml(plan.name ?? plan.label);
|
|
48948
|
+
const src = escapeHtml(plan.url);
|
|
48949
|
+
const caption = plan.name ? `<figcaption>${name}</figcaption>` : "";
|
|
48950
|
+
if (plan.display === "image")
|
|
48951
|
+
return `<figure class="attachment attachment-image"><img src="${src}" alt="${name}" loading="lazy"></figure>`;
|
|
48952
|
+
if (plan.display === "audio" || plan.display === "video")
|
|
48953
|
+
return `<figure class="attachment attachment-${plan.display}"><${plan.display} controls preload="metadata" src="${src}"></${plan.display}>${caption}</figure>`;
|
|
48954
|
+
return `<figure class="attachment attachment-document"><a href="${src}"><img src="${escapeHtml(plan.previewUrl)}" alt="${name}" loading="lazy"></a><figcaption><a href="${src}">${name}</a></figcaption></figure>`;
|
|
48955
|
+
}
|
|
48956
|
+
default:
|
|
48957
|
+
return `<p>${inlinePlanHtml(plan)}</p>`;
|
|
48958
|
+
}
|
|
48959
|
+
}
|
|
48960
|
+
function tableHtml(rows) {
|
|
48961
|
+
const width = Math.max(1, ...rows.map((row) => row.length));
|
|
48962
|
+
const cells = (row, tag) => Array.from(
|
|
48963
|
+
{ length: width },
|
|
48964
|
+
(_, i) => `<${tag}>${escapeHtml(row[i] ?? "").replace(/\r?\n/g, "<br>")}</${tag}>`
|
|
48965
|
+
).join("");
|
|
48966
|
+
const [head = [], ...body] = rows;
|
|
48967
|
+
return `<table><thead><tr>${cells(head, "th")}</tr></thead><tbody>${body.map((row) => `<tr>${cells(row, "td")}</tr>`).join("")}</tbody></table>`;
|
|
48968
|
+
}
|
|
48969
|
+
function inlineHtml(pieces) {
|
|
48970
|
+
let out = "";
|
|
48971
|
+
for (let i = 0; i < pieces.length; ) {
|
|
48972
|
+
const piece = pieces[i];
|
|
48973
|
+
if (piece.type === "attachment") {
|
|
48974
|
+
out += inlinePlanHtml(piece.plan);
|
|
48975
|
+
i++;
|
|
48976
|
+
continue;
|
|
48977
|
+
}
|
|
48978
|
+
const link = piece.fmt.link;
|
|
48979
|
+
let inner = "";
|
|
48980
|
+
let j = i;
|
|
48981
|
+
for (; j < pieces.length; j++) {
|
|
48982
|
+
const next = pieces[j];
|
|
48983
|
+
if (next.type !== "text" || next.fmt.link !== link) break;
|
|
48984
|
+
inner += wrapText(next.text, next.fmt);
|
|
48985
|
+
}
|
|
48986
|
+
out += link ? `<a href="${escapeHtml(link)}">${inner}</a>` : inner;
|
|
48987
|
+
i = j;
|
|
48988
|
+
}
|
|
48989
|
+
return out;
|
|
48990
|
+
}
|
|
48991
|
+
function blockParts(pieces) {
|
|
48992
|
+
const parts = [];
|
|
48993
|
+
let segment = [];
|
|
48994
|
+
const flush = () => {
|
|
48995
|
+
const html = inlineHtml(segment).trim();
|
|
48996
|
+
if (html) parts.push({ inline: html });
|
|
48997
|
+
segment = [];
|
|
48998
|
+
};
|
|
48999
|
+
for (const piece of pieces) {
|
|
49000
|
+
if (piece.type === "attachment" && isHtmlBlockPlan(piece.plan)) {
|
|
49001
|
+
flush();
|
|
49002
|
+
parts.push({ block: blockPlanHtml(piece.plan) });
|
|
49003
|
+
} else segment.push(piece);
|
|
49004
|
+
}
|
|
49005
|
+
flush();
|
|
49006
|
+
return parts;
|
|
49007
|
+
}
|
|
49008
|
+
var LIST_TAGS = {
|
|
49009
|
+
bulleted: "ul",
|
|
49010
|
+
dashed: "ul",
|
|
49011
|
+
checklist: "ul",
|
|
49012
|
+
numbered: "ol"
|
|
49013
|
+
};
|
|
49014
|
+
var alignAttr = (block) => ALIGN.has(block.alignment) ? ` style="text-align:${block.alignment}"` : "";
|
|
49015
|
+
function renderNoteHtml(note, ctx) {
|
|
49016
|
+
const plan = (id2) => planAttachment(note.attachments.get(id2), ctx);
|
|
49017
|
+
const titleIndex = titleBlockIndex(note);
|
|
49018
|
+
const out = [];
|
|
49019
|
+
const lists = [];
|
|
49020
|
+
let quote = false;
|
|
49021
|
+
let code;
|
|
49022
|
+
const closeLists = (depth = 0) => {
|
|
49023
|
+
while (lists.length > depth) {
|
|
49024
|
+
const list = lists.pop();
|
|
49025
|
+
out.push(`${list.open ? "</li>" : ""}</${list.tag}>`);
|
|
49026
|
+
}
|
|
49027
|
+
};
|
|
49028
|
+
const flushCode = () => {
|
|
49029
|
+
if (code) out.push(`<pre><code>${escapeHtml(code.join("\n"))}</code></pre>`);
|
|
49030
|
+
code = void 0;
|
|
49031
|
+
};
|
|
49032
|
+
const setQuote = (on) => {
|
|
49033
|
+
if (on === quote) return;
|
|
49034
|
+
flushCode();
|
|
49035
|
+
closeLists();
|
|
49036
|
+
out.push(on ? "<blockquote>" : "</blockquote>");
|
|
49037
|
+
quote = on;
|
|
49038
|
+
};
|
|
49039
|
+
if (titleIndex === -1 && note.title.trim()) out.push(`<h1>${escapeHtml(note.title.trim())}</h1>`);
|
|
49040
|
+
for (const block of note.doc.blocks) {
|
|
49041
|
+
setQuote(block.blockQuote);
|
|
49042
|
+
if (block.style === "monospaced") {
|
|
49043
|
+
closeLists();
|
|
49044
|
+
(code ??= []).push(block.text.replace(//g, ""));
|
|
49045
|
+
continue;
|
|
49046
|
+
}
|
|
49047
|
+
flushCode();
|
|
49048
|
+
const listTag = LIST_TAGS[block.style];
|
|
49049
|
+
if (!listTag) closeLists();
|
|
49050
|
+
if (!block.text.trim()) continue;
|
|
49051
|
+
const parts = blockParts(blockPieces(block, plan));
|
|
49052
|
+
if (!parts.length) continue;
|
|
49053
|
+
if (listTag) {
|
|
49054
|
+
const level = Math.min(block.indent, 20);
|
|
49055
|
+
const cls = block.style === "checklist" || block.style === "dashed" ? block.style : "";
|
|
49056
|
+
closeLists(level + 1);
|
|
49057
|
+
const top = lists[level];
|
|
49058
|
+
if (top && (top.tag !== listTag || top.cls !== cls)) closeLists(level);
|
|
49059
|
+
if (lists[level]?.open) out.push("</li>");
|
|
49060
|
+
while (lists.length < level) {
|
|
49061
|
+
out.push(`<${listTag}><li class="nest">`);
|
|
49062
|
+
lists.push({ tag: listTag, cls: "", open: true });
|
|
49063
|
+
}
|
|
49064
|
+
if (lists.length === level) {
|
|
49065
|
+
out.push(`<${listTag}${cls ? ` class="${cls}"` : ""}>`);
|
|
49066
|
+
lists.push({ tag: listTag, cls, open: false });
|
|
49067
|
+
}
|
|
49068
|
+
lists[level].open = true;
|
|
49069
|
+
const box = block.style === "checklist" ? `<input type="checkbox" disabled${block.checklist?.done ? " checked" : ""}> ` : "";
|
|
49070
|
+
const done = block.style === "checklist" && block.checklist?.done ? ` class="done"` : "";
|
|
49071
|
+
const body = parts.map((part) => "inline" in part ? part.inline : part.block).join("");
|
|
49072
|
+
out.push(`<li${done}${alignAttr(block)}>${box}${body}`);
|
|
49073
|
+
continue;
|
|
49074
|
+
}
|
|
49075
|
+
const tag = block.index === titleIndex || block.style === "title" ? "h1" : block.style === "heading" ? "h2" : block.style === "subheading" ? "h3" : "p";
|
|
49076
|
+
for (const part of parts)
|
|
49077
|
+
out.push(
|
|
49078
|
+
"inline" in part ? `<${tag}${alignAttr(block)}>${part.inline}</${tag}>` : part.block
|
|
49079
|
+
);
|
|
49080
|
+
}
|
|
49081
|
+
flushCode();
|
|
49082
|
+
closeLists();
|
|
49083
|
+
setQuote(false);
|
|
49084
|
+
for (const attachment of unreferencedAttachments(note)) {
|
|
49085
|
+
ctx.stats.unreferenced++;
|
|
49086
|
+
out.push(blockPlanHtml(planAttachment(attachment, ctx)));
|
|
49087
|
+
}
|
|
49088
|
+
return `<article class="note">
|
|
49089
|
+
${out.filter(Boolean).join("\n")}
|
|
49090
|
+
</article>`;
|
|
49091
|
+
}
|
|
49092
|
+
var CSS = `
|
|
49093
|
+
:root { color-scheme: light dark; --fg: #1d1d1f; --bg: #fff; --muted: #6e6e73; --line: #d2d2d7; --card: #f5f5f7; }
|
|
49094
|
+
@media (prefers-color-scheme: dark) { :root { --fg: #f5f5f7; --bg: #1d1d1f; --muted: #a1a1a6; --line: #424245; --card: #2c2c2e; } }
|
|
49095
|
+
body { margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif; }
|
|
49096
|
+
main { max-width: 46rem; margin: 0 auto; padding: 2rem 1rem; }
|
|
49097
|
+
h1, h2, h3 { line-height: 1.25; }
|
|
49098
|
+
blockquote { margin: 1rem 0; padding-left: 1rem; border-left: 3px solid var(--line); color: var(--muted); }
|
|
49099
|
+
pre { background: var(--card); padding: .75rem 1rem; overflow-x: auto; border-radius: 6px; }
|
|
49100
|
+
code { font: 14px/1.4 ui-monospace, Menlo, monospace; }
|
|
49101
|
+
ul.dashed { list-style-type: "\u2013 "; }
|
|
49102
|
+
ul.checklist { list-style: none; padding-left: 1.25rem; }
|
|
49103
|
+
ul.checklist li.done { color: var(--muted); text-decoration: line-through; }
|
|
49104
|
+
li.nest { list-style: none; }
|
|
49105
|
+
table { border-collapse: collapse; margin: 1rem 0; }
|
|
49106
|
+
th, td { border: 1px solid var(--line); padding: .35rem .6rem; text-align: left; vertical-align: top; }
|
|
49107
|
+
th { background: var(--card); }
|
|
49108
|
+
figure { margin: 1rem 0; }
|
|
49109
|
+
figure img, figure video { max-width: 100%; height: auto; border-radius: 6px; }
|
|
49110
|
+
figcaption { color: var(--muted); font-size: .875rem; }
|
|
49111
|
+
.attachment-gallery { display: flex; flex-wrap: wrap; gap: .5rem; }
|
|
49112
|
+
.attachment-gallery figure { margin: 0; flex: 1 1 12rem; }
|
|
49113
|
+
.link-card { display: flex; gap: .75rem; align-items: center; margin: 1rem 0; padding: .5rem; border: 1px solid var(--line); border-radius: 8px; background: var(--card); color: inherit; text-decoration: none; }
|
|
49114
|
+
.link-card img { width: 4rem; height: 4rem; object-fit: cover; border-radius: 4px; }
|
|
49115
|
+
.link-card-text { display: flex; flex-direction: column; min-width: 0; }
|
|
49116
|
+
.link-card-title { font-weight: 600; }
|
|
49117
|
+
.link-card-domain { color: var(--muted); font-size: .875rem; }
|
|
49118
|
+
.attachment-unavailable, .attachment-placeholder { display: inline-block; padding: 0 .35rem; border: 1px dashed var(--muted); border-radius: 4px; color: var(--muted); font-size: .875rem; }
|
|
49119
|
+
mark { border-radius: 2px; padding: 0 .1em; }
|
|
49120
|
+
mark.hl-purple { background: #e5d4ff; } mark.hl-pink { background: #ffd1e3; } mark.hl-orange { background: #ffe0b8; }
|
|
49121
|
+
mark.hl-mint { background: #c8f2de; } mark.hl-blue { background: #cfe3ff; } mark.hl-other { background: #fff3a8; }
|
|
49122
|
+
hr.note-separator { margin: 3rem 0; border: 0; border-top: 2px solid var(--line); }
|
|
49123
|
+
`.trim();
|
|
49124
|
+
function renderNotesHtml(notes, ctx, { title }) {
|
|
49125
|
+
const body = notes.map((note) => renderNoteHtml(note, ctx)).join('\n<hr class="note-separator">\n');
|
|
49126
|
+
return [
|
|
49127
|
+
"<!DOCTYPE html>",
|
|
49128
|
+
"<html>",
|
|
49129
|
+
"<head>",
|
|
49130
|
+
'<meta charset="utf-8">',
|
|
49131
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
49132
|
+
'<meta name="generator" content="apple-notes-mcp">',
|
|
49133
|
+
`<title>${escapeHtml(title)}</title>`,
|
|
49134
|
+
`<style>
|
|
49135
|
+
${CSS}
|
|
49136
|
+
</style>`,
|
|
49137
|
+
"</head>",
|
|
49138
|
+
"<body>",
|
|
49139
|
+
"<main>",
|
|
49140
|
+
body,
|
|
49141
|
+
"</main>",
|
|
49142
|
+
"</body>",
|
|
49143
|
+
"</html>",
|
|
49144
|
+
""
|
|
49145
|
+
].join("\n");
|
|
49146
|
+
}
|
|
49147
|
+
|
|
49148
|
+
// src/utils/markdownExport.ts
|
|
49149
|
+
var NOTE_SEPARATOR = "\n\n---\n\n";
|
|
49150
|
+
function escapeMarkdown(text2) {
|
|
49151
|
+
return text2.replace(/[\\`*_[\]<>~|]/g, (char) => `\\${char}`).replace(/&(?=#?[A-Za-z0-9]+;)/g, "&").replace(/==/g, "\\=\\=");
|
|
49152
|
+
}
|
|
49153
|
+
function escapeLineStart(line) {
|
|
49154
|
+
return line.replace(
|
|
49155
|
+
/^(\s*)([#>+-]|\d+[.)])(?=\s|$)/,
|
|
49156
|
+
(_, space, marker) => /^\d/.test(marker) ? `${space}${marker.slice(0, -1)}\\${marker.slice(-1)}` : `${space}\\${marker}`
|
|
49157
|
+
);
|
|
49158
|
+
}
|
|
49159
|
+
function linkDestination(url) {
|
|
49160
|
+
return url.replace(
|
|
49161
|
+
/[\s()<>]/g,
|
|
49162
|
+
(char) => char === " " ? "%20" : `%${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`
|
|
49163
|
+
);
|
|
49164
|
+
}
|
|
49165
|
+
function delimit(text2, open, close = open) {
|
|
49166
|
+
const match = /^(\s*)([\s\S]*?)(\s*)$/.exec(text2);
|
|
49167
|
+
return match[2] ? `${match[1]}${open}${match[2]}${close}${match[3]}` : text2;
|
|
49168
|
+
}
|
|
49169
|
+
var LAYERS = [
|
|
49170
|
+
["italic", "*", "*"],
|
|
49171
|
+
["bold", "**", "**"],
|
|
49172
|
+
["strikethrough", "~~", "~~"],
|
|
49173
|
+
["underline", "<u>", "</u>"],
|
|
49174
|
+
["highlight", "==", "=="],
|
|
49175
|
+
["superscript", "<sup>", "</sup>"],
|
|
49176
|
+
["subscript", "<sub>", "</sub>"]
|
|
49177
|
+
];
|
|
49178
|
+
function joinSafe(left, right) {
|
|
49179
|
+
return left && right && /[*~=]$/.test(left) && left.at(-1) === right[0] ? `${left}<!-- -->${right}` : left + right;
|
|
49180
|
+
}
|
|
49181
|
+
function layered(pieces, depth = 0) {
|
|
49182
|
+
if (depth === LAYERS.length)
|
|
49183
|
+
return pieces.map((piece) => escapeMarkdown(piece.text.replace(/\n/g, " "))).join("");
|
|
49184
|
+
const [key, open, close] = LAYERS[depth];
|
|
49185
|
+
let out = "";
|
|
49186
|
+
for (let i = 0; i < pieces.length; ) {
|
|
49187
|
+
const on = !!pieces[i].fmt[key];
|
|
49188
|
+
let j = i;
|
|
49189
|
+
while (j < pieces.length && !!pieces[j].fmt[key] === on) j++;
|
|
49190
|
+
const inner = layered(pieces.slice(i, j), depth + 1);
|
|
49191
|
+
out = joinSafe(out, on ? delimit(inner, open, close) : inner);
|
|
49192
|
+
i = j;
|
|
49193
|
+
}
|
|
49194
|
+
return out;
|
|
49195
|
+
}
|
|
49196
|
+
var bracket2 = (label, name) => `\\[${escapeMarkdown(name ? `${label}: ${name}` : label)}\\]`;
|
|
49197
|
+
function planMarkdown(plan) {
|
|
49198
|
+
switch (plan.type) {
|
|
49199
|
+
case "inline":
|
|
49200
|
+
return plan.link ? `[${escapeMarkdown(plan.text)}](${linkDestination(plan.link)})` : escapeMarkdown(plan.text);
|
|
49201
|
+
case "divider":
|
|
49202
|
+
return "---";
|
|
49203
|
+
case "table":
|
|
49204
|
+
return tableMarkdown(plan.rows);
|
|
49205
|
+
case "placeholder":
|
|
49206
|
+
return bracket2(plan.label, plan.name);
|
|
49207
|
+
case "unavailable":
|
|
49208
|
+
return bracket2(`${plan.label} unavailable`, plan.name);
|
|
49209
|
+
case "asset": {
|
|
49210
|
+
const text2 = escapeMarkdown(plan.name ?? plan.label);
|
|
49211
|
+
if (plan.display === "image") return `})`;
|
|
49212
|
+
const inner = plan.previewUrl ? `})` : text2;
|
|
49213
|
+
return `[${inner}](${linkDestination(plan.url)})`;
|
|
49214
|
+
}
|
|
49215
|
+
case "card":
|
|
49216
|
+
return plan.url ? `[${escapeMarkdown(plan.title)}](${linkDestination(plan.url)})` : `${escapeMarkdown(plan.title)} (${escapeMarkdown(plan.displayUrl)})`;
|
|
49217
|
+
case "gallery":
|
|
49218
|
+
return plan.items.map(planMarkdown).join("\n\n");
|
|
49219
|
+
}
|
|
49220
|
+
}
|
|
49221
|
+
function tableMarkdown(rows) {
|
|
49222
|
+
const width = Math.max(1, ...rows.map((row) => row.length));
|
|
49223
|
+
const cell = (value) => escapeMarkdown(value ?? "").replace(/\r?\n/g, "<br>").trim() || " ";
|
|
49224
|
+
const line = (row) => `| ${Array.from({ length: width }, (_, i) => cell(row[i])).join(" | ")} |`;
|
|
49225
|
+
const [head = [], ...body] = rows;
|
|
49226
|
+
return [line(head), `| ${Array(width).fill("---").join(" | ")} |`, ...body.map(line)].join("\n");
|
|
49227
|
+
}
|
|
49228
|
+
function inlineMarkdown(pieces) {
|
|
49229
|
+
let out = "";
|
|
49230
|
+
for (let i = 0; i < pieces.length; ) {
|
|
49231
|
+
const piece = pieces[i];
|
|
49232
|
+
if (piece.type === "attachment") {
|
|
49233
|
+
out = joinSafe(out, planMarkdown(piece.plan));
|
|
49234
|
+
i++;
|
|
49235
|
+
continue;
|
|
49236
|
+
}
|
|
49237
|
+
const link = piece.fmt.link;
|
|
49238
|
+
let j = i;
|
|
49239
|
+
while (j < pieces.length && pieces[j].type === "text" && pieces[j].fmt.link === link)
|
|
49240
|
+
j++;
|
|
49241
|
+
const inner = layered(pieces.slice(i, j));
|
|
49242
|
+
out = joinSafe(out, link ? delimit(inner, "[", `](${linkDestination(link)})`) : inner);
|
|
49243
|
+
i = j;
|
|
49244
|
+
}
|
|
49245
|
+
return out;
|
|
49246
|
+
}
|
|
49247
|
+
var LIST_STYLES = /* @__PURE__ */ new Set(["bulleted", "dashed", "numbered", "checklist"]);
|
|
49248
|
+
function renderNoteMarkdown(note, ctx) {
|
|
49249
|
+
const plan = (id2) => planAttachment(note.attachments.get(id2), ctx);
|
|
49250
|
+
const titleIndex = titleBlockIndex(note);
|
|
49251
|
+
const lines = [];
|
|
49252
|
+
const counters = [];
|
|
49253
|
+
let code;
|
|
49254
|
+
const flushCode = () => {
|
|
49255
|
+
if (!code) return;
|
|
49256
|
+
const longest = Math.max(
|
|
49257
|
+
2,
|
|
49258
|
+
...code.lines.map((l) => Math.max(0, ...(l.match(/`+/g) ?? []).map((m) => m.length)))
|
|
49259
|
+
);
|
|
49260
|
+
const fence = "`".repeat(longest + 1);
|
|
49261
|
+
lines.push({
|
|
49262
|
+
text: [fence, ...code.lines, fence].join("\n"),
|
|
49263
|
+
group: "code",
|
|
49264
|
+
quote: code.quote
|
|
49265
|
+
});
|
|
49266
|
+
code = void 0;
|
|
49267
|
+
};
|
|
49268
|
+
if (titleIndex === -1 && note.title.trim())
|
|
49269
|
+
lines.push({ text: `# ${escapeMarkdown(note.title.trim())}`, group: "para", quote: false });
|
|
49270
|
+
for (const block of note.doc.blocks) {
|
|
49271
|
+
if (block.style === "monospaced") {
|
|
49272
|
+
if (code && code.quote !== block.blockQuote) flushCode();
|
|
49273
|
+
code ??= { lines: [], quote: block.blockQuote };
|
|
49274
|
+
code.lines.push(block.text.replace(/\ufffc/g, ""));
|
|
49275
|
+
continue;
|
|
49276
|
+
}
|
|
49277
|
+
flushCode();
|
|
49278
|
+
if (!LIST_STYLES.has(block.style)) counters.length = 0;
|
|
49279
|
+
if (!block.text.trim()) continue;
|
|
49280
|
+
const pieces = blockPieces(block, plan);
|
|
49281
|
+
let segment = [];
|
|
49282
|
+
const segments = [];
|
|
49283
|
+
for (const piece of pieces) {
|
|
49284
|
+
if (piece.type === "attachment" && isBlockPlan(piece.plan)) {
|
|
49285
|
+
segments.push(segment, piece.plan);
|
|
49286
|
+
segment = [];
|
|
49287
|
+
} else segment.push(piece);
|
|
49288
|
+
}
|
|
49289
|
+
segments.push(segment);
|
|
49290
|
+
let first2 = true;
|
|
49291
|
+
for (const segment2 of segments) {
|
|
49292
|
+
if (!Array.isArray(segment2)) {
|
|
49293
|
+
lines.push({ text: planMarkdown(segment2), group: "block", quote: block.blockQuote });
|
|
49294
|
+
continue;
|
|
49295
|
+
}
|
|
49296
|
+
const body = inlineMarkdown(segment2).trim();
|
|
49297
|
+
if (!body) continue;
|
|
49298
|
+
lines.push(renderLine(block, body, first2, block.index === titleIndex, counters));
|
|
49299
|
+
first2 = false;
|
|
49300
|
+
}
|
|
49301
|
+
}
|
|
49302
|
+
flushCode();
|
|
49303
|
+
for (const attachment of unreferencedAttachments(note)) {
|
|
49304
|
+
ctx.stats.unreferenced++;
|
|
49305
|
+
lines.push({
|
|
49306
|
+
text: planMarkdown(planAttachment(attachment, ctx)),
|
|
49307
|
+
group: "block",
|
|
49308
|
+
quote: false
|
|
49309
|
+
});
|
|
49310
|
+
}
|
|
49311
|
+
return joinLines(lines);
|
|
49312
|
+
}
|
|
49313
|
+
function renderLine(block, body, first2, isTitle, counters) {
|
|
49314
|
+
const quote = block.blockQuote;
|
|
49315
|
+
if (isTitle || block.style === "title") return { text: `# ${body}`, group: "para", quote };
|
|
49316
|
+
if (block.style === "heading") return { text: `## ${body}`, group: "para", quote };
|
|
49317
|
+
if (block.style === "subheading") return { text: `### ${body}`, group: "para", quote };
|
|
49318
|
+
if (!LIST_STYLES.has(block.style) || !first2)
|
|
49319
|
+
return { text: escapeLineStart(body), group: "para", quote };
|
|
49320
|
+
const level = Math.min(block.indent, 20);
|
|
49321
|
+
counters.length = Math.min(counters.length, level + 1);
|
|
49322
|
+
while (counters.length <= level) counters.push(0);
|
|
49323
|
+
const indent = " ".repeat(level);
|
|
49324
|
+
let marker = "-";
|
|
49325
|
+
if (block.style === "numbered") marker = `${++counters[level]}.`;
|
|
49326
|
+
else {
|
|
49327
|
+
counters[level] = 0;
|
|
49328
|
+
if (block.style === "checklist") marker = block.checklist?.done ? "- [x]" : "- [ ]";
|
|
49329
|
+
}
|
|
49330
|
+
return { text: `${indent}${marker} ${body}`, group: "list", quote };
|
|
49331
|
+
}
|
|
49332
|
+
function joinLines(lines) {
|
|
49333
|
+
let out = "";
|
|
49334
|
+
let previous;
|
|
49335
|
+
for (const line of lines) {
|
|
49336
|
+
const text2 = line.quote ? line.text.split("\n").map((l) => l ? `> ${l}` : ">").join("\n") : line.text;
|
|
49337
|
+
if (previous) {
|
|
49338
|
+
const tight = previous.group === "list" && line.group === "list" && previous.quote === line.quote;
|
|
49339
|
+
out += tight ? "\n" : previous.quote && line.quote ? "\n>\n" : "\n\n";
|
|
49340
|
+
}
|
|
49341
|
+
out += text2;
|
|
49342
|
+
previous = line;
|
|
49343
|
+
}
|
|
49344
|
+
return out;
|
|
49345
|
+
}
|
|
49346
|
+
function wrapMarkdown(markdown, width) {
|
|
49347
|
+
if (!width) return markdown;
|
|
49348
|
+
let fenced = false;
|
|
49349
|
+
const out = [];
|
|
49350
|
+
for (const line of markdown.split("\n")) {
|
|
49351
|
+
const bare = line.replace(/^(?:> ?)+/, "");
|
|
49352
|
+
if (/^\s*```/.test(bare)) fenced = !fenced;
|
|
49353
|
+
if (fenced || /^\s*```/.test(bare) || line.length <= width || /^\s*(#|\||!\[)/.test(bare)) {
|
|
49354
|
+
out.push(line);
|
|
49355
|
+
continue;
|
|
49356
|
+
}
|
|
49357
|
+
const prefix = /^((?:> ?)*\s*(?:(?:[-*+]|\d+\.)(?: \[[ x]\])? )?)/.exec(line)[1];
|
|
49358
|
+
const hang = prefix.replace(/[^>\s]/g, " ").replace(/>(?! )/g, "> ");
|
|
49359
|
+
const words = line.slice(prefix.length).split(" ");
|
|
49360
|
+
let current = prefix;
|
|
49361
|
+
let empty = true;
|
|
49362
|
+
for (const word of words) {
|
|
49363
|
+
if (!empty && current.length + 1 + word.length > width) {
|
|
49364
|
+
out.push(current);
|
|
49365
|
+
current = hang + word;
|
|
49366
|
+
} else current += (empty ? "" : " ") + word;
|
|
49367
|
+
empty = false;
|
|
49368
|
+
}
|
|
49369
|
+
out.push(current);
|
|
49370
|
+
}
|
|
49371
|
+
return out.join("\n");
|
|
49372
|
+
}
|
|
49373
|
+
function renderNotesMarkdown(notes, ctx, { wrap: wrap2 = 0 } = {}) {
|
|
49374
|
+
const body = notes.map((note) => renderNoteMarkdown(note, ctx)).join(NOTE_SEPARATOR);
|
|
49375
|
+
return (wrap2 ? wrapMarkdown(body, wrap2) : body) + (notes.length ? "\n" : "");
|
|
49376
|
+
}
|
|
49377
|
+
|
|
49378
|
+
// src/utils/noteExportData.ts
|
|
49379
|
+
import { execFileSync as execFileSync17 } from "node:child_process";
|
|
49380
|
+
import { homedir as homedir16 } from "node:os";
|
|
49381
|
+
import { join as join19 } from "node:path";
|
|
49382
|
+
var NOTES_DB_PATH10 = join19(
|
|
49383
|
+
homedir16(),
|
|
49384
|
+
"Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
|
|
49385
|
+
);
|
|
49386
|
+
var IMAGE_UTIS2 = /* @__PURE__ */ new Set([
|
|
49387
|
+
"public.jpeg",
|
|
49388
|
+
"public.png",
|
|
49389
|
+
"public.heic",
|
|
49390
|
+
"public.heif",
|
|
49391
|
+
"public.image",
|
|
49392
|
+
"public.tiff",
|
|
49393
|
+
"public.webp",
|
|
49394
|
+
"org.webmproject.webp",
|
|
49395
|
+
"com.compuserve.gif",
|
|
49396
|
+
"com.microsoft.bmp",
|
|
49397
|
+
"com.adobe.raw-image",
|
|
49398
|
+
"public.camera-raw-image"
|
|
49399
|
+
]);
|
|
49400
|
+
var AUDIO_UTIS = /* @__PURE__ */ new Set([
|
|
49401
|
+
"com.apple.m4a-audio",
|
|
49402
|
+
"public.mpeg-4-audio",
|
|
49403
|
+
"public.mp3",
|
|
49404
|
+
"public.audio",
|
|
49405
|
+
"public.aiff-audio",
|
|
49406
|
+
"com.microsoft.waveform-audio"
|
|
49407
|
+
]);
|
|
49408
|
+
var VIDEO_UTIS = /* @__PURE__ */ new Set([
|
|
49409
|
+
"public.movie",
|
|
49410
|
+
"public.video",
|
|
49411
|
+
"public.mpeg-4",
|
|
49412
|
+
"com.apple.quicktime-movie"
|
|
49413
|
+
]);
|
|
49414
|
+
function classifyUti(uti) {
|
|
49415
|
+
if (uti === "com.apple.notes.table") return "table";
|
|
49416
|
+
if (uti === "com.apple.notes.inlinetextattachment.dividerline") return "divider";
|
|
49417
|
+
if (uti.startsWith("com.apple.notes.inlinetextattachment.")) return "inline";
|
|
49418
|
+
if (uti === "com.apple.notes.gallery") return "gallery";
|
|
49419
|
+
if (uti === "com.apple.drawing" || uti === "com.apple.drawing.2") return "drawing";
|
|
49420
|
+
if (uti === "com.apple.paper.doc.scan") return "scan";
|
|
49421
|
+
if (uti === "com.apple.paper") return "paper";
|
|
49422
|
+
if (uti === "public.url") return "link";
|
|
49423
|
+
if (uti === "com.adobe.pdf") return "pdf";
|
|
49424
|
+
if (IMAGE_UTIS2.has(uti)) return "image";
|
|
49425
|
+
if (AUDIO_UTIS.has(uti)) return "audio";
|
|
49426
|
+
if (VIDEO_UTIS.has(uti)) return "video";
|
|
49427
|
+
return "file";
|
|
49428
|
+
}
|
|
49429
|
+
var ATTACHMENT_COLUMNS = [
|
|
49430
|
+
["uti0", "a", "ZTYPEUTI"],
|
|
49431
|
+
["uti1", "a", "ZTYPEUTI1"],
|
|
49432
|
+
["parent", "a", "ZPARENTATTACHMENT"],
|
|
49433
|
+
["title", "a", "ZTITLE"],
|
|
49434
|
+
["userTitle", "a", "ZUSERTITLE"],
|
|
49435
|
+
["url", "a", "ZURLSTRING"],
|
|
49436
|
+
["alt", "a", "ZALTTEXT"],
|
|
49437
|
+
["token", "a", "ZTOKENCONTENTIDENTIFIER"],
|
|
49438
|
+
["fbImageGen", "a", "ZFALLBACKIMAGEGENERATION"],
|
|
49439
|
+
["fbPdfGen", "a", "ZFALLBACKPDFGENERATION"],
|
|
49440
|
+
["mediaId", "m", "ZIDENTIFIER"],
|
|
49441
|
+
["mediaFilename", "m", "ZFILENAME"],
|
|
49442
|
+
["mediaGen", "m", "ZGENERATION1"]
|
|
49443
|
+
];
|
|
49444
|
+
var columnCache = /* @__PURE__ */ new Map();
|
|
49445
|
+
function sqlite(dbPath2, args) {
|
|
49446
|
+
try {
|
|
49447
|
+
return execFileSync17(
|
|
49448
|
+
"/usr/bin/sqlite3",
|
|
49449
|
+
["-readonly", ...args.slice(0, -1), dbPath2, args.at(-1)],
|
|
49450
|
+
{
|
|
49451
|
+
encoding: "utf8",
|
|
49452
|
+
timeout: 1e4,
|
|
49453
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
49454
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
49455
|
+
}
|
|
49456
|
+
).trim();
|
|
49457
|
+
} catch (error2) {
|
|
49458
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
49459
|
+
if (/authorization denied|unable to open database/i.test(message))
|
|
49460
|
+
throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
|
|
49461
|
+
throw new NoteBlocksError("query-failed", "Failed to query the Notes database");
|
|
49462
|
+
}
|
|
49463
|
+
}
|
|
49464
|
+
function objectColumns(dbPath2 = NOTES_DB_PATH10) {
|
|
49465
|
+
let columns = columnCache.get(dbPath2);
|
|
49466
|
+
if (!columns) {
|
|
49467
|
+
columns = new Set(
|
|
49468
|
+
sqlite(dbPath2, ["SELECT name FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"]).split("\n").filter(Boolean)
|
|
49469
|
+
);
|
|
49470
|
+
columnCache.set(dbPath2, columns);
|
|
49471
|
+
}
|
|
49472
|
+
return columns;
|
|
49473
|
+
}
|
|
49474
|
+
function attachmentQuery(columns) {
|
|
49475
|
+
const col3 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
|
|
49476
|
+
const fields = ATTACHMENT_COLUMNS.map(([key, alias, name]) => `'${key}', ${col3(alias, name)}`);
|
|
49477
|
+
const uti = `COALESCE(${col3("a", "ZTYPEUTI")}, ${col3("a", "ZTYPEUTI1")})`;
|
|
49478
|
+
const mergeable = columns.has("ZMERGEABLEDATA1") ? columns.has("ZMERGEABLEDATA") ? "COALESCE(a.ZMERGEABLEDATA1, a.ZMERGEABLEDATA)" : "a.ZMERGEABLEDATA1" : col3("a", "ZMERGEABLEDATA");
|
|
49479
|
+
const noteLinks = ["ZNOTE", "ZNOTE1"].filter((c) => columns.has(c)).map((c) => `a.${c} = @pk`);
|
|
49480
|
+
const owner = noteLinks.length ? `(${noteLinks.join(" OR ")})` : "0";
|
|
49481
|
+
const media = columns.has("ZMEDIA") ? "m.Z_PK = a.ZMEDIA" : "0";
|
|
49482
|
+
const live = columns.has("ZMARKEDFORDELETION") ? "AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
|
|
49483
|
+
return `SELECT json_object('title', (SELECT ${col3("n", "ZTITLE1")} FROM ZICCLOUDSYNCINGOBJECT n WHERE n.Z_PK = @pk), 'attachments', (SELECT json_group_array(json_object('pk', a.Z_PK, 'id', a.ZIDENTIFIER, ${fields.join(", ")}, 'table', CASE WHEN ${uti} = 'com.apple.notes.table' THEN hex(${mergeable}) END)) FROM ZICCLOUDSYNCINGOBJECT a LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON ${media} WHERE ${owner} AND a.ZIDENTIFIER IS NOT NULL ${live}));`;
|
|
49484
|
+
}
|
|
49485
|
+
var text = (value) => typeof value === "string" && value.length ? value : typeof value === "number" ? String(value) : void 0;
|
|
49486
|
+
function buildAttachments(rows) {
|
|
49487
|
+
const all = rows.filter((row) => typeof row.id === "string" && Number.isInteger(row.pk)).map((row) => {
|
|
49488
|
+
const uti = text(row.uti0) ?? text(row.uti1) ?? "unknown";
|
|
49489
|
+
const attachment = {
|
|
49490
|
+
id: row.id,
|
|
49491
|
+
pk: row.pk,
|
|
49492
|
+
uti,
|
|
49493
|
+
kind: classifyUti(uti),
|
|
49494
|
+
children: []
|
|
49495
|
+
};
|
|
49496
|
+
const set = (key, value) => {
|
|
49497
|
+
if (value !== void 0) attachment[key] = value;
|
|
49498
|
+
};
|
|
49499
|
+
set("parentPk", Number.isInteger(row.parent) ? row.parent : void 0);
|
|
49500
|
+
set("title", text(row.title) ?? text(row.userTitle) ?? text(row.mediaFilename));
|
|
49501
|
+
set("url", text(row.url));
|
|
49502
|
+
set("altText", text(row.alt));
|
|
49503
|
+
set("tokenId", text(row.token));
|
|
49504
|
+
set("mediaId", text(row.mediaId));
|
|
49505
|
+
set("mediaFilename", text(row.mediaFilename));
|
|
49506
|
+
set("mediaGeneration", text(row.mediaGen));
|
|
49507
|
+
set("fallbackImageGeneration", text(row.fbImageGen));
|
|
49508
|
+
set("fallbackPdfGeneration", text(row.fbPdfGen));
|
|
49509
|
+
const table = text(row.table);
|
|
49510
|
+
set("tableData", table && /^[0-9a-f]+$/i.test(table) ? table : void 0);
|
|
49511
|
+
return attachment;
|
|
49512
|
+
}).sort((a, b) => a.pk - b.pk);
|
|
49513
|
+
const byPk = new Map(all.map((a) => [a.pk, a]));
|
|
49514
|
+
const ordered = [];
|
|
49515
|
+
for (const attachment of all) {
|
|
49516
|
+
const parent = attachment.parentPk !== void 0 ? byPk.get(attachment.parentPk) : void 0;
|
|
49517
|
+
if (parent) parent.children.push(attachment);
|
|
49518
|
+
else ordered.push(attachment);
|
|
49519
|
+
}
|
|
49520
|
+
return { byId: new Map(all.map((a) => [a.id, a])), ordered };
|
|
49521
|
+
}
|
|
49522
|
+
function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH10 } = {}) {
|
|
49523
|
+
const doc = readNoteBlocks(id2, { dbPath: dbPath2 });
|
|
49524
|
+
const pk = /\/ICNote\/p([0-9]{1,18})$/.exec(id2)[1];
|
|
49525
|
+
const output = sqlite(dbPath2, [
|
|
49526
|
+
"-cmd",
|
|
49527
|
+
".parameter init",
|
|
49528
|
+
"-cmd",
|
|
49529
|
+
`.parameter set @pk ${pk}`,
|
|
49530
|
+
attachmentQuery(objectColumns(dbPath2))
|
|
49531
|
+
]);
|
|
49532
|
+
let parsed;
|
|
49533
|
+
try {
|
|
49534
|
+
parsed = JSON.parse(output);
|
|
49535
|
+
} catch {
|
|
49536
|
+
throw new NoteBlocksError("query-failed", "Unexpected Notes database response");
|
|
49537
|
+
}
|
|
49538
|
+
const rows = Array.isArray(parsed.attachments) ? parsed.attachments : [];
|
|
49539
|
+
const { byId, ordered } = buildAttachments(rows);
|
|
49540
|
+
const firstLine = doc.blocks.find((block) => block.text.trim())?.text.trim() ?? "";
|
|
49541
|
+
return {
|
|
49542
|
+
id: id2,
|
|
49543
|
+
title: text(parsed.title) ?? firstLine,
|
|
49544
|
+
doc,
|
|
49545
|
+
attachments: byId,
|
|
49546
|
+
ordered
|
|
49547
|
+
};
|
|
49548
|
+
}
|
|
49549
|
+
|
|
49550
|
+
// src/services/notesExport.ts
|
|
49551
|
+
var DEFAULT_FOLDER_EXPORT_LIMIT = 100;
|
|
49552
|
+
var MAX_FOLDER_EXPORT_LIMIT = 1e3;
|
|
49553
|
+
var NotesExportError = class extends Error {
|
|
49554
|
+
constructor(code, message) {
|
|
49555
|
+
super(message);
|
|
49556
|
+
this.code = code;
|
|
49557
|
+
this.name = "NotesExportError";
|
|
49558
|
+
}
|
|
49559
|
+
code;
|
|
49560
|
+
};
|
|
49561
|
+
function validPath(path8, what) {
|
|
49562
|
+
try {
|
|
49563
|
+
return assertExportPath(path8);
|
|
49564
|
+
} catch (error2) {
|
|
49565
|
+
throw new NotesExportError(
|
|
49566
|
+
"invalid-path",
|
|
49567
|
+
`${what}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
49568
|
+
);
|
|
49569
|
+
}
|
|
49570
|
+
}
|
|
49571
|
+
function selectNotes(request, deps) {
|
|
49572
|
+
if (!!request.id === !!request.folder)
|
|
49573
|
+
throw new NotesExportError("invalid-request", "Provide exactly one of 'id' or 'folder'.");
|
|
49574
|
+
if (request.id) return [request.id];
|
|
49575
|
+
const limit = Math.min(request.limit ?? DEFAULT_FOLDER_EXPORT_LIMIT, MAX_FOLDER_EXPORT_LIMIT);
|
|
49576
|
+
try {
|
|
49577
|
+
return deps.listNoteRefs(request.account, request.folder, void 0, limit).map((ref) => ref.id);
|
|
49578
|
+
} catch (error2) {
|
|
49579
|
+
throw new NotesExportError(
|
|
49580
|
+
"folder-unavailable",
|
|
49581
|
+
`Could not list folder "${request.folder}": ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
49582
|
+
);
|
|
49583
|
+
}
|
|
49584
|
+
}
|
|
49585
|
+
function loadNotes(ids, single, read) {
|
|
49586
|
+
const notes = [];
|
|
49587
|
+
const skipped = [];
|
|
49588
|
+
for (const id2 of ids) {
|
|
49589
|
+
try {
|
|
49590
|
+
notes.push(read ? read(id2) : readExportNote(id2));
|
|
49591
|
+
} catch (error2) {
|
|
49592
|
+
if (!(error2 instanceof NoteBlocksError)) throw error2;
|
|
49593
|
+
if (single) throw new NotesExportError(error2.code, error2.message);
|
|
49594
|
+
skipped.push({ id: id2, code: error2.code });
|
|
49595
|
+
}
|
|
49596
|
+
}
|
|
49597
|
+
return { notes, skipped };
|
|
49598
|
+
}
|
|
49599
|
+
function openOutput(output) {
|
|
49600
|
+
mkdirSync5(dirname4(output), { recursive: true });
|
|
49601
|
+
try {
|
|
49602
|
+
return openCreateOnly(output);
|
|
49603
|
+
} catch (error2) {
|
|
49604
|
+
if (error2 instanceof OutputExistsError)
|
|
49605
|
+
throw new NotesExportError("output_exists", error2.message);
|
|
49606
|
+
throw error2;
|
|
49607
|
+
}
|
|
49608
|
+
}
|
|
49609
|
+
function renderInto(fd, render) {
|
|
49610
|
+
try {
|
|
49611
|
+
return render();
|
|
49612
|
+
} catch (error2) {
|
|
49613
|
+
if (fd !== void 0) writeAllAndClose(fd, "");
|
|
49614
|
+
throw error2;
|
|
49615
|
+
}
|
|
49616
|
+
}
|
|
49617
|
+
function exportNotesMarkdown(request, deps) {
|
|
49618
|
+
const output = request.outputPath ? validPath(request.outputPath, "outputPath") : void 0;
|
|
49619
|
+
const assetsDir = request.assetsDir ? validPath(request.assetsDir, "assetsDir") : void 0;
|
|
49620
|
+
if (output && assetsDir && output === assetsDir)
|
|
49621
|
+
throw new NotesExportError("invalid-path", "outputPath and assetsDir must differ.");
|
|
49622
|
+
const ids = selectNotes(request, deps);
|
|
49623
|
+
const { notes, skipped } = loadNotes(ids, !!request.id, deps.readNote);
|
|
49624
|
+
const fd = output ? openOutput(output) : void 0;
|
|
49625
|
+
const writer = assetsDir ? new SidecarWriter(assetsDir, output ? dirname4(output) : void 0) : void 0;
|
|
49626
|
+
const ctx = {
|
|
49627
|
+
stats: emptyStats(),
|
|
49628
|
+
...writer ? { writer, locator: deps.locator ?? new AssetLocator() } : {}
|
|
49629
|
+
};
|
|
49630
|
+
const markdown = renderInto(
|
|
49631
|
+
fd,
|
|
49632
|
+
() => renderNotesMarkdown(notes, ctx, { wrap: request.wrap ?? 0 })
|
|
49633
|
+
);
|
|
49634
|
+
const bytes = Buffer.byteLength(markdown);
|
|
49635
|
+
const receipt = {
|
|
49636
|
+
format: "markdown",
|
|
49637
|
+
count: notes.length,
|
|
49638
|
+
bytes,
|
|
49639
|
+
stats: ctx.stats,
|
|
49640
|
+
skipped,
|
|
49641
|
+
...assetsDir ? { assets: { dir: assetsDir, files: writer.count } } : {}
|
|
49642
|
+
};
|
|
49643
|
+
if (fd !== void 0) {
|
|
49644
|
+
writeAllAndClose(fd, markdown);
|
|
49645
|
+
return { ...receipt, output };
|
|
49646
|
+
}
|
|
49647
|
+
if (bytes > deps.maxInlineBytes)
|
|
49648
|
+
throw new NotesExportError(
|
|
49649
|
+
"too-large",
|
|
49650
|
+
`The Markdown is ${bytes} bytes, over the ${deps.maxInlineBytes}-byte inline limit. Pass outputPath to write it to a file, or export fewer notes.`
|
|
49651
|
+
);
|
|
49652
|
+
return { ...receipt, markdown };
|
|
49653
|
+
}
|
|
49654
|
+
function defaultSidecarDir(output) {
|
|
49655
|
+
return join20(dirname4(output), `${basename4(output, extname4(output))}.assets`);
|
|
49656
|
+
}
|
|
49657
|
+
function exportNotesHtml(request, deps) {
|
|
49658
|
+
if (!request.outputPath)
|
|
49659
|
+
throw new NotesExportError(
|
|
49660
|
+
"invalid-request",
|
|
49661
|
+
"outputPath is required for HTML export; the document is written to a file."
|
|
49662
|
+
);
|
|
49663
|
+
const embed = request.embedAssets ?? !request.assetsDir;
|
|
49664
|
+
if (embed && request.assetsDir)
|
|
49665
|
+
throw new NotesExportError(
|
|
49666
|
+
"invalid-request",
|
|
49667
|
+
"assetsDir applies only with embedAssets false (sidecar assets)."
|
|
49668
|
+
);
|
|
49669
|
+
const output = validPath(request.outputPath, "outputPath");
|
|
49670
|
+
const assetsDir = embed ? void 0 : validPath(request.assetsDir ?? defaultSidecarDir(output), "assetsDir");
|
|
49671
|
+
if (assetsDir === output)
|
|
49672
|
+
throw new NotesExportError("invalid-path", "outputPath and assetsDir must differ.");
|
|
49673
|
+
const ids = selectNotes(request, deps);
|
|
49674
|
+
const { notes, skipped } = loadNotes(ids, !!request.id, deps.readNote);
|
|
49675
|
+
const fd = openOutput(output);
|
|
49676
|
+
const writer = assetsDir ? new SidecarWriter(assetsDir, dirname4(output)) : new DataUrlWriter();
|
|
49677
|
+
const ctx = {
|
|
49678
|
+
stats: emptyStats(),
|
|
49679
|
+
writer,
|
|
49680
|
+
locator: deps.locator ?? new AssetLocator()
|
|
49681
|
+
};
|
|
49682
|
+
const title = request.id ? notes[0]?.title || "Note" : request.folder;
|
|
49683
|
+
const html = renderInto(fd, () => renderNotesHtml(notes, ctx, { title }));
|
|
49684
|
+
const bytes = writeAllAndClose(fd, html);
|
|
49685
|
+
return {
|
|
49686
|
+
format: "html",
|
|
49687
|
+
count: notes.length,
|
|
49688
|
+
bytes,
|
|
49689
|
+
output,
|
|
49690
|
+
stats: ctx.stats,
|
|
49691
|
+
skipped,
|
|
49692
|
+
...assetsDir ? { assets: { dir: assetsDir, files: writer.count } } : { embedded: writer.count }
|
|
49693
|
+
};
|
|
49694
|
+
}
|
|
49695
|
+
|
|
49696
|
+
// src/tools/directOperations.ts
|
|
49697
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
49698
|
+
import {
|
|
49699
|
+
closeSync as closeSync5,
|
|
49700
|
+
constants as constants5,
|
|
49701
|
+
fstatSync as fstatSync5,
|
|
49702
|
+
mkdtempSync as mkdtempSync4,
|
|
49703
|
+
openSync as openSync5,
|
|
48283
49704
|
readFileSync as readFileSync3,
|
|
48284
49705
|
rmSync as rmSync4,
|
|
48285
49706
|
writeFileSync as writeFileSync3
|
|
48286
49707
|
} from "node:fs";
|
|
48287
49708
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
48288
|
-
import { basename as
|
|
49709
|
+
import { basename as basename5, extname as extname5, isAbsolute as isAbsolute3, join as join21 } from "node:path";
|
|
48289
49710
|
var noteId = exactIdInput(
|
|
48290
49711
|
"ICNote",
|
|
48291
49712
|
/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
|
|
@@ -48308,7 +49729,7 @@ function readSnapshot(manager, id2) {
|
|
|
48308
49729
|
function assertExistingContentPreserved(before, after) {
|
|
48309
49730
|
if (before.id !== after.id || before.title !== after.title)
|
|
48310
49731
|
throw new Error("Note identity changed");
|
|
48311
|
-
const tidy = (
|
|
49732
|
+
const tidy = (text2) => text2.replace(/\r\n/g, "\n").replace(/[\s\ufffc]+$/gu, "");
|
|
48312
49733
|
if (!tidy(after.rich.text).startsWith(tidy(before.rich.text)))
|
|
48313
49734
|
throw new Error("Existing note text was not preserved");
|
|
48314
49735
|
if (linkSignature(before.rich.links) !== linkSignature(after.rich.links.slice(0, before.rich.links.length)))
|
|
@@ -48330,9 +49751,9 @@ function assertExistingContentPreserved(before, after) {
|
|
|
48330
49751
|
}
|
|
48331
49752
|
function localAttachment(path8) {
|
|
48332
49753
|
if (!isAbsolute3(path8)) throw new Error("An absolute local file path is required");
|
|
48333
|
-
const descriptor =
|
|
49754
|
+
const descriptor = openSync5(path8, constants5.O_RDONLY | constants5.O_NOFOLLOW);
|
|
48334
49755
|
try {
|
|
48335
|
-
const stat =
|
|
49756
|
+
const stat = fstatSync5(descriptor);
|
|
48336
49757
|
if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
|
|
48337
49758
|
throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
|
|
48338
49759
|
const bytes = readFileSync3(descriptor);
|
|
@@ -48340,7 +49761,7 @@ function localAttachment(path8) {
|
|
|
48340
49761
|
throw new Error("Attachment changed while it was being read; try again");
|
|
48341
49762
|
return bytes;
|
|
48342
49763
|
} finally {
|
|
48343
|
-
|
|
49764
|
+
closeSync5(descriptor);
|
|
48344
49765
|
}
|
|
48345
49766
|
}
|
|
48346
49767
|
function registerDirectOperations(server2, manager) {
|
|
@@ -48453,7 +49874,7 @@ function registerDirectOperations(server2, manager) {
|
|
|
48453
49874
|
);
|
|
48454
49875
|
}
|
|
48455
49876
|
function attachmentName(path8, filename) {
|
|
48456
|
-
const source =
|
|
49877
|
+
const source = basename5(path8);
|
|
48457
49878
|
if (filename === void 0) return source;
|
|
48458
49879
|
if (Buffer.byteLength(filename, "utf8") > 255)
|
|
48459
49880
|
throw new Error("filename must be at most 255 bytes");
|
|
@@ -48461,9 +49882,9 @@ function attachmentName(path8, filename) {
|
|
|
48461
49882
|
throw new Error(
|
|
48462
49883
|
"filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
|
|
48463
49884
|
);
|
|
48464
|
-
if (
|
|
49885
|
+
if (extname5(filename).toLowerCase() !== extname5(source).toLowerCase())
|
|
48465
49886
|
throw new Error(
|
|
48466
|
-
`filename must keep the source file's extension (${
|
|
49887
|
+
`filename must keep the source file's extension (${extname5(source) || "none"})`
|
|
48467
49888
|
);
|
|
48468
49889
|
return filename;
|
|
48469
49890
|
}
|
|
@@ -48474,8 +49895,8 @@ function attachFile(manager, args) {
|
|
|
48474
49895
|
if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
|
|
48475
49896
|
const bytes = localAttachment(path8);
|
|
48476
49897
|
const beforeAttachments = manager.listAttachmentsById(id2);
|
|
48477
|
-
const directory = mkdtempSync4(
|
|
48478
|
-
const temporaryFile =
|
|
49898
|
+
const directory = mkdtempSync4(join21(tmpdir4(), "notes-attachment-add-"));
|
|
49899
|
+
const temporaryFile = join21(directory, name);
|
|
48479
49900
|
try {
|
|
48480
49901
|
writeFileSync3(temporaryFile, bytes, { mode: 384 });
|
|
48481
49902
|
if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
|
|
@@ -48667,18 +50088,18 @@ function appendChecklistItems(args, deps, readRich) {
|
|
|
48667
50088
|
const existing = new Set(byPosition(readRich(args.id).checklistItems).map((item) => item.id));
|
|
48668
50089
|
const landed = [];
|
|
48669
50090
|
let contentHash = args.expectedContentHash;
|
|
48670
|
-
for (const [index,
|
|
50091
|
+
for (const [index, text2] of args.items.entries()) {
|
|
48671
50092
|
let wrote = false;
|
|
48672
50093
|
try {
|
|
48673
50094
|
const result = mutateBackground(
|
|
48674
50095
|
{ ...args, expectedContentHash: contentHash },
|
|
48675
50096
|
"create-checklist-item",
|
|
48676
|
-
{ text },
|
|
50097
|
+
{ text: text2 },
|
|
48677
50098
|
(before, after) => {
|
|
48678
50099
|
wrote = true;
|
|
48679
50100
|
assertPreserved(before, after, { append: true });
|
|
48680
50101
|
const added = after.checklist.slice(before.checklist.length);
|
|
48681
|
-
if (added.length !== 1 || added[0].text !==
|
|
50102
|
+
if (added.length !== 1 || added[0].text !== text2 || added[0].done)
|
|
48682
50103
|
throw new Error("Native checklist item not verified");
|
|
48683
50104
|
},
|
|
48684
50105
|
deps
|
|
@@ -48687,14 +50108,14 @@ function appendChecklistItems(args, deps, readRich) {
|
|
|
48687
50108
|
const fresh = items.filter(
|
|
48688
50109
|
(item) => !existing.has(item.id) && !landed.some((done) => done.id === item.id)
|
|
48689
50110
|
);
|
|
48690
|
-
if (fresh.length !== 1 || fresh[0].text !==
|
|
50111
|
+
if (fresh.length !== 1 || fresh[0].text !== text2 || fresh[0].done)
|
|
48691
50112
|
throw new Error("Native checklist identity not verified");
|
|
48692
50113
|
for (const done of landed) {
|
|
48693
50114
|
const current = items.find((item) => item.id === done.id);
|
|
48694
50115
|
if (!current || current.text !== done.text || current.done)
|
|
48695
50116
|
throw new Error("An earlier appended item changed identity or text");
|
|
48696
50117
|
}
|
|
48697
|
-
landed.push({ index, id: fresh[0].id, text });
|
|
50118
|
+
landed.push({ index, id: fresh[0].id, text: text2 });
|
|
48698
50119
|
contentHash = result.contentHash;
|
|
48699
50120
|
} catch (error2) {
|
|
48700
50121
|
return {
|
|
@@ -48703,7 +50124,7 @@ function appendChecklistItems(args, deps, readRich) {
|
|
|
48703
50124
|
landed,
|
|
48704
50125
|
stoppedAt: {
|
|
48705
50126
|
index,
|
|
48706
|
-
text,
|
|
50127
|
+
text: text2,
|
|
48707
50128
|
outcome: wrote ? "uncertain" : "not-written",
|
|
48708
50129
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
48709
50130
|
},
|
|
@@ -49035,7 +50456,7 @@ function registerNativeOperations(server2, manager) {
|
|
|
49035
50456
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
49036
50457
|
import { existsSync as existsSync12 } from "node:fs";
|
|
49037
50458
|
import { release as release2 } from "node:os";
|
|
49038
|
-
import { dirname as
|
|
50459
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
49039
50460
|
import { fileURLToPath } from "node:url";
|
|
49040
50461
|
var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
|
|
49041
50462
|
var MARKDOWN_MIN_DARWIN_MAJOR = 25;
|
|
@@ -49058,11 +50479,11 @@ function setupShortcuts(checkOnly, dependencies = {}) {
|
|
|
49058
50479
|
const result = spawnSync2("/usr/bin/open", [path8], { encoding: "utf8" });
|
|
49059
50480
|
return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
|
|
49060
50481
|
});
|
|
49061
|
-
const baseDirectory = dependencies.baseDirectory ||
|
|
50482
|
+
const baseDirectory = dependencies.baseDirectory || resolve4(dirname5(fileURLToPath(import.meta.url)), "../shortcuts");
|
|
49062
50483
|
const osRelease = (dependencies.osRelease || release2)();
|
|
49063
50484
|
const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
|
|
49064
50485
|
const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
|
|
49065
|
-
const path8 =
|
|
50486
|
+
const path8 = resolve4(baseDirectory, file);
|
|
49066
50487
|
let installed = false;
|
|
49067
50488
|
let identifier;
|
|
49068
50489
|
let error2;
|
|
@@ -50196,17 +51617,17 @@ function guardedAppend({
|
|
|
50196
51617
|
scopeText,
|
|
50197
51618
|
htmlSeparator
|
|
50198
51619
|
}, onRoute) {
|
|
50199
|
-
const contentToHtml = (
|
|
50200
|
-
if (format === "html") return
|
|
50201
|
-
return
|
|
51620
|
+
const contentToHtml = (text2) => {
|
|
51621
|
+
if (format === "html") return text2;
|
|
51622
|
+
return text2.split("\n").map((line) => {
|
|
50202
51623
|
const escaped = line.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
50203
51624
|
return `<div>${escaped || "<br>"}</div>`;
|
|
50204
51625
|
}).join("");
|
|
50205
51626
|
};
|
|
50206
|
-
const separatorToHtml = (
|
|
50207
|
-
if (format === "html") return
|
|
50208
|
-
if (
|
|
50209
|
-
const escaped =
|
|
51627
|
+
const separatorToHtml = (sep4) => {
|
|
51628
|
+
if (format === "html") return sep4;
|
|
51629
|
+
if (sep4 === "\n\n") return "<div><br></div>";
|
|
51630
|
+
const escaped = sep4.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
50210
51631
|
return `<div>${escaped}</div>`;
|
|
50211
51632
|
};
|
|
50212
51633
|
const snapshot = readExactNoteSnapshot(id2);
|
|
@@ -50970,8 +52391,8 @@ registerTool(
|
|
|
50970
52391
|
if (firstImage && id2) {
|
|
50971
52392
|
const assets = notesManager.getAttachmentAssetsById(id2);
|
|
50972
52393
|
const first2 = firstImageView(id2, selectFirstImage(assets));
|
|
50973
|
-
const
|
|
50974
|
-
return successResponse(
|
|
52394
|
+
const text2 = first2 ? `Lead visual: ${first2.kind} attachment ${first2.attachmentId} (${first2.path ? "asset on disk" : first2.previewPath ? "preview only" : "not downloaded"}; order from ${assets.orderSource}).` : "This note has no image, scan, or drawing attachment.";
|
|
52395
|
+
return successResponse(text2, { firstImage: first2, orderSource: assets.orderSource });
|
|
50975
52396
|
}
|
|
50976
52397
|
if (id2) {
|
|
50977
52398
|
const note2 = notesManager.getNoteById(id2);
|
|
@@ -51475,6 +52896,118 @@ registerTool(
|
|
|
51475
52896
|
return successResponse(markdown, { markdown });
|
|
51476
52897
|
}, "Error getting note as markdown")
|
|
51477
52898
|
);
|
|
52899
|
+
var exportPathInput = (what) => external_exports.string().min(1).max(MAX.SAVE_PATH).optional().describe(
|
|
52900
|
+
`${what} (absolute; under home, a temp dir, or /Volumes; never inside the Notes library)`
|
|
52901
|
+
);
|
|
52902
|
+
var exportStatsSchema = external_exports.object({
|
|
52903
|
+
attachments: external_exports.number(),
|
|
52904
|
+
placed: external_exports.number(),
|
|
52905
|
+
placeholders: external_exports.number(),
|
|
52906
|
+
unavailable: external_exports.number(),
|
|
52907
|
+
tables: external_exports.number(),
|
|
52908
|
+
unreadableTables: external_exports.number(),
|
|
52909
|
+
unreferenced: external_exports.number()
|
|
52910
|
+
});
|
|
52911
|
+
registerTool(
|
|
52912
|
+
"export-notes-markdown",
|
|
52913
|
+
{
|
|
52914
|
+
description: "Use when: exporting one note (by exact id) or a folder's notes as one Markdown document rendered from the decoded note body: headings, bulleted/dashed/numbered lists with indent, checklists with state, block quotes, monospaced blocks, bold/italic/strikethrough/underline/highlight, links, tables, and attachments in body order.\nReturns: the Markdown inline (capped by APPLE_NOTES_MCP_EXPORT_MAX_BYTES), or with outputPath a receipt {format, count, bytes, output}; plus attachment counts and skipped notes (for example password-protected ones).\nDo not use when: you need the legacy HTML-converted Markdown of one note (get-note-markdown) or a restorable backup (export-notes-json). A folder document separates notes with '---' and is a presentation format, not something to import back.\nSafety: read-only against Notes; requires Full Disk Access. outputPath is create-only (an existing file is refused with [output_exists]); assetsDir copies attachment files without replacing existing ones (collisions get -2, -3 suffixes). Without assetsDir, attachments render as labeled placeholders.",
|
|
52915
|
+
inputSchema: {
|
|
52916
|
+
id: noteIdInput.optional(),
|
|
52917
|
+
folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder path to export instead of one note (nested paths use '/')"),
|
|
52918
|
+
account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account holding the folder (defaults to Notes.app's default account)"),
|
|
52919
|
+
limit: external_exports.number().int().min(1).max(MAX_FOLDER_EXPORT_LIMIT).optional().describe(
|
|
52920
|
+
`Maximum notes read from the folder (default 100, max ${MAX_FOLDER_EXPORT_LIMIT})`
|
|
52921
|
+
),
|
|
52922
|
+
outputPath: exportPathInput("File to create for the Markdown"),
|
|
52923
|
+
assetsDir: exportPathInput("Directory that receives copies of attachment files"),
|
|
52924
|
+
wrap: external_exports.number().int().min(0).max(1e3).optional().describe("Hard-wrap prose at this many columns (0 or omitted: no wrapping)")
|
|
52925
|
+
},
|
|
52926
|
+
outputSchema: {
|
|
52927
|
+
format: external_exports.string().optional(),
|
|
52928
|
+
count: external_exports.number().optional(),
|
|
52929
|
+
bytes: external_exports.number().optional(),
|
|
52930
|
+
markdown: external_exports.string().optional(),
|
|
52931
|
+
output: external_exports.string().optional(),
|
|
52932
|
+
assets: external_exports.object({ dir: external_exports.string(), files: external_exports.number() }).optional(),
|
|
52933
|
+
stats: exportStatsSchema.optional(),
|
|
52934
|
+
skipped: external_exports.array(external_exports.object({ id: external_exports.string(), code: external_exports.string() })).optional()
|
|
52935
|
+
},
|
|
52936
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
|
|
52937
|
+
},
|
|
52938
|
+
withErrorHandling((request) => {
|
|
52939
|
+
let receipt;
|
|
52940
|
+
try {
|
|
52941
|
+
receipt = exportNotesMarkdown(request, {
|
|
52942
|
+
listNoteRefs: (account, folder, since, limit) => notesManager.listNoteRefs(account, folder, since, limit),
|
|
52943
|
+
// The document travels twice (text and structuredContent).
|
|
52944
|
+
maxInlineBytes: Math.floor(exportMaxResponseBytes() / 2) - 64 * 1024
|
|
52945
|
+
});
|
|
52946
|
+
} catch (error2) {
|
|
52947
|
+
if (!(error2 instanceof NotesExportError || error2 instanceof NoteBlocksError)) throw error2;
|
|
52948
|
+
const hint = error2.code === "no-full-disk-access" ? ` Grant Full Disk Access to the app that launches this server: ${FULL_DISK_ACCESS_GUIDE_URL}` : "";
|
|
52949
|
+
return errorResponse(`Error exporting Markdown [${error2.code}]: ${error2.message}${hint}`);
|
|
52950
|
+
}
|
|
52951
|
+
const skipped = receipt.skipped.length ? `; skipped ${receipt.skipped.length}` : "";
|
|
52952
|
+
if (receipt.output)
|
|
52953
|
+
return successResponse(
|
|
52954
|
+
`Wrote ${receipt.count} note(s) as Markdown (${receipt.bytes} bytes) to ${receipt.output}` + (receipt.assets ? `; copied ${receipt.assets.files} asset file(s) to ${receipt.assets.dir}` : "") + `${skipped}.`,
|
|
52955
|
+
{ ...receipt }
|
|
52956
|
+
);
|
|
52957
|
+
return successResponse(receipt.markdown ?? "", { ...receipt });
|
|
52958
|
+
}, "Error exporting Markdown")
|
|
52959
|
+
);
|
|
52960
|
+
registerTool(
|
|
52961
|
+
"export-notes-html",
|
|
52962
|
+
{
|
|
52963
|
+
description: "Use when: exporting one note (by exact id) or a folder's notes as one standalone HTML file rendered from the decoded note body, with semantic tables and images, drawings, scans, audio, files and link cards in body order.\nReturns: a receipt {format, count, bytes, output} plus embedded or sidecar asset counts, attachment counts and skipped notes. The HTML itself is never returned inline.\nDo not use when: you want Markdown (export-notes-markdown) or a restorable backup (export-notes-json). A folder document is a presentation format, not something to import back.\nSafety: read-only against Notes; requires Full Disk Access. outputPath is required and create-only ([output_exists] if it exists). Assets are embedded as data URLs (each up to 10 MiB) unless embedAssets is false, which copies them to a sidecar directory (assetsDir, default <output stem>.assets) with relative URLs and never replaces existing files. No file: URLs or Notes library paths are written; missing assets show a visible unavailable marker.",
|
|
52964
|
+
inputSchema: {
|
|
52965
|
+
id: noteIdInput.optional(),
|
|
52966
|
+
folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder path to export instead of one note (nested paths use '/')"),
|
|
52967
|
+
account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account holding the folder (defaults to Notes.app's default account)"),
|
|
52968
|
+
limit: external_exports.number().int().min(1).max(MAX_FOLDER_EXPORT_LIMIT).optional().describe(
|
|
52969
|
+
`Maximum notes read from the folder (default 100, max ${MAX_FOLDER_EXPORT_LIMIT})`
|
|
52970
|
+
),
|
|
52971
|
+
outputPath: external_exports.string().min(1).max(MAX.SAVE_PATH).describe(
|
|
52972
|
+
"HTML file to create (absolute; under home, a temp dir, or /Volumes; never inside the Notes library)"
|
|
52973
|
+
),
|
|
52974
|
+
embedAssets: external_exports.boolean().optional().describe("Embed assets as data URLs (default true). False writes a sidecar directory"),
|
|
52975
|
+
assetsDir: exportPathInput(
|
|
52976
|
+
"Sidecar directory when embedAssets is false (default <stem>.assets)"
|
|
52977
|
+
)
|
|
52978
|
+
},
|
|
52979
|
+
outputSchema: {
|
|
52980
|
+
format: external_exports.string().optional(),
|
|
52981
|
+
count: external_exports.number().optional(),
|
|
52982
|
+
bytes: external_exports.number().optional(),
|
|
52983
|
+
output: external_exports.string().optional(),
|
|
52984
|
+
assets: external_exports.object({ dir: external_exports.string(), files: external_exports.number() }).optional(),
|
|
52985
|
+
embedded: external_exports.number().optional(),
|
|
52986
|
+
stats: exportStatsSchema.optional(),
|
|
52987
|
+
skipped: external_exports.array(external_exports.object({ id: external_exports.string(), code: external_exports.string() })).optional()
|
|
52988
|
+
},
|
|
52989
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
|
|
52990
|
+
},
|
|
52991
|
+
withErrorHandling((request) => {
|
|
52992
|
+
let receipt;
|
|
52993
|
+
try {
|
|
52994
|
+
receipt = exportNotesHtml(request, {
|
|
52995
|
+
listNoteRefs: (account, folder, since, limit) => notesManager.listNoteRefs(account, folder, since, limit),
|
|
52996
|
+
maxInlineBytes: 0
|
|
52997
|
+
});
|
|
52998
|
+
} catch (error2) {
|
|
52999
|
+
if (!(error2 instanceof NotesExportError || error2 instanceof NoteBlocksError)) throw error2;
|
|
53000
|
+
const hint = error2.code === "no-full-disk-access" ? ` Grant Full Disk Access to the app that launches this server: ${FULL_DISK_ACCESS_GUIDE_URL}` : "";
|
|
53001
|
+
return errorResponse(`Error exporting HTML [${error2.code}]: ${error2.message}${hint}`);
|
|
53002
|
+
}
|
|
53003
|
+
const assets = receipt.assets ? `; copied ${receipt.assets.files} asset file(s) to ${receipt.assets.dir}` : `; embedded ${receipt.embedded ?? 0} asset(s)`;
|
|
53004
|
+
const skipped = receipt.skipped.length ? `; skipped ${receipt.skipped.length}` : "";
|
|
53005
|
+
return successResponse(
|
|
53006
|
+
`Wrote ${receipt.count} note(s) as HTML (${receipt.bytes} bytes) to ${receipt.output}${assets}${skipped}.`,
|
|
53007
|
+
{ ...receipt }
|
|
53008
|
+
);
|
|
53009
|
+
}, "Error exporting HTML")
|
|
53010
|
+
);
|
|
51478
53011
|
registerTool(
|
|
51479
53012
|
"get-checklist-state",
|
|
51480
53013
|
{
|