apple-notes-mcp 2.9.13 → 2.9.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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, constants7) {
420
+ optimizeNames(names, constants8) {
421
421
  if (!names[this.name.str])
422
422
  return;
423
423
  if (this.rhs)
424
- this.rhs = optimizeExpr(this.rhs, names, constants7);
424
+ this.rhs = optimizeExpr(this.rhs, names, constants8);
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, constants7) {
441
+ optimizeNames(names, constants8) {
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, constants7);
444
+ this.rhs = optimizeExpr(this.rhs, names, constants8);
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, constants7) {
506
- this.code = optimizeExpr(this.code, names, constants7);
505
+ optimizeNames(names, constants8) {
506
+ this.code = optimizeExpr(this.code, names, constants8);
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, constants7) {
535
+ optimizeNames(names, constants8) {
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, constants7))
540
+ if (n.optimizeNames(names, constants8))
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, constants7) {
593
+ optimizeNames(names, constants8) {
594
594
  var _a;
595
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants7);
596
- if (!(super.optimizeNames(names, constants7) || this.else))
595
+ this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants8);
596
+ if (!(super.optimizeNames(names, constants8) || this.else))
597
597
  return;
598
- this.condition = optimizeExpr(this.condition, names, constants7);
598
+ this.condition = optimizeExpr(this.condition, names, constants8);
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, constants7) {
622
- if (!super.optimizeNames(names, constants7))
621
+ optimizeNames(names, constants8) {
622
+ if (!super.optimizeNames(names, constants8))
623
623
  return;
624
- this.iteration = optimizeExpr(this.iteration, names, constants7);
624
+ this.iteration = optimizeExpr(this.iteration, names, constants8);
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, constants7) {
661
- if (!super.optimizeNames(names, constants7))
660
+ optimizeNames(names, constants8) {
661
+ if (!super.optimizeNames(names, constants8))
662
662
  return;
663
- this.iterable = optimizeExpr(this.iterable, names, constants7);
663
+ this.iterable = optimizeExpr(this.iterable, names, constants8);
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, constants7) {
705
+ optimizeNames(names, constants8) {
706
706
  var _a, _b;
707
- super.optimizeNames(names, constants7);
708
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants7);
709
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants7);
707
+ super.optimizeNames(names, constants8);
708
+ (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants8);
709
+ (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants8);
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, constants7) {
1010
+ function optimizeExpr(expr, names, constants8) {
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 = constants7[n.str];
1025
+ const c = constants8[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 && constants7[c.str] !== void 0);
1032
+ return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants8[c.str] !== void 0);
1033
1033
  }
1034
1034
  }
