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.
Files changed (3) hide show
  1. package/README.md +95 -2
  2. package/build/index.js +1773 -240
  3. 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, constants5) {
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, constants5);
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, constants5) {
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, constants5);
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, constants5) {
506
- this.code = optimizeExpr(this.code, names, constants5);
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, constants5) {
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, constants5))
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, constants5) {
593
+ optimizeNames(names, constants6) {
594
594
  var _a;
595
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
596
- if (!(super.optimizeNames(names, constants5) || this.else))
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, constants5);
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, constants5) {
622
- if (!super.optimizeNames(names, constants5))
621
+ optimizeNames(names, constants6) {
622
+ if (!super.optimizeNames(names, constants6))
623
623
  return;
624
- this.iteration = optimizeExpr(this.iteration, names, constants5);
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, constants5) {
661
- if (!super.optimizeNames(names, constants5))
660
+ optimizeNames(names, constants6) {
661
+ if (!super.optimizeNames(names, constants6))
662
662
  return;
663
- this.iterable = optimizeExpr(this.iterable, names, constants5);
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, constants5) {
705
+ optimizeNames(names, constants6) {
706
706
  var _a, _b;
707
- super.optimizeNames(names, constants5);
708
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
709
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants5);
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, constants5) {
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 = constants5[n.str];
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 && constants5[c.str] !== void 0);
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 = resolve4.call(this, root, ref);
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 resolve4(root, ref) {
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 resolve4(baseURI, relativeURI, options) {
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, relative3, options, skipNormalization) {
3879
+ function resolveComponent(base, relative4, options, skipNormalization) {
3880
3880
  const target = {};
3881
3881
  if (!skipNormalization) {
3882
3882
  base = parse3(serialize(base, options), options);
3883
- relative3 = parse3(serialize(relative3, options), options);
3883
+ relative4 = parse3(serialize(relative4, options), options);
3884
3884
  }
3885
3885
  options = options || {};
3886
- if (!options.tolerant && relative3.scheme) {
3887
- target.scheme = relative3.scheme;
3888
- target.userinfo = relative3.userinfo;
3889
- target.host = relative3.host;
3890
- target.port = relative3.port;
3891
- target.path = removeDotSegments(relative3.path || "");
3892
- target.query = relative3.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 (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
3895
- target.userinfo = relative3.userinfo;
3896
- target.host = relative3.host;
3897
- target.port = relative3.port;
3898
- target.path = removeDotSegments(relative3.path || "");
3899
- target.query = relative3.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 (!relative3.path) {
3901
+ if (!relative4.path) {
3902
3902
  target.path = base.path;
3903
- if (relative3.query !== void 0) {
3904
- target.query = relative3.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 (relative3.path[0] === "/") {
3910
- target.path = removeDotSegments(relative3.path);
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 = "/" + relative3.path;
3913
+ target.path = "/" + relative4.path;
3914
3914
  } else if (!base.path) {
3915
- target.path = relative3.path;
3915
+ target.path = relative4.path;
3916
3916
  } else {
3917
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
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 = relative3.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 = relative3.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: resolve4,
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((text, msg) => text + separator + msg);
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 constants5 = {
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 constants5) {
7465
- v = { value: constants5[c] };
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 text = el.innerText || el.textContent || el.value || "";
9625
- return text.indexOf(param) !== -1;
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, text) {
10292
+ insertAdjacentHTML: { value: function insertAdjacentHTML(position, text2) {
10293
10293
  position = utils.toASCIILowerCase(String(position));
10294
- text = String(text);
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(text, true);
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(relative3) {
12187
+ resolve: function(relative4) {
12188
12188
  var base = this;
12189
- var r = new URL2(relative3);
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 text = this.cssText;
12438
- this._parsedStyles = parseStyles(text);
12439
- this._lastParsedText = text;
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 escapeMarkdown(string3) {
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 = escapeMarkdown(cleanAttribute(node.getAttribute("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 text = node.data.replace(/[ \r\n\t]+/g, " ");
24185
- if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs && text[0] === " ") {
24186
- text = text.substr(1);
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 (!text) {
24188
+ if (!text2) {
24189
24189
  node = remove(node);
24190
24190
  continue;
24191
24191
  }
24192
- node.data = text;
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 escapeMarkdown(string3);
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 join19(output, replacement);
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 = join19(output, rule.append(self.options));
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 join19(output, replacement) {
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((resolve4) => setTimeout(resolve4, pollInterval));
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((resolve4, reject) => {
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
- resolve4(parseResult.data);
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((resolve4, reject) => {
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(resolve4, interval);
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((resolve4) => setTimeout(resolve4, pollInterval));
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((resolve4) => {
38973
+ return new Promise((resolve5) => {
38974
38974
  const json2 = serializeMessage(message);
38975
38975
  if (this._stdout.write(json2)) {
38976
- resolve4();
38976
+ resolve5();
38977
38977
  } else {
38978
- this._stdout.once("drain", resolve4);
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(text, position, length) {
39421
+ function checklistRunLineStart(text2, position, length) {
39422
39422
  const end = position + length;
39423
39423
  let anchor = position;
39424
- while (anchor < end && text[anchor] === "\n") anchor++;
39424
+ while (anchor < end && text2[anchor] === "\n") anchor++;
39425
39425
  if (anchor === end) anchor = position;
39426
- return anchor === 0 ? 0 : text.lastIndexOf("\n", anchor - 1) + 1;
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 = (text) => text.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
39629
- var normalized = (text) => text.replace(/[\s\ufffc]/gu, "");
39628
+ var escapeAttribute = (text2) => text2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
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 text = body && stringValue(getField(body, 2));
39663
- if (!body || text === void 0) throw new Error("Unsupported Notes document structure");
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 > text.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 += text.slice(position, position + length);
39695
+ previous.text += text2.slice(position, position + length);
39696
39696
  } else
39697
- links.push({ start: position, length, text: text.slice(position, position + length), url });
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(text, position, length);
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: text.slice(
39720
+ text: text2.slice(
39721
39721
  start,
39722
- text.indexOf("\n", start) === -1 ? text.length : text.indexOf("\n", start)
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 !== text.length) throw new Error("Incomplete Notes attribute runs");
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 text = note && stringValue(getField(note, 2));
40018
- return text?.replace(/\n+$/u, "") || void 0;
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 text = registerPrimitive(segment.values.get("text"));
40058
- if (typeof text !== "string") throw new Error("Segment without text");
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 (!text) continue;
40085
- const glue = !out || /\s$/u.test(out) || /^\s/u.test(text) || /^[.,!?;:%)\]}…'’]/u.test(text) ? "" : " ";
40086
- out += glue + text;
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 text = recording.fragments.map((f) => joinSegments(f.segments)).filter(Boolean).join("\n\n");
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
- ...text ? { text } : {},
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 text = stringValue(getField(note, 2));
40382
- if (text === void 0 || text.includes("\uFFFC")) {
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: text === void 0 ? "Cell text is missing" : "Cell contains an embedded object"
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] = text.replace(/\n$/u, "");
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(text) {
40413
- return text.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r\n|[\r\n\u2028\u2029]/g, "<br>");
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 text = filter.description;
40554
- const negated = text.startsWith("has ") ? text.replace(/^has /, "does not have ") : text.startsWith("is ") ? text.replace(/^is /, "is not ") : text.startsWith("mentions ") ? text.replace(/^mentions /, "does not mention ") : `not ${text}`;
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(text) {
42007
- if (!text) {
42006
+ function escapeForAppleScript(text2) {
42007
+ if (!text2) {
42008
42008
  return "";
42009
42009
  }
42010
- let escaped = text.replace(/&/g, "&amp;");
42010
+ let escaped = text2.replace(/&/g, "&amp;");
42011
42011
  escaped = escaped.replace(/\\/g, "&#92;");
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(text) {
42024
- if (!text) return "";
42025
- return text.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
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 text = html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/div>/gi, "\n").replace(/<\/p>/gi, "\n");
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 = text;
44326
- text = text.replace(/<[^>]*>/g, "");
44327
- } while (text !== prev);
44328
- return text.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#92;/g, "\\").replace(/&amp;/g, "&").replace(/\n{3,}/g, "\n\n").trim();
44325
+ prev = text2;
44326
+ text2 = text2.replace(/<[^>]*>/g, "");
44327
+ } while (text2 !== prev);
44328
+ return text2.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#92;/g, "\\").replace(/&amp;/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, text] = listMatch;
44505
- const done = checklistMap.get(text.trim());
44504
+ const [, prefix, text2] = listMatch;
44505
+ const done = checklistMap.get(text2.trim());
44506
44506
  if (done === void 0) return line;
44507
- checklistMap.delete(text.trim());
44508
- return `${prefix} ${done ? "[x]" : "[ ]"} ${text}`;
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 = (text) => text.replace(/^#/, "").trim();
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 = (text, weight) => {
45137
- const key = text.toLocaleLowerCase();
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(text, (found.spellings.get(text) ?? 0) + weight);
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(([text]) => text);
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 text = htmlToText(body);
45434
+ const text2 = htmlToText(body);
45435
45435
  const seen = /* @__PURE__ */ new Set();
45436
45436
  const result = [];
45437
- for (const match of text.matchAll(HASHTAG_RE)) {
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(text) {
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 text.replace(/&#x([0-9a-f]+);?/gi, (match, hex3) => decodeCodePoint(match, hex3, 16)).replace(/&#([0-9]+);?/g, (match, decimal) => decodeCodePoint(match, decimal, 10)).replace(/&nbsp(?:;|(?![0-9a-z]))/gi, " ").replace(/&quot(?:;|(?![0-9a-z]))/gi, '"').replace(/&apos(?:;|(?![0-9a-z]))/gi, "'").replace(/&lt(?:;|(?![0-9a-z]))/gi, "<").replace(/&gt(?:;|(?![0-9a-z]))/gi, ">").replace(/&amp(?:;|(?![0-9a-z]))/gi, "&");
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(/&nbsp(?:;|(?![0-9a-z]))/gi, " ").replace(/&quot(?:;|(?![0-9a-z]))/gi, '"').replace(/&apos(?:;|(?![0-9a-z]))/gi, "'").replace(/&lt(?:;|(?![0-9a-z]))/gi, "<").replace(/&gt(?:;|(?![0-9a-z]))/gi, ">").replace(/&amp(?:;|(?![0-9a-z]))/gi, "&");
45462
45462
  }
45463
45463
  function firstVisibleHtmlLine(html) {
45464
- let text = html;
45464
+ let text2 = html;
45465
45465
  let previous;
45466
45466
  do {
45467
- previous = text;
45468
- text = text.replace(NON_RENDERED_BLOCK_RE, "");
45469
- } while (text !== previous);
45470
- text = text.replace(BREAK_RE, "\n").replace(BLOCK_END_RE, "\n");
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 = text;
45473
- text = text.replace(TAG_RE, "");
45474
- } while (text !== previous);
45475
- return decodeHtmlEntities(text).split(/[\r\n\u2028\u2029]+/).map((line) => line.replace(/\s+/g, " ").trim()).find(Boolean);
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(text, pos) {
45641
- const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
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 "${text}"`, pos);
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(`"${text}" is not a valid calendar date`, pos);
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(text) {
45823
- return text.normalize("NFC").replace(/[\ufffc\u00a0]/gu, " ").toLowerCase();
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 text = body && stringValue(getField(body, 2));
46003
- if (!body || text === void 0) return null;
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:${text.lastIndexOf("\n", position - 1) + 1}`;
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(text) {
46038
+ function countWords(text2) {
46039
46039
  let count = 0;
46040
- for (const word of text.replace(/\ufffc/gu, " ").split(/\s+/u)) {
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 resolve4 = (pk, seen) => {
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 ? resolve4(row.parent, seen) : void 0;
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) resolve4(row.pk, /* @__PURE__ */ new Set());
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(text, terms) {
46137
- const clean = text.replace(/\ufffc/gu, " ");
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 text = body2.text;
46241
- const firstBreak = text.indexOf("\n");
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(text),
46251
- bodyLower: normalizeForMatch(firstBreak === -1 ? "" : text.slice(firstBreak + 1)),
46252
- words: countWords(text),
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 = (text) => {
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
- text = text.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
46353
+ text2 = text2.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
46354
46354
  }
46355
- return text.replace(/[\s\ufffc]/gu, "");
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 = (text) => {
46476
+ const inline = (text2) => {
46477
46477
  const spans = [];
46478
- let value = text;
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 text = "", inTag = false;
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) text += ch;
46504
+ else if (!inTag) text2 += ch;
46505
46505
  }
46506
- return text;
46506
+ return text2;
46507
46507
  };
46508
46508
  const visible = (html2) => withoutTags(html2).replace(/&quot;/g, '"').replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/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 text = line.replace(/^> ?/, "");
46544
- if (!text.trim()) throw new Error("Empty block quote lines are unsupported");
46545
- if (/^(?:#|[-+*][ \t]|\d+[.)][ \t]|>|```)/.test(text))
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(text);
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 text = request.format === "html" ? "<div><br></div>" + request.content : "\n\n" + request.content;
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 = (text) => text.replace(/[!-/:-@[-`{-~]/g, "\\$&");
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 text = cause instanceof Error && cause.message && !message.includes(cause.message) ? `${message}
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(text)) code = "permission_denied";
47721
- else code = RULES.find((rule) => rule.pattern.test(text))?.code ?? "operation_failed";
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(text)) envelope.committed = true;
47726
- } else if (code === "revision_conflict" || NOTHING_WRITTEN.test(text)) {
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 text = utf8.decode(textBytes);
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 > text.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 !== text.length)
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 < text.length) {
47949
- const newline = text.indexOf("\n", paragraphStart);
47950
- const end = newline === -1 ? text.length : newline;
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: text.slice(paragraphStart, end),
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: text.slice(start, stop),
47980
+ text: text2.slice(start, stop),
47981
47981
  ...run.inline
47982
47982
  });
47983
47983
  if (run.inline.attachment)
47984
- for (let at = text.indexOf("\uFFFC", start); at !== -1 && at < stop; at = text.indexOf("\uFFFC", at + 1)) {
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: text.length,
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 = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
48185
+ var escapeText = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
48186
48186
  var escapeHref = (url) => escapeText(url).replace(/"/g, "&quot;");
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/tools/directOperations.ts
48276
- import { createHash as createHash2 } from "node:crypto";
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
- mkdtempSync as mkdtempSync4,
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) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[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, "&amp;").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 `![${text2}](${linkDestination(plan.url)})`;
49212
+ const inner = plan.previewUrl ? `![${text2}](${linkDestination(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 basename3, extname as extname3, isAbsolute as isAbsolute3, join as join18 } from "node:path";
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 = (text) => text.replace(/\r\n/g, "\n").replace(/[\s\ufffc]+$/gu, "");
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 = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
49754
+ const descriptor = openSync5(path8, constants5.O_RDONLY | constants5.O_NOFOLLOW);
48334
49755
  try {
48335
- const stat = fstatSync4(descriptor);
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
- closeSync4(descriptor);
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 = basename3(path8);
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 (extname3(filename).toLowerCase() !== extname3(source).toLowerCase())
49885
+ if (extname5(filename).toLowerCase() !== extname5(source).toLowerCase())
48465
49886
  throw new Error(
48466
- `filename must keep the source file's extension (${extname3(source) || "none"})`
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(join18(tmpdir4(), "notes-attachment-add-"));
48478
- const temporaryFile = join18(directory, name);
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, text] of args.items.entries()) {
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 !== text || added[0].done)
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 !== text || fresh[0].done)
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 dirname4, resolve as resolve3 } from "node:path";
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 || resolve3(dirname4(fileURLToPath(import.meta.url)), "../shortcuts");
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 = resolve3(baseDirectory, file);
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 = (text) => {
50200
- if (format === "html") return text;
50201
- return text.split("\n").map((line) => {
51620
+ const contentToHtml = (text2) => {
51621
+ if (format === "html") return text2;
51622
+ return text2.split("\n").map((line) => {
50202
51623
  const escaped = line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
50203
51624
  return `<div>${escaped || "<br>"}</div>`;
50204
51625
  }).join("");
50205
51626
  };
50206
- const separatorToHtml = (sep3) => {
50207
- if (format === "html") return sep3;
50208
- if (sep3 === "\n\n") return "<div><br></div>";
50209
- const escaped = sep3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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 text = 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.";
50974
- return successResponse(text, { firstImage: first2, orderSource: assets.orderSource });
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
  {