@herb-tools/config 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,7 @@ bun add @herb-tools/config
33
33
  The configuration is stored in a `.herb.yml` file in the project root:
34
34
 
35
35
  ```yaml [.herb.yml]
36
- version: 0.8.2
36
+ version: 0.8.3
37
37
 
38
38
  linter:
39
39
  enabled: true
@@ -33,21 +33,30 @@ var actualFS__namespace = /*#__PURE__*/_interopNamespaceDefault(actualFS);
33
33
  /** A special constant with type `never` */
34
34
  function $constructor(name, initializer, params) {
35
35
  function init(inst, def) {
36
- var _a;
37
- Object.defineProperty(inst, "_zod", {
38
- value: inst._zod ?? {},
39
- enumerable: false,
40
- });
41
- (_a = inst._zod).traits ?? (_a.traits = new Set());
36
+ if (!inst._zod) {
37
+ Object.defineProperty(inst, "_zod", {
38
+ value: {
39
+ def,
40
+ constr: _,
41
+ traits: new Set(),
42
+ },
43
+ enumerable: false,
44
+ });
45
+ }
46
+ if (inst._zod.traits.has(name)) {
47
+ return;
48
+ }
42
49
  inst._zod.traits.add(name);
43
50
  initializer(inst, def);
44
51
  // support prototype modifications
45
- for (const k in _.prototype) {
46
- if (!(k in inst))
47
- Object.defineProperty(inst, k, { value: _.prototype[k].bind(inst) });
52
+ const proto = _.prototype;
53
+ const keys = Object.keys(proto);
54
+ for (let i = 0; i < keys.length; i++) {
55
+ const k = keys[i];
56
+ if (!(k in inst)) {
57
+ inst[k] = proto[k].bind(inst);
58
+ }
48
59
  }
49
- inst._zod.constr = _;
50
- inst._zod.def = def;
51
60
  }
52
61
  // doesn't work if Parent has a constructor with arguments
53
62
  const Parent = params?.Parent ?? Object;
@@ -182,6 +191,14 @@ function mergeDefs(...defs) {
182
191
  function esc(str) {
183
192
  return JSON.stringify(str);
184
193
  }
194
+ function slugify(input) {
195
+ return input
196
+ .toLowerCase()
197
+ .trim()
198
+ .replace(/[^\w\s-]/g, "")
199
+ .replace(/[\s_-]+/g, "-")
200
+ .replace(/^-+|-+$/g, "");
201
+ }
185
202
  const captureStackTrace = ("captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => { });
186
203
  function isObject$1(data) {
187
204
  return typeof data === "object" && data !== null && !Array.isArray(data);
@@ -207,6 +224,8 @@ function isPlainObject(o) {
207
224
  const ctor = o.constructor;
208
225
  if (ctor === undefined)
209
226
  return true;
227
+ if (typeof ctor !== "function")
228
+ return true;
210
229
  // modified prototype
211
230
  const prot = ctor.prototype;
212
231
  if (isObject$1(prot) === false)
@@ -670,9 +689,6 @@ const cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?:
670
689
  // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
671
690
  const base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
672
691
  const base64url = /^[A-Za-z0-9_-]*$/;
673
- // based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
674
- // export const hostname: RegExp = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
675
- const hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
676
692
  // https://blog.stevenlevithan.com/archives/validate-phone-number#r4-3 (regex sans spaces)
677
693
  const e164 = /^\+(?:[0-9]){6,14}[0-9]$/;
678
694
  // const dateSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
@@ -1163,7 +1179,7 @@ class Doc {
1163
1179
  const version$1 = {
1164
1180
  major: 4,
1165
1181
  minor: 1,
1166
- patch: 12,
1182
+ patch: 13,
1167
1183
  };
1168
1184
 
1169
1185
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
@@ -1366,7 +1382,7 @@ const $ZodURL = /*@__PURE__*/ $constructor("$ZodURL", (inst, def) => {
1366
1382
  code: "invalid_format",
1367
1383
  format: "url",
1368
1384
  note: "Invalid hostname",
1369
- pattern: hostname.source,
1385
+ pattern: def.hostname.source,
1370
1386
  input: payload.value,
1371
1387
  inst,
1372
1388
  continue: !def.abort,
@@ -1456,18 +1472,12 @@ const $ZodISODuration = /*@__PURE__*/ $constructor("$ZodISODuration", (inst, def
1456
1472
  const $ZodIPv4 = /*@__PURE__*/ $constructor("$ZodIPv4", (inst, def) => {
1457
1473
  def.pattern ?? (def.pattern = ipv4);
1458
1474
  $ZodStringFormat.init(inst, def);
1459
- inst._zod.onattach.push((inst) => {
1460
- const bag = inst._zod.bag;
1461
- bag.format = `ipv4`;
1462
- });
1475
+ inst._zod.bag.format = `ipv4`;
1463
1476
  });
1464
1477
  const $ZodIPv6 = /*@__PURE__*/ $constructor("$ZodIPv6", (inst, def) => {
1465
1478
  def.pattern ?? (def.pattern = ipv6);
1466
1479
  $ZodStringFormat.init(inst, def);
1467
- inst._zod.onattach.push((inst) => {
1468
- const bag = inst._zod.bag;
1469
- bag.format = `ipv6`;
1470
- });
1480
+ inst._zod.bag.format = `ipv6`;
1471
1481
  inst._zod.check = (payload) => {
1472
1482
  try {
1473
1483
  // @ts-ignore
@@ -1537,9 +1547,7 @@ function isValidBase64(data) {
1537
1547
  const $ZodBase64 = /*@__PURE__*/ $constructor("$ZodBase64", (inst, def) => {
1538
1548
  def.pattern ?? (def.pattern = base64);
1539
1549
  $ZodStringFormat.init(inst, def);
1540
- inst._zod.onattach.push((inst) => {
1541
- inst._zod.bag.contentEncoding = "base64";
1542
- });
1550
+ inst._zod.bag.contentEncoding = "base64";
1543
1551
  inst._zod.check = (payload) => {
1544
1552
  if (isValidBase64(payload.value))
1545
1553
  return;
@@ -1563,9 +1571,7 @@ function isValidBase64URL(data) {
1563
1571
  const $ZodBase64URL = /*@__PURE__*/ $constructor("$ZodBase64URL", (inst, def) => {
1564
1572
  def.pattern ?? (def.pattern = base64url);
1565
1573
  $ZodStringFormat.init(inst, def);
1566
- inst._zod.onattach.push((inst) => {
1567
- inst._zod.bag.contentEncoding = "base64url";
1568
- });
1574
+ inst._zod.bag.contentEncoding = "base64url";
1569
1575
  inst._zod.check = (payload) => {
1570
1576
  if (isValidBase64URL(payload.value))
1571
1577
  return;
@@ -1649,9 +1655,9 @@ const $ZodNumber = /*@__PURE__*/ $constructor("$ZodNumber", (inst, def) => {
1649
1655
  return payload;
1650
1656
  };
1651
1657
  });
1652
- const $ZodNumberFormat = /*@__PURE__*/ $constructor("$ZodNumber", (inst, def) => {
1658
+ const $ZodNumberFormat = /*@__PURE__*/ $constructor("$ZodNumberFormat", (inst, def) => {
1653
1659
  $ZodCheckNumberFormat.init(inst, def);
1654
- $ZodNumber.init(inst, def); // no format checksp
1660
+ $ZodNumber.init(inst, def); // no format checks
1655
1661
  });
1656
1662
  const $ZodBoolean = /*@__PURE__*/ $constructor("$ZodBoolean", (inst, def) => {
1657
1663
  $ZodType.init(inst, def);
@@ -1765,7 +1771,7 @@ function handleCatchall(proms, input, payload, ctx, def, inst) {
1765
1771
  const keySet = def.keySet;
1766
1772
  const _catchall = def.catchall._zod;
1767
1773
  const t = _catchall.def.type;
1768
- for (const key of Object.keys(input)) {
1774
+ for (const key in input) {
1769
1775
  if (keySet.has(key))
1770
1776
  continue;
1771
1777
  if (t === "never") {
@@ -2096,11 +2102,13 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
2096
2102
  return payload;
2097
2103
  }
2098
2104
  const proms = [];
2099
- if (def.keyType._zod.values) {
2100
- const values = def.keyType._zod.values;
2105
+ const values = def.keyType._zod.values;
2106
+ if (values) {
2101
2107
  payload.value = {};
2108
+ const recordKeys = new Set();
2102
2109
  for (const key of values) {
2103
2110
  if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
2111
+ recordKeys.add(typeof key === "number" ? key.toString() : key);
2104
2112
  const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
2105
2113
  if (result instanceof Promise) {
2106
2114
  proms.push(result.then((result) => {
@@ -2120,7 +2128,7 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
2120
2128
  }
2121
2129
  let unrecognized;
2122
2130
  for (const key in input) {
2123
- if (!values.has(key)) {
2131
+ if (!recordKeys.has(key)) {
2124
2132
  unrecognized = unrecognized ?? [];
2125
2133
  unrecognized.push(key);
2126
2134
  }
@@ -2415,8 +2423,8 @@ const $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
2415
2423
  $ZodType.init(inst, def);
2416
2424
  defineLazy(inst._zod, "propValues", () => def.innerType._zod.propValues);
2417
2425
  defineLazy(inst._zod, "values", () => def.innerType._zod.values);
2418
- defineLazy(inst._zod, "optin", () => def.innerType._zod.optin);
2419
- defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
2426
+ defineLazy(inst._zod, "optin", () => def.innerType?._zod?.optin);
2427
+ defineLazy(inst._zod, "optout", () => def.innerType?._zod?.optout);
2420
2428
  inst._zod.parse = (payload, ctx) => {
2421
2429
  if (ctx.direction === "backward") {
2422
2430
  return def.innerType._zod.run(payload, ctx);
@@ -2464,6 +2472,7 @@ function handleRefineResult(result, payload, input, inst) {
2464
2472
  }
2465
2473
  }
2466
2474
 
2475
+ var _a;
2467
2476
  class $ZodRegistry {
2468
2477
  constructor() {
2469
2478
  this._map = new WeakMap();
@@ -2513,7 +2522,8 @@ class $ZodRegistry {
2513
2522
  function registry() {
2514
2523
  return new $ZodRegistry();
2515
2524
  }
2516
- const globalRegistry = /*@__PURE__*/ registry();
2525
+ (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
2526
+ const globalRegistry = globalThis.__zod_globalRegistry;
2517
2527
 
2518
2528
  function _string(Class, params) {
2519
2529
  return new Class({
@@ -2920,6 +2930,10 @@ function _toLowerCase() {
2920
2930
  function _toUpperCase() {
2921
2931
  return _overwrite((input) => input.toUpperCase());
2922
2932
  }
2933
+ // slugify
2934
+ function _slugify() {
2935
+ return _overwrite((input) => slugify(input));
2936
+ }
2923
2937
  function _array(Class, element, params) {
2924
2938
  return new Class({
2925
2939
  type: "array",
@@ -3163,6 +3177,7 @@ const _ZodString = /*@__PURE__*/ $constructor("_ZodString", (inst, def) => {
3163
3177
  inst.normalize = (...args) => inst.check(_normalize(...args));
3164
3178
  inst.toLowerCase = () => inst.check(_toLowerCase());
3165
3179
  inst.toUpperCase = () => inst.check(_toUpperCase());
3180
+ inst.slugify = () => inst.check(_slugify());
3166
3181
  });
3167
3182
  const ZodString = /*@__PURE__*/ $constructor("ZodString", (inst, def) => {
3168
3183
  $ZodString.init(inst, def);
@@ -11807,11 +11822,11 @@ function deepMerge(target, source) {
11807
11822
  return output;
11808
11823
  }
11809
11824
 
11810
- var version = "0.8.2";
11825
+ var version = "0.8.3";
11811
11826
  var packageJson = {
11812
11827
  version: version};
11813
11828
 
11814
- var configTemplate = "# This file configures Herb for your project and team.\n# Settings here take precedence over individual editor preferences.\n#\n# Herb is a suite of tools for HTML+ERB templates including:\n# - Linter: Validates templates and enforces best practices\n# - Formatter: Auto-formats templates with intelligent indentation\n# - Language Server: Provides IDE support (VS Code, Zed, Neovim, etc.)\n#\n# Website: https://herb-tools.dev\n# Configuration: https://herb-tools.dev/configuration\n# GitHub Repo: https://github.com/marcoroth/herb\n#\n\nversion: 0.8.2\n\n# files:\n# # Additional patterns beyond the defaults (**.html, **.rhtml, **.html.erb, etc.)\n# include:\n# - '**/*.xml.erb'\n# - 'custom/**/*.html'\n#\n# # Patterns to exclude (can exclude defaults too)\n# exclude:\n# - 'public/**/*'\n# - 'tmp/**/*'\n\nlinter:\n enabled: true\n\n # # Additional patterns beyond the defaults for linting\n # include:\n # - '**/*.xml.erb'\n #\n # # Patterns to exclude from linting\n # exclude:\n # - 'app/views/admin/**/*'\n\n # rules:\n # erb-no-extra-newline:\n # enabled: false\n #\n # # Rules can have 'include', 'only', and 'exclude' patterns\n # some-rule:\n # # Additional patterns to check (additive, ignored when 'only' is present)\n # include:\n # - 'app/components/**/*'\n # # Don't apply this rule to files matching these patterns\n # exclude:\n # - 'app/views/admin/**/*'\n #\n # another-rule:\n # # Only apply this rule to files matching these patterns (overrides all 'include')\n # only:\n # - 'app/views/**/*'\n # # Exclude still applies even with 'only'\n # exclude:\n # - 'app/views/admin/**/*'\n\nformatter:\n enabled: false\n indentWidth: 2\n maxLineLength: 80\n\n # # Additional patterns beyond the defaults for formatting\n # include:\n # - '**/*.xml.erb'\n #\n # # Patterns to exclude from formatting\n # exclude:\n # - 'app/views/admin/**/*'\n\n # # Rewriters modify templates during formatting\n # rewriter:\n # # Pre-format rewriters (modify AST before formatting)\n # pre:\n # - tailwind-class-sorter\n # # Post-format rewriters (modify formatted output string)\n # post: []\n";
11829
+ var configTemplate = "# This file configures Herb for your project and team.\n# Settings here take precedence over individual editor preferences.\n#\n# Herb is a suite of tools for HTML+ERB templates including:\n# - Linter: Validates templates and enforces best practices\n# - Formatter: Auto-formats templates with intelligent indentation\n# - Language Server: Provides IDE support (VS Code, Zed, Neovim, etc.)\n#\n# Website: https://herb-tools.dev\n# Configuration: https://herb-tools.dev/configuration\n# GitHub Repo: https://github.com/marcoroth/herb\n#\n\nversion: 0.8.3\n\n# files:\n# # Additional patterns beyond the defaults (**.html, **.rhtml, **.html.erb, etc.)\n# include:\n# - '**/*.xml.erb'\n# - 'custom/**/*.html'\n#\n# # Patterns to exclude (can exclude defaults too)\n# exclude:\n# - 'public/**/*'\n# - 'tmp/**/*'\n\nlinter:\n enabled: true\n\n # # Additional patterns beyond the defaults for linting\n # include:\n # - '**/*.xml.erb'\n #\n # # Patterns to exclude from linting\n # exclude:\n # - 'app/views/admin/**/*'\n\n # rules:\n # erb-no-extra-newline:\n # enabled: false\n #\n # # Rules can have 'include', 'only', and 'exclude' patterns\n # some-rule:\n # # Additional patterns to check (additive, ignored when 'only' is present)\n # include:\n # - 'app/components/**/*'\n # # Don't apply this rule to files matching these patterns\n # exclude:\n # - 'app/views/admin/**/*'\n #\n # another-rule:\n # # Only apply this rule to files matching these patterns (overrides all 'include')\n # only:\n # - 'app/views/**/*'\n # # Exclude still applies even with 'only'\n # exclude:\n # - 'app/views/admin/**/*'\n\nformatter:\n enabled: false\n indentWidth: 2\n maxLineLength: 80\n\n # # Additional patterns beyond the defaults for formatting\n # include:\n # - '**/*.xml.erb'\n #\n # # Patterns to exclude from formatting\n # exclude:\n # - 'app/views/admin/**/*'\n\n # # Rewriters modify templates during formatting\n # rewriter:\n # # Pre-format rewriters (modify AST before formatting)\n # pre:\n # - tailwind-class-sorter\n # # Post-format rewriters (modify formatted output string)\n # post: []\n";
11815
11830
 
11816
11831
  const DEFAULT_VERSION = packageJson.version;
11817
11832
  class Config {