1035
1035
  function subtractNames(names, from) {
@@ -1785,14 +1785,14 @@ var require_code2 = __commonJS({
1785
1785
  }
1786
1786
  exports.callValidateCode = callValidateCode;
1787
1787
  var newRegExp = (0, codegen_1._)`new RegExp`;
1788
- function usePattern({ gen, it: { opts } }, pattern) {
1788
+ function usePattern({ gen, it: { opts } }, pattern2) {
1789
1789
  const u = opts.unicodeRegExp ? "u" : "";
1790
1790
  const { regExp } = opts.code;
1791
- const rx = regExp(pattern, u);
1791
+ const rx = regExp(pattern2, u);
1792
1792
  return gen.scopeValue("pattern", {
1793
1793
  key: rx.toString(),
1794
1794
  ref: rx,
1795
- code: (0, codegen_1._)`${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern}, ${u})`
1795
+ code: (0, codegen_1._)`${regExp.code === "new RegExp" ? newRegExp : (0, util_2.useFunc)(gen, regExp)}(${pattern2}, ${u})`
1796
1796
  });
1797
1797
  }
1798
1798
  exports.usePattern = usePattern;
@@ -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 = resolve7.call(this, root, ref);
2994
+ let _sch = resolve8.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 resolve7(root, ref) {
3021
+ function resolve8(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 resolve7(baseURI, relativeURI, options) {
3846
+ function resolve8(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, relative4, options, skipNormalization) {
3879
+ function resolveComponent(base, relative5, options, skipNormalization) {
3880
3880
  const target = {};
3881
3881
  if (!skipNormalization) {
3882
3882
  base = parse3(serialize(base, options), options);
3883
- relative4 = parse3(serialize(relative4, options), options);
3883
+ relative5 = parse3(serialize(relative5, options), options);
3884
3884
  }
3885
3885
  options = options || {};
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;
3886
+ if (!options.tolerant && relative5.scheme) {
3887
+ target.scheme = relative5.scheme;
3888
+ target.userinfo = relative5.userinfo;
3889
+ target.host = relative5.host;
3890
+ target.port = relative5.port;
3891
+ target.path = removeDotSegments(relative5.path || "");
3892
+ target.query = relative5.query;
3893
3893
  } else {
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;
3894
+ if (relative5.userinfo !== void 0 || relative5.host !== void 0 || relative5.port !== void 0) {
3895
+ target.userinfo = relative5.userinfo;
3896
+ target.host = relative5.host;
3897
+ target.port = relative5.port;
3898
+ target.path = removeDotSegments(relative5.path || "");
3899
+ target.query = relative5.query;
3900
3900
  } else {
3901
- if (!relative4.path) {
3901
+ if (!relative5.path) {
3902
3902
  target.path = base.path;
3903
- if (relative4.query !== void 0) {
3904
- target.query = relative4.query;
3903
+ if (relative5.query !== void 0) {
3904
+ target.query = relative5.query;
3905
3905
  } else {
3906
3906
  target.query = base.query;
3907
3907
  }
3908
3908
  } else {
3909
- if (relative4.path[0] === "/") {
3910
- target.path = removeDotSegments(relative4.path);
3909
+ if (relative5.path[0] === "/") {
3910
+ target.path = removeDotSegments(relative5.path);
3911
3911
  } else {
3912
3912
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3913
- target.path = "/" + relative4.path;
3913
+ target.path = "/" + relative5.path;
3914
3914
  } else if (!base.path) {
3915
- target.path = relative4.path;
3915
+ target.path = relative5.path;
3916
3916
  } else {
3917
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
3917
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative5.path;
3918
3918
  }
3919
3919
  target.path = removeDotSegments(target.path);
3920
3920
  }
3921
- target.query = relative4.query;
3921
+ target.query = relative5.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 = relative4.fragment;
3929
+ target.fragment = relative5.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: resolve7,
4208
+ resolve: resolve8,
4209
4209
  resolveComponent,
4210
4210
  equal,
4211
4211
  serialize,
@@ -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 constants7 = {
7425
+ var constants8 = {
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 constants7) {
7465
- v = { value: constants7[c] };
7464
+ for (c in constants8) {
7465
+ v = { value: constants8[c] };
7466
7466
  Object.defineProperty(DOMException, c, v);
7467
7467
  Object.defineProperty(DOMException.prototype, c, v);
7468
7468
  }
@@ -8184,7 +8184,7 @@ var require_Node = __commonJS({
8184
8184
  }
8185
8185
  return sum;
8186
8186
  } },
8187
- _ensureInsertValid: { value: function _ensureInsertValid(node, child, isPreinsert) {
8187
+ _ensureInsertValid: { value: function _ensureInsertValid(node, child2, isPreinsert) {
8188
8188
  var parent = this, i, kid;
8189
8189
  if (!node.nodeType) throw new TypeError("not a node");
8190
8190
  switch (parent.nodeType) {
@@ -8196,8 +8196,8 @@ var require_Node = __commonJS({
8196
8196
  utils.HierarchyRequestError();
8197
8197
  }
8198
8198
  if (node.isAncestor(parent)) utils.HierarchyRequestError();
8199
- if (child !== null || !isPreinsert) {
8200
- if (child.parentNode !== parent) utils.NotFoundError();
8199
+ if (child2 !== null || !isPreinsert) {
8200
+ if (child2.parentNode !== parent) utils.NotFoundError();
8201
8201
  }
8202
8202
  switch (node.nodeType) {
8203
8203
  case DOCUMENT_FRAGMENT_NODE:
@@ -8222,10 +8222,10 @@ var require_Node = __commonJS({
8222
8222
  case 0:
8223
8223
  break;
8224
8224
  case 1:
8225
- if (child !== null) {
8226
- if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE)
8225
+ if (child2 !== null) {
8226
+ if (isPreinsert && child2.nodeType === DOCUMENT_TYPE_NODE)
8227
8227
  utils.HierarchyRequestError();
8228
- for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) {
8228
+ for (kid = child2.nextSibling; kid !== null; kid = kid.nextSibling) {
8229
8229
  if (kid.nodeType === DOCUMENT_TYPE_NODE)
8230
8230
  utils.HierarchyRequestError();
8231
8231
  }
@@ -8235,7 +8235,7 @@ var require_Node = __commonJS({
8235
8235
  if (i > 0)
8236
8236
  utils.HierarchyRequestError();
8237
8237
  } else {
8238
- if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE)
8238
+ if (i > 1 || i === 1 && child2.nodeType !== ELEMENT_NODE)
8239
8239
  utils.HierarchyRequestError();
8240
8240
  }
8241
8241
  break;
@@ -8244,10 +8244,10 @@ var require_Node = __commonJS({
8244
8244
  }
8245
8245
  break;
8246
8246
  case ELEMENT_NODE:
8247
- if (child !== null) {
8248
- if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE)
8247
+ if (child2 !== null) {
8248
+ if (isPreinsert && child2.nodeType === DOCUMENT_TYPE_NODE)
8249
8249
  utils.HierarchyRequestError();
8250
- for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) {
8250
+ for (kid = child2.nextSibling; kid !== null; kid = kid.nextSibling) {
8251
8251
  if (kid.nodeType === DOCUMENT_TYPE_NODE)
8252
8252
  utils.HierarchyRequestError();
8253
8253
  }
@@ -8257,17 +8257,17 @@ var require_Node = __commonJS({
8257
8257
  if (i > 0)
8258
8258
  utils.HierarchyRequestError();
8259
8259
  } else {
8260
- if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE)
8260
+ if (i > 1 || i === 1 && child2.nodeType !== ELEMENT_NODE)
8261
8261
  utils.HierarchyRequestError();
8262
8262
  }
8263
8263
  break;
8264
8264
  case DOCUMENT_TYPE_NODE:
8265
- if (child === null) {
8265
+ if (child2 === null) {
8266
8266
  if (parent._countChildrenOfType(ELEMENT_NODE))
8267
8267
  utils.HierarchyRequestError();
8268
8268
  } else {
8269
8269
  for (kid = parent.firstChild; kid !== null; kid = kid.nextSibling) {
8270
- if (kid === child) break;
8270
+ if (kid === child2) break;
8271
8271
  if (kid.nodeType === ELEMENT_NODE)
8272
8272
  utils.HierarchyRequestError();
8273
8273
  }
@@ -8277,7 +8277,7 @@ var require_Node = __commonJS({
8277
8277
  if (i > 0)
8278
8278
  utils.HierarchyRequestError();
8279
8279
  } else {
8280
- if (i > 1 || i === 1 && child.nodeType !== DOCUMENT_TYPE_NODE)
8280
+ if (i > 1 || i === 1 && child2.nodeType !== DOCUMENT_TYPE_NODE)
8281
8281
  utils.HierarchyRequestError();
8282
8282
  }
8283
8283
  break;
@@ -8286,10 +8286,10 @@ var require_Node = __commonJS({
8286
8286
  if (node.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError();
8287
8287
  }
8288
8288
  } },
8289
- insertBefore: { value: function insertBefore(node, child) {
8289
+ insertBefore: { value: function insertBefore(node, child2) {
8290
8290
  var parent = this;
8291
- parent._ensureInsertValid(node, child, true);
8292
- var refChild = child;
8291
+ parent._ensureInsertValid(node, child2, true);
8292
+ var refChild = child2;
8293
8293
  if (refChild === node) {
8294
8294
  refChild = node.nextSibling;
8295
8295
  }
@@ -8297,28 +8297,28 @@ var require_Node = __commonJS({
8297
8297
  node._insertOrReplace(parent, refChild, false);
8298
8298
  return node;
8299
8299
  } },
8300
- appendChild: { value: function(child) {
8301
- return this.insertBefore(child, null);
8300
+ appendChild: { value: function(child2) {
8301
+ return this.insertBefore(child2, null);
8302
8302
  } },
8303
- _appendChild: { value: function(child) {
8304
- child._insertOrReplace(this, null, false);
8303
+ _appendChild: { value: function(child2) {
8304
+ child2._insertOrReplace(this, null, false);
8305
8305
  } },
8306
- removeChild: { value: function removeChild(child) {
8306
+ removeChild: { value: function removeChild(child2) {
8307
8307
  var parent = this;
8308
- if (!child.nodeType) throw new TypeError("not a node");
8309
- if (child.parentNode !== parent) utils.NotFoundError();
8310
- child.remove();
8311
- return child;
8308
+ if (!child2.nodeType) throw new TypeError("not a node");
8309
+ if (child2.parentNode !== parent) utils.NotFoundError();
8310
+ child2.remove();
8311
+ return child2;
8312
8312
  } },
8313
8313
  // To replace a `child` with `node` within a `parent` (this)
8314
- replaceChild: { value: function replaceChild(node, child) {
8314
+ replaceChild: { value: function replaceChild(node, child2) {
8315
8315
  var parent = this;
8316
- parent._ensureInsertValid(node, child, false);
8316
+ parent._ensureInsertValid(node, child2, false);
8317
8317
  if (node.doc !== parent.doc) {
8318
8318
  parent.doc.adoptNode(node);
8319
8319
  }
8320
- node._insertOrReplace(parent, child, true);
8321
- return child;
8320
+ node._insertOrReplace(parent, child2, true);
8321
+ return child2;
8322
8322
  } },
8323
8323
  // See: http://ejohn.org/blog/comparing-document-position/
8324
8324
  contains: { value: function contains(node) {
@@ -8474,14 +8474,14 @@ var require_Node = __commonJS({
8474
8474
  // or replace the specified child with this node, firing mutation events as
8475
8475
  // necessary
8476
8476
  _insertOrReplace: { value: function _insertOrReplace(parent, before, isReplace) {
8477
- var child = this, before_index, i;
8478
- if (child.nodeType === DOCUMENT_FRAGMENT_NODE && child.rooted) {
8477
+ var child2 = this, before_index, i;
8478
+ if (child2.nodeType === DOCUMENT_FRAGMENT_NODE && child2.rooted) {
8479
8479
  utils.HierarchyRequestError();
8480
8480
  }
8481
8481
  if (parent._childNodes) {
8482
8482
  before_index = before === null ? parent._childNodes.length : before.index;
8483
- if (child.parentNode === parent) {
8484
- var child_index = child.index;
8483
+ if (child2.parentNode === parent) {
8484
+ var child_index = child2.index;
8485
8485
  if (child_index < before_index) {
8486
8486
  before_index--;
8487
8487
  }
@@ -8495,10 +8495,10 @@ var require_Node = __commonJS({
8495
8495
  if (n === null) {
8496
8496
  n = parent.firstChild;
8497
8497
  }
8498
- var bothRooted = child.rooted && parent.rooted;
8499
- if (child.nodeType === DOCUMENT_FRAGMENT_NODE) {
8498
+ var bothRooted = child2.rooted && parent.rooted;
8499
+ if (child2.nodeType === DOCUMENT_FRAGMENT_NODE) {
8500
8500
  var spliceArgs = [0, isReplace ? 1 : 0], next;
8501
- for (var kid = child.firstChild; kid !== null; kid = next) {
8501
+ for (var kid = child2.firstChild; kid !== null; kid = next) {
8502
8502
  next = kid.nextSibling;
8503
8503
  spliceArgs.push(kid);
8504
8504
  kid.parentNode = parent;
@@ -8522,10 +8522,10 @@ var require_Node = __commonJS({
8522
8522
  parent._firstChild = null;
8523
8523
  }
8524
8524
  }
8525
- if (child._childNodes) {
8526
- child._childNodes.length = 0;
8525
+ if (child2._childNodes) {
8526
+ child2._childNodes.length = 0;
8527
8527
  } else {
8528
- child._firstChild = null;
8528
+ child2._firstChild = null;
8529
8529
  }
8530
8530
  if (parent.rooted) {
8531
8531
  parent.modify();
@@ -8534,40 +8534,40 @@ var require_Node = __commonJS({
8534
8534
  }
8535
8535
  }
8536
8536
  } else {
8537
- if (before === child) {
8537
+ if (before === child2) {
8538
8538
  return;
8539
8539
  }
8540
8540
  if (bothRooted) {
8541
- child._remove();
8542
- } else if (child.parentNode) {
8543
- child.remove();
8541
+ child2._remove();
8542
+ } else if (child2.parentNode) {
8543
+ child2.remove();
8544
8544
  }
8545
- child.parentNode = parent;
8545
+ child2.parentNode = parent;
8546
8546
  if (isReplace) {
8547
- LinkedList.replace(n, child);
8547
+ LinkedList.replace(n, child2);
8548
8548
  if (parent._childNodes) {
8549
- child._index = before_index;
8550
- parent._childNodes[before_index] = child;
8549
+ child2._index = before_index;
8550
+ parent._childNodes[before_index] = child2;
8551
8551
  } else if (parent._firstChild === before) {
8552
- parent._firstChild = child;
8552
+ parent._firstChild = child2;
8553
8553
  }
8554
8554
  } else {
8555
8555
  if (n !== null) {
8556
- LinkedList.insertBefore(child, n);
8556
+ LinkedList.insertBefore(child2, n);
8557
8557
  }
8558
8558
  if (parent._childNodes) {
8559
- child._index = before_index;
8560
- parent._childNodes.splice(before_index, 0, child);
8559
+ child2._index = before_index;
8560
+ parent._childNodes.splice(before_index, 0, child2);
8561
8561
  } else if (parent._firstChild === before) {
8562
- parent._firstChild = child;
8562
+ parent._firstChild = child2;
8563
8563
  }
8564
8564
  }
8565
8565
  if (bothRooted) {
8566
8566
  parent.modify();
8567
- parent.doc.mutateMove(child);
8567
+ parent.doc.mutateMove(child2);
8568
8568
  } else if (parent.rooted) {
8569
8569
  parent.modify();
8570
- parent.doc.mutateInsert(child);
8570
+ parent.doc.mutateInsert(child2);
8571
8571
  }
8572
8572
  }
8573
8573
  } },
@@ -8615,24 +8615,24 @@ var require_Node = __commonJS({
8615
8615
  } },
8616
8616
  normalize: { value: function() {
8617
8617
  var next;
8618
- for (var child = this.firstChild; child !== null; child = next) {
8619
- next = child.nextSibling;
8620
- if (child.normalize) {
8621
- child.normalize();
8618
+ for (var child2 = this.firstChild; child2 !== null; child2 = next) {
8619
+ next = child2.nextSibling;
8620
+ if (child2.normalize) {
8621
+ child2.normalize();
8622
8622
  }
8623
- if (child.nodeType !== Node.TEXT_NODE) {
8623
+ if (child2.nodeType !== Node.TEXT_NODE) {
8624
8624
  continue;
8625
8625
  }
8626
- if (child.nodeValue === "") {
8627
- this.removeChild(child);
8626
+ if (child2.nodeValue === "") {
8627
+ this.removeChild(child2);
8628
8628
  continue;
8629
8629
  }
8630
- var prevChild = child.previousSibling;
8630
+ var prevChild = child2.previousSibling;
8631
8631
  if (prevChild === null) {
8632
8632
  continue;
8633
8633
  } else if (prevChild.nodeType === Node.TEXT_NODE) {
8634
- prevChild.appendData(child.nodeValue);
8635
- this.removeChild(child);
8634
+ prevChild.appendData(child2.nodeValue);
8635
+ this.removeChild(child2);
8636
8636
  }
8637
8637
  }
8638
8638
  } },
@@ -9247,7 +9247,7 @@ var require_select = __commonJS({
9247
9247
  while ((el = el.previousSibling) && el.nodeType !== 1) ;
9248
9248
  return el;
9249
9249
  };
9250
- var child = function(el) {
9250
+ var child2 = function(el) {
9251
9251
  if (el = el.firstChild) {
9252
9252
  while (el.nodeType !== 1 && (el = el.nextSibling)) ;
9253
9253
  }
@@ -9348,7 +9348,7 @@ var require_select = __commonJS({
9348
9348
  };
9349
9349
  };
9350
9350
  var nth = function(param_, test, last) {
9351
- var param = parseNth(param_), group = param.group, offset = param.offset, find2 = !last ? child : lastChild, advance = !last ? next : prev;
9351
+ var param = parseNth(param_), group = param.group, offset = param.offset, find2 = !last ? child2 : lastChild, advance = !last ? next : prev;
9352
9352
  return function(el) {
9353
9353
  if (!parentIsElement(el)) return;
9354
9354
  var rel = find2(el.parentNode), pos = 0;
@@ -11181,11 +11181,11 @@ var require_Leaf = __commonJS({
11181
11181
  } },
11182
11182
  firstChild: { value: null },
11183
11183
  lastChild: { value: null },
11184
- insertBefore: { value: function(node, child) {
11184
+ insertBefore: { value: function(node, child2) {
11185
11185
  if (!node.nodeType) throw new TypeError("not a node");
11186
11186
  HierarchyRequestError();
11187
11187
  } },
11188
- replaceChild: { value: function(node, child) {
11188
+ replaceChild: { value: function(node, child2) {
11189
11189
  if (!node.nodeType) throw new TypeError("not a node");
11190
11190
  HierarchyRequestError();
11191
11191
  } },
@@ -11676,7 +11676,7 @@ var require_TreeWalker = __commonJS({
11676
11676
  previous: "previousSibling"
11677
11677
  };
11678
11678
  function traverseChildren(tw, type) {
11679
- var child, node, parent, result, sibling;
11679
+ var child2, node, parent, result, sibling;
11680
11680
  node = tw._currentNode[mapChild[type]];
11681
11681
  while (node !== null) {
11682
11682
  result = tw._internalFilter(node);
@@ -11685,9 +11685,9 @@ var require_TreeWalker = __commonJS({
11685
11685
  return node;
11686
11686
  }
11687
11687
  if (result === NodeFilter.FILTER_SKIP) {
11688
- child = node[mapChild[type]];
11689
- if (child !== null) {
11690
- node = child;
11688
+ child2 = node[mapChild[type]];
11689
+ if (child2 !== null) {
11690
+ node = child2;
11691
11691
  continue;
11692
11692
  }
11693
11693
  }
@@ -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(relative4) {
12187
+ resolve: function(relative5) {
12188
12188
  var base = this;
12189
- var r = new URL2(relative4);
12189
+ var r = new URL2(relative5);
12190
12190
  var t = new URL2();
12191
12191
  if (r.scheme !== void 0) {
12192
12192
  t.scheme = r.scheme;
@@ -12220,7 +12220,7 @@ var require_URL = __commonJS({
12220
12220
  if (r.path.charAt(0) === "/") {
12221
12221
  t.path = remove_dot_segments(r.path);
12222
12222
  } else {
12223
- t.path = merge2(base.path, r.path);
12223
+ t.path = merge3(base.path, r.path);
12224
12224
  t.path = remove_dot_segments(t.path);
12225
12225
  }
12226
12226
  t.query = r.query;
@@ -12229,7 +12229,7 @@ var require_URL = __commonJS({
12229
12229
  }
12230
12230
  t.fragment = r.fragment;
12231
12231
  return t.toString();
12232
- function merge2(basepath, refpath) {
12232
+ function merge3(basepath, refpath) {
12233
12233
  if (base.host !== void 0 && !base.path)
12234
12234
  return "/" + refpath;
12235
12235
  var lastslash = basepath.lastIndexOf("/");
@@ -13867,9 +13867,9 @@ var require_htmlelts = __commonJS({
13867
13867
  get: function() {
13868
13868
  var s = "";
13869
13869
  for (var i = 0, n = this.childNodes.length; i < n; i++) {
13870
- var child = this.childNodes[i];
13871
- if (child.nodeType === Node.TEXT_NODE)
13872
- s += child._data;
13870
+ var child2 = this.childNodes[i];
13871
+ if (child2.nodeType === Node.TEXT_NODE)
13872
+ s += child2._data;
13873
13873
  }
13874
13874
  return s;
13875
13875
  },
@@ -14830,20 +14830,20 @@ var require_Document = __commonJS({
14830
14830
  this.documentElement = kid;
14831
14831
  }
14832
14832
  } },
14833
- insertBefore: { value: function insertBefore(child, refChild) {
14834
- Node.prototype.insertBefore.call(this, child, refChild);
14833
+ insertBefore: { value: function insertBefore(child2, refChild) {
14834
+ Node.prototype.insertBefore.call(this, child2, refChild);
14835
14835
  this._updateDocTypeElement();
14836
- return child;
14836
+ return child2;
14837
14837
  } },
14838
- replaceChild: { value: function replaceChild(node, child) {
14839
- Node.prototype.replaceChild.call(this, node, child);
14838
+ replaceChild: { value: function replaceChild(node, child2) {
14839
+ Node.prototype.replaceChild.call(this, node, child2);
14840
14840
  this._updateDocTypeElement();
14841
- return child;
14841
+ return child2;
14842
14842
  } },
14843
- removeChild: { value: function removeChild(child) {
14844
- Node.prototype.removeChild.call(this, child);
14843
+ removeChild: { value: function removeChild(child2) {
14844
+ Node.prototype.removeChild.call(this, child2);
14845
14845
  this._updateDocTypeElement();
14846
- return child;
14846
+ return child2;
14847
14847
  } },
14848
14848
  getElementById: { value: function(id2) {
14849
14849
  var n = this.byId[id2];
@@ -18469,7 +18469,7 @@ var require_HTMLParser = __commonJS({
18469
18469
  }
18470
18470
  }
18471
18471
  function scanChars(shouldPauseFunc) {
18472
- var codepoint, s, pattern, eof;
18472
+ var codepoint, s, pattern2, eof;
18473
18473
  while (nextchar < numchars) {
18474
18474
  if (paused > 0 || shouldPauseFunc && shouldPauseFunc()) {
18475
18475
  return true;
@@ -18530,10 +18530,10 @@ var require_HTMLParser = __commonJS({
18530
18530
  break;
18531
18531
  case "string":
18532
18532
  codepoint = chars.charCodeAt(nextchar);
18533
- pattern = tokenizer.lookahead;
18534
- var pos = chars.indexOf(pattern, nextchar);
18533
+ pattern2 = tokenizer.lookahead;
18534
+ var pos = chars.indexOf(pattern2, nextchar);
18535
18535
  if (pos !== -1) {
18536
- s = chars.substring(nextchar, pos + pattern.length);
18536
+ s = chars.substring(nextchar, pos + pattern2.length);
18537
18537
  eof = false;
18538
18538
  } else {
18539
18539
  if (!input_complete) return true;
@@ -18641,9 +18641,9 @@ var require_HTMLParser = __commonJS({
18641
18641
  }
18642
18642
  ignore_linefeed = false;
18643
18643
  }
18644
- function getMatchingChars(pattern) {
18645
- pattern.lastIndex = nextchar - 1;
18646
- var match = pattern.exec(chars);
18644
+ function getMatchingChars(pattern2) {
18645
+ pattern2.lastIndex = nextchar - 1;
18646
+ var match = pattern2.exec(chars);
18647
18647
  if (match && match.index === nextchar - 1) {
18648
18648
  match = match[0];
18649
18649
  nextchar += match.length - 1;
@@ -18656,9 +18656,9 @@ var require_HTMLParser = __commonJS({
18656
18656
  throw new Error("should never happen");
18657
18657
  }
18658
18658
  }
18659
- function emitCharsWhile(pattern) {
18660
- pattern.lastIndex = nextchar - 1;
18661
- var match = pattern.exec(chars)[0];
18659
+ function emitCharsWhile(pattern2) {
18660
+ pattern2.lastIndex = nextchar - 1;
18661
+ var match = pattern2.exec(chars)[0];
18662
18662
  if (!match) return false;
18663
18663
  emitCharString(match);
18664
18664
  nextchar += match.length - 1;
@@ -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 join28(output, replacement);
24468
+ return join29(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 = join28(output, rule.append(self.options));
24475
+ output = join29(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 join28(output, replacement) {
24487
+ function join29(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);
@@ -29618,12 +29618,12 @@ var $ZodCheckUpperCase = /* @__PURE__ */ $constructor("$ZodCheckUpperCase", (ins
29618
29618
  var $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst, def) => {
29619
29619
  $ZodCheck.init(inst, def);
29620
29620
  const escapedRegex = escapeRegex(def.includes);
29621
- const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position}}${escapedRegex}` : escapedRegex);
29622
- def.pattern = pattern;
29621
+ const pattern2 = new RegExp(typeof def.position === "number" ? `^.{${def.position}}${escapedRegex}` : escapedRegex);
29622
+ def.pattern = pattern2;
29623
29623
  inst._zod.onattach.push((inst2) => {
29624
29624
  const bag = inst2._zod.bag;
29625
29625
  bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
29626
- bag.patterns.add(pattern);
29626
+ bag.patterns.add(pattern2);
29627
29627
  });
29628
29628
  inst._zod.check = (payload) => {
29629
29629
  if (payload.value.includes(def.includes, def.position))
@@ -29641,12 +29641,12 @@ var $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst,
29641
29641
  });
29642
29642
  var $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (inst, def) => {
29643
29643
  $ZodCheck.init(inst, def);
29644
- const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
29645
- def.pattern ?? (def.pattern = pattern);
29644
+ const pattern2 = new RegExp(`^${escapeRegex(def.prefix)}.*`);
29645
+ def.pattern ?? (def.pattern = pattern2);
29646
29646
  inst._zod.onattach.push((inst2) => {
29647
29647
  const bag = inst2._zod.bag;
29648
29648
  bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
29649
- bag.patterns.add(pattern);
29649
+ bag.patterns.add(pattern2);
29650
29650
  });
29651
29651
  inst._zod.check = (payload) => {
29652
29652
  if (payload.value.startsWith(def.prefix))
@@ -29664,12 +29664,12 @@ var $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (i
29664
29664
  });
29665
29665
  var $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst, def) => {
29666
29666
  $ZodCheck.init(inst, def);
29667
- const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
29668
- def.pattern ?? (def.pattern = pattern);
29667
+ const pattern2 = new RegExp(`.*${escapeRegex(def.suffix)}$`);
29668
+ def.pattern ?? (def.pattern = pattern2);
29669
29669
  inst._zod.onattach.push((inst2) => {
29670
29670
  const bag = inst2._zod.bag;
29671
29671
  bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
29672
- bag.patterns.add(pattern);
29672
+ bag.patterns.add(pattern2);
29673
29673
  });
29674
29674
  inst._zod.check = (payload) => {
29675
29675
  if (payload.value.endsWith(def.suffix))
@@ -30351,7 +30351,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
30351
30351
  return (payload, ctx) => fn(shape, payload, ctx);
30352
30352
  };
30353
30353
  let fastpass;
30354
- const isObject2 = isObject;
30354
+ const isObject3 = isObject;
30355
30355
  const jit = !globalConfig.jitless;
30356
30356
  const allowsEval2 = allowsEval;
30357
30357
  const fastEnabled = jit && allowsEval2.value;
@@ -30360,7 +30360,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
30360
30360
  inst._zod.parse = (payload, ctx) => {
30361
30361
  value ?? (value = _normalized.value);
30362
30362
  const input = payload.value;
30363
- if (!isObject2(input)) {
30363
+ if (!isObject3(input)) {
30364
30364
  payload.issues.push({
30365
30365
  expected: "object",
30366
30366
  code: "invalid_type",
@@ -30777,8 +30777,8 @@ var $ZodOptional = /* @__PURE__ */ $constructor("$ZodOptional", (inst, def) => {
30777
30777
  return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
30778
30778
  });
30779
30779
  defineLazy(inst._zod, "pattern", () => {
30780
- const pattern = def.innerType._zod.pattern;
30781
- return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;
30780
+ const pattern2 = def.innerType._zod.pattern;
30781
+ return pattern2 ? new RegExp(`^(${cleanRegex(pattern2.source)})?$`) : void 0;
30782
30782
  });
30783
30783
  inst._zod.parse = (payload, ctx) => {
30784
30784
  if (def.innerType._zod.optin === "optional") {
@@ -30795,8 +30795,8 @@ var $ZodNullable = /* @__PURE__ */ $constructor("$ZodNullable", (inst, def) => {
30795
30795
  defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
30796
30796
  defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
30797
30797
  defineLazy(inst._zod, "pattern", () => {
30798
- const pattern = def.innerType._zod.pattern;
30799
- return pattern ? new RegExp(`^(${cleanRegex(pattern.source)}|null)$`) : void 0;
30798
+ const pattern2 = def.innerType._zod.pattern;
30799
+ return pattern2 ? new RegExp(`^(${cleanRegex(pattern2.source)}|null)$`) : void 0;
30800
30800
  });
30801
30801
  defineLazy(inst._zod, "values", () => {
30802
30802
  return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, null]) : void 0;
@@ -31483,12 +31483,12 @@ function _length(length, params) {
31483
31483
  length
31484
31484
  });
31485
31485
  }
31486
- function _regex(pattern, params) {
31486
+ function _regex(pattern2, params) {
31487
31487
  return new $ZodCheckRegex({
31488
31488
  check: "string_format",
31489
31489
  format: "regex",
31490
31490
  ...normalizeParams(params),
31491
- pattern
31491
+ pattern: pattern2
31492
31492
  });
31493
31493
  }
31494
31494
  function _lowercase(params) {
@@ -31997,11 +31997,11 @@ var JSONSchemaGenerator = class {
31997
31997
  }
31998
31998
  case "template_literal": {
31999
31999
  const json2 = _json;
32000
- const pattern = schema._zod.pattern;
32001
- if (!pattern)
32000
+ const pattern2 = schema._zod.pattern;
32001
+ if (!pattern2)
32002
32002
  throw new Error("Pattern not found in template literal");
32003
32003
  json2.type = "string";
32004
- json2.pattern = pattern.source;
32004
+ json2.pattern = pattern2.source;
32005
32005
  break;
32006
32006
  }
32007
32007
  case "pipe": {
@@ -35368,13 +35368,13 @@ function stringifyRegExpWithFlags(regex, refs) {
35368
35368
  // `.` matches newlines
35369
35369
  };
35370
35370
  const source = flags.i ? regex.source.toLowerCase() : regex.source;
35371
- let pattern = "";
35371
+ let pattern2 = "";
35372
35372
  let isEscaped = false;
35373
35373
  let inCharGroup = false;
35374
35374
  let inCharRange = false;
35375
35375
  for (let i = 0; i < source.length; i++) {
35376
35376
  if (isEscaped) {
35377
- pattern += source[i];
35377
+ pattern2 += source[i];
35378
35378
  isEscaped = false;
35379
35379
  continue;
35380
35380
  }
@@ -35382,40 +35382,40 @@ function stringifyRegExpWithFlags(regex, refs) {
35382
35382
  if (inCharGroup) {
35383
35383
  if (source[i].match(/[a-z]/)) {
35384
35384
  if (inCharRange) {
35385
- pattern += source[i];
35386
- pattern += `${source[i - 2]}-${source[i]}`.toUpperCase();
35385
+ pattern2 += source[i];
35386
+ pattern2 += `${source[i - 2]}-${source[i]}`.toUpperCase();
35387
35387
  inCharRange = false;
35388
35388
  } else if (source[i + 1] === "-" && source[i + 2]?.match(/[a-z]/)) {
35389
- pattern += source[i];
35389
+ pattern2 += source[i];
35390
35390
  inCharRange = true;
35391
35391
  } else {
35392
- pattern += `${source[i]}${source[i].toUpperCase()}`;
35392
+ pattern2 += `${source[i]}${source[i].toUpperCase()}`;
35393
35393
  }
35394
35394
  continue;
35395
35395
  }
35396
35396
  } else if (source[i].match(/[a-z]/)) {
35397
- pattern += `[${source[i]}${source[i].toUpperCase()}]`;
35397
+ pattern2 += `[${source[i]}${source[i].toUpperCase()}]`;
35398
35398
  continue;
35399
35399
  }
35400
35400
  }
35401
35401
  if (flags.m) {
35402
35402
  if (source[i] === "^") {
35403
- pattern += `(^|(?<=[\r
35403
+ pattern2 += `(^|(?<=[\r
35404
35404
  ]))`;
35405
35405
  continue;
35406
35406
  } else if (source[i] === "$") {
35407
- pattern += `($|(?=[\r
35407
+ pattern2 += `($|(?=[\r
35408
35408
  ]))`;
35409
35409
  continue;
35410
35410
  }
35411
35411
  }
35412
35412
  if (flags.s && source[i] === ".") {
35413
- pattern += inCharGroup ? `${source[i]}\r
35413
+ pattern2 += inCharGroup ? `${source[i]}\r
35414
35414
  ` : `[${source[i]}\r
35415
35415
  ]`;
35416
35416
  continue;
35417
35417
  }
35418
- pattern += source[i];
35418
+ pattern2 += source[i];
35419
35419
  if (source[i] === "\\") {
35420
35420
  isEscaped = true;
35421
35421
  } else if (inCharGroup && source[i] === "]") {
@@ -35425,12 +35425,12 @@ function stringifyRegExpWithFlags(regex, refs) {
35425
35425
  }
35426
35426
  }
35427
35427
  try {
35428
- new RegExp(pattern);
35428
+ new RegExp(pattern2);
35429
35429
  } catch {
35430
35430
  console.warn(`Could not convert regex pattern at ${refs.currentPath.join("/")} to a flag-independent form! Falling back to the flag-ignorant source`);
35431
35431
  return regex.source;
35432
35432
  }
35433
- return pattern;
35433
+ return pattern2;
35434
35434
  }
35435
35435
 
35436
35436
  // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/record.js
@@ -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((resolve7) => setTimeout(resolve7, pollInterval));
36611
+ await new Promise((resolve8) => setTimeout(resolve8, 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((resolve7, reject) => {
36628
+ return new Promise((resolve8, 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
- resolve7(parseResult.data);
36706
+ resolve8(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((resolve7, reject) => {
36967
+ return new Promise((resolve8, reject) => {
36968
36968
  if (signal.aborted) {
36969
36969
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
36970
36970
  return;
36971
36971
  }
36972
- const timeoutId = setTimeout(resolve7, interval);
36972
+ const timeoutId = setTimeout(resolve8, interval);
36973
36973
  signal.addEventListener("abort", () => {
36974
36974
  clearTimeout(timeoutId);
36975
36975
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -37927,46 +37927,46 @@ var UriTemplate = class _UriTemplate {
37927
37927
  }
37928
37928
  return patterns;
37929
37929
  }
37930
- let pattern;
37930
+ let pattern2;
37931
37931
  const name = part.name;
37932
37932
  switch (part.operator) {
37933
37933
  case "":
37934
- pattern = part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)";
37934
+ pattern2 = part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)";
37935
37935
  break;
37936
37936
  case "+":
37937
37937
  case "#":
37938
- pattern = "(.+)";
37938
+ pattern2 = "(.+)";
37939
37939
  break;
37940
37940
  case ".":
37941
- pattern = "\\.([^/,]+)";
37941
+ pattern2 = "\\.([^/,]+)";
37942
37942
  break;
37943
37943
  case "/":
37944
- pattern = "/" + (part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)");
37944
+ pattern2 = "/" + (part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)");
37945
37945
  break;
37946
37946
  default:
37947
- pattern = "([^/]+)";
37947
+ pattern2 = "([^/]+)";
37948
37948
  }
37949
- patterns.push({ pattern, name });
37949
+ patterns.push({ pattern: pattern2, name });
37950
37950
  return patterns;
37951
37951
  }
37952
37952
  match(uri) {
37953
37953
  _UriTemplate.validateLength(uri, MAX_TEMPLATE_LENGTH, "URI");
37954
- let pattern = "^";
37954
+ let pattern2 = "^";
37955
37955
  const names = [];
37956
37956
  for (const part of this.parts) {
37957
37957
  if (typeof part === "string") {
37958
- pattern += this.escapeRegExp(part);
37958
+ pattern2 += this.escapeRegExp(part);
37959
37959
  } else {
37960
37960
  const patterns = this.partToRegExp(part);
37961
37961
  for (const { pattern: partPattern, name } of patterns) {
37962
- pattern += partPattern;
37962
+ pattern2 += partPattern;
37963
37963
  names.push({ name, exploded: part.exploded });
37964
37964
  }
37965
37965
  }
37966
37966
  }
37967
- pattern += "$";
37968
- _UriTemplate.validateLength(pattern, MAX_REGEX_LENGTH, "Generated regex pattern");
37969
- const regex = new RegExp(pattern);
37967
+ pattern2 += "$";
37968
+ _UriTemplate.validateLength(pattern2, MAX_REGEX_LENGTH, "Generated regex pattern");
37969
+ const regex = new RegExp(pattern2);
37970
37970
  const match = uri.match(regex);
37971
37971
  if (!match)
37972
37972
  return null;
@@ -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((resolve7) => setTimeout(resolve7, pollInterval));
38285
+ await new Promise((resolve8) => setTimeout(resolve8, 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((resolve7) => {
38973
+ return new Promise((resolve8) => {
38974
38974
  const json2 = serializeMessage(message);
38975
38975
  if (this._stdout.write(json2)) {
38976
- resolve7();
38976
+ resolve8();
38977
38977
  } else {
38978
- this._stdout.once("drain", resolve7);
38978
+ this._stdout.once("drain", resolve8);
38979
38979
  }
38980
38980
  });
38981
38981
  }
@@ -39077,7 +39077,7 @@ var RETRYABLE_ERROR_PATTERNS = [
39077
39077
  /changed during listing/i
39078
39078
  ];
39079
39079
  function isRetryableError(errorMessage) {
39080
- return RETRYABLE_ERROR_PATTERNS.some((pattern) => pattern.test(errorMessage));
39080
+ return RETRYABLE_ERROR_PATTERNS.some((pattern2) => pattern2.test(errorMessage));
39081
39081
  }
39082
39082
  function sleep(ms) {
39083
39083
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
@@ -39161,8 +39161,8 @@ function parseErrorMessage(errorOutput) {
39161
39161
  if (isPermissionDenied(errorOutput)) {
39162
39162
  return PERMISSION_DENIED_MESSAGE;
39163
39163
  }
39164
- for (const { pattern, message } of ERROR_MAPPINGS) {
39165
- const match = coreError.match(pattern);
39164
+ for (const { pattern: pattern2, message } of ERROR_MAPPINGS) {
39165
+ const match = coreError.match(pattern2);
39166
39166
  if (match) {
39167
39167
  let result = message;
39168
39168
  for (let i = 1; i < match.length; i++) {
@@ -41540,10 +41540,10 @@ function previewFileInBundle(bundle, accountDir) {
41540
41540
  const direct = [];
41541
41541
  const nested = [];
41542
41542
  for (const entry of boundedEntries(bundle, MAX_BUNDLE_ENTRIES) ?? []) {
41543
- const child = realInside(join7(bundle, entry), accountDir);
41544
- if (!child) continue;
41545
- if (isRegularFile(child)) direct.push(child);
41546
- else if (isDirectory(child)) nested.push(child);
41543
+ const child2 = realInside(join7(bundle, entry), accountDir);
41544
+ if (!child2) continue;
41545
+ if (isRegularFile(child2)) direct.push(child2);
41546
+ else if (isDirectory(child2)) nested.push(child2);
41547
41547
  }
41548
41548
  nested.sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41549
41549
  const pick2 = (files) => files.find((f) => basename(f) === "Preview.png") ?? files.find((f) => PREVIEW_IMAGE_SUFFIXES.has(extname(f).toLowerCase())) ?? null;
@@ -41648,8 +41648,8 @@ function assembleAttachmentAssets(rows, bodyOrder, containerDir = NOTES_CONTAINE
41648
41648
  const attachments = [];
41649
41649
  for (const root of orderedRoots) {
41650
41650
  attachments.push(record2(root, null));
41651
- for (const child of rows.filter((r) => r.parentPk === root.pk && r !== root)) {
41652
- attachments.push(record2(child, root));
41651
+ for (const child2 of rows.filter((r) => r.parentPk === root.pk && r !== root)) {
41652
+ attachments.push(record2(child2, root));
41653
41653
  }
41654
41654
  }
41655
41655
  return { orderSource, attachments };
@@ -42644,8 +42644,8 @@ function getNoteLinkFromDB(coreDataId3) {
42644
42644
  }
42645
42645
  }
42646
42646
  function extractCoreDataId(output, prefix) {
42647
- const pattern = new RegExp(`${prefix} id ([^\\s]+)`);
42648
- const match = output.match(pattern);
42647
+ const pattern2 = new RegExp(`${prefix} id ([^\\s]+)`);
42648
+ const match = output.match(pattern2);
42649
42649
  return match ? match[1] : "";
42650
42650
  }
42651
42651
  var AppleNotesManager = class {
@@ -46643,9 +46643,9 @@ var NO_FDA_MESSAGE = `Resolving a Notes UUID or numeric key reads the Notes data
46643
46643
  function canonicalKey(value) {
46644
46644
  return BigInt(value).toString();
46645
46645
  }
46646
- function assertAll(values, pattern, label) {
46646
+ function assertAll(values, pattern2, label) {
46647
46647
  for (const value of values) {
46648
- if (!pattern.test(value)) throw new Error(`Refusing to query with an invalid ${label}`);
46648
+ if (!pattern2.test(value)) throw new Error(`Refusing to query with an invalid ${label}`);
46649
46649
  }
46650
46650
  }
46651
46651
  function entityClause(entity3) {
@@ -46802,10 +46802,10 @@ function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH9) {
46802
46802
  }
46803
46803
  var defaultResolver = (values, entity3) => resolveIdentifiers(values, entity3);
46804
46804
  var DEFAULT_MAX_ID_LENGTH = 2e3;
46805
- function acceptAlternateForms(pattern) {
46805
+ function acceptAlternateForms(pattern2) {
46806
46806
  return new RegExp(
46807
- `${pattern.source}|${UUID_PATTERN.source}|${NUMERIC_KEY_PATTERN.source}`,
46808
- pattern.flags
46807
+ `${pattern2.source}|${UUID_PATTERN.source}|${NUMERIC_KEY_PATTERN.source}`,
46808
+ pattern2.flags
46809
46809
  );
46810
46810
  }
46811
46811
  function resolveInSchema(values, entity3, ctx, resolver) {
@@ -46820,16 +46820,16 @@ function resolveInSchema(values, entity3, ctx, resolver) {
46820
46820
  return null;
46821
46821
  }
46822
46822
  }
46823
- function exactIdInput(entity3, pattern, message, options = {}) {
46823
+ function exactIdInput(entity3, pattern2, message, options = {}) {
46824
46824
  const resolver = options.resolver ?? defaultResolver;
46825
- return external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message).transform((value, ctx) => {
46825
+ return external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern2), message).transform((value, ctx) => {
46826
46826
  const map = resolveInSchema([value], entity3, ctx, resolver);
46827
46827
  return map ? map.get(value) ?? value : external_exports.NEVER;
46828
46828
  });
46829
46829
  }
46830
- function exactIdArrayInput(entity3, pattern, message, options = {}) {
46830
+ function exactIdArrayInput(entity3, pattern2, message, options = {}) {
46831
46831
  const resolver = options.resolver ?? defaultResolver;
46832
- const item = external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message);
46832
+ const item = external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern2), message);
46833
46833
  const array2 = options.maxItems === void 0 ? external_exports.array(item) : external_exports.array(item).max(options.maxItems);
46834
46834
  return array2.transform((values, ctx) => {
46835
46835
  const map = resolveInSchema(values, entity3, ctx, resolver);
@@ -46933,13 +46933,6 @@ function describeSearchScope(searchContent, resultCount) {
46933
46933
  return "\n\n\u2139\uFE0F Only note titles were searched, so a term that appears in note bodies would not match. Retry with `searchContent: true` to search bodies instead.";
46934
46934
  }
46935
46935
 
46936
- // src/utils/noteQueryStore.ts
46937
- import { execFileSync as execFileSync14 } from "child_process";
46938
- import * as fs8 from "fs";
46939
- import * as os8 from "os";
46940
- import * as path8 from "path";
46941
- import { gunzipSync as gunzipSync8 } from "zlib";
46942
-
46943
46936
  // src/utils/noteQuery.ts
46944
46937
  var QUERY_LIMITS = {
46945
46938
  /** Maximum number of tokens (terms, operators, parentheses). */
@@ -47043,12 +47036,12 @@ function tokenize(input) {
47043
47036
  const field = prefix.toLowerCase();
47044
47037
  let value = word.slice(colon + 1);
47045
47038
  if (FIELDS.has(field)) {
47046
- let quoted = false;
47039
+ let quoted2 = false;
47047
47040
  if (value === "" && input[j] === '"') {
47048
47041
  [value, j] = readQuoted(input, j);
47049
- quoted = true;
47042
+ quoted2 = true;
47050
47043
  }
47051
- push({ kind: "term", pos: i, field, value, quoted });
47044
+ push({ kind: "term", pos: i, field, value, quoted: quoted2 });
47052
47045
  i = j;
47053
47046
  continue;
47054
47047
  }
@@ -47087,11 +47080,11 @@ function parseLocalDate(text2, pos) {
47087
47080
  return { start: start.getTime(), end: new Date(year, month - 1, day + 1).getTime() };
47088
47081
  }
47089
47082
  function termNode(token) {
47090
- const { field, value, quoted, pos } = token;
47083
+ const { field, value, quoted: quoted2, pos } = token;
47091
47084
  if (field === void 0) {
47092
47085
  if (value === "") throw new NoteQueryError("Empty quoted phrase", pos);
47093
47086
  const lower2 = value.toLowerCase();
47094
- if (!quoted && FLAGS.includes(lower2)) {
47087
+ if (!quoted2 && FLAGS.includes(lower2)) {
47095
47088
  return { type: "flag", flag: lower2 };
47096
47089
  }
47097
47090
  return { type: "text", field: "any", value };
@@ -47210,9 +47203,9 @@ var Parser = class {
47210
47203
  if (token?.kind === "not") {
47211
47204
  this.index++;
47212
47205
  this.enter(token.pos);
47213
- const child = this.parseUnary();
47206
+ const child2 = this.parseUnary();
47214
47207
  this.depth--;
47215
- return { type: "not", child };
47208
+ return { type: "not", child: child2 };
47216
47209
  }
47217
47210
  return this.parsePrimary();
47218
47211
  }
@@ -47333,9 +47326,9 @@ function cheapFirst(children) {
47333
47326
  function evaluateNoteQuery(node, note) {
47334
47327
  switch (node.type) {
47335
47328
  case "and":
47336
- return cheapFirst(node.children).every((child) => evaluateNoteQuery(child, note));
47329
+ return cheapFirst(node.children).every((child2) => evaluateNoteQuery(child2, note));
47337
47330
  case "or":
47338
- return cheapFirst(node.children).some((child) => evaluateNoteQuery(child, note));
47331
+ return cheapFirst(node.children).some((child2) => evaluateNoteQuery(child2, note));
47339
47332
  case "not":
47340
47333
  return !evaluateNoteQuery(node.child, note);
47341
47334
  case "text": {
@@ -47371,21 +47364,50 @@ function evaluateNoteQuery(node, note) {
47371
47364
  }
47372
47365
  }
47373
47366
  }
47374
- function positiveTextTerms(node, negated = false) {
47367
+ function positiveTextPredicates(node, negated = false) {
47375
47368
  switch (node.type) {
47376
47369
  case "and":
47377
47370
  case "or":
47378
- return node.children.flatMap((child) => positiveTextTerms(child, negated));
47371
+ return node.children.flatMap((child2) => positiveTextPredicates(child2, negated));
47379
47372
  case "not":
47380
- return positiveTextTerms(node.child, !negated);
47373
+ return positiveTextPredicates(node.child, !negated);
47381
47374
  case "text":
47382
- return negated ? [] : [node.value];
47375
+ return negated ? [] : [{ field: node.field, value: node.value }];
47383
47376
  default:
47384
47377
  return [];
47385
47378
  }
47386
47379
  }
47380
+ function positiveTextTerms(node, negated = false) {
47381
+ return positiveTextPredicates(node, negated).map((predicate) => predicate.value);
47382
+ }
47383
+ function matchLocations(predicates, title, text2) {
47384
+ if (predicates.length === 0) return void 0;
47385
+ if (text2 === null && predicates.some((p) => p.field !== "title")) return void 0;
47386
+ const firstBreak = text2 === null ? -1 : text2.indexOf("\n");
47387
+ const titleLower = normalizeForMatch(title);
47388
+ const firstLineLower = text2 === null ? "" : normalizeForMatch(firstBreak === -1 ? text2 : text2.slice(0, firstBreak));
47389
+ const bodyLower = text2 === null || firstBreak === -1 ? "" : normalizeForMatch(text2.slice(firstBreak + 1));
47390
+ let inTitle = false;
47391
+ let inBody = false;
47392
+ for (const predicate of predicates) {
47393
+ const needle = normalizeForMatch(predicate.value);
47394
+ if (predicate.field !== "body" && !inTitle) {
47395
+ inTitle = titleLower.includes(needle) || firstLineLower.includes(needle);
47396
+ }
47397
+ if (predicate.field !== "title" && !inBody) inBody = bodyLower.includes(needle);
47398
+ }
47399
+ const locations = [];
47400
+ if (inTitle) locations.push("title");
47401
+ if (inBody) locations.push("body");
47402
+ return locations;
47403
+ }
47387
47404
 
47388
47405
  // src/utils/noteQueryStore.ts
47406
+ import { execFileSync as execFileSync14 } from "child_process";
47407
+ import * as fs8 from "fs";
47408
+ import * as os8 from "os";
47409
+ import * as path8 from "path";
47410
+ import { gunzipSync as gunzipSync8 } from "zlib";
47389
47411
  var NOTES_DB_PATH10 = path8.join(
47390
47412
  os8.homedir(),
47391
47413
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
@@ -47467,6 +47489,15 @@ function decodeNoteBody(data) {
47467
47489
  objectIds
47468
47490
  };
47469
47491
  }
47492
+ function decodeBodyHex(hex3) {
47493
+ try {
47494
+ return decodeNoteBody(
47495
+ new Uint8Array(gunzipSync8(Buffer.from(hex3, "hex"), { maxOutputLength: 32 * 1024 * 1024 }))
47496
+ );
47497
+ } catch {
47498
+ return null;
47499
+ }
47500
+ }
47470
47501
  function countWords(text2) {
47471
47502
  let count = 0;
47472
47503
  for (const word of text2.replace(/\ufffc/gu, " ").split(/\s+/u)) {
@@ -47537,17 +47568,78 @@ function presentColumns2(dbPath2) {
47537
47568
  }
47538
47569
  return cols;
47539
47570
  }
47571
+ function readStore(dbPath2, build) {
47572
+ if (!fs8.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
47573
+ try {
47574
+ return runSqlite6(dbPath2, build(presentColumns2(dbPath2)));
47575
+ } catch (error2) {
47576
+ if (error2 instanceof NoteQueryStoreError) throw error2;
47577
+ const message = error2 instanceof Error ? error2.message : String(error2);
47578
+ if (message.includes("authorization denied") || message.includes("unable to open database")) {
47579
+ throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
47580
+ }
47581
+ console.error(`query-notes: database read failed: ${message}`);
47582
+ throw new NoteQueryStoreError("Failed to read the Notes database.", "query_error");
47583
+ }
47584
+ }
47585
+ var NOTE_TEXT_BATCH_MAX = QUERY_RESULTS.MAX;
47586
+ function buildNoteTextsSql(available, pks) {
47587
+ const missing = ["Z_PK", "Z_ENT"].filter((c) => !available.has(c));
47588
+ if (missing.length) {
47589
+ throw new NoteQueryStoreError(
47590
+ `This macOS version's Notes database lacks columns search enrichment needs (${missing.join(", ")}).`,
47591
+ "schema"
47592
+ );
47593
+ }
47594
+ const keys = [...new Set(pks)];
47595
+ if (keys.length > NOTE_TEXT_BATCH_MAX) {
47596
+ throw new NoteQueryStoreError(
47597
+ `At most ${NOTE_TEXT_BATCH_MAX} notes can be read at once.`,
47598
+ "query_error"
47599
+ );
47600
+ }
47601
+ for (const pk of keys) {
47602
+ if (!Number.isSafeInteger(pk) || pk < 1) {
47603
+ throw new NoteQueryStoreError(`Invalid note key ${String(pk)}`, "query_error");
47604
+ }
47605
+ }
47606
+ const locked = available.has("ZISPASSWORDPROTECTED") ? "COALESCE(n.ZISPASSWORDPROTECTED, 0)" : "0";
47607
+ return [
47608
+ "BEGIN;",
47609
+ "SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
47610
+ `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'locked', ${locked}, 'data', (SELECT hex(d.ZDATA) FROM ZICNOTEDATA d WHERE d.ZNOTE = n.Z_PK ORDER BY d.Z_PK DESC LIMIT 1)) FROM ZICCLOUDSYNCINGOBJECT n WHERE n.Z_ENT = ${entity2("ICNote")} AND n.Z_PK IN (${keys.length ? keys.join(", ") : "NULL"});`,
47611
+ "COMMIT;"
47612
+ ].join(" ");
47613
+ }
47614
+ function readNoteTexts(pks, options = {}) {
47615
+ const output = readStore(
47616
+ options.dbPath ?? NOTES_DB_PATH10,
47617
+ (available) => buildNoteTextsSql(available, pks)
47618
+ );
47619
+ let uuid2;
47620
+ const texts = /* @__PURE__ */ new Map();
47621
+ for (const line of output.split("\n")) {
47622
+ if (!line.trim()) continue;
47623
+ const row = JSON.parse(line);
47624
+ if (row.k === "meta") uuid2 = typeof row.uuid === "string" ? row.uuid : void 0;
47625
+ else if (row.k === "note" && typeof row.pk === "number") {
47626
+ const body = row.locked || !row.data ? null : decodeBodyHex(row.data);
47627
+ texts.set(row.pk, body ? body.text : null);
47628
+ }
47629
+ }
47630
+ return { uuid: uuid2, texts };
47631
+ }
47540
47632
  var escapeSegment = escapeFolderName;
47541
47633
  function resolveFolders(rows) {
47542
47634
  const byPk = new Map(rows.map((row) => [row.pk, row]));
47543
47635
  const resolved = /* @__PURE__ */ new Map();
47544
- const resolve7 = (pk, seen) => {
47636
+ const resolve8 = (pk, seen) => {
47545
47637
  const cached2 = resolved.get(pk);
47546
47638
  if (cached2) return cached2;
47547
47639
  const row = byPk.get(pk);
47548
47640
  if (!row || seen.has(pk)) return void 0;
47549
47641
  seen.add(pk);
47550
- const parent = row.parent !== null ? resolve7(row.parent, seen) : void 0;
47642
+ const parent = row.parent !== null ? resolve8(row.parent, seen) : void 0;
47551
47643
  const name = row.name ?? "";
47552
47644
  const path10 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
47553
47645
  const plainPath = parent ? `${parent.plainPath}/${name}` : name;
@@ -47561,7 +47653,7 @@ function resolveFolders(rows) {
47561
47653
  resolved.set(pk, info);
47562
47654
  return info;
47563
47655
  };
47564
- for (const row of rows) resolve7(row.pk, /* @__PURE__ */ new Set());
47656
+ for (const row of rows) resolve8(row.pk, /* @__PURE__ */ new Set());
47565
47657
  return resolved;
47566
47658
  }
47567
47659
  var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS2 + seconds * 1e3;
@@ -47593,23 +47685,10 @@ function runNoteQuery(ast, options = {}) {
47593
47685
  const withBodies = needsContent(ast);
47594
47686
  const withTags = needsTags(ast);
47595
47687
  const dbPath2 = options.dbPath ?? NOTES_DB_PATH10;
47596
- if (!fs8.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
47597
- let output;
47598
- try {
47599
- const available = presentColumns2(dbPath2);
47600
- output = runSqlite6(
47601
- dbPath2,
47602
- buildScanSql(available, { scanLimit, includeDeleted, withBodies, withTags })
47603
- );
47604
- } catch (error2) {
47605
- if (error2 instanceof NoteQueryStoreError) throw error2;
47606
- const message = error2 instanceof Error ? error2.message : String(error2);
47607
- if (message.includes("authorization denied") || message.includes("unable to open database")) {
47608
- throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
47609
- }
47610
- console.error(`query-notes: database read failed: ${message}`);
47611
- throw new NoteQueryStoreError("Failed to read the Notes database.", "query_error");
47612
- }
47688
+ const output = readStore(
47689
+ dbPath2,
47690
+ (available) => buildScanSql(available, { scanLimit, includeDeleted, withBodies, withTags })
47691
+ );
47613
47692
  let uuid2;
47614
47693
  let eligible = 0;
47615
47694
  const folderRows = [];
@@ -47633,6 +47712,8 @@ function runNoteQuery(ast, options = {}) {
47633
47712
  }
47634
47713
  const folders = resolveFolders(folderRows);
47635
47714
  const textTerms = positiveTextTerms(ast);
47715
+ const textPredicates = positiveTextPredicates(ast);
47716
+ const pendingWordCounts = [];
47636
47717
  const hits = [];
47637
47718
  let matched = 0;
47638
47719
  let unreadable = 0;
@@ -47650,15 +47731,7 @@ function runNoteQuery(ast, options = {}) {
47650
47731
  if (withBodies) unreadable++;
47651
47732
  return decoded;
47652
47733
  }
47653
- try {
47654
- decoded = decodeNoteBody(
47655
- new Uint8Array(
47656
- gunzipSync8(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
47657
- )
47658
- );
47659
- } catch {
47660
- decoded = null;
47661
- }
47734
+ decoded = decodeBodyHex(row.data);
47662
47735
  if (!decoded) unreadable++;
47663
47736
  return decoded;
47664
47737
  };
@@ -47699,6 +47772,8 @@ function runNoteQuery(ast, options = {}) {
47699
47772
  matched++;
47700
47773
  if (hits.length >= limit) continue;
47701
47774
  const body = locked ? null : decode2();
47775
+ const matchedIn = matchLocations(textPredicates, row.title ?? "", body ? body.text : null);
47776
+ if (options.includeWordCount && !withBodies) pendingWordCounts.push(row.pk);
47702
47777
  hits.push({
47703
47778
  id: `x-coredata://${uuid2}/ICNote/p${row.pk}`,
47704
47779
  title: row.title ?? "",
@@ -47707,7 +47782,16 @@ function runNoteQuery(ast, options = {}) {
47707
47782
  ...note.modified !== void 0 ? { modified: new Date(note.modified).toISOString() } : {},
47708
47783
  ...note.created !== void 0 ? { created: new Date(note.created).toISOString() } : {},
47709
47784
  snippet: locked ? "" : body ? buildSnippet(body.text, textTerms) : (row.snippet ?? "").replace(/\s+/gu, " ").trim(),
47710
- ...locked ? { locked: true } : {}
47785
+ ...locked ? { locked: true } : {},
47786
+ ...matchedIn ? { matchedIn } : {},
47787
+ ...options.includeWordCount && withBodies ? { wordCount: body ? countWords(body.text) : null } : {}
47788
+ });
47789
+ }
47790
+ if (pendingWordCounts.length) {
47791
+ const { texts } = readNoteTexts(pendingWordCounts, { dbPath: dbPath2 });
47792
+ pendingWordCounts.forEach((pk, index) => {
47793
+ const text2 = texts.get(pk);
47794
+ hits[index].wordCount = typeof text2 === "string" ? countWords(text2) : null;
47711
47795
  });
47712
47796
  }
47713
47797
  return {
@@ -47750,6 +47834,7 @@ function searchContentViaDatabase(options) {
47750
47834
  const result = runNoteQuery(buildSearchContentQuery(options), {
47751
47835
  limit: options.limit,
47752
47836
  scanLimit: QUERY_SCAN.MAX,
47837
+ includeWordCount: options.includeWordCount,
47753
47838
  dbPath: options.dbPath
47754
47839
  });
47755
47840
  const notes = result.notes.map((hit) => ({
@@ -47760,7 +47845,9 @@ function searchContentViaDatabase(options) {
47760
47845
  created: hit.created ? new Date(hit.created) : /* @__PURE__ */ new Date(0),
47761
47846
  modified: hit.modified ? new Date(hit.modified) : /* @__PURE__ */ new Date(0),
47762
47847
  ...hit.folder !== void 0 ? { folder: hit.folder } : {},
47763
- ...hit.account !== void 0 ? { account: hit.account } : {}
47848
+ ...hit.account !== void 0 ? { account: hit.account } : {},
47849
+ ...hit.matchedIn ? { matchedIn: hit.matchedIn } : {},
47850
+ ...hit.wordCount !== void 0 ? { wordCount: hit.wordCount } : {}
47764
47851
  }));
47765
47852
  return {
47766
47853
  notes,
@@ -47783,6 +47870,55 @@ function contentSearchFailureHint(message, dbUnavailable) {
47783
47870
  const remedy = dbUnavailable === "no_fda" ? " Grant Full Disk Access to the Node binary running this server (run the doctor tool for its path) so search-notes can search note bodies through the Notes database instead, which takes well under a second." : "";
47784
47871
  return `${message} Body search through AppleScript scans every note body before the result limit applies, so a broad term can exceed the time budget on a large library.${remedy} Otherwise narrow the search with \`folder\` or \`modifiedSince\`, or use a more specific term.`;
47785
47872
  }
47873
+ var NOTE_ID = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/ICNote\/p(\d{1,15})$/;
47874
+ function addWordCountsFromDatabase(notes, query2, options = {}) {
47875
+ const keys = /* @__PURE__ */ new Map();
47876
+ for (const note of notes) {
47877
+ const match = NOTE_ID.exec(note.id ?? "");
47878
+ if (match) keys.set(note, { store: match[1].toUpperCase(), pk: Number(match[2]) });
47879
+ }
47880
+ const pks = [...new Set([...keys.values()].map((key) => key.pk))];
47881
+ let store;
47882
+ const texts = /* @__PURE__ */ new Map();
47883
+ try {
47884
+ for (let start = 0; start < pks.length; start += NOTE_TEXT_BATCH_MAX) {
47885
+ const read = readNoteTexts(pks.slice(start, start + NOTE_TEXT_BATCH_MAX), options);
47886
+ store = read.uuid?.toUpperCase();
47887
+ for (const [pk, text2] of read.texts) texts.set(pk, text2);
47888
+ }
47889
+ } catch (error2) {
47890
+ if (error2 instanceof NoteQueryStoreError) return { notes, unavailable: error2.kind };
47891
+ throw error2;
47892
+ }
47893
+ const predicates = [{ field: "any", value: query2 }];
47894
+ return {
47895
+ notes: notes.map((note) => {
47896
+ const key = keys.get(note);
47897
+ const text2 = key && key.store === store ? texts.get(key.pk) : void 0;
47898
+ if (typeof text2 !== "string") return { ...note, wordCount: null };
47899
+ const matchedIn = matchLocations(predicates, note.title, text2);
47900
+ return {
47901
+ ...note,
47902
+ ...matchedIn?.length ? { matchedIn } : {},
47903
+ wordCount: countWords(text2)
47904
+ };
47905
+ })
47906
+ };
47907
+ }
47908
+ function describeMatchDetails(hit) {
47909
+ const parts = [];
47910
+ if (hit.matchedIn) {
47911
+ parts.push(
47912
+ hit.matchedIn.length ? `matched in ${hit.matchedIn.join(", ")}` : "no text match (metadata)"
47913
+ );
47914
+ }
47915
+ if (hit.wordCount !== void 0) {
47916
+ parts.push(
47917
+ hit.wordCount === null ? "word count unavailable" : `${hit.wordCount} word${hit.wordCount === 1 ? "" : "s"}`
47918
+ );
47919
+ }
47920
+ return parts.map((part) => ` \xB7 ${part}`).join("");
47921
+ }
47786
47922
 
47787
47923
  // src/tools/doctor.ts
47788
47924
  import { spawnSync } from "child_process";
@@ -48232,8 +48368,8 @@ function validateAppendContent(content, format, options = {}) {
48232
48368
  if (/!\[|<\/?[a-z]|\]\(\s*(?:javascript|data|file):/i.test(checked))
48233
48369
  throw new Error("Markdown images, raw HTML and local/executable links are unsupported");
48234
48370
  const withoutLinkDestinations = checked.replace(/(\[[^\]\n]+\])\([^()\s]+\)/g, "$1()");
48235
- for (const [pattern, name] of UNMODELED_MARKDOWN)
48236
- if (pattern.test(name === UNDERSCORES_OUTSIDE_A_WORD ? withoutLinkDestinations : checked))
48371
+ for (const [pattern2, name] of UNMODELED_MARKDOWN)
48372
+ if (pattern2.test(name === UNDERSCORES_OUTSIDE_A_WORD ? withoutLinkDestinations : checked))
48237
48373
  throw new Error(
48238
48374
  `Markdown cannot use ${name}; Notes would change that text, so the result could not be verified`
48239
48375
  );
@@ -49333,7 +49469,7 @@ function selectParagraph(paragraphs, selector) {
49333
49469
  );
49334
49470
  return matches[occurrence - 1];
49335
49471
  }
49336
- var NOTE_ID = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,15})$/i;
49472
+ var NOTE_ID2 = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,15})$/i;
49337
49473
  function titleMatchSql(columns) {
49338
49474
  return `SELECT json_object('pk', n.Z_PK, 'folder', n.ZFOLDER) FROM ZICCLOUDSYNCINGOBJECT n LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = n.ZFOLDER WHERE n.Z_ENT = ${entity("ICNote")} AND n.ZTITLE1 = CAST(@title AS TEXT) AND ${activeNoteSql(columns, "n", "f")} ORDER BY n.Z_PK;`;
49339
49475
  }
@@ -49344,7 +49480,7 @@ function checkNoteSelector(selector) {
49344
49480
  if (selector.folder !== void 0 && selector.title === void 0)
49345
49481
  throw new ParagraphLinkError("invalid-argument", "folder only narrows a title lookup");
49346
49482
  if (selector.id === void 0) return void 0;
49347
- const pk = NOTE_ID.exec(selector.id)?.[1];
49483
+ const pk = NOTE_ID2.exec(selector.id)?.[1];
49348
49484
  if (!pk)
49349
49485
  throw new ParagraphLinkError(
49350
49486
  "invalid-argument",
@@ -49759,8 +49895,8 @@ function describeBodyReadFailure(title, error2, attachments) {
49759
49895
  const kind = classifyBodyReadError(error2);
49760
49896
  if (kind === "other") return base;
49761
49897
  const large = attachments ? largeAttachments(attachments) : [];
49762
- const listed = large.map((a) => `${a.name}, ${formatBytes2(a.bytes)}`).join("; ");
49763
- const holds = large.length > 0 ? `The note holds ${large.length === 1 ? "a large attachment" : "large attachments"} (${listed}). ` : "";
49898
+ const listed2 = large.map((a) => `${a.name}, ${formatBytes2(a.bytes)}`).join("; ");
49899
+ const holds = large.length > 0 ? `The note holds ${large.length === 1 ? "a large attachment" : "large attachments"} (${listed2}). ` : "";
49764
49900
  if (kind === "buffer") {
49765
49901
  const cause2 = `${holds}Notes.app returns images inside the note body as base64, so a large image makes the body bigger than this server can read in one call.`;
49766
49902
  const remedy2 = "Retrying, or a longer timeoutSeconds, will not help. Remove or shrink the attachment in Notes.app, or delete the note there; delete-note needs a successful read to verify the note first.";
@@ -50097,8 +50233,8 @@ function insertLink(request, deps) {
50097
50233
  }
50098
50234
 
50099
50235
  // src/services/notesExport.ts
50100
- import { mkdirSync as mkdirSync5 } from "node:fs";
50101
- import { basename as basename4, dirname as dirname6, extname as extname4, join as join21 } from "node:path";
50236
+ import { mkdirSync as mkdirSync6 } from "node:fs";
50237
+ import { basename as basename4, dirname as dirname6, extname as extname5, join as join22 } from "node:path";
50102
50238
 
50103
50239
  // src/utils/exportAssets.ts
50104
50240
  import {
@@ -50288,8 +50424,8 @@ var AssetLocator = class {
50288
50424
  /** Preview.png (or another image) at most two levels inside a bundle. */
50289
50425
  bundleImage(bundle, account) {
50290
50426
  const found = [];
50291
- for (const child of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
50292
- const path10 = confine(join19(bundle, child), account);
50427
+ for (const child2 of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
50428
+ const path10 = confine(join19(bundle, child2), account);
50293
50429
  if (!path10) continue;
50294
50430
  if (isFile(path10)) found.push(path10);
50295
50431
  else
@@ -50624,7 +50760,7 @@ function planAttachment(attachment, ctx) {
50624
50760
  ctx.stats.attachments--;
50625
50761
  return {
50626
50762
  type: "gallery",
50627
- items: attachment.children.map((child) => planAttachment(child, ctx))
50763
+ items: attachment.children.map((child2) => planAttachment(child2, ctx))
50628
50764
  };
50629
50765
  }
50630
50766
  case "link": {
@@ -51196,9 +51332,9 @@ function wrapMarkdown(markdown, width) {
51196
51332
  }
51197
51333
  return out.join("\n");
51198
51334
  }
51199
- function renderNotesMarkdown(notes, ctx, { wrap: wrap2 = 0 } = {}) {
51335
+ function renderNotesMarkdown(notes, ctx, { wrap: wrap3 = 0 } = {}) {
51200
51336
  const body = notes.map((note) => renderNoteMarkdown(note, ctx)).join(NOTE_SEPARATOR);
51201
- return (wrap2 ? wrapMarkdown(body, wrap2) : body) + (notes.length ? "\n" : "");
51337
+ return (wrap3 ? wrapMarkdown(body, wrap3) : body) + (notes.length ? "\n" : "");
51202
51338
  }
51203
51339
 
51204
51340
  // src/utils/noteExportData.ts
@@ -51372,18 +51508,1290 @@ function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH11 } = {}) {
51372
51508
  ordered
51373
51509
  };
51374
51510
  }
51511
+ var CORE_DATA_EPOCH = 978307200;
51512
+ function coreDataDate(value) {
51513
+ const seconds = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : NaN;
51514
+ if (!Number.isFinite(seconds) || Math.abs(seconds) > 1e10) return void 0;
51515
+ return new Date((seconds + CORE_DATA_EPOCH) * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
51516
+ }
51517
+ function noteMetaQuery(columns) {
51518
+ const first2 = (names) => {
51519
+ const present = names.filter((name) => columns.has(name)).map((name) => `n.${name}`);
51520
+ if (!present.length) return "NULL";
51521
+ return present.length === 1 ? present[0] : `COALESCE(${present.join(", ")})`;
51522
+ };
51523
+ const accountColumns = [...columns].filter((name) => /^ZACCOUNT\d*$/.test(name)).sort((a, b) => Number(b.slice(8) || 0) - Number(a.slice(8) || 0));
51524
+ const folder = columns.has("ZFOLDER") && columns.has("ZTITLE2") ? "(SELECT f.ZTITLE2 FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_PK = n.ZFOLDER)" : "NULL";
51525
+ const account = columns.has("ZNAME") && accountColumns.length ? `(SELECT a.ZNAME FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_PK = ${first2(accountColumns)})` : "NULL";
51526
+ return `SELECT json_object('uuid', ${first2(["ZIDENTIFIER"])}, 'created', ${first2(["ZCREATIONDATE3", "ZCREATIONDATE1", "ZCREATIONDATE"])}, 'modified', ${first2(["ZMODIFICATIONDATE1", "ZMODIFICATIONDATE"])}, 'folder', ${folder}, 'account', ${account}) FROM ZICCLOUDSYNCINGOBJECT n WHERE n.Z_PK = @pk;`;
51527
+ }
51528
+ function readExportNoteMeta(id2, { dbPath: dbPath2 = NOTES_DB_PATH11 } = {}) {
51529
+ const match = /\/ICNote\/p([0-9]{1,18})$/.exec(id2);
51530
+ if (!match) throw new NoteBlocksError("invalid-id", "Not a note id");
51531
+ const output = sqlite(dbPath2, [
51532
+ "-cmd",
51533
+ ".parameter init",
51534
+ "-cmd",
51535
+ `.parameter set @pk ${match[1]}`,
51536
+ noteMetaQuery(objectColumns(dbPath2))
51537
+ ]);
51538
+ if (!output) return {};
51539
+ let row;
51540
+ try {
51541
+ row = JSON.parse(output);
51542
+ } catch {
51543
+ throw new NoteBlocksError("query-failed", "Unexpected Notes database response");
51544
+ }
51545
+ const meta = {};
51546
+ const set = (key, value) => {
51547
+ if (value !== void 0) meta[key] = value;
51548
+ };
51549
+ set("uuid", text(row.uuid));
51550
+ set("created", coreDataDate(row.created));
51551
+ set("modified", coreDataDate(row.modified));
51552
+ set("folder", text(row.folder));
51553
+ set("account", text(row.account));
51554
+ return meta;
51555
+ }
51556
+
51557
+ // src/utils/markdownTemplate.ts
51558
+ var TEMPLATE_SCHEMA_VERSION = 1;
51559
+ var MAX_TEMPLATE_BYTES = 256 * 1024;
51560
+ var MAX_META_LENGTH = 512;
51561
+ var MAX_RULE_TEXT = 4096;
51562
+ var MAX_DIRECTORY_LENGTH = 1024;
51563
+ var RULE_IDS = [
51564
+ "document.header",
51565
+ "document.footer",
51566
+ "document.separator",
51567
+ "block.title",
51568
+ "block.heading",
51569
+ "block.subheading",
51570
+ "block.body",
51571
+ "block.bulleted",
51572
+ "block.dashed",
51573
+ "block.numbered",
51574
+ "block.checklist.checked",
51575
+ "block.checklist.unchecked",
51576
+ "block.code",
51577
+ "paragraph.quote",
51578
+ "inline.bold",
51579
+ "inline.italic",
51580
+ "inline.underline",
51581
+ "inline.strikethrough",
51582
+ "inline.superscript",
51583
+ "inline.subscript",
51584
+ "inline.highlight.purple",
51585
+ "inline.highlight.pink",
51586
+ "inline.highlight.orange",
51587
+ "inline.highlight.mint",
51588
+ "inline.highlight.blue",
51589
+ "inline.highlight.other",
51590
+ "inline.color",
51591
+ "inline.link",
51592
+ "attachment.image",
51593
+ "attachment.drawing.classic",
51594
+ "attachment.drawing.paper",
51595
+ "attachment.scan",
51596
+ "attachment.pdf",
51597
+ "attachment.audio",
51598
+ "attachment.video",
51599
+ "attachment.other",
51600
+ "attachment.table",
51601
+ "attachment.divider",
51602
+ "attachment.gallery",
51603
+ "attachment.url",
51604
+ "attachment.url.image",
51605
+ "attachment.map",
51606
+ "attachment.placeholder"
51607
+ ];
51608
+ var RULE_MODES = ["wrap", "linePrefix", "pattern", "plain", "omit"];
51609
+ var INLINE_FORMATS = [
51610
+ "subscript",
51611
+ "superscript",
51612
+ "highlight",
51613
+ "underline",
51614
+ "strikethrough",
51615
+ "bold",
51616
+ "italic",
51617
+ "color",
51618
+ "link"
51619
+ ];
51620
+ var PLACEHOLDERS = [
51621
+ "content",
51622
+ "title",
51623
+ "id",
51624
+ "uuid",
51625
+ "folder",
51626
+ "account",
51627
+ "created",
51628
+ "modified",
51629
+ "tags",
51630
+ "exportStem",
51631
+ "index",
51632
+ "checked",
51633
+ "url",
51634
+ "path",
51635
+ "alt",
51636
+ "caption",
51637
+ "linkText",
51638
+ "filename",
51639
+ "kind",
51640
+ "uti",
51641
+ "color",
51642
+ "highlight",
51643
+ "fence"
51644
+ ];
51645
+ var NOTE_PLACEHOLDERS = [
51646
+ "title",
51647
+ "id",
51648
+ "uuid",
51649
+ "folder",
51650
+ "account",
51651
+ "created",
51652
+ "modified",
51653
+ "exportStem"
51654
+ ];
51655
+ var PLACEHOLDER_MODIFIERS = ["raw", "yaml"];
51656
+ var wrap2 = (before, after = "", join29) => ({
51657
+ mode: "wrap",
51658
+ before,
51659
+ after,
51660
+ ...join29 ? { join: join29 } : {}
51661
+ });
51662
+ var pattern = (value, join29) => ({
51663
+ mode: "pattern",
51664
+ value,
51665
+ ...join29 ? { join: join29 } : {}
51666
+ });
51667
+ var STANDARD = {
51668
+ schemaVersion: 1,
51669
+ name: "standard-markdown",
51670
+ description: "The default export-notes-markdown output",
51671
+ assets: { mode: "copy", pathStyle: "relative", directory: null },
51672
+ inlineOrder: [...INLINE_FORMATS],
51673
+ options: {
51674
+ titleFallback: true,
51675
+ richLinkImages: false,
51676
+ richLinkImageCaption: "none",
51677
+ listIndent: " "
51678
+ },
51679
+ rules: {
51680
+ "document.header": pattern(""),
51681
+ "document.footer": pattern(""),
51682
+ "document.separator": pattern("\n\n---\n\n"),
51683
+ "block.title": wrap2("# ", "", "paragraph"),
51684
+ "block.heading": wrap2("## ", "", "paragraph"),
51685
+ "block.subheading": wrap2("### ", "", "paragraph"),
51686
+ "block.body": { mode: "plain", join: "paragraph" },
51687
+ "block.bulleted": wrap2("- ", "", "line"),
51688
+ "block.dashed": wrap2("- ", "", "line"),
51689
+ "block.numbered": pattern("{{index}}. {{content}}", "line"),
51690
+ "block.checklist.checked": wrap2("- [x] ", "", "line"),
51691
+ "block.checklist.unchecked": wrap2("- [ ] ", "", "line"),
51692
+ "block.code": wrap2("{{fence}}\n", "\n{{fence}}", "paragraph"),
51693
+ "paragraph.quote": { mode: "linePrefix", value: "> " },
51694
+ "inline.bold": wrap2("**", "**"),
51695
+ "inline.italic": wrap2("*", "*"),
51696
+ "inline.underline": wrap2("<u>", "</u>"),
51697
+ "inline.strikethrough": wrap2("~~", "~~"),
51698
+ "inline.superscript": wrap2("<sup>", "</sup>"),
51699
+ "inline.subscript": wrap2("<sub>", "</sub>"),
51700
+ "inline.highlight.purple": wrap2("==", "=="),
51701
+ "inline.highlight.pink": wrap2("==", "=="),
51702
+ "inline.highlight.orange": wrap2("==", "=="),
51703
+ "inline.highlight.mint": wrap2("==", "=="),
51704
+ "inline.highlight.blue": wrap2("==", "=="),
51705
+ "inline.highlight.other": wrap2("==", "=="),
51706
+ "inline.color": { mode: "plain" },
51707
+ "inline.link": pattern("[{{content}}]({{url}})"),
51708
+ "attachment.image": pattern("![{{alt}}]({{path}})"),
51709
+ "attachment.drawing.classic": pattern("![{{alt}}]({{path}})"),
51710
+ "attachment.drawing.paper": pattern("![{{alt}}]({{path}})"),
51711
+ "attachment.scan": pattern("[{{linkText}}]({{path}})"),
51712
+ "attachment.pdf": pattern("[{{linkText}}]({{path}})"),
51713
+ "attachment.audio": pattern("[{{linkText}}]({{path}})"),
51714
+ "attachment.video": pattern("[{{linkText}}]({{path}})"),
51715
+ "attachment.other": pattern("[{{linkText}}]({{path}})"),
51716
+ "attachment.table": { mode: "plain" },
51717
+ "attachment.divider": pattern("---"),
51718
+ "attachment.gallery": { mode: "plain", join: "paragraph" },
51719
+ "attachment.url": pattern("[{{alt}}]({{url}})"),
51720
+ "attachment.url.image": pattern("![{{alt}}]({{url}})"),
51721
+ "attachment.map": pattern("[{{alt}}]({{url}})"),
51722
+ "attachment.placeholder": pattern("\\[{{content}}\\]")
51723
+ }
51724
+ };
51725
+ var OBSIDIAN = {
51726
+ schemaVersion: 1,
51727
+ name: "obsidian",
51728
+ description: "Obsidian-style Markdown: YAML front matter (title, dates, folder, tags, id), image-URL link cards as images, attachments copied to <file>.assets",
51729
+ extends: "standard-markdown",
51730
+ assets: { directory: "{{exportStem}}.assets" },
51731
+ options: { richLinkImages: true, richLinkImageCaption: "followingItalicParagraph" },
51732
+ rules: {
51733
+ "document.header": pattern(
51734
+ "---\ntitle: {{title:yaml}}\ncreated: {{created:yaml}}\nmodified: {{modified:yaml}}\nfolder: {{folder:yaml}}\ntags: {{tags:yaml}}\nnote-id: {{uuid:yaml}}\n---\n\n"
51735
+ )
51736
+ }
51737
+ };
51738
+ var BUILTINS = { "standard-markdown": STANDARD, obsidian: OBSIDIAN };
51739
+ var BUILTIN_TEMPLATE_NAMES = Object.keys(BUILTINS);
51740
+ var isBuiltinTemplate = (name) => Object.prototype.hasOwnProperty.call(BUILTINS, name);
51741
+ function builtinTemplate(name) {
51742
+ return JSON.parse(JSON.stringify(BUILTINS[name]));
51743
+ }
51744
+ var TemplateValidationError = class extends Error {
51745
+ constructor(errors) {
51746
+ super(
51747
+ `Invalid template (${errors.length} problem${errors.length === 1 ? "" : "s"}): ` + errors.map((e) => `${e.path}: ${e.message}`).join("; ")
51748
+ );
51749
+ this.errors = errors;
51750
+ this.name = "TemplateValidationError";
51751
+ }
51752
+ errors;
51753
+ code = "invalid-template";
51754
+ };
51755
+ var MAX_QUOTED_TOKEN = 32;
51756
+ function child(path10, key) {
51757
+ if (typeof key === "number") return `${path10}[${key}]`;
51758
+ if (key.length > MAX_QUOTED_TOKEN) key = `${key.slice(0, MAX_QUOTED_TOKEN - 3)}...`;
51759
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? `${path10}.${key}` : `${path10}[${JSON.stringify(key)}]`;
51760
+ }
51761
+ var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
51762
+ var describe = (value) => value === null ? "null" : Array.isArray(value) ? "an array" : `a ${typeof value}`;
51763
+ var describeVersion = (value) => typeof value === "number" && Number.isFinite(value) ? String(value) : describe(value);
51764
+ var listed = (values) => values.map((v) => JSON.stringify(v)).join(", ");
51765
+ var quoted = (token) => token.length <= MAX_QUOTED_TOKEN ? token : `${token.slice(0, MAX_QUOTED_TOKEN - 3)}...}}`;
51766
+ var TOKEN = /\{\{([^{}]*)\}\}/g;
51767
+ var TOKEN_BODY = /^\s*([A-Za-z]+)(?::([A-Za-z]+))?\s*$/;
51768
+ var META_PLACEHOLDERS = ["uuid", "folder", "account", "created", "modified"];
51769
+ function usesNoteMeta(template) {
51770
+ const uses = (value) => typeof value === "string" ? placeholderTokens(value).some(({ name }) => META_PLACEHOLDERS.includes(name)) : typeof value === "object" && value !== null && Object.values(value).some(uses);
51771
+ return uses(template.rules) || uses(template.assets) || uses(template.options);
51772
+ }
51773
+ function placeholderTokens(text2) {
51774
+ return [...text2.matchAll(TOKEN)].map((match) => {
51775
+ const body = TOKEN_BODY.exec(match[1]);
51776
+ return {
51777
+ token: match[0],
51778
+ name: body?.[1] ?? match[1],
51779
+ ...body?.[2] ? { modifier: body[2] } : {}
51780
+ };
51781
+ });
51782
+ }
51783
+ var Collector = class {
51784
+ errors = [];
51785
+ add(path10, message) {
51786
+ this.errors.push({ path: path10, message });
51787
+ }
51788
+ /** Report unknown keys; returns the known keys present, sorted. */
51789
+ keys(value, path10, allowed) {
51790
+ const present = Object.keys(value).sort();
51791
+ for (const key of present)
51792
+ if (!allowed.includes(key))
51793
+ this.add(child(path10, key), `unknown key; allowed keys are ${listed(allowed)}`);
51794
+ return present.filter((key) => allowed.includes(key));
51795
+ }
51796
+ text(value, path10, { max, allowed = PLACEHOLDERS }) {
51797
+ if (typeof value !== "string") {
51798
+ this.add(path10, `must be a string, not ${describe(value)}`);
51799
+ return false;
51800
+ }
51801
+ if (value.length > max)
51802
+ this.add(path10, `must be at most ${max} characters (is ${value.length})`);
51803
+ for (const { token: raw, name, modifier } of placeholderTokens(value)) {
51804
+ const token = quoted(raw);
51805
+ if (!PLACEHOLDERS.includes(name))
51806
+ this.add(path10, `unknown placeholder ${token}; allowed: ${PLACEHOLDERS.join(", ")}`);
51807
+ else if (!allowed.includes(name))
51808
+ this.add(
51809
+ path10,
51810
+ `placeholder ${token} is not available here; allowed: ${allowed.join(", ")}`
51811
+ );
51812
+ else if (modifier && !PLACEHOLDER_MODIFIERS.includes(modifier))
51813
+ this.add(
51814
+ path10,
51815
+ `unknown modifier in ${token}; allowed modifiers are ${PLACEHOLDER_MODIFIERS.join(", ")}`
51816
+ );
51817
+ }
51818
+ return true;
51819
+ }
51820
+ oneOf(value, path10, allowed) {
51821
+ if (typeof value === "string" && allowed.includes(value)) return true;
51822
+ this.add(
51823
+ path10,
51824
+ typeof value === "string" ? `must be one of ${listed(allowed)}` : `must be one of ${listed(allowed)}, not ${describe(value)}`
51825
+ );
51826
+ return false;
51827
+ }
51828
+ boolean(value, path10) {
51829
+ if (typeof value === "boolean") return true;
51830
+ this.add(path10, `must be true or false, not ${describe(value)}`);
51831
+ return false;
51832
+ }
51833
+ };
51834
+ var RULE_FIELDS = {
51835
+ wrap: ["before", "after"],
51836
+ linePrefix: ["value"],
51837
+ pattern: ["value"],
51838
+ plain: [],
51839
+ omit: []
51840
+ };
51841
+ function validateRule(c, rule, path10) {
51842
+ if (!isObject2(rule)) {
51843
+ c.add(path10, `must be an object, not ${describe(rule)}`);
51844
+ return;
51845
+ }
51846
+ const keys = c.keys(rule, path10, ["mode", "before", "after", "value", "join"]);
51847
+ if (!("mode" in rule)) {
51848
+ c.add(child(path10, "mode"), `is required; one of ${listed(RULE_MODES)}`);
51849
+ return;
51850
+ }
51851
+ if (!c.oneOf(rule.mode, child(path10, "mode"), RULE_MODES)) return;
51852
+ const needed = RULE_FIELDS[rule.mode];
51853
+ for (const field of ["before", "after", "value"]) {
51854
+ const fieldPath = child(path10, field);
51855
+ if (needed.includes(field)) {
51856
+ if (!(field in rule)) c.add(fieldPath, `is required when mode is "${rule.mode}"`);
51857
+ else c.text(rule[field], fieldPath, { max: MAX_RULE_TEXT });
51858
+ } else if (keys.includes(field)) c.add(fieldPath, `is not used when mode is "${rule.mode}"`);
51859
+ }
51860
+ if ("join" in rule) c.oneOf(rule.join, child(path10, "join"), ["line", "paragraph"]);
51861
+ }
51862
+ function validateDirectory(c, value, path10) {
51863
+ if (value === null) return;
51864
+ if (!c.text(value, path10, { max: MAX_DIRECTORY_LENGTH, allowed: NOTE_PLACEHOLDERS })) return;
51865
+ if (!value.trim()) c.add(path10, "must not be empty; use null to copy only with assetsDir");
51866
+ else if (/^[/~]/.test(value)) c.add(path10, "must be relative to the output file's directory");
51867
+ else if (/[\\\0]/.test(value)) c.add(path10, "must not contain a backslash or NUL");
51868
+ else if (value.split("/").some((part) => part.trim() === ".."))
51869
+ c.add(path10, 'must not contain a ".." component');
51870
+ }
51871
+ function validateInlineOrder(c, value, path10) {
51872
+ if (!Array.isArray(value)) {
51873
+ c.add(
51874
+ path10,
51875
+ `must be an array of ${INLINE_FORMATS.length} inline formats, not ${describe(value)}`
51876
+ );
51877
+ return;
51878
+ }
51879
+ const seen = /* @__PURE__ */ new Set();
51880
+ value.forEach((item, i) => {
51881
+ if (!c.oneOf(item, child(path10, i), INLINE_FORMATS)) return;
51882
+ if (seen.has(item)) c.add(child(path10, i), `duplicate format "${item}"`);
51883
+ seen.add(item);
51884
+ });
51885
+ const missing = INLINE_FORMATS.filter((format) => !seen.has(format));
51886
+ if (missing.length) c.add(path10, `must list every inline format; missing ${listed(missing)}`);
51887
+ }
51888
+ function validateOptions(c, value, path10) {
51889
+ if (!isObject2(value)) {
51890
+ c.add(path10, `must be an object, not ${describe(value)}`);
51891
+ return;
51892
+ }
51893
+ for (const key of c.keys(value, path10, [
51894
+ "titleFallback",
51895
+ "richLinkImages",
51896
+ "richLinkImageCaption",
51897
+ "listIndent"
51898
+ ])) {
51899
+ const at = child(path10, key);
51900
+ if (key === "richLinkImageCaption")
51901
+ c.oneOf(value[key], at, ["none", "followingItalicParagraph"]);
51902
+ else if (key === "listIndent") {
51903
+ if (typeof value[key] !== "string" || !/^[ \t]{0,16}$/.test(value[key]))
51904
+ c.add(at, "must be a string of at most 16 spaces or tabs");
51905
+ } else c.boolean(value[key], at);
51906
+ }
51907
+ }
51908
+ function templateErrors(input) {
51909
+ const c = new Collector();
51910
+ if (!isObject2(input)) {
51911
+ c.add("$", `a template must be a JSON object, not ${describe(input)}`);
51912
+ return c.errors;
51913
+ }
51914
+ if (input.schemaVersion !== TEMPLATE_SCHEMA_VERSION) {
51915
+ c.add(
51916
+ "$.schemaVersion",
51917
+ "schemaVersion" in input ? `must be ${TEMPLATE_SCHEMA_VERSION}, not ${describeVersion(input.schemaVersion)}` : `is required and must be ${TEMPLATE_SCHEMA_VERSION}`
51918
+ );
51919
+ return c.errors;
51920
+ }
51921
+ const keys = c.keys(input, "$", [
51922
+ "schemaVersion",
51923
+ "name",
51924
+ "description",
51925
+ "extends",
51926
+ "assets",
51927
+ "inlineOrder",
51928
+ "rules",
51929
+ "options"
51930
+ ]);
51931
+ for (const key of keys) {
51932
+ const path10 = child("$", key);
51933
+ const value = input[key];
51934
+ switch (key) {
51935
+ case "schemaVersion":
51936
+ break;
51937
+ case "name":
51938
+ case "description":
51939
+ c.text(value, path10, { max: MAX_META_LENGTH, allowed: [] });
51940
+ break;
51941
+ case "extends":
51942
+ c.oneOf(value, path10, BUILTIN_TEMPLATE_NAMES);
51943
+ break;
51944
+ case "assets":
51945
+ if (!isObject2(value)) {
51946
+ c.add(path10, `must be an object, not ${describe(value)}`);
51947
+ break;
51948
+ }
51949
+ for (const field of c.keys(value, path10, ["mode", "pathStyle", "directory"])) {
51950
+ const at = child(path10, field);
51951
+ if (field === "mode") c.oneOf(value.mode, at, ["copy", "reference", "omit"]);
51952
+ else if (field === "pathStyle")
51953
+ c.oneOf(value.pathStyle, at, ["relative", "absolute"]);
51954
+ else validateDirectory(c, value.directory, at);
51955
+ }
51956
+ break;
51957
+ case "inlineOrder":
51958
+ validateInlineOrder(c, value, path10);
51959
+ break;
51960
+ case "rules":
51961
+ if (!isObject2(value)) {
51962
+ c.add(path10, `must be an object keyed by rule id, not ${describe(value)}`);
51963
+ break;
51964
+ }
51965
+ for (const id2 of Object.keys(value).sort()) {
51966
+ if (!RULE_IDS.includes(id2))
51967
+ c.add(child(path10, id2), "unknown rule id; see the template reference for the list");
51968
+ else validateRule(c, value[id2], child(path10, id2));
51969
+ }
51970
+ break;
51971
+ default:
51972
+ validateOptions(c, value, path10);
51973
+ }
51974
+ }
51975
+ return c.errors;
51976
+ }
51977
+ function validateTemplate(input) {
51978
+ const errors = templateErrors(input);
51979
+ if (errors.length) throw new TemplateValidationError(errors);
51980
+ return input;
51981
+ }
51982
+ function jsonErrorLocation(text2, message) {
51983
+ const lineColumn = /\(line (\d+) column (\d+)\)/.exec(message);
51984
+ if (lineColumn) return { line: Number(lineColumn[1]), column: Number(lineColumn[2]) };
51985
+ const position = /at position (\d+)/.exec(message);
51986
+ if (!position) return void 0;
51987
+ const offset = Math.min(Number(position[1]), text2.length);
51988
+ const before = text2.slice(0, offset).split("\n");
51989
+ return { line: before.length, column: before[before.length - 1].length + 1 };
51990
+ }
51991
+ function parseTemplate(text2) {
51992
+ const bytes = Buffer.byteLength(text2, "utf8");
51993
+ if (bytes > MAX_TEMPLATE_BYTES)
51994
+ throw new TemplateValidationError([
51995
+ { path: "$", message: `template is ${bytes} bytes; the limit is ${MAX_TEMPLATE_BYTES}` }
51996
+ ]);
51997
+ let parsed;
51998
+ try {
51999
+ parsed = JSON.parse(text2);
52000
+ } catch (error2) {
52001
+ const at = jsonErrorLocation(text2, error2.message);
52002
+ throw new TemplateValidationError([
52003
+ {
52004
+ path: "$",
52005
+ message: at ? `not valid JSON at line ${at.line}, column ${at.column}` : "not valid JSON"
52006
+ }
52007
+ ]);
52008
+ }
52009
+ return validateTemplate(parsed);
52010
+ }
52011
+ function resolveTemplate(template, name) {
52012
+ if (template === STANDARD) return merge2(void 0, STANDARD, name);
52013
+ return merge2(resolveTemplate(BUILTINS[template.extends ?? "standard-markdown"]), template, name);
52014
+ }
52015
+ function merge2(base, template, name) {
52016
+ return {
52017
+ name: name ?? template.name ?? base?.name ?? "template",
52018
+ ...template.description !== void 0 ? { description: template.description } : base?.description !== void 0 ? { description: base.description } : {},
52019
+ assets: { ...base?.assets, ...template.assets },
52020
+ inlineOrder: [...template.inlineOrder ?? base.inlineOrder],
52021
+ rules: { ...base?.rules, ...template.rules },
52022
+ options: { ...base?.options, ...template.options }
52023
+ };
52024
+ }
52025
+ var plainValue = (text2) => ({ md: text2, raw: text2 });
52026
+ function fillPlaceholders(text2, values) {
52027
+ return text2.replace(TOKEN, (token, body) => {
52028
+ const parsed = TOKEN_BODY.exec(body);
52029
+ const raw = parsed ? values[parsed[1]] : void 0;
52030
+ const value = typeof raw === "string" ? plainValue(raw) : raw;
52031
+ if (parsed?.[2] === "yaml") {
52032
+ if (!value) return "null";
52033
+ return JSON.stringify(value.list ?? value.raw);
52034
+ }
52035
+ if (!value) return "";
52036
+ return parsed?.[2] === "raw" ? value.raw : value.md;
52037
+ });
52038
+ }
52039
+ function ruleUses(rule, name) {
52040
+ return [rule.before, rule.after, rule.value].some(
52041
+ (text2) => text2 !== void 0 && placeholderTokens(text2).some((token) => token.name === name)
52042
+ );
52043
+ }
52044
+
52045
+ // src/utils/templateRender.ts
52046
+ var FILE_BACKED = /* @__PURE__ */ new Set([
52047
+ "image",
52048
+ "drawing",
52049
+ "paper",
52050
+ "scan",
52051
+ "pdf",
52052
+ "audio",
52053
+ "video",
52054
+ "file",
52055
+ "gallery"
52056
+ ]);
52057
+ var KIND_RULES = {
52058
+ image: "attachment.image",
52059
+ drawing: "attachment.drawing.classic",
52060
+ paper: "attachment.drawing.paper",
52061
+ scan: "attachment.scan",
52062
+ pdf: "attachment.pdf",
52063
+ audio: "attachment.audio",
52064
+ video: "attachment.video",
52065
+ file: "attachment.other",
52066
+ table: "attachment.table",
52067
+ divider: "attachment.divider",
52068
+ gallery: "attachment.gallery",
52069
+ link: "attachment.url"
52070
+ };
52071
+ var IMAGE_URL_EXTENSIONS = /\.(?:apng|avif|bmp|gif|heic|heif|ico|jfif|jpe?g|jxl|png|svgz?|tiff?|webp)$/i;
52072
+ function isImageUrl(url) {
52073
+ try {
52074
+ const parsed = new URL(url);
52075
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
52076
+ let path10 = parsed.pathname;
52077
+ try {
52078
+ path10 = decodeURIComponent(path10);
52079
+ } catch {
52080
+ }
52081
+ return IMAGE_URL_EXTENSIONS.test(path10);
52082
+ } catch {
52083
+ return false;
52084
+ }
52085
+ }
52086
+ function isMapUrl(url) {
52087
+ try {
52088
+ const host = new URL(url).hostname.toLowerCase();
52089
+ return host === "maps.apple.com" || host.endsWith(".maps.apple.com");
52090
+ } catch {
52091
+ return false;
52092
+ }
52093
+ }
52094
+ function attachmentRuleId(attachment, template) {
52095
+ if (attachment.kind === "inline") return void 0;
52096
+ if (attachment.kind === "link") {
52097
+ const url = attachment.url ?? "";
52098
+ if (template.options.richLinkImages && isImageUrl(url)) return "attachment.url.image";
52099
+ if (isMapUrl(url)) return "attachment.map";
52100
+ }
52101
+ return KIND_RULES[attachment.kind] ?? "attachment.other";
52102
+ }
52103
+ function applyRule(rule, content, values) {
52104
+ const fill = (text2 = "") => fillPlaceholders(text2, { ...values, content: plainValue(content) });
52105
+ switch (rule.mode) {
52106
+ case "omit":
52107
+ return void 0;
52108
+ case "plain":
52109
+ return content;
52110
+ case "wrap":
52111
+ return fill(rule.before) + content + fill(rule.after);
52112
+ case "pattern":
52113
+ return fill(rule.value);
52114
+ case "linePrefix": {
52115
+ const prefix = fill(rule.value);
52116
+ return content.split("\n").map((line) => line ? prefix + line : prefix.trimEnd()).join("\n");
52117
+ }
52118
+ }
52119
+ }
52120
+ function applyInline(rule, text2, values) {
52121
+ const match = /^(\s*)([\s\S]*?)(\s*)$/.exec(text2);
52122
+ if (!match[2]) return text2;
52123
+ const out = applyRule(rule, match[2], values);
52124
+ return out === void 0 ? "" : `${match[1]}${out}${match[3]}`;
52125
+ }
52126
+ var HIGHLIGHT_RULES = /* @__PURE__ */ new Set(["purple", "pink", "orange", "mint", "blue"]);
52127
+ function highlightRule(name) {
52128
+ return HIGHLIGHT_RULES.has(name) ? `inline.highlight.${name}` : "inline.highlight.other";
52129
+ }
52130
+ function buildLayers(template) {
52131
+ const { rules } = template;
52132
+ const active = (rule) => rule.mode !== "plain";
52133
+ const flag3 = (format) => {
52134
+ const rule = rules[`inline.${format}`];
52135
+ return {
52136
+ key: (fmt) => fmt[format] && active(rule) ? "on" : void 0,
52137
+ rule: () => rule,
52138
+ values: () => ({})
52139
+ };
52140
+ };
52141
+ const layers = {
52142
+ bold: flag3("bold"),
52143
+ italic: flag3("italic"),
52144
+ underline: flag3("underline"),
52145
+ strikethrough: flag3("strikethrough"),
52146
+ superscript: flag3("superscript"),
52147
+ subscript: flag3("subscript"),
52148
+ highlight: {
52149
+ key: (fmt) => {
52150
+ if (!fmt.highlight) return void 0;
52151
+ const rule = rules[highlightRule(fmt.highlight)];
52152
+ if (!active(rule)) return void 0;
52153
+ return JSON.stringify(rule) + (ruleUses(rule, "highlight") ? fmt.highlight : "");
52154
+ },
52155
+ rule: (fmt) => rules[highlightRule(fmt.highlight)],
52156
+ values: (fmt) => ({ highlight: fmt.highlight })
52157
+ },
52158
+ color: {
52159
+ key: (fmt) => {
52160
+ const rule = rules["inline.color"];
52161
+ if (!fmt.color || !active(rule)) return void 0;
52162
+ return ruleUses(rule, "color") ? fmt.color : "on";
52163
+ },
52164
+ rule: () => rules["inline.color"],
52165
+ values: (fmt) => ({ color: fmt.color })
52166
+ },
52167
+ link: {
52168
+ key: (fmt) => fmt.link,
52169
+ rule: () => rules["inline.link"],
52170
+ values: (fmt) => ({ url: { md: linkDestination(fmt.link), raw: fmt.link } })
52171
+ }
52172
+ };
52173
+ return [...template.inlineOrder].reverse().map((format) => layers[format]);
52174
+ }
52175
+ var LIST_STYLES2 = /* @__PURE__ */ new Set(["bulleted", "dashed", "numbered", "checklist"]);
52176
+ var TemplateRenderer = class {
52177
+ constructor(ctx, options) {
52178
+ this.ctx = ctx;
52179
+ this.options = options;
52180
+ this.layers = buildLayers(options.template);
52181
+ this.rules = options.template.rules;
52182
+ }
52183
+ ctx;
52184
+ options;
52185
+ warnings = [];
52186
+ layers;
52187
+ rules;
52188
+ /** The attachment each plan was made from, for rule and placeholder lookup. */
52189
+ origins = /* @__PURE__ */ new WeakMap();
52190
+ get template() {
52191
+ return this.options.template;
52192
+ }
52193
+ /** Placeholder values describing the note. */
52194
+ noteValues(note) {
52195
+ const meta = this.options.metaFor?.(note) ?? {};
52196
+ const text2 = (value) => value === void 0 ? void 0 : { md: escapeMarkdown(value), raw: value };
52197
+ const tags = noteTags(note);
52198
+ const values = {
52199
+ title: text2(note.title.trim()),
52200
+ id: note.id,
52201
+ uuid: meta.uuid,
52202
+ folder: text2(meta.folder),
52203
+ account: text2(meta.account),
52204
+ created: meta.created,
52205
+ modified: meta.modified,
52206
+ tags: {
52207
+ md: tags.map((tag) => escapeMarkdown(tag)).join(", "),
52208
+ raw: tags.join(", "),
52209
+ list: tags
52210
+ },
52211
+ exportStem: this.options.exportStem ?? "export"
52212
+ };
52213
+ return Object.fromEntries(Object.entries(values).filter(([, v]) => v !== void 0));
52214
+ }
52215
+ warn(code, note, attachmentId) {
52216
+ this.warnings.push({ code, noteId: note.id, ...attachmentId ? { attachmentId } : {} });
52217
+ }
52218
+ /** Plan one attachment, honoring omit rules before any file is placed. */
52219
+ plan(note, id2, attachment, binding) {
52220
+ const omitted = { type: "inline", text: "" };
52221
+ if (!attachment) {
52222
+ this.warn("attachment_not_found", note, id2);
52223
+ return planAttachment(void 0, this.ctx);
52224
+ }
52225
+ const ruleId = attachmentRuleId(attachment, this.template);
52226
+ if (ruleId && this.rules[ruleId].mode === "omit") return omitted;
52227
+ const fileBacked = FILE_BACKED.has(attachment.kind);
52228
+ if (fileBacked && this.template.assets.mode === "omit") return omitted;
52229
+ if (fileBacked && !binding.writer && binding.required)
52230
+ this.warn("assets_dir_required", note, attachment.id);
52231
+ const plan = planAttachment(attachment, {
52232
+ ...this.ctx,
52233
+ ...binding.writer ? { writer: binding.writer } : { writer: void 0 }
52234
+ });
52235
+ this.inspect(note, plan, attachment);
52236
+ return plan;
52237
+ }
52238
+ /** Record origins and warnings for a plan and any gallery items. */
52239
+ inspect(note, plan, attachment) {
52240
+ this.origins.set(plan, attachment);
52241
+ switch (plan.type) {
52242
+ case "inline":
52243
+ if (!plan.text) this.warn("inline_token_metadata_missing", note, attachment.id);
52244
+ break;
52245
+ case "unavailable":
52246
+ this.warn(
52247
+ plan.reason === "undecodable" ? "table_decode_failed" : plan.reason === "missing" ? "missing_asset" : "asset_copy_failed",
52248
+ note,
52249
+ attachment.id
52250
+ );
52251
+ break;
52252
+ case "gallery":
52253
+ if (!plan.items.length) this.warn("gallery_children_missing", note, attachment.id);
52254
+ plan.items.forEach((item, i) => this.inspect(note, item, attachment.children[i]));
52255
+ break;
52256
+ }
52257
+ }
52258
+ /** Placeholder values for an attachment. */
52259
+ attachmentValues(attachment, base) {
52260
+ if (!attachment) return base;
52261
+ const filename = attachment.mediaFilename ?? attachment.title;
52262
+ return {
52263
+ ...base,
52264
+ kind: attachment.kind,
52265
+ uti: attachment.uti,
52266
+ ...filename ? { filename: { md: escapeMarkdown(filename), raw: filename } } : {}
52267
+ };
52268
+ }
52269
+ /** Render a plan through its template rule; "" when omitted. */
52270
+ renderPlan(plan, values, caption) {
52271
+ const origin = this.origins.get(plan);
52272
+ const vars = this.attachmentValues(origin, values);
52273
+ const apply2 = (id2, content, extra = {}) => applyRule(this.rules[id2], content, { ...vars, ...extra }) ?? "";
52274
+ switch (plan.type) {
52275
+ case "inline":
52276
+ return plan.link ? applyInline(this.rules["inline.link"], escapeMarkdown(plan.text), {
52277
+ ...vars,
52278
+ url: { md: linkDestination(plan.link), raw: plan.link }
52279
+ }) : escapeMarkdown(plan.text);
52280
+ case "divider":
52281
+ return apply2("attachment.divider", "");
52282
+ case "table":
52283
+ return apply2("attachment.table", tableMarkdown(plan.rows));
52284
+ case "placeholder":
52285
+ case "unavailable": {
52286
+ const label = plan.type === "unavailable" ? `${plan.label} unavailable` : plan.label;
52287
+ return apply2(
52288
+ "attachment.placeholder",
52289
+ escapeMarkdown(plan.name ? `${label}: ${plan.name}` : label)
52290
+ );
52291
+ }
52292
+ case "asset": {
52293
+ const alt = escapeMarkdown(plan.name ?? plan.label);
52294
+ const id2 = origin && attachmentRuleId(origin, this.template) || "attachment.other";
52295
+ return apply2(id2, "", {
52296
+ alt: { md: alt, raw: plan.name ?? plan.label },
52297
+ path: { md: linkDestination(plan.url), raw: plan.url },
52298
+ linkText: plan.previewUrl ? `![${alt}](${linkDestination(plan.previewUrl)})` : alt
52299
+ });
52300
+ }
52301
+ case "card": {
52302
+ if (!plan.url) return `${escapeMarkdown(plan.title)} (${escapeMarkdown(plan.displayUrl)})`;
52303
+ const id2 = origin && attachmentRuleId(origin, this.template) || "attachment.url";
52304
+ const alt = caption ?? plan.title;
52305
+ return apply2(id2, "", {
52306
+ alt: { md: escapeMarkdown(alt), raw: alt },
52307
+ url: { md: linkDestination(plan.url), raw: plan.url },
52308
+ ...caption !== void 0 ? { caption: { md: escapeMarkdown(caption), raw: caption } } : {}
52309
+ });
52310
+ }
52311
+ case "gallery": {
52312
+ const rule = this.rules["attachment.gallery"];
52313
+ const items = plan.items.map((item) => this.renderPlan(item, values)).filter(Boolean);
52314
+ if (!items.length) return "";
52315
+ return apply2("attachment.gallery", items.join(rule.join === "line" ? "\n" : "\n\n"));
52316
+ }
52317
+ }
52318
+ }
52319
+ /** Format text runs through the inline layers. */
52320
+ layered(pieces, values, depth = 0) {
52321
+ if (depth === this.layers.length)
52322
+ return pieces.map((piece) => escapeMarkdown(piece.text.replace(/\n/g, " "))).join("");
52323
+ const layer = this.layers[depth];
52324
+ let out = "";
52325
+ for (let i = 0; i < pieces.length; ) {
52326
+ const key = layer.key(pieces[i].fmt);
52327
+ let j = i;
52328
+ while (j < pieces.length && layer.key(pieces[j].fmt) === key) j++;
52329
+ const inner = this.layered(pieces.slice(i, j), values, depth + 1);
52330
+ const fmt = pieces[i].fmt;
52331
+ out = joinSafe(
52332
+ out,
52333
+ key === void 0 ? inner : applyInline(layer.rule(fmt), inner, { ...values, ...layer.values(fmt) })
52334
+ );
52335
+ i = j;
52336
+ }
52337
+ return out;
52338
+ }
52339
+ inline(pieces, values, caption) {
52340
+ let out = "";
52341
+ for (let i = 0; i < pieces.length; ) {
52342
+ const piece = pieces[i];
52343
+ if (piece.type === "attachment") {
52344
+ out = joinSafe(out, this.renderPlan(piece.plan, values, caption));
52345
+ i++;
52346
+ continue;
52347
+ }
52348
+ let j = i;
52349
+ while (j < pieces.length && pieces[j].type === "text") j++;
52350
+ out = joinSafe(out, this.layered(pieces.slice(i, j), values));
52351
+ i = j;
52352
+ }
52353
+ return out;
52354
+ }
52355
+ /** The caption paragraph after a lone image-URL link card, if the template wants one. */
52356
+ captionFor(note, index) {
52357
+ const { options } = this.template;
52358
+ if (!options.richLinkImages || options.richLinkImageCaption !== "followingItalicParagraph")
52359
+ return void 0;
52360
+ const blocks = note.doc.blocks;
52361
+ const current = blocks[index];
52362
+ if (current.text.trim() !== "\uFFFC" || current.attachments.length !== 1) return void 0;
52363
+ const attachment = note.attachments.get(current.attachments[0].id);
52364
+ if (!attachment || attachmentRuleId(attachment, this.template) !== "attachment.url.image")
52365
+ return void 0;
52366
+ if (this.rules["attachment.url.image"].mode === "omit" || !isSafe(attachment.url))
52367
+ return void 0;
52368
+ const next = blocks[index + 1];
52369
+ if (!next || next.style !== "body" || next.blockQuote || next.indent !== 0 || next.attachments.length || next.text.includes("\uFFFC") || !next.text.trim() || !next.runs.every((run) => !run.text.trim() || run.italic))
52370
+ return void 0;
52371
+ return next.text.trim();
52372
+ }
52373
+ /** Render one note's body. */
52374
+ renderBody(note, values) {
52375
+ const binding = this.options.assetsFor?.(note) ?? {};
52376
+ const plan = (id2) => this.plan(note, id2, note.attachments.get(id2), binding);
52377
+ const titleIndex = titleBlockIndex(note);
52378
+ const lines = [];
52379
+ const counters = [];
52380
+ const skip = /* @__PURE__ */ new Set();
52381
+ let code;
52382
+ const push = (text2, quote, group) => {
52383
+ if (!text2) return;
52384
+ if (quote) {
52385
+ const quoted2 = applyRule(this.rules["paragraph.quote"], text2, values);
52386
+ if (!quoted2) return;
52387
+ text2 = quoted2;
52388
+ }
52389
+ lines.push({ text: text2, quote, ...group ? { group } : {} });
52390
+ };
52391
+ const ruled = (id2, content, extra = {}) => applyRule(this.rules[id2], content, { ...values, ...extra });
52392
+ const groupOf = (id2, list) => this.rules[id2].join === "line" ? list ? "list" : id2 : void 0;
52393
+ const flushCode = () => {
52394
+ if (!code) return;
52395
+ const longest = Math.max(
52396
+ 2,
52397
+ ...code.lines.map((l) => Math.max(0, ...(l.match(/`+/g) ?? []).map((m) => m.length)))
52398
+ );
52399
+ push(
52400
+ ruled("block.code", code.lines.join("\n"), { fence: "`".repeat(longest + 1) }),
52401
+ code.quote,
52402
+ groupOf("block.code", false)
52403
+ );
52404
+ code = void 0;
52405
+ };
52406
+ if (this.template.options.titleFallback && titleIndex === -1 && note.title.trim())
52407
+ push(
52408
+ ruled("block.title", escapeMarkdown(note.title.trim())),
52409
+ false,
52410
+ groupOf("block.title", false)
52411
+ );
52412
+ for (const block of note.doc.blocks) {
52413
+ if (skip.has(block.index)) continue;
52414
+ if (block.style === "monospaced") {
52415
+ if (code && code.quote !== block.blockQuote) flushCode();
52416
+ code ??= { lines: [], quote: block.blockQuote };
52417
+ code.lines.push(block.text.replace(//g, ""));
52418
+ continue;
52419
+ }
52420
+ flushCode();
52421
+ if (!LIST_STYLES2.has(block.style)) counters.length = 0;
52422
+ if (!block.text.trim()) continue;
52423
+ const caption = this.captionFor(note, block.index);
52424
+ if (caption !== void 0) skip.add(block.index + 1);
52425
+ const pieces = blockPieces(block, plan);
52426
+ let segment = [];
52427
+ const segments = [];
52428
+ for (const piece of pieces) {
52429
+ if (piece.type === "attachment" && isBlockPlan(piece.plan)) {
52430
+ segments.push(segment, piece.plan);
52431
+ segment = [];
52432
+ } else segment.push(piece);
52433
+ }
52434
+ segments.push(segment);
52435
+ let first2 = true;
52436
+ for (const segment2 of segments) {
52437
+ if (!Array.isArray(segment2)) {
52438
+ push(this.renderPlan(segment2, values), block.blockQuote);
52439
+ continue;
52440
+ }
52441
+ const body = this.inline(segment2, values, caption).trim();
52442
+ if (!body) continue;
52443
+ const [text2, group] = this.blockLine(
52444
+ block,
52445
+ body,
52446
+ first2,
52447
+ block.index === titleIndex,
52448
+ counters,
52449
+ values
52450
+ );
52451
+ push(text2, block.blockQuote, group);
52452
+ first2 = false;
52453
+ }
52454
+ }
52455
+ flushCode();
52456
+ for (const attachment of unreferencedAttachments(note)) {
52457
+ this.ctx.stats.unreferenced++;
52458
+ push(this.renderPlan(this.plan(note, attachment.id, attachment, binding), values), false);
52459
+ }
52460
+ return this.join(lines, values);
52461
+ }
52462
+ /** One paragraph through its block rule, with list indent and numbering. */
52463
+ blockLine(block, body, first2, isTitle, counters, values) {
52464
+ const rule = (id2, content, extra = {}, list = false) => [
52465
+ applyRule(this.rules[id2], content, { ...values, ...extra }),
52466
+ this.rules[id2].join === "line" ? list ? "list" : id2 : void 0
52467
+ ];
52468
+ if (isTitle || block.style === "title") return rule("block.title", body);
52469
+ if (block.style === "heading") return rule("block.heading", body);
52470
+ if (block.style === "subheading") return rule("block.subheading", body);
52471
+ if (!LIST_STYLES2.has(block.style) || !first2) return rule("block.body", escapeLineStart(body));
52472
+ const item = escapeLineStart(body);
52473
+ const level = Math.min(block.indent, 20);
52474
+ counters.length = Math.min(counters.length, level + 1);
52475
+ while (counters.length <= level) counters.push(0);
52476
+ let result;
52477
+ if (block.style === "numbered")
52478
+ result = rule("block.numbered", item, { index: String(++counters[level]) }, true);
52479
+ else {
52480
+ counters[level] = 0;
52481
+ if (block.style === "checklist") {
52482
+ const done = !!block.checklist?.done;
52483
+ result = rule(
52484
+ done ? "block.checklist.checked" : "block.checklist.unchecked",
52485
+ item,
52486
+ { checked: String(done) },
52487
+ true
52488
+ );
52489
+ } else
52490
+ result = rule(block.style === "dashed" ? "block.dashed" : "block.bulleted", item, {}, true);
52491
+ }
52492
+ const indent = this.template.options.listIndent.repeat(level);
52493
+ if (result[0] && indent)
52494
+ result[0] = result[0].split("\n").map((line) => line ? indent + line : line).join("\n");
52495
+ return result;
52496
+ }
52497
+ /** Join lines: one newline within a `line`-join group, a blank line elsewhere. */
52498
+ join(lines, values) {
52499
+ const quote = this.rules["paragraph.quote"];
52500
+ const quoteGap = quote.mode === "linePrefix" ? `
52501
+ ${fillPlaceholders(quote.value ?? "", values).trimEnd()}
52502
+ ` : "\n\n";
52503
+ let out = "";
52504
+ let previous;
52505
+ for (const line of lines) {
52506
+ if (previous) {
52507
+ const tight = previous.group !== void 0 && previous.group === line.group && previous.quote === line.quote;
52508
+ out += tight ? "\n" : previous.quote && line.quote ? quoteGap : "\n\n";
52509
+ }
52510
+ out += line.text;
52511
+ previous = line;
52512
+ }
52513
+ return out;
52514
+ }
52515
+ };
52516
+ var isSafe = (url) => !!url && /^https?:\/\//i.test(url) && !Array.from(url).some((c) => c.charCodeAt(0) < 32);
52517
+ function noteTags(note) {
52518
+ const tags = [];
52519
+ for (const attachment of note.attachments.values()) {
52520
+ if (!attachment.uti.endsWith(".hashtag") || !attachment.altText) continue;
52521
+ const tag = attachment.altText.replace(/^#/, "").trim();
52522
+ if (tag && !tags.includes(tag)) tags.push(tag);
52523
+ }
52524
+ return tags;
52525
+ }
52526
+ function renderNotesWithTemplate(notes, ctx, options) {
52527
+ const renderer = new TemplateRenderer(ctx, options);
52528
+ const rules = options.template.rules;
52529
+ let markdown = "";
52530
+ notes.forEach((note, i) => {
52531
+ const values = renderer.noteValues(note);
52532
+ if (i > 0) markdown += applyRule(rules["document.separator"], "", values) ?? "";
52533
+ const body = renderer.renderBody(note, values);
52534
+ markdown += (applyRule(rules["document.header"], "", values) ?? "") + (options.wrap ? wrapMarkdown(body, options.wrap) : body) + (applyRule(rules["document.footer"], "", values) ?? "");
52535
+ });
52536
+ return { markdown: markdown + (notes.length ? "\n" : ""), warnings: renderer.warnings };
52537
+ }
52538
+
52539
+ // src/utils/templateAssets.ts
52540
+ import { createHash as createHash2 } from "node:crypto";
52541
+ import {
52542
+ closeSync as closeSync5,
52543
+ constants as constants5,
52544
+ fstatSync as fstatSync5,
52545
+ lstatSync as lstatSync4,
52546
+ mkdirSync as mkdirSync5,
52547
+ openSync as openSync5,
52548
+ readSync as readSync4,
52549
+ writeSync as writeSync4
52550
+ } from "node:fs";
52551
+ import { extname as extname4, isAbsolute as isAbsolute3, join as join21, relative as relative4, resolve as resolve4, sep as sep4 } from "node:path";
52552
+ var CHUNK = 1024 * 1024;
52553
+ function openRegular(path10) {
52554
+ const fd = openSync5(path10, constants5.O_RDONLY | constants5.O_NOFOLLOW);
52555
+ if (!fstatSync5(fd).isFile()) {
52556
+ closeSync5(fd);
52557
+ throw new Error("not a regular file");
52558
+ }
52559
+ return fd;
52560
+ }
52561
+ function digest(fd) {
52562
+ const hash = createHash2("sha256");
52563
+ const chunk = Buffer.alloc(CHUNK);
52564
+ let head = Buffer.alloc(0);
52565
+ for (let position = 0; ; ) {
52566
+ const n = readSync4(fd, chunk, 0, chunk.length, position);
52567
+ if (n <= 0) break;
52568
+ if (position === 0) head = Buffer.from(chunk.subarray(0, Math.min(n, 16)));
52569
+ hash.update(chunk.subarray(0, n));
52570
+ position += n;
52571
+ }
52572
+ return { hash: hash.digest("hex"), head };
52573
+ }
52574
+ function urlFor(target, linkBase) {
52575
+ return encodePathUrl(linkBase ? relative4(linkBase, target).split(sep4).join("/") : target);
52576
+ }
52577
+ var HashedSidecarWriter = class {
52578
+ constructor(dir, linkBase) {
52579
+ this.dir = dir;
52580
+ this.linkBase = linkBase;
52581
+ }
52582
+ dir;
52583
+ linkBase;
52584
+ placed = /* @__PURE__ */ new Map();
52585
+ ready = false;
52586
+ /** Absolute paths of files written or reused. */
52587
+ files = [];
52588
+ count = 0;
52589
+ prepare() {
52590
+ if (this.ready) return;
52591
+ assertExportPath(this.dir);
52592
+ mkdirSync5(this.dir, { recursive: true });
52593
+ if (!lstatSync4(this.dir).isDirectory()) throw new Error("assets directory is not a directory");
52594
+ this.ready = true;
52595
+ }
52596
+ place(asset) {
52597
+ const done = this.placed.get(asset.path);
52598
+ if (done) return done;
52599
+ let source;
52600
+ try {
52601
+ source = openRegular(asset.path);
52602
+ } catch {
52603
+ return { error: "unreadable" };
52604
+ }
52605
+ try {
52606
+ const { hash, head } = digest(source);
52607
+ const mime = sniffMime(head, asset.name);
52608
+ this.prepare();
52609
+ const name = safeAssetName(asset.name, mime);
52610
+ const ext = extname4(name);
52611
+ const target = join21(
52612
+ this.dir,
52613
+ `${name.slice(0, name.length - ext.length)}-${hash.slice(0, 8)}${ext}`
52614
+ );
52615
+ let existing;
52616
+ try {
52617
+ existing = openRegular(target);
52618
+ } catch (error2) {
52619
+ const code = error2.code;
52620
+ if (code !== "ENOENT") return { error: "destination-not-regular" };
52621
+ }
52622
+ if (existing !== void 0) {
52623
+ try {
52624
+ if (digest(existing).hash !== hash) return { error: "name-taken" };
52625
+ } finally {
52626
+ closeSync5(existing);
52627
+ }
52628
+ } else this.copy(source, target);
52629
+ this.count++;
52630
+ this.files.push(target);
52631
+ const result = { url: urlFor(target, this.linkBase), mime };
52632
+ this.placed.set(asset.path, result);
52633
+ return result;
52634
+ } catch (error2) {
52635
+ return { error: error2 instanceof Error ? error2.message : String(error2) };
52636
+ } finally {
52637
+ closeSync5(source);
52638
+ }
52639
+ }
52640
+ copy(source, target) {
52641
+ const out = openSync5(
52642
+ target,
52643
+ constants5.O_WRONLY | constants5.O_CREAT | constants5.O_EXCL | constants5.O_NOFOLLOW,
52644
+ 420
52645
+ );
52646
+ try {
52647
+ const chunk = Buffer.alloc(CHUNK);
52648
+ for (let position = 0; ; ) {
52649
+ const n = readSync4(source, chunk, 0, chunk.length, position);
52650
+ if (n <= 0) break;
52651
+ let written = 0;
52652
+ while (written < n) written += writeSync4(out, chunk, written, n - written);
52653
+ position += n;
52654
+ }
52655
+ } finally {
52656
+ closeSync5(out);
52657
+ }
52658
+ }
52659
+ };
52660
+ var ReferenceWriter = class {
52661
+ constructor(linkBase) {
52662
+ this.linkBase = linkBase;
52663
+ }
52664
+ linkBase;
52665
+ count = 0;
52666
+ place(asset) {
52667
+ let fd;
52668
+ try {
52669
+ fd = openRegular(asset.path);
52670
+ } catch {
52671
+ return { error: "unreadable" };
52672
+ }
52673
+ try {
52674
+ const head = Buffer.alloc(16);
52675
+ const n = readSync4(fd, head, 0, 16, 0);
52676
+ this.count++;
52677
+ return {
52678
+ url: urlFor(asset.path, this.linkBase),
52679
+ mime: sniffMime(head.subarray(0, n), asset.name)
52680
+ };
52681
+ } finally {
52682
+ closeSync5(fd);
52683
+ }
52684
+ }
52685
+ };
52686
+ function pathComponent(value) {
52687
+ const clean = Array.from(
52688
+ value.normalize("NFC"),
52689
+ (char) => char.charCodeAt(0) < 32 || char === "\x7F" ? "_" : char
52690
+ ).join("").replace(/[/\\:]+/g, "_").replace(/^[.\s]+/, "").trim().slice(0, 120);
52691
+ return clean || "untitled";
52692
+ }
52693
+ function templateAssetsDir(directory, outputDir, values) {
52694
+ const safe = {};
52695
+ for (const [key, value] of Object.entries(values)) {
52696
+ const raw = typeof value === "string" ? value : value?.raw;
52697
+ if (raw !== void 0) safe[key] = pathComponent(raw);
52698
+ }
52699
+ const filled = fillPlaceholders(directory, safe);
52700
+ const base = resolve4(outputDir);
52701
+ const dir = resolve4(base, filled);
52702
+ if (isAbsolute3(filled) || filled.split("/").includes("..") || !dir.startsWith(base + sep4))
52703
+ throw new Error(`assets.directory "${directory}" resolves outside the output directory`);
52704
+ return dir;
52705
+ }
52706
+ function readTemplateFile(path10) {
52707
+ const abs = assertExportPath(path10);
52708
+ if (extname4(abs).toLowerCase() !== ".json")
52709
+ throw new Error(`Template file must have a .json extension: ${abs}`);
52710
+ let fd;
52711
+ try {
52712
+ fd = openRegular(abs);
52713
+ } catch (error2) {
52714
+ const code = error2.code;
52715
+ throw new Error(
52716
+ code === "ENOENT" ? `Template file not found: ${abs}` : code === "ELOOP" ? `Refusing to read the symbolic link ${abs}` : `Template file is not a readable regular file: ${abs}`
52717
+ );
52718
+ }
52719
+ try {
52720
+ const size = fstatSync5(fd).size;
52721
+ if (size > MAX_TEMPLATE_BYTES)
52722
+ throw new Error(`Template file is ${size} bytes; the limit is ${MAX_TEMPLATE_BYTES}`);
52723
+ const data = Buffer.alloc(size);
52724
+ let read = 0;
52725
+ while (read < size) {
52726
+ const n = readSync4(fd, data, read, size - read, read);
52727
+ if (n <= 0) break;
52728
+ read += n;
52729
+ }
52730
+ return data.subarray(0, read).toString("utf8");
52731
+ } finally {
52732
+ closeSync5(fd);
52733
+ }
52734
+ }
51375
52735
 
51376
52736
  // src/services/notesExport.ts
51377
52737
  var DEFAULT_FOLDER_EXPORT_LIMIT = 100;
51378
52738
  var MAX_FOLDER_EXPORT_LIMIT = 1e3;
51379
52739
  var NotesExportError = class extends Error {
51380
- constructor(code, message) {
52740
+ constructor(code, message, details) {
51381
52741
  super(message);
51382
52742
  this.code = code;
52743
+ this.details = details;
51383
52744
  this.name = "NotesExportError";
51384
52745
  }
51385
52746
  code;
52747
+ details;
51386
52748
  };
52749
+ var MAX_EXPORT_WARNINGS = 200;
52750
+ var MAX_LISTED_ASSETS = 1e3;
52751
+ function chooseTemplate(request, deps) {
52752
+ if (request.template !== void 0 && request.templateFile !== void 0)
52753
+ throw new NotesExportError(
52754
+ "invalid-request",
52755
+ "Provide at most one of 'template' or 'templateFile'."
52756
+ );
52757
+ const invalid2 = (error2, where) => new NotesExportError("invalid-template", `${where}: ${error2.message}`, error2.errors);
52758
+ if (request.template !== void 0) {
52759
+ const name2 = request.template;
52760
+ if (isBuiltinTemplate(name2))
52761
+ return {
52762
+ info: { name: name2, source: "builtin" },
52763
+ template: resolveTemplate(builtinTemplate(name2), name2)
52764
+ };
52765
+ let portable2;
52766
+ try {
52767
+ portable2 = deps.findTemplate?.(name2);
52768
+ } catch (error2) {
52769
+ if (error2 instanceof TemplateValidationError)
52770
+ throw invalid2(error2, `Saved template "${name2}"`);
52771
+ throw error2;
52772
+ }
52773
+ if (!portable2) throw new NotesExportError("template-not-found", `No template named "${name2}".`);
52774
+ return { info: { name: name2, source: "saved" }, template: resolveTemplate(portable2, name2) };
52775
+ }
52776
+ if (request.templateFile === void 0) return void 0;
52777
+ let text2;
52778
+ try {
52779
+ text2 = readTemplateFile(request.templateFile);
52780
+ } catch (error2) {
52781
+ throw new NotesExportError(
52782
+ "invalid-path",
52783
+ `templateFile: ${error2 instanceof Error ? error2.message : String(error2)}`
52784
+ );
52785
+ }
52786
+ let portable;
52787
+ try {
52788
+ portable = parseTemplate(text2);
52789
+ } catch (error2) {
52790
+ throw invalid2(error2, "templateFile");
52791
+ }
52792
+ const name = portable.name ?? basename4(request.templateFile, extname5(request.templateFile));
52793
+ return { info: { name, source: "file" }, template: resolveTemplate(portable, name) };
52794
+ }
51387
52795
  function validPath(path10, what) {
51388
52796
  try {
51389
52797
  return assertExportPath(path10);
@@ -51423,7 +52831,7 @@ function loadNotes(ids, single, read) {
51423
52831
  return { notes, skipped };
51424
52832
  }
51425
52833
  function openOutput(output) {
51426
- mkdirSync5(dirname6(output), { recursive: true });
52834
+ mkdirSync6(dirname6(output), { recursive: true });
51427
52835
  try {
51428
52836
  return openCreateOnly(output);
51429
52837
  } catch (error2) {
@@ -51445,8 +52853,16 @@ function exportNotesMarkdown(request, deps) {
51445
52853
  const assetsDir = request.assetsDir ? validPath(request.assetsDir, "assetsDir") : void 0;
51446
52854
  if (output && assetsDir && output === assetsDir)
51447
52855
  throw new NotesExportError("invalid-path", "outputPath and assetsDir must differ.");
52856
+ const chosen = chooseTemplate(request, deps);
52857
+ if (chosen && assetsDir && chosen.template.assets.mode !== "copy")
52858
+ throw new NotesExportError(
52859
+ "invalid-request",
52860
+ `assetsDir has no effect: template "${chosen.info.name}" sets assets.mode to "${chosen.template.assets.mode}".`
52861
+ );
51448
52862
  const ids = selectNotes(request, deps);
51449
52863
  const { notes, skipped } = loadNotes(ids, !!request.id, deps.readNote);
52864
+ if (chosen)
52865
+ return exportWithTemplate(request, deps, chosen, notes, skipped, { output, assetsDir });
51450
52866
  const fd = output ? openOutput(output) : void 0;
51451
52867
  const writer = assetsDir ? new SidecarWriter(assetsDir, output ? dirname6(output) : void 0) : void 0;
51452
52868
  const ctx = {
@@ -51478,7 +52894,7 @@ function exportNotesMarkdown(request, deps) {
51478
52894
  return { ...receipt, markdown };
51479
52895
  }
51480
52896
  function defaultSidecarDir(output) {
51481
- return join21(dirname6(output), `${basename4(output, extname4(output))}.assets`);
52897
+ return join22(dirname6(output), `${basename4(output, extname5(output))}.assets`);
51482
52898
  }
51483
52899
  function exportNotesHtml(request, deps) {
51484
52900
  if (!request.outputPath)
@@ -51518,21 +52934,127 @@ function exportNotesHtml(request, deps) {
51518
52934
  ...assetsDir ? { assets: { dir: assetsDir, files: writer.count } } : { embedded: writer.count }
51519
52935
  };
51520
52936
  }
52937
+ function readMetaSafely(read, id2) {
52938
+ try {
52939
+ return read(id2);
52940
+ } catch {
52941
+ return {};
52942
+ }
52943
+ }
52944
+ function pathValues(note, meta, exportStem) {
52945
+ const values = { title: note.title.trim(), id: note.id, exportStem };
52946
+ for (const [key, value] of Object.entries(meta)) if (value) values[key] = value;
52947
+ return values;
52948
+ }
52949
+ function assetBindings(template, notes, meta, { output, assetsDir, exportStem }) {
52950
+ const linkBase = template.assets.pathStyle === "relative" && output ? dirname6(output) : void 0;
52951
+ const writers = /* @__PURE__ */ new Map();
52952
+ const writerFor = (dir) => {
52953
+ let writer = writers.get(dir);
52954
+ if (!writer) writers.set(dir, writer = new HashedSidecarWriter(dir, linkBase));
52955
+ return writer;
52956
+ };
52957
+ const reference = template.assets.mode === "reference" ? new ReferenceWriter(linkBase) : void 0;
52958
+ const bindings = /* @__PURE__ */ new Map();
52959
+ for (const note of notes) {
52960
+ let binding = {};
52961
+ if (reference) binding = { writer: reference };
52962
+ else if (template.assets.mode === "copy") {
52963
+ if (assetsDir) binding = { writer: writerFor(assetsDir) };
52964
+ else if (template.assets.directory !== null && output) {
52965
+ let dir;
52966
+ try {
52967
+ dir = templateAssetsDir(
52968
+ template.assets.directory,
52969
+ dirname6(output),
52970
+ pathValues(note, meta.get(note) ?? {}, exportStem)
52971
+ );
52972
+ } catch (error2) {
52973
+ throw new NotesExportError("invalid-path", error2.message);
52974
+ }
52975
+ dir = validPath(dir, "assets.directory");
52976
+ if (dir === output)
52977
+ throw new NotesExportError("invalid-path", "assets.directory resolves to outputPath.");
52978
+ binding = { writer: writerFor(dir) };
52979
+ } else if (template.assets.directory !== null) binding = { required: true };
52980
+ }
52981
+ bindings.set(note, binding);
52982
+ }
52983
+ return { bindings, writers };
52984
+ }
52985
+ function exportWithTemplate(request, deps, chosen, notes, skipped, { output, assetsDir }) {
52986
+ const { template } = chosen;
52987
+ const readMeta = deps.readMeta ?? ((id2) => readExportNoteMeta(id2));
52988
+ const needsMeta = usesNoteMeta(template);
52989
+ const meta = new Map(
52990
+ notes.map((note) => [note, needsMeta ? readMetaSafely(readMeta, note.id) : {}])
52991
+ );
52992
+ const exportStem = output ? basename4(output, extname5(output)) : "export";
52993
+ const { bindings, writers } = assetBindings(template, notes, meta, {
52994
+ output,
52995
+ assetsDir,
52996
+ exportStem
52997
+ });
52998
+ const fd = output ? openOutput(output) : void 0;
52999
+ const ctx = { stats: emptyStats(), locator: deps.locator ?? new AssetLocator() };
53000
+ let warnings = [];
53001
+ const markdown = renderInto(fd, () => {
53002
+ const result = renderNotesWithTemplate(notes, ctx, {
53003
+ template,
53004
+ exportStem,
53005
+ wrap: request.wrap ?? 0,
53006
+ assetsFor: (note) => bindings.get(note) ?? {},
53007
+ metaFor: (note) => meta.get(note) ?? {}
53008
+ });
53009
+ warnings = result.warnings;
53010
+ return result.markdown;
53011
+ });
53012
+ const bytes = Buffer.byteLength(markdown);
53013
+ const used = [...writers.values()].filter((writer) => writer.count > 0);
53014
+ const files = used.flatMap((writer) => writer.files);
53015
+ const receipt = {
53016
+ format: "markdown",
53017
+ count: notes.length,
53018
+ bytes,
53019
+ stats: ctx.stats,
53020
+ skipped,
53021
+ template: chosen.info,
53022
+ warnings: warnings.slice(0, MAX_EXPORT_WARNINGS),
53023
+ ...warnings.length > MAX_EXPORT_WARNINGS ? { warningsOmitted: warnings.length - MAX_EXPORT_WARNINGS } : {},
53024
+ ...used.length ? {
53025
+ assets: {
53026
+ dir: used.length === 1 ? used[0].dir : dirname6(output),
53027
+ files: files.length
53028
+ },
53029
+ assetFiles: files.slice(0, MAX_LISTED_ASSETS)
53030
+ } : {}
53031
+ };
53032
+ if (fd !== void 0) {
53033
+ writeAllAndClose(fd, markdown);
53034
+ return { ...receipt, output };
53035
+ }
53036
+ if (bytes > deps.maxInlineBytes)
53037
+ throw new NotesExportError(
53038
+ "too-large",
53039
+ `The Markdown is ${bytes} bytes, over the ${deps.maxInlineBytes}-byte inline limit. Pass outputPath to write it to a file, or export fewer notes.`
53040
+ );
53041
+ return { ...receipt, markdown };
53042
+ }
51521
53043
 
51522
53044
  // src/tools/directOperations.ts
51523
- import { createHash as createHash2 } from "node:crypto";
53045
+ import { createHash as createHash3 } from "node:crypto";
51524
53046
  import {
51525
- closeSync as closeSync5,
51526
- constants as constants5,
51527
- fstatSync as fstatSync5,
53047
+ closeSync as closeSync6,
53048
+ constants as constants6,
53049
+ fstatSync as fstatSync6,
51528
53050
  mkdtempSync as mkdtempSync5,
51529
- openSync as openSync5,
53051
+ openSync as openSync6,
51530
53052
  readFileSync as readFileSync3,
51531
53053
  rmSync as rmSync5,
51532
53054
  writeFileSync as writeFileSync4
51533
53055
  } from "node:fs";
51534
53056
  import { tmpdir as tmpdir5 } from "node:os";
51535
- import { basename as basename5, extname as extname5, isAbsolute as isAbsolute3, join as join22 } from "node:path";
53057
+ import { basename as basename5, extname as extname6, isAbsolute as isAbsolute4, join as join23 } from "node:path";
51536
53058
  var noteId = exactIdInput(
51537
53059
  "ICNote",
51538
53060
  /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
@@ -51576,10 +53098,10 @@ function assertExistingContentPreserved(before, after) {
51576
53098
  }
51577
53099
  }
51578
53100
  function localAttachment(path10) {
51579
- if (!isAbsolute3(path10)) throw new Error("An absolute local file path is required");
51580
- const descriptor = openSync5(path10, constants5.O_RDONLY | constants5.O_NOFOLLOW);
53101
+ if (!isAbsolute4(path10)) throw new Error("An absolute local file path is required");
53102
+ const descriptor = openSync6(path10, constants6.O_RDONLY | constants6.O_NOFOLLOW);
51581
53103
  try {
51582
- const stat = fstatSync5(descriptor);
53104
+ const stat = fstatSync6(descriptor);
51583
53105
  if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
51584
53106
  throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
51585
53107
  const bytes = readFileSync3(descriptor);
@@ -51587,7 +53109,7 @@ function localAttachment(path10) {
51587
53109
  throw new Error("Attachment changed while it was being read; try again");
51588
53110
  return bytes;
51589
53111
  } finally {
51590
- closeSync5(descriptor);
53112
+ closeSync6(descriptor);
51591
53113
  }
51592
53114
  }
51593
53115
  function registerDirectOperations(server2, manager) {
@@ -51710,15 +53232,15 @@ function attachmentName(path10, filename) {
51710
53232
  throw new Error(
51711
53233
  "filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
51712
53234
  );
51713
- if (extname5(filename).toLowerCase() !== extname5(source).toLowerCase())
53235
+ if (extname6(filename).toLowerCase() !== extname6(source).toLowerCase())
51714
53236
  throw new Error(
51715
- `filename must keep the source file's extension (${extname5(source) || "none"})`
53237
+ `filename must keep the source file's extension (${extname6(source) || "none"})`
51716
53238
  );
51717
53239
  return filename;
51718
53240
  }
51719
53241
  var UNCERTAIN = "Attachment insertion outcome uncertain; read the exact note before retrying";
51720
53242
  var pause = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
51721
- var sha256 = (data) => createHash2("sha256").update(data).digest("hex");
53243
+ var sha256 = (data) => createHash3("sha256").update(data).digest("hex");
51722
53244
  function storedAttachmentIds(manager, id2) {
51723
53245
  try {
51724
53246
  return new Set(
@@ -51751,13 +53273,13 @@ function storedInsertion(manager, id2, before, bytes, returnedId) {
51751
53273
  const matches = row.assetPaths.some((path10) => {
51752
53274
  let descriptor;
51753
53275
  try {
51754
- descriptor = openSync5(path10, constants5.O_RDONLY | constants5.O_NOFOLLOW);
51755
- const stat = fstatSync5(descriptor);
53276
+ descriptor = openSync6(path10, constants6.O_RDONLY | constants6.O_NOFOLLOW);
53277
+ const stat = fstatSync6(descriptor);
51756
53278
  return stat.isFile() && stat.size === bytes.length && sha256(readFileSync3(descriptor)) === expected;
51757
53279
  } catch {
51758
53280
  return false;
51759
53281
  } finally {
51760
- if (descriptor !== void 0) closeSync5(descriptor);
53282
+ if (descriptor !== void 0) closeSync6(descriptor);
51761
53283
  }
51762
53284
  });
51763
53285
  if (!matches)
@@ -51774,8 +53296,8 @@ function attachFile(manager, args) {
51774
53296
  const bytes = localAttachment(path10);
51775
53297
  const beforeAttachments = manager.listAttachmentsById(id2);
51776
53298
  const beforeStored = storedAttachmentIds(manager, id2);
51777
- const directory = mkdtempSync5(join22(tmpdir5(), "notes-attachment-add-"));
51778
- const temporaryFile = join22(directory, name);
53299
+ const directory = mkdtempSync5(join23(tmpdir5(), "notes-attachment-add-"));
53300
+ const temporaryFile = join23(directory, name);
51779
53301
  try {
51780
53302
  writeFileSync4(temporaryFile, bytes, { mode: 384 });
51781
53303
  if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
@@ -51842,7 +53364,7 @@ function attachFile(manager, args) {
51842
53364
  }
51843
53365
 
51844
53366
  // src/tools/folderDelete.ts
51845
- import { createHash as createHash3 } from "node:crypto";
53367
+ import { createHash as createHash4 } from "node:crypto";
51846
53368
 
51847
53369
  // src/utils/folderStore.ts
51848
53370
  import { execFileSync as execFileSync19 } from "child_process";
@@ -52029,7 +53551,7 @@ function folderDeleteRevision(app, store) {
52029
53551
  store.childFolderCount,
52030
53552
  store.noteCount
52031
53553
  ];
52032
- return `sha256:${createHash3("sha256").update(JSON.stringify(state)).digest("hex")}`;
53554
+ return `sha256:${createHash4("sha256").update(JSON.stringify(state)).digest("hex")}`;
52033
53555
  }
52034
53556
  function checkFolder(manager, args, deps) {
52035
53557
  const app = manager.readFolderForDelete(args.id);
@@ -52165,8 +53687,8 @@ function registerFolderDelete(server2, manager, deps = defaultDeps) {
52165
53687
  }
52166
53688
 
52167
53689
  // src/utils/svgAnalyzer.ts
52168
- import { createHash as createHash4 } from "node:crypto";
52169
- import { closeSync as closeSync6, constants as constants6, fstatSync as fstatSync6, openSync as openSync6, readSync as readSync4 } from "node:fs";
53690
+ import { createHash as createHash5 } from "node:crypto";
53691
+ import { closeSync as closeSync7, constants as constants7, fstatSync as fstatSync7, openSync as openSync7, readSync as readSync5 } from "node:fs";
52170
53692
 
52171
53693
  // src/utils/svgColor.ts
52172
53694
  var NAMED = {
@@ -52840,10 +54362,10 @@ function clipPolyline(points, r) {
52840
54362
  if (run.length) parts.push(run);
52841
54363
  return { parts, clipped: true };
52842
54364
  }
52843
- function dashPolyline(points, pattern, offset, charge) {
52844
- const total = pattern.reduce((s, v) => s + v, 0);
54365
+ function dashPolyline(points, pattern2, offset, charge) {
54366
+ const total = pattern2.reduce((s, v) => s + v, 0);
52845
54367
  let index = 0;
52846
- let remaining = pattern[0];
54368
+ let remaining = pattern2[0];
52847
54369
  let on = true;
52848
54370
  let shift = (offset % total + total) % total;
52849
54371
  while (shift > 0) {
@@ -52851,8 +54373,8 @@ function dashPolyline(points, pattern, offset, charge) {
52851
54373
  remaining -= step;
52852
54374
  shift -= step;
52853
54375
  if (remaining <= 0) {
52854
- index = (index + 1) % pattern.length;
52855
- remaining = pattern[index];
54376
+ index = (index + 1) % pattern2.length;
54377
+ remaining = pattern2[index];
52856
54378
  on = !on;
52857
54379
  }
52858
54380
  }
@@ -52874,8 +54396,8 @@ function dashPolyline(points, pattern, offset, charge) {
52874
54396
  on = !on;
52875
54397
  segLen -= remaining;
52876
54398
  a = cut;
52877
- index = (index + 1) % pattern.length;
52878
- remaining = pattern[index];
54399
+ index = (index + 1) % pattern2.length;
54400
+ remaining = pattern2[index];
52879
54401
  }
52880
54402
  remaining -= segLen;
52881
54403
  if (on && currentDash) currentDash.push(b);
@@ -53107,7 +54629,7 @@ function parseXml(source, limits) {
53107
54629
  if (a.name === "xmlns") scope2.set("", a.value);
53108
54630
  else if (a.name.startsWith("xmlns:")) scope2.set(a.name.slice(6), a.value);
53109
54631
  }
53110
- const resolve7 = (qualified, isAttribute) => {
54632
+ const resolve8 = (qualified, isAttribute) => {
53111
54633
  const colon = qualified.indexOf(":");
53112
54634
  if (colon < 0) return { local: qualified, ns: isAttribute ? null : scope2.get("") ?? null };
53113
54635
  const prefix = qualified.slice(0, colon);
@@ -53117,12 +54639,12 @@ function parseXml(source, limits) {
53117
54639
  if (ns === void 0) fail(`Undeclared namespace prefix "${prefix.slice(0, 40)}"`);
53118
54640
  return { local, ns };
53119
54641
  };
53120
- const resolved = resolve7(name, false);
54642
+ const resolved = resolve8(name, false);
53121
54643
  const element = {
53122
54644
  name,
53123
54645
  local: resolved.local,
53124
54646
  ns: resolved.ns,
53125
- attributes: rawAttributes.filter((a) => a.name !== "xmlns" && !a.name.startsWith("xmlns:")).map((a) => ({ name: a.name, value: a.value, ...resolve7(a.name, true) })),
54647
+ attributes: rawAttributes.filter((a) => a.name !== "xmlns" && !a.name.startsWith("xmlns:")).map((a) => ({ name: a.name, value: a.value, ...resolve8(a.name, true) })),
53126
54648
  children: [],
53127
54649
  text: "",
53128
54650
  line: tagLine
@@ -53248,7 +54770,7 @@ function canonicalJson(value) {
53248
54770
  return JSON.stringify(value);
53249
54771
  }
53250
54772
  function sha2562(text2) {
53251
- return createHash4("sha256").update(text2).digest("hex");
54773
+ return createHash5("sha256").update(text2).digest("hex");
53252
54774
  }
53253
54775
  var round = (v, digits) => {
53254
54776
  const r = Number(v.toFixed(digits));
@@ -53365,10 +54887,10 @@ function assertInert(el, location) {
53365
54887
  throw new SvgError("svg_unsafe", "Active content in a style attribute", location);
53366
54888
  }
53367
54889
  const counts = /* @__PURE__ */ new Map();
53368
- for (const child of el.children) {
53369
- const n = (counts.get(child.local) ?? 0) + 1;
53370
- counts.set(child.local, n);
53371
- assertInert(child, `${location}/${child.local}[${n}]`);
54890
+ for (const child2 of el.children) {
54891
+ const n = (counts.get(child2.local) ?? 0) + 1;
54892
+ counts.set(child2.local, n);
54893
+ assertInert(child2, `${location}/${child2.local}[${n}]`);
53372
54894
  }
53373
54895
  }
53374
54896
  var INITIAL_STYLE = {
@@ -53620,14 +55142,14 @@ var Analyzer = class {
53620
55142
  /** Walk an element's children with its own style and transform applied. */
53621
55143
  container(el, ctx) {
53622
55144
  const counts = /* @__PURE__ */ new Map();
53623
- for (const child of el.children) {
53624
- const n = (counts.get(child.local) ?? 0) + 1;
53625
- counts.set(child.local, n);
53626
- const id2 = attr(child, "id");
53627
- this.element(child, {
55145
+ for (const child2 of el.children) {
55146
+ const n = (counts.get(child2.local) ?? 0) + 1;
55147
+ counts.set(child2.local, n);
55148
+ const id2 = attr(child2, "id");
55149
+ this.element(child2, {
53628
55150
  ...ctx,
53629
55151
  depth: ctx.depth + 1,
53630
- location: `${ctx.location}/${child.local}[${n}]${id2 ? `#${id2}` : ""}`
55152
+ location: `${ctx.location}/${child2.local}[${n}]${id2 ? `#${id2}` : ""}`
53631
55153
  });
53632
55154
  }
53633
55155
  }
@@ -54050,9 +55572,9 @@ var Analyzer = class {
54050
55572
  let pieces = polylines;
54051
55573
  if (style.dasharray) {
54052
55574
  const k = nonScaling ? 1 : mean;
54053
- const pattern = style.dasharray.map((v) => v * k);
55575
+ const pattern2 = style.dasharray.map((v) => v * k);
54054
55576
  pieces = polylines.flatMap(
54055
- (p) => dashPolyline(p, pattern, style.dashoffset * k, (n) => this.charge("dashWork", n))
55577
+ (p) => dashPolyline(p, pattern2, style.dashoffset * k, (n) => this.charge("dashWork", n))
54056
55578
  );
54057
55579
  }
54058
55580
  this.layers++;
@@ -54135,14 +55657,14 @@ function analyzeSvgBuffer(source) {
54135
55657
  function readSvgSource(path10) {
54136
55658
  let fd;
54137
55659
  try {
54138
- fd = openSync6(path10, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
55660
+ fd = openSync7(path10, constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
54139
55661
  } catch (error2) {
54140
55662
  if (error2.code === "ELOOP")
54141
55663
  throw new SvgError("svg_file_invalid", "The SVG path is a symbolic link");
54142
55664
  throw new SvgError("svg_file_invalid", "The SVG file does not exist or cannot be read");
54143
55665
  }
54144
55666
  try {
54145
- const info = fstatSync6(fd);
55667
+ const info = fstatSync7(fd);
54146
55668
  if (!info.isFile())
54147
55669
  throw new SvgError("svg_file_invalid", "The SVG path is not a regular file");
54148
55670
  if (info.size > SVG_LIMITS.maxSourceBytes)
@@ -54153,7 +55675,7 @@ function readSvgSource(path10) {
54153
55675
  const buffer = Buffer.alloc(SVG_LIMITS.maxSourceBytes + 1);
54154
55676
  let total = 0;
54155
55677
  for (; ; ) {
54156
- const n = readSync4(fd, buffer, total, buffer.length - total, null);
55678
+ const n = readSync5(fd, buffer, total, buffer.length - total, null);
54157
55679
  if (n === 0) break;
54158
55680
  total += n;
54159
55681
  if (total > SVG_LIMITS.maxSourceBytes)
@@ -54164,7 +55686,7 @@ function readSvgSource(path10) {
54164
55686
  }
54165
55687
  return buffer.subarray(0, total);
54166
55688
  } finally {
54167
- closeSync6(fd);
55689
+ closeSync7(fd);
54168
55690
  }
54169
55691
  }
54170
55692
  function analyzeSvgFile(path10) {
@@ -54735,7 +56257,7 @@ function registerNativeOperations(server2, manager) {
54735
56257
  import { spawnSync as spawnSync2 } from "node:child_process";
54736
56258
  import { existsSync as existsSync13 } from "node:fs";
54737
56259
  import { release as release2 } from "node:os";
54738
- import { dirname as dirname7, resolve as resolve4 } from "node:path";
56260
+ import { dirname as dirname7, resolve as resolve5 } from "node:path";
54739
56261
  import { fileURLToPath } from "node:url";
54740
56262
  var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
54741
56263
  var MARKDOWN_MIN_DARWIN_MAJOR = 25;
@@ -54758,11 +56280,11 @@ function setupShortcuts(checkOnly, dependencies = {}) {
54758
56280
  const result = spawnSync2("/usr/bin/open", [path10], { encoding: "utf8" });
54759
56281
  return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
54760
56282
  });
54761
- const baseDirectory = dependencies.baseDirectory || resolve4(dirname7(fileURLToPath(import.meta.url)), "../shortcuts");
56283
+ const baseDirectory = dependencies.baseDirectory || resolve5(dirname7(fileURLToPath(import.meta.url)), "../shortcuts");
54762
56284
  const osRelease = (dependencies.osRelease || release2)();
54763
56285
  const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
54764
56286
  const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
54765
- const path10 = resolve4(baseDirectory, file);
56287
+ const path10 = resolve5(baseDirectory, file);
54766
56288
  let installed = false;
54767
56289
  let identifier;
54768
56290
  let error2;
@@ -54822,11 +56344,11 @@ function formatShortcutSetup(report) {
54822
56344
 
54823
56345
  // src/services/publicHelper.ts
54824
56346
  import { spawn, spawnSync as spawnSync3 } from "node:child_process";
54825
- import { createHash as createHash5 } from "node:crypto";
56347
+ import { createHash as createHash6 } from "node:crypto";
54826
56348
  import {
54827
56349
  chmodSync,
54828
56350
  existsSync as existsSync14,
54829
- mkdirSync as mkdirSync6,
56351
+ mkdirSync as mkdirSync7,
54830
56352
  mkdtempSync as mkdtempSync6,
54831
56353
  readFileSync as readFileSync4,
54832
56354
  renameSync,
@@ -54834,7 +56356,7 @@ import {
54834
56356
  writeFileSync as writeFileSync5
54835
56357
  } from "node:fs";
54836
56358
  import { homedir as homedir19, release as release3 } from "node:os";
54837
- import { dirname as dirname8, join as join24, resolve as resolve5 } from "node:path";
56359
+ import { dirname as dirname8, join as join25, resolve as resolve6 } from "node:path";
54838
56360
  import { fileURLToPath as fileURLToPath2 } from "node:url";
54839
56361
  var PUBLIC_HELPER_PROTOCOL = 1;
54840
56362
  var PUBLIC_HELPER_DIR_ENV = "APPLE_NOTES_MCP_PUBLIC_HELPER_DIR";
@@ -54862,7 +56384,7 @@ var publicManifestSchema = external_exports.object({
54862
56384
  function packageRoot(fromDir = dirname8(fileURLToPath2(import.meta.url))) {
54863
56385
  let dir = fromDir;
54864
56386
  for (; ; ) {
54865
- const candidate = join24(dir, "package.json");
56387
+ const candidate = join25(dir, "package.json");
54866
56388
  if (existsSync14(candidate)) {
54867
56389
  try {
54868
56390
  if (JSON.parse(readFileSync4(candidate, "utf8")).name === "apple-notes-mcp")
@@ -54871,7 +56393,7 @@ function packageRoot(fromDir = dirname8(fileURLToPath2(import.meta.url))) {
54871
56393
  }
54872
56394
  }
54873
56395
  const parent = dirname8(dir);
54874
- if (parent === dir) return resolve5(fromDir, "..");
56396
+ if (parent === dir) return resolve6(fromDir, "..");
54875
56397
  dir = parent;
54876
56398
  }
54877
56399
  }
@@ -54879,7 +56401,7 @@ function defaultPublicHelperDeps(overrides = {}) {
54879
56401
  return {
54880
56402
  env: process.env,
54881
56403
  platform: process.platform,
54882
- sourcePath: join24(packageRoot(), PUBLIC_HELPER_SOURCE),
56404
+ sourcePath: join25(packageRoot(), PUBLIC_HELPER_SOURCE),
54883
56405
  exists: existsSync14,
54884
56406
  readFile: (path10) => readFileSync4(path10),
54885
56407
  spawn: spawnSync3,
@@ -54890,14 +56412,14 @@ function defaultPublicHelperDeps(overrides = {}) {
54890
56412
  function publicHelperInstallDir(env = process.env) {
54891
56413
  const override = env[PUBLIC_HELPER_DIR_ENV]?.trim();
54892
56414
  if (override) return override;
54893
- return join24(homedir19(), "Library", "Application Support", "apple-notes-mcp", "public-helper");
56415
+ return join25(homedir19(), "Library", "Application Support", "apple-notes-mcp", "public-helper");
54894
56416
  }
54895
56417
  function sha256Hex(data) {
54896
- return createHash5("sha256").update(data).digest("hex");
56418
+ return createHash6("sha256").update(data).digest("hex");
54897
56419
  }
54898
56420
  function inspectPublicHelper(deps = defaultPublicHelperDeps()) {
54899
56421
  const installDir = publicHelperInstallDir(deps.env);
54900
- const binaryPath = join24(installDir, PUBLIC_HELPER_BINARY);
56422
+ const binaryPath = join25(installDir, PUBLIC_HELPER_BINARY);
54901
56423
  const base = { installDir, binaryPath, sourcePath: deps.sourcePath, manifest: null };
54902
56424
  const fail = (reason, detail) => ({
54903
56425
  ...base,
@@ -54908,7 +56430,7 @@ function inspectPublicHelper(deps = defaultPublicHelperDeps()) {
54908
56430
  if (deps.platform !== "darwin") return fail("unsupported_platform", "macOS only");
54909
56431
  if (!deps.exists(deps.sourcePath))
54910
56432
  return fail("helper_not_installed", `Packaged helper source is missing: ${deps.sourcePath}`);
54911
- const manifestPath = join24(installDir, PUBLIC_HELPER_MANIFEST);
56433
+ const manifestPath = join25(installDir, PUBLIC_HELPER_MANIFEST);
54912
56434
  if (!deps.exists(binaryPath) || !deps.exists(manifestPath))
54913
56435
  return fail(
54914
56436
  "helper_not_installed",
@@ -54995,7 +56517,7 @@ async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHe
54995
56517
  const aborted2 = () => new PublicHelperError("aborted", "The request was cancelled; the helper was stopped.");
54996
56518
  if (signal?.aborted) throw aborted2();
54997
56519
  return new Promise((resolvePromise, reject) => {
54998
- const child = (deps.spawnAsync ?? spawn)(binaryPath, [], {
56520
+ const child2 = (deps.spawnAsync ?? spawn)(binaryPath, [], {
54999
56521
  stdio: ["pipe", "pipe", "ignore"]
55000
56522
  });
55001
56523
  const chunks = [];
@@ -55003,7 +56525,7 @@ async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHe
55003
56525
  let failure = null;
55004
56526
  const stop = (error2) => {
55005
56527
  failure ??= error2;
55006
- child.kill("SIGKILL");
56528
+ child2.kill("SIGKILL");
55007
56529
  };
55008
56530
  const timer = setTimeout(
55009
56531
  () => stop(new PublicHelperError("timeout", `The helper did not answer within ${timeout} ms.`)),
@@ -55015,19 +56537,19 @@ async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHe
55015
56537
  clearTimeout(timer);
55016
56538
  signal?.removeEventListener("abort", onAbort);
55017
56539
  };
55018
- child.stdout?.on("data", (chunk) => {
56540
+ child2.stdout?.on("data", (chunk) => {
55019
56541
  size += chunk.length;
55020
56542
  if (size > MAX_OUTPUT_BYTES2)
55021
56543
  stop(new PublicHelperError("invalid_response", "The helper response is too large."));
55022
56544
  else chunks.push(chunk);
55023
56545
  });
55024
- child.on("error", (error2) => {
56546
+ child2.on("error", (error2) => {
55025
56547
  settle();
55026
56548
  reject(
55027
56549
  failure ?? new PublicHelperError("helper_unreachable", `Could not run the helper: ${error2.message}`)
55028
56550
  );
55029
56551
  });
55030
- child.on("close", (status, exitSignal) => {
56552
+ child2.on("close", (status, exitSignal) => {
55031
56553
  settle();
55032
56554
  if (failure) return reject(failure);
55033
56555
  if (status === null && exitSignal)
@@ -55040,9 +56562,9 @@ async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHe
55040
56562
  reject(error2);
55041
56563
  }
55042
56564
  });
55043
- child.stdin?.on("error", () => {
56565
+ child2.stdin?.on("error", () => {
55044
56566
  });
55045
- child.stdin?.end(input);
56567
+ child2.stdin?.end(input);
55046
56568
  });
55047
56569
  }
55048
56570
  function prepareCall(action, fields, deps, options) {
@@ -55184,12 +56706,12 @@ function buildPublicHelper(checkOnly, deps = defaultPublicHelperBuildDeps()) {
55184
56706
  const compiler = String(version3.stdout || version3.stderr || "").split("\n").find((line) => line.includes("Swift version"))?.trim() || "swiftc";
55185
56707
  steps.push({ step: "find compiler", ok: true, detail: compiler });
55186
56708
  const installDir = publicHelperInstallDir(deps.env);
55187
- mkdirSync6(installDir, { recursive: true, mode: 448 });
55188
- const staging = mkdtempSync6(join24(installDir, ".staging-"));
56709
+ mkdirSync7(installDir, { recursive: true, mode: 448 });
56710
+ const staging = mkdtempSync6(join25(installDir, ".staging-"));
55189
56711
  try {
55190
- const stagedBinary = join24(staging, PUBLIC_HELPER_BINARY);
55191
- const digestPath = join24(staging, "source-digest.swift");
55192
- const plistPath = join24(staging, "Info.plist");
56712
+ const stagedBinary = join25(staging, PUBLIC_HELPER_BINARY);
56713
+ const digestPath = join25(staging, "source-digest.swift");
56714
+ const plistPath = join25(staging, "Info.plist");
55193
56715
  writeFileSync5(digestPath, sourceDigestSwift(sourceSha), { mode: 384 });
55194
56716
  writeFileSync5(plistPath, publicHelperInfoPlist(), { mode: 384 });
55195
56717
  const compile = deps.spawn(
@@ -55252,9 +56774,9 @@ function buildPublicHelper(checkOnly, deps = defaultPublicHelperBuildDeps()) {
55252
56774
  compiler
55253
56775
  };
55254
56776
  chmodSync(stagedBinary, 448);
55255
- renameSync(stagedBinary, join24(installDir, PUBLIC_HELPER_BINARY));
56777
+ renameSync(stagedBinary, join25(installDir, PUBLIC_HELPER_BINARY));
55256
56778
  writeFileSync5(
55257
- join24(installDir, PUBLIC_HELPER_MANIFEST),
56779
+ join25(installDir, PUBLIC_HELPER_MANIFEST),
55258
56780
  JSON.stringify(manifest, null, 2) + "\n",
55259
56781
  { mode: 384 }
55260
56782
  );
@@ -55499,7 +57021,7 @@ function formatNoteDrawings(result) {
55499
57021
 
55500
57022
  // src/utils/noteAudio.ts
55501
57023
  import { readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
55502
- import { join as join25 } from "node:path";
57024
+ import { join as join26 } from "node:path";
55503
57025
  var EXTRA_AUDIO_UTIS = [
55504
57026
  "public.mp3",
55505
57027
  "public.aiff-audio",
@@ -55524,7 +57046,7 @@ function accountDirsFor(containerDir, accountIdentifier) {
55524
57046
  if (own) return [own];
55525
57047
  let names;
55526
57048
  try {
55527
- names = readdirSync4(join25(containerDir, "Accounts")).sort();
57049
+ names = readdirSync4(join26(containerDir, "Accounts")).sort();
55528
57050
  } catch {
55529
57051
  return [];
55530
57052
  }
@@ -55536,8 +57058,8 @@ function resolveMediaPath(media, accountIdentifier = null, containerDir = NOTES_
55536
57058
  if (!id2 || !filename) return null;
55537
57059
  const generation = safeComponent(media?.generation);
55538
57060
  for (const dir of accountDirsFor(containerDir, accountIdentifier)) {
55539
- const base = join25(dir, "Media", id2);
55540
- const candidates = generation ? [join25(base, generation, filename), join25(base, filename)] : [join25(base, filename)];
57061
+ const base = join26(dir, "Media", id2);
57062
+ const candidates = generation ? [join26(base, generation, filename), join26(base, filename)] : [join26(base, filename)];
55541
57063
  for (const candidate of candidates) {
55542
57064
  const real = realInside(candidate, dir);
55543
57065
  if (real && isFile2(real)) return real;
@@ -55809,21 +57331,21 @@ import { spawnSync as spawnSync5 } from "node:child_process";
55809
57331
  import {
55810
57332
  chmodSync as chmodSync2,
55811
57333
  existsSync as existsSync16,
55812
- mkdirSync as mkdirSync7,
57334
+ mkdirSync as mkdirSync8,
55813
57335
  mkdtempSync as mkdtempSync7,
55814
57336
  renameSync as renameSync2,
55815
57337
  rmSync as rmSync7,
55816
57338
  writeFileSync as writeFileSync6
55817
57339
  } from "node:fs";
55818
57340
  import { release as release4 } from "node:os";
55819
- import { join as join27 } from "node:path";
57341
+ import { join as join28 } from "node:path";
55820
57342
 
55821
57343
  // src/services/privateHelper.ts
55822
57344
  import { spawnSync as spawnSync4 } from "node:child_process";
55823
- import { createHash as createHash6 } from "node:crypto";
57345
+ import { createHash as createHash7 } from "node:crypto";
55824
57346
  import { existsSync as existsSync15, readFileSync as readFileSync5 } from "node:fs";
55825
57347
  import { homedir as homedir20 } from "node:os";
55826
- import { dirname as dirname9, join as join26, resolve as resolve6 } from "node:path";
57348
+ import { dirname as dirname9, join as join27, resolve as resolve7 } from "node:path";
55827
57349
  import { fileURLToPath as fileURLToPath3 } from "node:url";
55828
57350
  var PRIVATE_HELPER_PROTOCOL = 1;
55829
57351
  var ENABLE_ENV = "APPLE_NOTES_MCP_ENABLE_PRIVATE";
@@ -55851,7 +57373,7 @@ var manifestSchema = external_exports.object({
55851
57373
  function packageRoot2(fromDir = dirname9(fileURLToPath3(import.meta.url))) {
55852
57374
  let dir = fromDir;
55853
57375
  for (; ; ) {
55854
- const candidate = join26(dir, "package.json");
57376
+ const candidate = join27(dir, "package.json");
55855
57377
  if (existsSync15(candidate)) {
55856
57378
  try {
55857
57379
  const pkg = JSON.parse(readFileSync5(candidate, "utf8"));
@@ -55860,7 +57382,7 @@ function packageRoot2(fromDir = dirname9(fileURLToPath3(import.meta.url))) {
55860
57382
  }
55861
57383
  }
55862
57384
  const parent = dirname9(dir);
55863
- if (parent === dir) return resolve6(fromDir, "..");
57385
+ if (parent === dir) return resolve7(fromDir, "..");
55864
57386
  dir = parent;
55865
57387
  }
55866
57388
  }
@@ -55868,7 +57390,7 @@ function defaultDeps2(overrides = {}) {
55868
57390
  return {
55869
57391
  env: process.env,
55870
57392
  platform: process.platform,
55871
- sourcePath: join26(packageRoot2(), HELPER_SOURCE_RELATIVE),
57393
+ sourcePath: join27(packageRoot2(), HELPER_SOURCE_RELATIVE),
55872
57394
  exists: existsSync15,
55873
57395
  readFile: (path10) => readFileSync5(path10),
55874
57396
  spawn: spawnSync4,
@@ -55881,14 +57403,14 @@ function privateHelperEnabled(env = process.env) {
55881
57403
  function helperInstallDir(env = process.env) {
55882
57404
  const override = env[HELPER_DIR_ENV]?.trim();
55883
57405
  if (override) return override;
55884
- return join26(homedir20(), "Library", "Application Support", "apple-notes-mcp", "private-helper");
57406
+ return join27(homedir20(), "Library", "Application Support", "apple-notes-mcp", "private-helper");
55885
57407
  }
55886
57408
  function sha256Hex2(data) {
55887
- return createHash6("sha256").update(data).digest("hex");
57409
+ return createHash7("sha256").update(data).digest("hex");
55888
57410
  }
55889
57411
  function inspectInstallation(deps = defaultDeps2()) {
55890
57412
  const installDir = helperInstallDir(deps.env);
55891
- const binaryPath = join26(installDir, HELPER_BINARY_NAME);
57413
+ const binaryPath = join27(installDir, HELPER_BINARY_NAME);
55892
57414
  const base = {
55893
57415
  installDir,
55894
57416
  binaryPath,
@@ -55906,7 +57428,7 @@ function inspectInstallation(deps = defaultDeps2()) {
55906
57428
  if (!deps.exists(deps.sourcePath))
55907
57429
  return fail("helper_not_installed", `Packaged helper source is missing: ${deps.sourcePath}`);
55908
57430
  base.expectedSourceSha256 = sha256Hex2(deps.readFile(deps.sourcePath));
55909
- const manifestPath = join26(installDir, MANIFEST_NAME);
57431
+ const manifestPath = join27(installDir, MANIFEST_NAME);
55910
57432
  if (!deps.exists(binaryPath) || !deps.exists(manifestPath))
55911
57433
  return fail(
55912
57434
  "helper_not_installed",
@@ -56220,10 +57742,10 @@ function buildPrivateHelper(checkOnly, deps = defaultBuildDeps()) {
56220
57742
  const compiler = String(clangVersion.stdout || "").split("\n")[0] || "clang";
56221
57743
  steps.push({ step: "find compiler", ok: true, detail: compiler });
56222
57744
  const installDir = helperInstallDir(deps.env);
56223
- mkdirSync7(installDir, { recursive: true, mode: 448 });
56224
- const staging = mkdtempSync7(join27(installDir, ".staging-"));
57745
+ mkdirSync8(installDir, { recursive: true, mode: 448 });
57746
+ const staging = mkdtempSync7(join28(installDir, ".staging-"));
56225
57747
  try {
56226
- const stagedBinary = join27(staging, HELPER_BINARY_NAME);
57748
+ const stagedBinary = join28(staging, HELPER_BINARY_NAME);
56227
57749
  const compile = deps.spawn(
56228
57750
  "/usr/bin/xcrun",
56229
57751
  compileArguments(deps.sourcePath, stagedBinary, sourceSha),
@@ -56300,8 +57822,8 @@ function buildPrivateHelper(checkOnly, deps = defaultBuildDeps()) {
56300
57822
  compiler
56301
57823
  };
56302
57824
  chmodSync2(stagedBinary, 448);
56303
- renameSync2(stagedBinary, join27(installDir, HELPER_BINARY_NAME));
56304
- writeFileSync6(join27(installDir, MANIFEST_NAME), JSON.stringify(manifest, null, 2) + "\n", {
57825
+ renameSync2(stagedBinary, join28(installDir, HELPER_BINARY_NAME));
57826
+ writeFileSync6(join28(installDir, MANIFEST_NAME), JSON.stringify(manifest, null, 2) + "\n", {
56305
57827
  mode: 384
56306
57828
  });
56307
57829
  steps.push({ step: "install", ok: true, detail: installDir });
@@ -56827,7 +58349,7 @@ registerTool(
56827
58349
  registerTool(
56828
58350
  "search-notes",
56829
58351
  {
56830
- description: "Use when: finding notes by a keyword in the title (or body with searchContent=true) and you need their ids.\nReturns: matching notes with title, folder, and id; `source` says whether a body search read the Notes database or fell back to AppleScript.\nDo not use when: you already have a note id (use get-note-content), want every note (use list-notes), or need boolean or metadata filters (use query-notes).\nPrefer this first to obtain ids for subsequent read/update/delete/move calls.\nNote: with Full Disk Access, body search reads the Notes database (fast; the most recent 5000 notes, Recently Deleted excluded); without it, it falls back to AppleScript, which scans every body and can time out on broad terms.",
58352
+ description: "Use when: finding notes by a keyword in the title (or body with searchContent=true) and you need their ids.\nReturns: matching notes with title, folder, and id; `source` says whether a body search read the Notes database or fell back to AppleScript. When the note text came from the database, each result has matchedIn (title, body, or both); includeWordCount adds wordCount.\nDo not use when: you already have a note id (use get-note-content), want every note (use list-notes), or need boolean or metadata filters (use query-notes).\nPrefer this first to obtain ids for subsequent read/update/delete/move calls.\nNote: with Full Disk Access, body search reads the Notes database (fast; the most recent 5000 notes, Recently Deleted excluded); without it, it falls back to AppleScript, which scans every body and can time out on broad terms.",
56831
58353
  inputSchema: {
56832
58354
  query: external_exports.string().min(1, "Search query is required").max(MAX.QUERY),
56833
58355
  searchContent: external_exports.boolean().optional().describe(
@@ -56840,112 +58362,132 @@ registerTool(
56840
58362
  ),
56841
58363
  limit: external_exports.number().int().positive().optional().describe(
56842
58364
  "Maximum number of results to return. Defaults to 50 \u2014 a broad query reads several properties per match via AppleScript, so an unbounded search can time out. Pass a higher value to see more; the applied limit is disclosed in the response."
58365
+ ),
58366
+ includeWordCount: external_exports.boolean().optional().describe(
58367
+ "Add wordCount to each result (null when locked or unreadable). A database body search already has the text; otherwise the bodies are read in one batched read-only database query (needs Full Disk Access), which also adds matchedIn"
56843
58368
  )
56844
58369
  },
56845
58370
  outputSchema: {
56846
58371
  notes: external_exports.array(external_exports.object({}).passthrough()).optional(),
56847
58372
  count: external_exports.number().optional(),
56848
58373
  source: external_exports.enum(["database", "applescript"]).optional(),
56849
- scanTruncated: external_exports.boolean().optional()
58374
+ scanTruncated: external_exports.boolean().optional(),
58375
+ wordCountUnavailable: external_exports.string().optional()
56850
58376
  }
56851
58377
  },
56852
- withErrorHandling(({ query: query2, searchContent = false, account, folder, modifiedSince, limit }) => {
56853
- const effectiveLimit = resolveSearchLimit(limit);
56854
- const limitWasDefault = limit === void 0;
56855
- let source;
56856
- let dbScan;
56857
- let dbUnavailable;
56858
- const runSearch = () => {
56859
- if (searchContent) {
58378
+ withErrorHandling(
58379
+ ({ query: query2, searchContent = false, account, folder, modifiedSince, limit, includeWordCount }) => {
58380
+ const effectiveLimit = resolveSearchLimit(limit);
58381
+ const limitWasDefault = limit === void 0;
58382
+ let source;
58383
+ let dbScan;
58384
+ let dbUnavailable;
58385
+ const runSearch = () => {
58386
+ if (searchContent) {
58387
+ try {
58388
+ const db = searchContentViaDatabase({
58389
+ query: query2,
58390
+ account: notesManager.searchAccountScope(account),
58391
+ folder,
58392
+ modifiedSince,
58393
+ limit: effectiveLimit,
58394
+ includeWordCount
58395
+ });
58396
+ source = "database";
58397
+ dbScan = db.scan;
58398
+ return db.notes;
58399
+ } catch (error2) {
58400
+ if (!(error2 instanceof NoteQueryStoreError)) throw error2;
58401
+ dbUnavailable = error2.kind;
58402
+ }
58403
+ source = "applescript";
58404
+ }
56860
58405
  try {
56861
- const db = searchContentViaDatabase({
56862
- query: query2,
56863
- account: notesManager.searchAccountScope(account),
58406
+ return notesManager.searchNotes(
58407
+ query2,
58408
+ searchContent,
58409
+ account,
56864
58410
  folder,
56865
58411
  modifiedSince,
56866
- limit: effectiveLimit
56867
- });
56868
- source = "database";
56869
- dbScan = db.scan;
56870
- return db.notes;
58412
+ effectiveLimit
58413
+ );
56871
58414
  } catch (error2) {
56872
- if (!(error2 instanceof NoteQueryStoreError)) throw error2;
56873
- dbUnavailable = error2.kind;
58415
+ if (!searchContent || !(error2 instanceof Error)) throw error2;
58416
+ throw new Error(contentSearchFailureHint(error2.message, dbUnavailable));
56874
58417
  }
56875
- source = "applescript";
58418
+ };
58419
+ const {
58420
+ result: found,
58421
+ syncBefore,
58422
+ syncInterference
58423
+ } = withSyncAwarenessSync("search-notes", runSearch);
58424
+ let notes = found;
58425
+ let wordCountUnavailable;
58426
+ if (includeWordCount && source !== "database" && found.length > 0) {
58427
+ const enriched = addWordCountsFromDatabase(found, query2);
58428
+ notes = enriched.notes;
58429
+ wordCountUnavailable = enriched.unavailable;
58430
+ }
58431
+ const wordCountFields = wordCountUnavailable ? { wordCountUnavailable } : {};
58432
+ const wordCountNote = wordCountUnavailable ? `
58433
+
58434
+ \u2139\uFE0F Word counts were not added: ${wordCountUnavailable === "no_fda" ? "they are read from the Notes database, which needs Full Disk Access (run the doctor tool)" : "the Notes database could not be read"}.` : "";
58435
+ const searchType = searchContent ? source === "database" ? "content via the Notes database" : "content" : "titles";
58436
+ const sourceFields = source ? { source } : {};
58437
+ const scanFields = dbScan ? { scanTruncated: dbScan.scanTruncated } : {};
58438
+ const scanNote = describeContentScan(dbScan);
58439
+ const folderInfo = folder ? ` in folder "${folder}"` : "";
58440
+ const dateInfo = modifiedSince ? ` modified since ${modifiedSince}` : "";
58441
+ const { info: limitInfo, truncationNote } = describeSearchLimit(
58442
+ effectiveLimit,
58443
+ limitWasDefault,
58444
+ notes.length
58445
+ );
58446
+ const syncWarnings = [];
58447
+ if (syncBefore.syncDetected) {
58448
+ syncWarnings.push(`\u26A0\uFE0F iCloud sync was active during search.`);
56876
58449
  }
56877
- try {
56878
- return notesManager.searchNotes(
56879
- query2,
56880
- searchContent,
56881
- account,
56882
- folder,
56883
- modifiedSince,
56884
- effectiveLimit
56885
- );
56886
- } catch (error2) {
56887
- if (!searchContent || !(error2 instanceof Error)) throw error2;
56888
- throw new Error(contentSearchFailureHint(error2.message, dbUnavailable));
58450
+ if (syncInterference) {
58451
+ syncWarnings.push(`\u26A0\uFE0F Sync activity detected - results may be incomplete.`);
56889
58452
  }
56890
- };
56891
- const {
56892
- result: notes,
56893
- syncBefore,
56894
- syncInterference
56895
- } = withSyncAwarenessSync("search-notes", runSearch);
56896
- const searchType = searchContent ? source === "database" ? "content via the Notes database" : "content" : "titles";
56897
- const sourceFields = source ? { source } : {};
56898
- const scanFields = dbScan ? { scanTruncated: dbScan.scanTruncated } : {};
56899
- const scanNote = describeContentScan(dbScan);
56900
- const folderInfo = folder ? ` in folder "${folder}"` : "";
56901
- const dateInfo = modifiedSince ? ` modified since ${modifiedSince}` : "";
56902
- const { info: limitInfo, truncationNote } = describeSearchLimit(
56903
- effectiveLimit,
56904
- limitWasDefault,
56905
- notes.length
56906
- );
56907
- const syncWarnings = [];
56908
- if (syncBefore.syncDetected) {
56909
- syncWarnings.push(`\u26A0\uFE0F iCloud sync was active during search.`);
56910
- }
56911
- if (syncInterference) {
56912
- syncWarnings.push(`\u26A0\uFE0F Sync activity detected - results may be incomplete.`);
56913
- }
56914
- const syncNote = syncWarnings.length > 0 ? `
58453
+ const syncNote = syncWarnings.length > 0 ? `
56915
58454
 
56916
58455
  ${syncWarnings.join(" ")}` : "";
56917
- if (notes.length === 0) {
56918
- const scopeHint = describeSearchScope(searchContent, notes.length);
58456
+ if (notes.length === 0) {
58457
+ const scopeHint = describeSearchScope(searchContent, notes.length);
58458
+ return successResponse(
58459
+ `No notes found matching "${query2}" in ${searchType}${folderInfo}${dateInfo}${scopeHint}${scanNote}${syncNote}`,
58460
+ { notes: [], count: 0, ...sourceFields, ...scanFields }
58461
+ );
58462
+ }
58463
+ const noteList = notes.map((n) => {
58464
+ const idSuffix = `${n.id ? ` [id: ${n.id}]` : ""}${describeMatchDetails(n)}`;
58465
+ if (n.folder === "Recently Deleted") {
58466
+ return ` - ${n.title} [DELETED]${idSuffix}`;
58467
+ } else if (n.folder) {
58468
+ return ` - ${n.title} (${n.folder})${idSuffix}`;
58469
+ }
58470
+ return ` - ${n.title}${idSuffix}`;
58471
+ }).join("\n");
56919
58472
  return successResponse(
56920
- `No notes found matching "${query2}" in ${searchType}${folderInfo}${dateInfo}${scopeHint}${scanNote}${syncNote}`,
56921
- { notes: [], count: 0, ...sourceFields, ...scanFields }
58473
+ `Found ${notes.length} notes (searched ${searchType}${folderInfo}${dateInfo}${limitInfo}):
58474
+ ${noteList}${truncationNote}${scanNote}${wordCountNote}${syncNote}`,
58475
+ {
58476
+ notes: withStableIdentifiers(notes, "ICNote"),
58477
+ count: notes.length,
58478
+ ...sourceFields,
58479
+ ...scanFields,
58480
+ ...wordCountFields
58481
+ }
56922
58482
  );
56923
- }
56924
- const noteList = notes.map((n) => {
56925
- const idSuffix = n.id ? ` [id: ${n.id}]` : "";
56926
- if (n.folder === "Recently Deleted") {
56927
- return ` - ${n.title} [DELETED]${idSuffix}`;
56928
- } else if (n.folder) {
56929
- return ` - ${n.title} (${n.folder})${idSuffix}`;
56930
- }
56931
- return ` - ${n.title}${idSuffix}`;
56932
- }).join("\n");
56933
- return successResponse(
56934
- `Found ${notes.length} notes (searched ${searchType}${folderInfo}${dateInfo}${limitInfo}):
56935
- ${noteList}${truncationNote}${scanNote}${syncNote}`,
56936
- {
56937
- notes: withStableIdentifiers(notes, "ICNote"),
56938
- count: notes.length,
56939
- ...sourceFields,
56940
- ...scanFields
56941
- }
56942
- );
56943
- }, "Error searching notes")
58483
+ },
58484
+ "Error searching notes"
58485
+ )
56944
58486
  );
56945
58487
  registerTool(
56946
58488
  "query-notes",
56947
58489
  {
56948
- description: 'Use when: finding notes with a boolean expression over text and metadata \u2014 e.g. `folder:Work has:checklist -checklist:done`, `(title:invoice OR tag:finance) modified:>=2026-07-01`, `pinned words:>250`. Reads the Notes database directly, so it is fast and can match title OR body in one call.\nSyntax: bare words and "quoted phrases" match title or body (case-insensitive substring); fields title:, body:, text:, folder:, account:, tag: (values may be quoted, e.g. folder:"Work Projects"); facets has:link|attachment|checklist|drawing|image|video|audio|pdf|table|scan|tag; checklist:open|done; flags pinned, locked, shared (or is:pinned); words:>250 and created:/modified: with =, >, >=, <, <= and YYYY-MM-DD local dates. AND is implicit; OR, NOT, leading -, and parentheses are supported; operators are case-insensitive and a quoted "and" searches the literal word.\nReturns: matching notes (most recently modified first) with id, title, folder, account, modified date, and snippet, plus scan/match counts. Ids work with get-note-content and every other id-based tool.\nDo not use when: Full Disk Access is unavailable (use search-notes). Scans the most recent scanLimit notes (default 500); raise it for older notes.\nSafety: read-only; never writes the database. Excludes Recently Deleted and folderless notes unless includeDeleted is true. Locked notes match on title and metadata only; body predicates never match them.',
58490
+ description: 'Use when: finding notes with a boolean expression over text and metadata \u2014 e.g. `folder:Work has:checklist -checklist:done`, `(title:invoice OR tag:finance) modified:>=2026-07-01`, `pinned words:>250`. Reads the Notes database directly, so it is fast and can match title OR body in one call.\nSyntax: bare words and "quoted phrases" match title or body (case-insensitive substring); fields title:, body:, text:, folder:, account:, tag: (values may be quoted, e.g. folder:"Work Projects"); facets has:link|attachment|checklist|drawing|image|video|audio|pdf|table|scan|tag; checklist:open|done; flags pinned, locked, shared (or is:pinned); words:>250 and created:/modified: with =, >, >=, <, <= and YYYY-MM-DD local dates. AND is implicit; OR, NOT, leading -, and parentheses are supported; operators are case-insensitive and a quoted "and" searches the literal word.\nReturns: matching notes (most recently modified first) with id, title, folder, account, modified date, snippet, and matchedIn (where the positive text terms occur: title, body, or both; absent when the body is unreadable or the query has no text term), plus scan/match counts; includeWordCount adds wordCount. Ids work with get-note-content and every other id-based tool.\nDo not use when: Full Disk Access is unavailable (use search-notes). Scans the most recent scanLimit notes (default 500); raise it for older notes.\nSafety: read-only; never writes the database. Excludes Recently Deleted and folderless notes unless includeDeleted is true. Locked notes match on title and metadata only; body predicates never match them.',
56949
58491
  inputSchema: {
56950
58492
  query: external_exports.string().min(1, "A query expression is required").max(MAX.QUERY).describe(
56951
58493
  'Boolean query expression, e.g. `folder:"Work Projects" has:checklist -checklist:done`'
@@ -56958,6 +58500,9 @@ registerTool(
56958
58500
  ),
56959
58501
  includeDeleted: external_exports.boolean().optional().describe(
56960
58502
  "Also scan notes in Recently Deleted, notes pending deletion, and folderless notes (default false)"
58503
+ ),
58504
+ includeWordCount: external_exports.boolean().optional().describe(
58505
+ "Add wordCount to each returned note (the count words: filters on; null when locked or unreadable). Free when the query reads bodies; a metadata-only query reads just the returned notes' bodies in one extra query (default false)"
56961
58506
  )
56962
58507
  },
56963
58508
  outputSchema: {
@@ -56974,10 +58519,10 @@ registerTool(
56974
58519
  },
56975
58520
  annotations: { readOnlyHint: true }
56976
58521
  },
56977
- withErrorHandling(({ query: query2, limit, scanLimit, includeDeleted }) => {
58522
+ withErrorHandling(({ query: query2, limit, scanLimit, includeDeleted, includeWordCount }) => {
56978
58523
  let result;
56979
58524
  try {
56980
- result = queryNotes(query2, { limit, scanLimit, includeDeleted });
58525
+ result = queryNotes(query2, { limit, scanLimit, includeDeleted, includeWordCount });
56981
58526
  } catch (error2) {
56982
58527
  if (error2 instanceof NoteQueryError || error2 instanceof NoteQueryStoreError) {
56983
58528
  return errorResponse(
@@ -57008,7 +58553,7 @@ ${notes.join("\n")}` : "";
57008
58553
  const where = [n.account, n.folder].filter(Boolean).join(" / ");
57009
58554
  const snippet = n.snippet ? `
57010
58555
  ${n.snippet}` : "";
57011
- return ` - ${n.title}${where ? ` (${where})` : ""}${n.locked ? " [locked]" : ""} [id: ${n.id}]${snippet}`;
58556
+ return ` - ${n.title}${where ? ` (${where})` : ""}${n.locked ? " [locked]" : ""} [id: ${n.id}]${describeMatchDetails(n)}${snippet}`;
57012
58557
  }).join("\n");
57013
58558
  return successResponse(
57014
58559
  `Found ${result.matched} matching notes (${scope2}):
@@ -57875,10 +59420,10 @@ function guardedAppend({
57875
59420
  return `<div>${escaped || "<br>"}</div>`;
57876
59421
  }).join("");
57877
59422
  };
57878
- const separatorToHtml = (sep4) => {
57879
- if (format === "html") return sep4;
57880
- if (sep4 === "\n\n") return "<div><br></div>";
57881
- const escaped = sep4.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
59423
+ const separatorToHtml = (sep5) => {
59424
+ if (format === "html") return sep5;
59425
+ if (sep5 === "\n\n") return "<div><br></div>";
59426
+ const escaped = sep5.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
57882
59427
  return `<div>${escaped}</div>`;
57883
59428
  };
57884
59429
  const snapshot = readExactNoteSnapshot(id2);
@@ -59251,7 +60796,7 @@ var exportStatsSchema = external_exports.object({
59251
60796
  registerTool(
59252
60797
  "export-notes-markdown",
59253
60798
  {
59254
- 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.",
60799
+ 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.\nTemplates: pass template ('standard-markdown' reproduces the default output; 'obsidian' adds YAML front matter and copies attachments beside outputPath) or templateFile (a JSON template) to control how every block, inline style, attachment, per-note header/footer and separator renders. Templated receipts add template, warnings (e.g. missing_asset) and assetFiles; an invalid template is refused with [invalid-template] and every problem's JSON path.",
59255
60800
  inputSchema: {
59256
60801
  id: noteIdInput.optional(),
59257
60802
  folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder path to export instead of one note (nested paths use '/')"),
@@ -59261,7 +60806,13 @@ registerTool(
59261
60806
  ),
59262
60807
  outputPath: exportPathInput("File to create for the Markdown"),
59263
60808
  assetsDir: exportPathInput("Directory that receives copies of attachment files"),
59264
- wrap: external_exports.number().int().min(0).max(1e3).optional().describe("Hard-wrap prose at this many columns (0 or omitted: no wrapping)")
60809
+ wrap: external_exports.number().int().min(0).max(1e3).optional().describe("Hard-wrap prose at this many columns (0 or omitted: no wrapping)"),
60810
+ template: external_exports.string().min(1).max(64).optional().describe(
60811
+ `Render through this template: built-in ${BUILTIN_TEMPLATE_NAMES.map((n) => `'${n}'`).join(" or ")}. Exclusive with templateFile`
60812
+ ),
60813
+ templateFile: exportPathInput(
60814
+ "JSON template file (.json) to render through (exclusive with template; at most 256 KiB)"
60815
+ )
59265
60816
  },
59266
60817
  outputSchema: {
59267
60818
  format: external_exports.string().optional(),
@@ -59271,7 +60822,13 @@ registerTool(
59271
60822
  output: external_exports.string().optional(),
59272
60823
  assets: external_exports.object({ dir: external_exports.string(), files: external_exports.number() }).optional(),
59273
60824
  stats: exportStatsSchema.optional(),
59274
- skipped: external_exports.array(external_exports.object({ id: external_exports.string(), code: external_exports.string() })).optional()
60825
+ skipped: external_exports.array(external_exports.object({ id: external_exports.string(), code: external_exports.string() })).optional(),
60826
+ template: external_exports.object({ name: external_exports.string(), source: external_exports.string() }).optional(),
60827
+ warnings: external_exports.array(
60828
+ external_exports.object({ code: external_exports.string(), noteId: external_exports.string(), attachmentId: external_exports.string().optional() })
60829
+ ).optional(),
60830
+ warningsOmitted: external_exports.number().optional(),
60831
+ assetFiles: external_exports.array(external_exports.string()).optional()
59275
60832
  },
59276
60833
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
59277
60834
  },
@@ -59286,9 +60843,15 @@ registerTool(
59286
60843
  } catch (error2) {
59287
60844
  if (!(error2 instanceof NotesExportError || error2 instanceof NoteBlocksError)) throw error2;
59288
60845
  const hint = error2.code === "no-full-disk-access" ? ` Grant Full Disk Access to the Node binary running this server (run the doctor tool for its path): ${FULL_DISK_ACCESS_GUIDE_URL}` : "";
60846
+ if (error2 instanceof NotesExportError && error2.details)
60847
+ return errorResponse(
60848
+ `Error exporting Markdown [${error2.code}]: the template is invalid:
60849
+ ` + error2.details.map((detail) => `${detail.path}: ${detail.message}`).join("\n")
60850
+ );
59289
60851
  return errorResponse(`Error exporting Markdown [${error2.code}]: ${error2.message}${hint}`);
59290
60852
  }
59291
- const skipped = receipt.skipped.length ? `; skipped ${receipt.skipped.length}` : "";
60853
+ const warned = receipt.warnings?.length ? `; ${receipt.warnings.length + (receipt.warningsOmitted ?? 0)} warning(s)` : "";
60854
+ const skipped = (receipt.skipped.length ? `; skipped ${receipt.skipped.length}` : "") + warned;
59292
60855
  if (receipt.output)
59293
60856
  return successResponse(
59294
60857
  `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}.`,