@canonical/utils 0.17.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/esm/casing/capitalize.js +12 -0
  2. package/dist/esm/casing/capitalize.js.map +1 -0
  3. package/dist/esm/casing/capitalize.test.js +17 -0
  4. package/dist/esm/casing/capitalize.test.js.map +1 -0
  5. package/dist/esm/casing/index.js +8 -0
  6. package/dist/esm/casing/index.js.map +1 -0
  7. package/dist/esm/casing/isPascalCase.js +11 -0
  8. package/dist/esm/casing/isPascalCase.js.map +1 -0
  9. package/dist/esm/casing/isPascalCase.test.js +22 -0
  10. package/dist/esm/casing/isPascalCase.test.js.map +1 -0
  11. package/dist/esm/casing/toCamelCase.js +15 -0
  12. package/dist/esm/casing/toCamelCase.js.map +1 -0
  13. package/dist/esm/casing/toCamelCase.test.js +20 -0
  14. package/dist/esm/casing/toCamelCase.test.js.map +1 -0
  15. package/dist/esm/casing/toConstantCase.js +14 -0
  16. package/dist/esm/casing/toConstantCase.js.map +1 -0
  17. package/dist/esm/casing/toConstantCase.test.js +17 -0
  18. package/dist/esm/casing/toConstantCase.test.js.map +1 -0
  19. package/dist/esm/casing/toKebabCase.js +21 -0
  20. package/dist/esm/casing/toKebabCase.js.map +1 -0
  21. package/dist/esm/casing/toKebabCase.test.js +26 -0
  22. package/dist/esm/casing/toKebabCase.test.js.map +1 -0
  23. package/dist/esm/casing/toPascalCase.js +16 -0
  24. package/dist/esm/casing/toPascalCase.js.map +1 -0
  25. package/dist/esm/casing/toPascalCase.test.js +20 -0
  26. package/dist/esm/casing/toPascalCase.test.js.map +1 -0
  27. package/dist/esm/casing/toSnakeCase.js +17 -0
  28. package/dist/esm/casing/toSnakeCase.js.map +1 -0
  29. package/dist/esm/casing/toSnakeCase.test.js +20 -0
  30. package/dist/esm/casing/toSnakeCase.test.js.map +1 -0
  31. package/dist/esm/debounce.test.js +68 -0
  32. package/dist/esm/debounce.test.js.map +1 -0
  33. package/dist/esm/indent.js +14 -0
  34. package/dist/esm/indent.js.map +1 -0
  35. package/dist/esm/indent.test.js +14 -0
  36. package/dist/esm/indent.test.js.map +1 -0
  37. package/dist/esm/index.js +3 -1
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/join.js +11 -0
  40. package/dist/esm/join.js.map +1 -0
  41. package/dist/esm/join.test.js +17 -0
  42. package/dist/esm/join.test.js.map +1 -0
  43. package/dist/esm/throttle.test.js +59 -0
  44. package/dist/esm/throttle.test.js.map +1 -0
  45. package/dist/types/casing/capitalize.d.ts +8 -0
  46. package/dist/types/casing/capitalize.d.ts.map +1 -0
  47. package/dist/types/casing/capitalize.test.d.ts +2 -0
  48. package/dist/types/casing/capitalize.test.d.ts.map +1 -0
  49. package/dist/types/casing/index.d.ts +8 -0
  50. package/dist/types/casing/index.d.ts.map +1 -0
  51. package/dist/types/casing/isPascalCase.d.ts +9 -0
  52. package/dist/types/casing/isPascalCase.d.ts.map +1 -0
  53. package/dist/types/casing/isPascalCase.test.d.ts +2 -0
  54. package/dist/types/casing/isPascalCase.test.d.ts.map +1 -0
  55. package/dist/types/casing/toCamelCase.d.ts +9 -0
  56. package/dist/types/casing/toCamelCase.d.ts.map +1 -0
  57. package/dist/types/casing/toCamelCase.test.d.ts +2 -0
  58. package/dist/types/casing/toCamelCase.test.d.ts.map +1 -0
  59. package/dist/types/casing/toConstantCase.d.ts +9 -0
  60. package/dist/types/casing/toConstantCase.d.ts.map +1 -0
  61. package/dist/types/casing/toConstantCase.test.d.ts +2 -0
  62. package/dist/types/casing/toConstantCase.test.d.ts.map +1 -0
  63. package/dist/types/casing/toKebabCase.d.ts +12 -0
  64. package/dist/types/casing/toKebabCase.d.ts.map +1 -0
  65. package/dist/types/casing/toKebabCase.test.d.ts +2 -0
  66. package/dist/types/casing/toKebabCase.test.d.ts.map +1 -0
  67. package/dist/types/casing/toPascalCase.d.ts +9 -0
  68. package/dist/types/casing/toPascalCase.d.ts.map +1 -0
  69. package/dist/types/casing/toPascalCase.test.d.ts +2 -0
  70. package/dist/types/casing/toPascalCase.test.d.ts.map +1 -0
  71. package/dist/types/casing/toSnakeCase.d.ts +10 -0
  72. package/dist/types/casing/toSnakeCase.d.ts.map +1 -0
  73. package/dist/types/casing/toSnakeCase.test.d.ts +2 -0
  74. package/dist/types/casing/toSnakeCase.test.d.ts.map +1 -0
  75. package/dist/types/debounce.test.d.ts +2 -0
  76. package/dist/types/debounce.test.d.ts.map +1 -0
  77. package/dist/types/indent.d.ts +8 -0
  78. package/dist/types/indent.d.ts.map +1 -0
  79. package/dist/types/indent.test.d.ts +2 -0
  80. package/dist/types/indent.test.d.ts.map +1 -0
  81. package/dist/types/index.d.ts +3 -1
  82. package/dist/types/index.d.ts.map +1 -1
  83. package/dist/types/join.d.ts +9 -0
  84. package/dist/types/join.d.ts.map +1 -0
  85. package/dist/types/join.test.d.ts +2 -0
  86. package/dist/types/join.test.d.ts.map +1 -0
  87. package/dist/types/throttle.test.d.ts +2 -0
  88. package/dist/types/throttle.test.d.ts.map +1 -0
  89. package/package.json +14 -14
  90. package/dist/esm/casing.js +0 -66
  91. package/dist/esm/casing.js.map +0 -1
  92. package/dist/types/casing.d.ts +0 -8
  93. package/dist/types/casing.d.ts.map +0 -1
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Capitalize the first character of a string.
3
+ *
4
+ * @example
5
+ * capitalize("hello") // "Hello"
6
+ */
7
+ export default function capitalize(s) {
8
+ if (!s)
9
+ return "";
10
+ return s.charAt(0).toUpperCase() + s.slice(1);
11
+ }
12
+ //# sourceMappingURL=capitalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.js","sourceRoot":"","sources":["../../../src/casing/capitalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAS;IAC1C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import capitalize from "./capitalize.js";
3
+ describe("capitalize", () => {
4
+ it("capitalizes the first character", () => {
5
+ expect(capitalize("hello")).toBe("Hello");
6
+ });
7
+ it("preserves the rest of the string", () => {
8
+ expect(capitalize("hello world")).toBe("Hello world");
9
+ });
10
+ it("handles already capitalized strings", () => {
11
+ expect(capitalize("Hello")).toBe("Hello");
12
+ });
13
+ it("returns empty string for empty input", () => {
14
+ expect(capitalize("")).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=capitalize.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.test.js","sourceRoot":"","sources":["../../../src/casing/capitalize.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { default as capitalize } from "./capitalize.js";
2
+ export { default as isPascalCase } from "./isPascalCase.js";
3
+ export { default as toCamelCase } from "./toCamelCase.js";
4
+ export { default as toConstantCase } from "./toConstantCase.js";
5
+ export { default as toKebabCase } from "./toKebabCase.js";
6
+ export { default as toPascalCase } from "./toPascalCase.js";
7
+ export { default as toSnakeCase } from "./toSnakeCase.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/casing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Check if a string is in PascalCase.
3
+ *
4
+ * @example
5
+ * isPascalCase("MyComponent") // true
6
+ * isPascalCase("myComponent") // false
7
+ */
8
+ export default function isPascalCase(s) {
9
+ return /^[A-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/.test(s);
10
+ }
11
+ //# sourceMappingURL=isPascalCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.js","sourceRoot":"","sources":["../../../src/casing/isPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAS;IAC5C,OAAO,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import isPascalCase from "./isPascalCase.js";
3
+ describe("isPascalCase", () => {
4
+ it("returns true for PascalCase strings", () => {
5
+ expect(isPascalCase("MyComponent")).toBe(true);
6
+ expect(isPascalCase("Hello")).toBe(true);
7
+ expect(isPascalCase("A")).toBe(true);
8
+ });
9
+ it("returns false for camelCase", () => {
10
+ expect(isPascalCase("myComponent")).toBe(false);
11
+ });
12
+ it("returns false for kebab-case", () => {
13
+ expect(isPascalCase("my-component")).toBe(false);
14
+ });
15
+ it("returns false for snake_case", () => {
16
+ expect(isPascalCase("my_component")).toBe(false);
17
+ });
18
+ it("returns false for empty string", () => {
19
+ expect(isPascalCase("")).toBe(false);
20
+ });
21
+ });
22
+ //# sourceMappingURL=isPascalCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.test.js","sourceRoot":"","sources":["../../../src/casing/isPascalCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Convert a string to camelCase.
3
+ *
4
+ * @example
5
+ * toCamelCase("my-component") // "myComponent"
6
+ * toCamelCase("some_thing") // "someThing"
7
+ */
8
+ export default function toCamelCase(s) {
9
+ if (!s)
10
+ return "";
11
+ return s
12
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
13
+ .replace(/^[A-Z]/, (c) => c.toLowerCase());
14
+ }
15
+ //# sourceMappingURL=toCamelCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.js","sourceRoot":"","sources":["../../../src/casing/toCamelCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toCamelCase from "./toCamelCase.js";
3
+ describe("toCamelCase", () => {
4
+ it("converts kebab-case", () => {
5
+ expect(toCamelCase("my-component")).toBe("myComponent");
6
+ });
7
+ it("converts snake_case", () => {
8
+ expect(toCamelCase("some_thing")).toBe("someThing");
9
+ });
10
+ it("converts space-separated", () => {
11
+ expect(toCamelCase("hello world")).toBe("helloWorld");
12
+ });
13
+ it("lowercases leading uppercase", () => {
14
+ expect(toCamelCase("MyComponent")).toBe("myComponent");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toCamelCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toCamelCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.test.js","sourceRoot":"","sources":["../../../src/casing/toCamelCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import toSnakeCase from "./toSnakeCase.js";
2
+ /**
3
+ * Convert a string to CONSTANT_CASE.
4
+ *
5
+ * @example
6
+ * toConstantCase("myComponent") // "MY_COMPONENT"
7
+ * toConstantCase("some-thing") // "SOME_THING"
8
+ */
9
+ export default function toConstantCase(s) {
10
+ if (!s)
11
+ return "";
12
+ return toSnakeCase(s).toUpperCase();
13
+ }
14
+ //# sourceMappingURL=toConstantCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.js","sourceRoot":"","sources":["../../../src/casing/toConstantCase.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAS;IAC9C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toConstantCase from "./toConstantCase.js";
3
+ describe("toConstantCase", () => {
4
+ it("converts camelCase", () => {
5
+ expect(toConstantCase("myComponent")).toBe("MY_COMPONENT");
6
+ });
7
+ it("converts kebab-case", () => {
8
+ expect(toConstantCase("some-thing")).toBe("SOME_THING");
9
+ });
10
+ it("converts PascalCase", () => {
11
+ expect(toConstantCase("MyComponent")).toBe("MY_COMPONENT");
12
+ });
13
+ it("returns empty string for empty input", () => {
14
+ expect(toConstantCase("")).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=toConstantCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.test.js","sourceRoot":"","sources":["../../../src/casing/toConstantCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Convert a string to kebab-case.
3
+ *
4
+ * Handles camelCase, PascalCase, snake_case, spaces, and consecutive uppercase.
5
+ *
6
+ * @example
7
+ * toKebabCase("MyComponent") // "my-component"
8
+ * toKebabCase("some_thing") // "some-thing"
9
+ * toKebabCase("HTMLParser") // "html-parser"
10
+ */
11
+ export default function toKebabCase(s) {
12
+ if (!s)
13
+ return "";
14
+ return s
15
+ .trim()
16
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
17
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1-$2")
18
+ .replace(/[\s_]+/g, "-")
19
+ .toLowerCase();
20
+ }
21
+ //# sourceMappingURL=toKebabCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.js","sourceRoot":"","sources":["../../../src/casing/toKebabCase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,IAAI,EAAE;SACN,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,sBAAsB,EAAE,OAAO,CAAC;SACxC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toKebabCase from "./toKebabCase.js";
3
+ describe("toKebabCase", () => {
4
+ it("converts PascalCase", () => {
5
+ expect(toKebabCase("MyComponent")).toBe("my-component");
6
+ });
7
+ it("converts camelCase", () => {
8
+ expect(toKebabCase("myComponent")).toBe("my-component");
9
+ });
10
+ it("converts snake_case", () => {
11
+ expect(toKebabCase("some_thing")).toBe("some-thing");
12
+ });
13
+ it("converts spaces", () => {
14
+ expect(toKebabCase("hello world")).toBe("hello-world");
15
+ });
16
+ it("handles consecutive uppercase", () => {
17
+ expect(toKebabCase("HTMLParser")).toBe("html-parser");
18
+ });
19
+ it("returns empty string for empty input", () => {
20
+ expect(toKebabCase("")).toBe("");
21
+ });
22
+ it("trims whitespace", () => {
23
+ expect(toKebabCase(" MyComponent ")).toBe("my-component");
24
+ });
25
+ });
26
+ //# sourceMappingURL=toKebabCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.test.js","sourceRoot":"","sources":["../../../src/casing/toKebabCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Convert a string to PascalCase.
3
+ *
4
+ * @example
5
+ * toPascalCase("my-component") // "MyComponent"
6
+ * toPascalCase("some_thing") // "SomeThing"
7
+ */
8
+ export default function toPascalCase(s) {
9
+ if (!s)
10
+ return "";
11
+ const camel = s
12
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
13
+ .replace(/^[A-Z]/, (c) => c.toLowerCase());
14
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
15
+ }
16
+ //# sourceMappingURL=toPascalCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../src/casing/toPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAS;IAC5C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,KAAK,GAAG,CAAC;SACZ,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAE7C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toPascalCase from "./toPascalCase.js";
3
+ describe("toPascalCase", () => {
4
+ it("converts kebab-case", () => {
5
+ expect(toPascalCase("my-component")).toBe("MyComponent");
6
+ });
7
+ it("converts snake_case", () => {
8
+ expect(toPascalCase("some_thing")).toBe("SomeThing");
9
+ });
10
+ it("converts space-separated", () => {
11
+ expect(toPascalCase("hello world")).toBe("HelloWorld");
12
+ });
13
+ it("handles already PascalCase", () => {
14
+ expect(toPascalCase("MyComponent")).toBe("MyComponent");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toPascalCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toPascalCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.test.js","sourceRoot":"","sources":["../../../src/casing/toPascalCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Convert a string to snake_case.
3
+ *
4
+ * @example
5
+ * toSnakeCase("myComponent") // "my_component"
6
+ * toSnakeCase("MyComponent") // "my_component"
7
+ * toSnakeCase("some-thing") // "some_thing"
8
+ */
9
+ export default function toSnakeCase(s) {
10
+ if (!s)
11
+ return "";
12
+ return s
13
+ .replace(/([a-z])([A-Z])/g, "$1_$2")
14
+ .replace(/[\s-]+/g, "_")
15
+ .toLowerCase();
16
+ }
17
+ //# sourceMappingURL=toSnakeCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.js","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toSnakeCase from "./toSnakeCase.js";
3
+ describe("toSnakeCase", () => {
4
+ it("converts camelCase", () => {
5
+ expect(toSnakeCase("myComponent")).toBe("my_component");
6
+ });
7
+ it("converts PascalCase", () => {
8
+ expect(toSnakeCase("MyComponent")).toBe("my_component");
9
+ });
10
+ it("converts kebab-case", () => {
11
+ expect(toSnakeCase("some-thing")).toBe("some_thing");
12
+ });
13
+ it("converts spaces", () => {
14
+ expect(toSnakeCase("hello world")).toBe("hello_world");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toSnakeCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toSnakeCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.test.js","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import debounce from "./debounce.js";
3
+ describe("debounce", () => {
4
+ beforeEach(() => {
5
+ vi.useFakeTimers();
6
+ });
7
+ afterEach(() => {
8
+ vi.useRealTimers();
9
+ });
10
+ it("delays execution until after the wait period", async () => {
11
+ const fn = vi.fn(() => 42);
12
+ const debounced = debounce(fn, 100);
13
+ const promise = debounced();
14
+ expect(fn).not.toHaveBeenCalled();
15
+ vi.advanceTimersByTime(100);
16
+ await expect(promise).resolves.toBe(42);
17
+ expect(fn).toHaveBeenCalledOnce();
18
+ });
19
+ it("only calls the function once for rapid invocations", async () => {
20
+ const fn = vi.fn((x) => x * 2);
21
+ const debounced = debounce(fn, 100);
22
+ debounced(1);
23
+ debounced(2);
24
+ const promise = debounced(3);
25
+ vi.advanceTimersByTime(100);
26
+ await expect(promise).resolves.toBe(6);
27
+ expect(fn).toHaveBeenCalledOnce();
28
+ expect(fn).toHaveBeenCalledWith(3);
29
+ });
30
+ it("resets the timer on each call", async () => {
31
+ const fn = vi.fn(() => "done");
32
+ const debounced = debounce(fn, 100);
33
+ debounced();
34
+ vi.advanceTimersByTime(50);
35
+ expect(fn).not.toHaveBeenCalled();
36
+ const promise = debounced();
37
+ vi.advanceTimersByTime(50);
38
+ expect(fn).not.toHaveBeenCalled();
39
+ vi.advanceTimersByTime(50);
40
+ await expect(promise).resolves.toBe("done");
41
+ expect(fn).toHaveBeenCalledOnce();
42
+ });
43
+ it("cancel prevents the function from being called", () => {
44
+ const fn = vi.fn();
45
+ const debounced = debounce(fn, 100);
46
+ debounced();
47
+ debounced.cancel();
48
+ vi.advanceTimersByTime(200);
49
+ expect(fn).not.toHaveBeenCalled();
50
+ });
51
+ it("propagates errors from the debounced function", async () => {
52
+ const fn = vi.fn(() => {
53
+ throw new Error("boom");
54
+ });
55
+ const debounced = debounce(fn, 100);
56
+ const promise = debounced();
57
+ vi.advanceTimersByTime(100);
58
+ await expect(promise).rejects.toThrow("boom");
59
+ });
60
+ it("works with async functions", async () => {
61
+ const fn = vi.fn(async (x) => `hello ${x}`);
62
+ const debounced = debounce(fn, 50);
63
+ const promise = debounced("world");
64
+ vi.advanceTimersByTime(50);
65
+ await expect(promise).resolves.toBe("hello world");
66
+ });
67
+ });
68
+ //# sourceMappingURL=debounce.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.js","sourceRoot":"","sources":["../../src/debounce.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Indent every line of a string by a given number of spaces.
3
+ *
4
+ * @example
5
+ * indent("a\nb", 2) // " a\n b"
6
+ */
7
+ export default function indent(str, spaces) {
8
+ const pad = " ".repeat(spaces);
9
+ return str
10
+ .split("\n")
11
+ .map((line) => pad + line)
12
+ .join("\n");
13
+ }
14
+ //# sourceMappingURL=indent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.js","sourceRoot":"","sources":["../../src/indent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAW,EAAE,MAAc;IACxD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,GAAG;SACP,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC;SACzB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import indent from "./indent.js";
3
+ describe("indent", () => {
4
+ it("indents a single line", () => {
5
+ expect(indent("hello", 2)).toBe(" hello");
6
+ });
7
+ it("indents every line of a multi-line string", () => {
8
+ expect(indent("a\nb\nc", 4)).toBe(" a\n b\n c");
9
+ });
10
+ it("handles zero spaces", () => {
11
+ expect(indent("hello", 0)).toBe("hello");
12
+ });
13
+ });
14
+ //# sourceMappingURL=indent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.test.js","sourceRoot":"","sources":["../../src/indent.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,7 +1,9 @@
1
- export { default as casing } from "./casing.js";
1
+ export * from "./casing/index.js";
2
2
  export { default as debounce } from "./debounce.js";
3
3
  export { default as humanizeNumber } from "./humanizeNumber/index.js";
4
+ export { default as indent } from "./indent.js";
4
5
  export { default as invariant } from "./invariant.js";
6
+ export { default as join } from "./join.js";
5
7
  export * from "./navigation/index.js";
6
8
  export { default as pluralize } from "./pluralize/index.js";
7
9
  export { default as throttle } from "./throttle.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtD,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Join an array into a string, converting each element to a string first.
3
+ *
4
+ * @example
5
+ * join(["a", "b", "c"]) // "a, b, c"
6
+ * join([1, 2, 3], " | ") // "1 | 2 | 3"
7
+ */
8
+ export default function join(arr, separator = ", ") {
9
+ return arr.map(String).join(separator);
10
+ }
11
+ //# sourceMappingURL=join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/join.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,GAAc,EAAE,SAAS,GAAG,IAAI;IAC3D,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import join from "./join.js";
3
+ describe("join", () => {
4
+ it("joins with default separator", () => {
5
+ expect(join(["a", "b", "c"])).toBe("a, b, c");
6
+ });
7
+ it("joins with custom separator", () => {
8
+ expect(join([1, 2, 3], " | ")).toBe("1 | 2 | 3");
9
+ });
10
+ it("converts elements to strings", () => {
11
+ expect(join([1, true, null])).toBe("1, true, null");
12
+ });
13
+ it("returns empty string for empty array", () => {
14
+ expect(join([])).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=join.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.test.js","sourceRoot":"","sources":["../../src/join.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import throttle from "./throttle.js";
3
+ describe("throttle", () => {
4
+ beforeEach(() => {
5
+ vi.useFakeTimers();
6
+ });
7
+ afterEach(() => {
8
+ vi.useRealTimers();
9
+ });
10
+ it("calls the function after the wait period", () => {
11
+ const fn = vi.fn();
12
+ const throttled = throttle(fn, 100);
13
+ throttled();
14
+ expect(fn).not.toHaveBeenCalled();
15
+ vi.advanceTimersByTime(100);
16
+ expect(fn).toHaveBeenCalledOnce();
17
+ });
18
+ it("only executes the last call when called rapidly", () => {
19
+ const fn = vi.fn();
20
+ const throttled = throttle(fn, 100);
21
+ throttled();
22
+ throttled();
23
+ throttled();
24
+ vi.advanceTimersByTime(100);
25
+ expect(fn).toHaveBeenCalledOnce();
26
+ });
27
+ it("passes the latest arguments", () => {
28
+ const fn = vi.fn((x) => x);
29
+ const throttled = throttle(fn, 100);
30
+ throttled(1);
31
+ throttled(2);
32
+ throttled(3);
33
+ vi.advanceTimersByTime(100);
34
+ expect(fn).toHaveBeenCalledWith(3);
35
+ });
36
+ it("resets the timer on each call", () => {
37
+ const fn = vi.fn();
38
+ const throttled = throttle(fn, 100);
39
+ throttled();
40
+ vi.advanceTimersByTime(50);
41
+ expect(fn).not.toHaveBeenCalled();
42
+ throttled();
43
+ vi.advanceTimersByTime(50);
44
+ expect(fn).not.toHaveBeenCalled();
45
+ vi.advanceTimersByTime(50);
46
+ expect(fn).toHaveBeenCalledOnce();
47
+ });
48
+ it("allows subsequent calls after the wait period expires", () => {
49
+ const fn = vi.fn();
50
+ const throttled = throttle(fn, 100);
51
+ throttled();
52
+ vi.advanceTimersByTime(100);
53
+ expect(fn).toHaveBeenCalledOnce();
54
+ throttled();
55
+ vi.advanceTimersByTime(100);
56
+ expect(fn).toHaveBeenCalledTimes(2);
57
+ });
58
+ });
59
+ //# sourceMappingURL=throttle.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.test.js","sourceRoot":"","sources":["../../src/throttle.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Capitalize the first character of a string.
3
+ *
4
+ * @example
5
+ * capitalize("hello") // "Hello"
6
+ */
7
+ export default function capitalize(s: string): string;
8
+ //# sourceMappingURL=capitalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.d.ts","sourceRoot":"","sources":["../../../src/casing/capitalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIpD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=capitalize.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.test.d.ts","sourceRoot":"","sources":["../../../src/casing/capitalize.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export { default as capitalize } from "./capitalize.js";
2
+ export { default as isPascalCase } from "./isPascalCase.js";
3
+ export { default as toCamelCase } from "./toCamelCase.js";
4
+ export { default as toConstantCase } from "./toConstantCase.js";
5
+ export { default as toKebabCase } from "./toKebabCase.js";
6
+ export { default as toPascalCase } from "./toPascalCase.js";
7
+ export { default as toSnakeCase } from "./toSnakeCase.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/casing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Check if a string is in PascalCase.
3
+ *
4
+ * @example
5
+ * isPascalCase("MyComponent") // true
6
+ * isPascalCase("myComponent") // false
7
+ */
8
+ export default function isPascalCase(s: string): boolean;
9
+ //# sourceMappingURL=isPascalCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.d.ts","sourceRoot":"","sources":["../../../src/casing/isPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=isPascalCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/isPascalCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to camelCase.
3
+ *
4
+ * @example
5
+ * toCamelCase("my-component") // "myComponent"
6
+ * toCamelCase("some_thing") // "someThing"
7
+ */
8
+ export default function toCamelCase(s: string): string;
9
+ //# sourceMappingURL=toCamelCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toCamelCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toCamelCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toCamelCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to CONSTANT_CASE.
3
+ *
4
+ * @example
5
+ * toConstantCase("myComponent") // "MY_COMPONENT"
6
+ * toConstantCase("some-thing") // "SOME_THING"
7
+ */
8
+ export default function toConstantCase(s: string): string;
9
+ //# sourceMappingURL=toConstantCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toConstantCase.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toConstantCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toConstantCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Convert a string to kebab-case.
3
+ *
4
+ * Handles camelCase, PascalCase, snake_case, spaces, and consecutive uppercase.
5
+ *
6
+ * @example
7
+ * toKebabCase("MyComponent") // "my-component"
8
+ * toKebabCase("some_thing") // "some-thing"
9
+ * toKebabCase("HTMLParser") // "html-parser"
10
+ */
11
+ export default function toKebabCase(s: string): string;
12
+ //# sourceMappingURL=toKebabCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toKebabCase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toKebabCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toKebabCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to PascalCase.
3
+ *
4
+ * @example
5
+ * toPascalCase("my-component") // "MyComponent"
6
+ * toPascalCase("some_thing") // "SomeThing"
7
+ */
8
+ export default function toPascalCase(s: string): string;
9
+ //# sourceMappingURL=toPascalCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQtD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toPascalCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toPascalCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Convert a string to snake_case.
3
+ *
4
+ * @example
5
+ * toSnakeCase("myComponent") // "my_component"
6
+ * toSnakeCase("MyComponent") // "my_component"
7
+ * toSnakeCase("some-thing") // "some_thing"
8
+ */
9
+ export default function toSnakeCase(s: string): string;
10
+ //# sourceMappingURL=toSnakeCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toSnakeCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debounce.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.d.ts","sourceRoot":"","sources":["../../src/debounce.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Indent every line of a string by a given number of spaces.
3
+ *
4
+ * @example
5
+ * indent("a\nb", 2) // " a\n b"
6
+ */
7
+ export default function indent(str: string, spaces: number): string;
8
+ //# sourceMappingURL=indent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.d.ts","sourceRoot":"","sources":["../../src/indent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMlE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=indent.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.test.d.ts","sourceRoot":"","sources":["../../src/indent.test.ts"],"names":[],"mappings":""}
@@ -1,8 +1,10 @@
1
- export { default as casing } from "./casing.js";
1
+ export * from "./casing/index.js";
2
2
  export { default as debounce } from "./debounce.js";
3
3
  export type * from "./humanizeNumber/index.js";
4
4
  export { default as humanizeNumber } from "./humanizeNumber/index.js";
5
+ export { default as indent } from "./indent.js";
5
6
  export { default as invariant } from "./invariant.js";
7
+ export { default as join } from "./join.js";
6
8
  export * from "./navigation/index.js";
7
9
  export type * from "./pluralize/index.js";
8
10
  export { default as pluralize } from "./pluralize/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtD,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpD,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Join an array into a string, converting each element to a string first.
3
+ *
4
+ * @example
5
+ * join(["a", "b", "c"]) // "a, b, c"
6
+ * join([1, 2, 3], " | ") // "1 | 2 | 3"
7
+ */
8
+ export default function join(arr: unknown[], separator?: string): string;
9
+ //# sourceMappingURL=join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/join.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,SAAS,SAAO,GAAG,MAAM,CAErE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=join.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.test.d.ts","sourceRoot":"","sources":["../../src/join.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=throttle.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.test.d.ts","sourceRoot":"","sources":["../../src/throttle.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@canonical/utils",
3
3
  "description": "Standard utility functions for Canonical's Web Engineering team",
4
- "version": "0.17.1",
4
+ "version": "0.21.0",
5
5
  "type": "module",
6
6
  "module": "dist/esm/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -21,13 +21,13 @@
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/canonical/ds25"
24
+ "url": "https://github.com/canonical/pragma"
25
25
  },
26
26
  "license": "LGPL-3.0",
27
27
  "bugs": {
28
- "url": "https://github.com/canonical/ds25/issues"
28
+ "url": "https://github.com/canonical/pragma/issues"
29
29
  },
30
- "homepage": "https://github.com/canonical/ds25#readme",
30
+ "homepage": "https://github.com/canonical/pragma#readme",
31
31
  "scripts": {
32
32
  "build": "tsc -p tsconfig.build.json",
33
33
  "build:all": "tsc -p tsconfig.build.json",
@@ -42,19 +42,19 @@
42
42
  "test:vitest:watch": "vitest"
43
43
  },
44
44
  "dependencies": {
45
- "@canonical/ds-types": "^0.17.1"
45
+ "@canonical/ds-types": "^0.21.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@biomejs/biome": "2.4.5",
49
- "@canonical/biome-config": "^0.17.1",
50
- "@canonical/typescript-config": "^0.17.1",
51
- "@canonical/webarchitect": "^0.17.1",
52
- "@types/node": "^24.10.13",
53
- "globals": "^17.3.0",
48
+ "@biomejs/biome": "2.4.9",
49
+ "@canonical/biome-config": "^0.21.0",
50
+ "@canonical/typescript-config": "^0.21.0",
51
+ "@canonical/webarchitect": "^0.21.0",
52
+ "@types/node": "^24.12.0",
53
+ "globals": "^17.4.0",
54
54
  "typescript": "^5.9.3",
55
- "vite": "^7.3.1",
56
- "vite-tsconfig-paths": "^6.1.0",
55
+ "vite": "^8.0.1",
56
+ "vite-tsconfig-paths": "^6.1.1",
57
57
  "vitest": "^4.0.18"
58
58
  },
59
- "gitHead": "e3eaaa9efdb58fa72acb8fdd3c7dffa25a1341c4"
59
+ "gitHead": "4a39c954e7bbad4903397f8371f801982034a26d"
60
60
  }
@@ -1,66 +0,0 @@
1
- /**
2
- * Convert a string to PascalCase
3
- * @param s - The string to convert
4
- * @returns The PascalCase string
5
- * @example
6
- * toPascalCase("my-component") // "MyComponent"
7
- */
8
- const toPascalCase = (s) => {
9
- if (!s)
10
- return "";
11
- const camelCased = toCamelCase(s);
12
- return camelCased.charAt(0).toUpperCase() + camelCased.slice(1);
13
- };
14
- /**
15
- * Convert a string to kebab-case
16
- * @param s - The string to convert
17
- * @returns The kebab-case string
18
- * @example
19
- * toKebabCase("MyComponent") // "my-component"
20
- */
21
- const toKebabCase = (s) => {
22
- if (!s)
23
- return "";
24
- return s
25
- .trim()
26
- .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
27
- .toLowerCase();
28
- };
29
- /**
30
- * Convert a string to camelCase
31
- * @param s - The string to convert
32
- * @returns The camelCase string
33
- * @example
34
- * toCamelCase("my-component") // "myComponent"
35
- */
36
- const toCamelCase = (s) => {
37
- if (!s)
38
- return "";
39
- return s
40
- .replace(/-([a-z])/g, (g) => g[1].toUpperCase())
41
- .replaceAll("-", "")
42
- .replaceAll("_", "")
43
- .replaceAll(" ", "");
44
- };
45
- /**
46
- * Check if a string is in PascalCase.
47
- * @param s - The string to check
48
- * @returns True if the string is in PascalCase, false otherwise.
49
- * @example
50
- * isPascalCase("MyComponent") // true
51
- * isPascalCase("myComponent") // false
52
- */
53
- const isPascalCase = (s) => {
54
- // A simple regular expression that requires:
55
- // - the string to start with an uppercase letter
56
- // - followed by zero or more lowercase letters or digits,
57
- // - then zero or more groups that start with an uppercase letter followed by zero or more lowercase letters or digits.
58
- return /^[A-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/.test(s);
59
- };
60
- export default {
61
- toPascalCase,
62
- toKebabCase,
63
- toCamelCase,
64
- isPascalCase,
65
- };
66
- //# sourceMappingURL=casing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"casing.js","sourceRoot":"","sources":["../../src/casing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,YAAY,GAAG,CAAC,CAAS,EAAU,EAAE;IACzC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAElC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,IAAI,EAAE;SACN,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,WAAW,EAAE,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC/C,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;SACnB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;SACnB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,CAAC,CAAS,EAAW,EAAE;IAC1C,6CAA6C;IAC7C,iDAAiD;IACjD,0DAA0D;IAC1D,uHAAuH;IACvH,OAAO,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,eAAe;IACb,YAAY;IACZ,WAAW;IACX,WAAW;IACX,YAAY;CACb,CAAC"}
@@ -1,8 +0,0 @@
1
- declare const _default: {
2
- toPascalCase: (s: string) => string;
3
- toKebabCase: (s: string) => string;
4
- toCamelCase: (s: string) => string;
5
- isPascalCase: (s: string) => boolean;
6
- };
7
- export default _default;
8
- //# sourceMappingURL=casing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"casing.d.ts","sourceRoot":"","sources":["../../src/casing.ts"],"names":[],"mappings":";sBAOyB,MAAM,KAAG,MAAM;qBAehB,MAAM,KAAG,MAAM;qBAgBf,MAAM,KAAG,MAAM;sBAkBd,MAAM,KAAG,OAAO;;AAQzC,wBAKE"}