@accelint/geo 0.5.1 → 0.6.1

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 (113) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +233 -1
  3. package/catalog-info.yaml +1 -1
  4. package/dist/cartesian.d.ts +2 -0
  5. package/dist/cartesian.js +3 -1
  6. package/dist/cartesian.js.map +1 -1
  7. package/dist/coordinates/coordinate.d.ts +42 -8
  8. package/dist/coordinates/coordinate.js +103 -13
  9. package/dist/coordinates/coordinate.js.map +1 -1
  10. package/dist/coordinates/latlon/decimal-degrees/formatter.d.ts +21 -1
  11. package/dist/coordinates/latlon/decimal-degrees/formatter.js +39 -1
  12. package/dist/coordinates/latlon/decimal-degrees/formatter.js.map +1 -1
  13. package/dist/coordinates/latlon/decimal-degrees/parser.d.ts +69 -3
  14. package/dist/coordinates/latlon/decimal-degrees/parser.js +67 -6
  15. package/dist/coordinates/latlon/decimal-degrees/parser.js.map +1 -1
  16. package/dist/coordinates/latlon/decimal-degrees/system.d.ts +33 -1
  17. package/dist/coordinates/latlon/decimal-degrees/system.js +32 -1
  18. package/dist/coordinates/latlon/decimal-degrees/system.js.map +1 -1
  19. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.d.ts +21 -1
  20. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js +43 -3
  21. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js.map +1 -1
  22. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.d.ts +73 -3
  23. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js +67 -4
  24. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js.map +1 -1
  25. package/dist/coordinates/latlon/degrees-decimal-minutes/system.d.ts +33 -1
  26. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js +32 -1
  27. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js.map +1 -1
  28. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.d.ts +21 -1
  29. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js +46 -4
  30. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js.map +1 -1
  31. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.d.ts +75 -3
  32. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js +67 -4
  33. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js.map +1 -1
  34. package/dist/coordinates/latlon/degrees-minutes-seconds/system.d.ts +33 -1
  35. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js +32 -1
  36. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js.map +1 -1
  37. package/dist/coordinates/latlon/internal/coordinate-system.d.ts +23 -1
  38. package/dist/coordinates/latlon/internal/coordinate-system.js +1 -1
  39. package/dist/coordinates/latlon/internal/create-cache.d.ts +18 -2
  40. package/dist/coordinates/latlon/internal/create-cache.js +20 -4
  41. package/dist/coordinates/latlon/internal/create-cache.js.map +1 -1
  42. package/dist/coordinates/latlon/internal/exhaustive-errors.d.ts +15 -0
  43. package/dist/coordinates/latlon/internal/exhaustive-errors.js +29 -1
  44. package/dist/coordinates/latlon/internal/exhaustive-errors.js.map +1 -1
  45. package/dist/coordinates/latlon/internal/format.d.ts +20 -0
  46. package/dist/coordinates/latlon/internal/format.js +21 -1
  47. package/dist/coordinates/latlon/internal/format.js.map +1 -1
  48. package/dist/coordinates/latlon/internal/in-range.d.ts +23 -0
  49. package/dist/coordinates/latlon/internal/in-range.js +25 -1
  50. package/dist/coordinates/latlon/internal/in-range.js.map +1 -1
  51. package/dist/coordinates/latlon/internal/index.d.ts +16 -1
  52. package/dist/coordinates/latlon/internal/index.js +26 -2
  53. package/dist/coordinates/latlon/internal/index.js.map +1 -1
  54. package/dist/coordinates/latlon/internal/lexer.d.ts +2 -0
  55. package/dist/coordinates/latlon/internal/lexer.js +27 -1
  56. package/dist/coordinates/latlon/internal/lexer.js.map +1 -1
  57. package/dist/coordinates/latlon/internal/normalize.d.ts +67 -0
  58. package/dist/coordinates/latlon/internal/normalize.js +87 -0
  59. package/dist/coordinates/latlon/internal/normalize.js.map +1 -0
  60. package/dist/coordinates/latlon/internal/ordinal.d.ts +25 -0
  61. package/dist/coordinates/latlon/internal/ordinal.js +26 -1
  62. package/dist/coordinates/latlon/internal/ordinal.js.map +1 -1
  63. package/dist/coordinates/latlon/internal/parse-format.d.ts +23 -1
  64. package/dist/coordinates/latlon/internal/parse-format.js +44 -2
  65. package/dist/coordinates/latlon/internal/parse-format.js.map +1 -1
  66. package/dist/coordinates/latlon/internal/parse.d.ts +3 -1
  67. package/dist/coordinates/latlon/internal/parse.js +5 -2
  68. package/dist/coordinates/latlon/internal/parse.js.map +1 -1
  69. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.d.ts +18 -1
  70. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js +17 -1
  71. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js.map +1 -1
  72. package/dist/coordinates/latlon/internal/pipes/check-numbers.d.ts +26 -1
  73. package/dist/coordinates/latlon/internal/pipes/check-numbers.js +34 -1
  74. package/dist/coordinates/latlon/internal/pipes/check-numbers.js.map +1 -1
  75. package/dist/coordinates/latlon/internal/pipes/fix-bearings.d.ts +18 -1
  76. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js +32 -1
  77. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js.map +1 -1
  78. package/dist/coordinates/latlon/internal/pipes/fix-dividers.d.ts +18 -1
  79. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js +30 -1
  80. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js.map +1 -1
  81. package/dist/coordinates/latlon/internal/pipes/genome.d.ts +17 -1
  82. package/dist/coordinates/latlon/internal/pipes/genome.js +42 -1
  83. package/dist/coordinates/latlon/internal/pipes/genome.js.map +1 -1
  84. package/dist/coordinates/latlon/internal/pipes/index.d.ts +33 -3
  85. package/dist/coordinates/latlon/internal/pipes/index.js +58 -5
  86. package/dist/coordinates/latlon/internal/pipes/index.js.map +1 -1
  87. package/dist/coordinates/latlon/internal/pipes/simpler.d.ts +17 -4
  88. package/dist/coordinates/latlon/internal/pipes/simpler.js +16 -4
  89. package/dist/coordinates/latlon/internal/pipes/simpler.js.map +1 -1
  90. package/dist/coordinates/latlon/internal/validate.d.ts +75 -0
  91. package/dist/coordinates/latlon/internal/validate.js +105 -0
  92. package/dist/coordinates/latlon/internal/validate.js.map +1 -0
  93. package/dist/coordinates/latlon/internal/violation.d.ts +18 -0
  94. package/dist/coordinates/latlon/internal/violation.js +19 -1
  95. package/dist/coordinates/latlon/internal/violation.js.map +1 -1
  96. package/dist/coordinates/mgrs/parser.d.ts +25 -1
  97. package/dist/coordinates/mgrs/parser.js +57 -1
  98. package/dist/coordinates/mgrs/parser.js.map +1 -1
  99. package/dist/coordinates/mgrs/system.d.ts +32 -1
  100. package/dist/coordinates/mgrs/system.js +31 -1
  101. package/dist/coordinates/mgrs/system.js.map +1 -1
  102. package/dist/coordinates/utm/parser.d.ts +25 -1
  103. package/dist/coordinates/utm/parser.js +57 -1
  104. package/dist/coordinates/utm/parser.js.map +1 -1
  105. package/dist/coordinates/utm/system.d.ts +22 -1
  106. package/dist/coordinates/utm/system.js +21 -1
  107. package/dist/coordinates/utm/system.js.map +1 -1
  108. package/dist/index.d.ts +4 -2
  109. package/dist/index.js +4 -2
  110. package/dist/patterning.d.ts +12 -2
  111. package/dist/patterning.js +13 -3
  112. package/dist/patterning.js.map +1 -1
  113. package/package.json +5 -3
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -13,6 +13,38 @@
13
13
  import { CoordinateSystem } from "../internal/coordinate-system.js";
14
14
 
15
15
  //#region src/coordinates/latlon/degrees-minutes-seconds/system.d.ts
16
+
17
+ /**
18
+ * Degrees Minutes Seconds coordinate system implementation.
19
+ *
20
+ * Provides parsing, conversion, and formatting for coordinates in degrees minutes seconds notation.
21
+ * Coordinates are expressed as integer degrees, integer minutes, and decimal seconds (e.g., 37° 46' 29.64″ N).
22
+ *
23
+ * @property name - Human-readable name of the coordinate system.
24
+ * @property parse - Parses degrees minutes seconds coordinate strings.
25
+ * @property toFloat - Converts parsed coordinate components to floating point numbers.
26
+ * @property toFormat - Formats numeric coordinates back to degrees minutes seconds string.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Parse a coordinate string
31
+ * const [coords, errors] = systemDegreesMinutesSeconds.parse('37° 46' 29.64″ N / 122° 25' 9.84″ W', 'LATLON');
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Convert to float
37
+ * const lat = systemDegreesMinutesSeconds.toFloat(['37', '46', '29.64', 'N']);
38
+ * // 37.7749
39
+ * ```
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // Format to string
44
+ * const formatted = systemDegreesMinutesSeconds.toFormat('LATLON', [37.7749, -122.4194]);
45
+ * // '37 46 29.64 N / 122 25 9.84 W'
46
+ * ```
47
+ */
16
48
  declare const systemDegreesMinutesSeconds: CoordinateSystem;
17
49
  //#endregion
18
50
  export { systemDegreesMinutesSeconds };
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -15,6 +15,37 @@ import { BEARINGS, SYMBOLS, SYMBOL_PATTERNS } from "../internal/index.js";
15
15
  import { parseDegreesMinutesSeconds } from "./parser.js";
16
16
 
17
17
  //#region src/coordinates/latlon/degrees-minutes-seconds/system.ts
18
+ /**
19
+ * Degrees Minutes Seconds coordinate system implementation.
20
+ *
21
+ * Provides parsing, conversion, and formatting for coordinates in degrees minutes seconds notation.
22
+ * Coordinates are expressed as integer degrees, integer minutes, and decimal seconds (e.g., 37° 46' 29.64″ N).
23
+ *
24
+ * @property name - Human-readable name of the coordinate system.
25
+ * @property parse - Parses degrees minutes seconds coordinate strings.
26
+ * @property toFloat - Converts parsed coordinate components to floating point numbers.
27
+ * @property toFormat - Formats numeric coordinates back to degrees minutes seconds string.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Parse a coordinate string
32
+ * const [coords, errors] = systemDegreesMinutesSeconds.parse('37° 46' 29.64″ N / 122° 25' 9.84″ W', 'LATLON');
33
+ * ```
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // Convert to float
38
+ * const lat = systemDegreesMinutesSeconds.toFloat(['37', '46', '29.64', 'N']);
39
+ * // 37.7749
40
+ * ```
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * // Format to string
45
+ * const formatted = systemDegreesMinutesSeconds.toFormat('LATLON', [37.7749, -122.4194]);
46
+ * // '37 46 29.64 N / 122 25 9.84 W'
47
+ * ```
48
+ */
18
49
  const systemDegreesMinutesSeconds = {
19
50
  name: "Degrees Minutes Seconds",
20
51
  parse: parseDegreesMinutesSeconds,
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","names":["systemDegreesMinutesSeconds: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOL_PATTERNS,\n SYMBOLS,\n} from '../internal';\nimport { parseDegreesMinutesSeconds } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\nexport const systemDegreesMinutesSeconds: CoordinateSystem = {\n name: 'Degrees Minutes Seconds',\n\n parse: parseDegreesMinutesSeconds,\n\n toFloat(arg) {\n const [degrees, minutes, seconds, bear] = arg as [\n string,\n string,\n string,\n Compass,\n ];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) +\n Number.parseFloat(minutes) / 60 +\n Number.parseFloat(seconds) / 3600) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map((num, index) => {\n const abs = Math.abs(num);\n const deg = Math.floor(abs);\n const rem = (abs - deg) * 60;\n const min = Math.floor(rem);\n const sec = Number.parseFloat(((rem - min) * 60).toFixed(10));\n\n return `${deg} ${min} ${sec} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAuBA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,SAAS,QAAQ;AAO1C,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GACzB,OAAO,WAAW,QAAQ,GAAG,KAC7B,OAAO,WAAW,QAAQ,GAAG,SAC9B,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,CAAC,MAAM,QAA0B;AACxD,SAAO,CAAC,MAAM,MAAM,CACjB,KAAK,KAAK,UAAU;GACnB,MAAM,MAAM,KAAK,IAAI,IAAI;GACzB,MAAM,MAAM,KAAK,MAAM,IAAI;GAC3B,MAAM,OAAO,MAAM,OAAO;GAC1B,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAAG,IAAI,GAFT,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAEjC,GAAG,SAAS,QAAQ,OAAgB,EAAE,MAAM;IACxE,CACD,KAAK,IAAI,QAAQ,QAAQ,GAAG;;CAElC"}
1
+ {"version":3,"file":"system.js","names":["systemDegreesMinutesSeconds: CoordinateSystem"],"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/system.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOL_PATTERNS,\n SYMBOLS,\n} from '../internal';\nimport { parseDegreesMinutesSeconds } from './parser';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\n/**\n * Degrees Minutes Seconds coordinate system implementation.\n *\n * Provides parsing, conversion, and formatting for coordinates in degrees minutes seconds notation.\n * Coordinates are expressed as integer degrees, integer minutes, and decimal seconds (e.g., 37° 46' 29.64″ N).\n *\n * @property name - Human-readable name of the coordinate system.\n * @property parse - Parses degrees minutes seconds coordinate strings.\n * @property toFloat - Converts parsed coordinate components to floating point numbers.\n * @property toFormat - Formats numeric coordinates back to degrees minutes seconds string.\n *\n * @example\n * ```typescript\n * // Parse a coordinate string\n * const [coords, errors] = systemDegreesMinutesSeconds.parse('37° 46' 29.64″ N / 122° 25' 9.84″ W', 'LATLON');\n * ```\n *\n * @example\n * ```typescript\n * // Convert to float\n * const lat = systemDegreesMinutesSeconds.toFloat(['37', '46', '29.64', 'N']);\n * // 37.7749\n * ```\n *\n * @example\n * ```typescript\n * // Format to string\n * const formatted = systemDegreesMinutesSeconds.toFormat('LATLON', [37.7749, -122.4194]);\n * // '37 46 29.64 N / 122 25 9.84 W'\n * ```\n */\nexport const systemDegreesMinutesSeconds: CoordinateSystem = {\n name: 'Degrees Minutes Seconds',\n\n parse: parseDegreesMinutesSeconds,\n\n toFloat(arg) {\n const [degrees, minutes, seconds, bear] = arg as [\n string,\n string,\n string,\n Compass,\n ];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) +\n Number.parseFloat(minutes) / 60 +\n Number.parseFloat(seconds) / 3600) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map((num, index) => {\n const abs = Math.abs(num);\n const deg = Math.floor(abs);\n const rem = (abs - deg) * 60;\n const min = Math.floor(rem);\n const sec = Number.parseFloat(((rem - min) * 60).toFixed(10));\n\n return `${deg} ${min} ${sec} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAaA,8BAAgD;CAC3D,MAAM;CAEN,OAAO;CAEP,QAAQ,KAAK;EACX,MAAM,CAAC,SAAS,SAAS,SAAS,QAAQ;AAO1C,SAAO,OAAO,aAET,OAAO,WAAW,QAAQ,GACzB,OAAO,WAAW,QAAQ,GAAG,KAC7B,OAAO,WAAW,QAAQ,GAAG,SAC9B,gBAAgB,kBAAkB,KAAK,KAAK,GAAG,KAAK,IACrD,QAAQ,EAAE,CACb;;CAGH,SAAS,QAAgB,CAAC,MAAM,QAA0B;AACxD,SAAO,CAAC,MAAM,MAAM,CACjB,KAAK,KAAK,UAAU;GACnB,MAAM,MAAM,KAAK,IAAI,IAAI;GACzB,MAAM,MAAM,KAAK,MAAM,IAAI;GAC3B,MAAM,OAAO,MAAM,OAAO;GAC1B,MAAM,MAAM,KAAK,MAAM,IAAI;AAG3B,UAAO,GAAG,IAAI,GAAG,IAAI,GAFT,OAAO,aAAa,MAAM,OAAO,IAAI,QAAQ,GAAG,CAAC,CAEjC,GAAG,SAAS,QAAQ,OAAgB,EAAE,MAAM;IACxE,CACD,KAAK,IAAI,QAAQ,QAAQ,GAAG;;CAElC"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -14,6 +14,28 @@ import { Compass, Format } from "./index.js";
14
14
  import { ParseResults } from "./parse.js";
15
15
 
16
16
  //#region src/coordinates/latlon/internal/coordinate-system.d.ts
17
+
18
+ /**
19
+ * Coordinate system interface for parsing, converting, and formatting geographic coordinates.
20
+ *
21
+ * Defines the contract for coordinate notation systems (Decimal Degrees, Degrees Decimal Minutes,
22
+ * Degrees Minutes Seconds) to parse, convert to float, and format coordinate values.
23
+ *
24
+ * @property name - Human-readable name of the coordinate system.
25
+ * @property parse - Parses a coordinate string into validated tokens or error messages.
26
+ * @property toFloat - Converts parsed coordinate components (degrees, minutes, seconds, bearing) to a float.
27
+ * @property toFormat - Formats numeric coordinate pair back to string representation.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const system: CoordinateSystem = {
32
+ * name: 'Decimal Degrees',
33
+ * parse: (format, input) => parseDecimalDegrees(input, format),
34
+ * toFloat: ([deg, bear]) => Number.parseFloat(deg) * (bear === 'S' || bear === 'W' ? -1 : 1),
35
+ * toFormat: (format, [lat, lon]) => `${Math.abs(lat)}° ${lat >= 0 ? 'N' : 'S'} / ${Math.abs(lon)}° ${lon >= 0 ? 'E' : 'W'}`
36
+ * };
37
+ * ```
38
+ */
17
39
  type CoordinateSystem = {
18
40
  name: string;
19
41
  parse: (format: Format, input: string) => ParseResults;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -19,7 +19,23 @@ type CoordinateCache = Record<Format, string>;
19
19
  * conversions are only ever done once and only "one-direction-ally". The
20
20
  * "one-direction" concept is to avoid the problem of encountering rounding
21
21
  * errors when converting between multiple formats.
22
- * */
22
+ *
23
+ * @param format - The coordinate format (LATLON or LONLAT) for the provided value.
24
+ * @param value - The formatted coordinate string to cache.
25
+ * @returns Cache object with both LATLON and LONLAT format strings.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * createCache('LATLON', '37.7749 N / 122.4194 W');
30
+ * // { LATLON: '37.7749 N / 122.4194 W', LONLAT: '122.4194 W / 37.7749 N' }
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * createCache('LONLAT', '122° W / 37° N');
36
+ * // { LONLAT: '122° W / 37° N', LATLON: '37° N / 122° W' }
37
+ * ```
38
+ */
23
39
  declare function createCache(format: Format, value: string): CoordinateCache;
24
40
  //#endregion
25
41
  export { CoordinateCache, createCache };
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
 
14
- import { FORMATS, SYMBOLS } from "./index.js";
14
+ import { SYMBOLS } from "./index.js";
15
15
 
16
16
  //#region src/coordinates/latlon/internal/create-cache.ts
17
17
  const DIVIDER = ` ${SYMBOLS.DIVIDER} `;
@@ -20,9 +20,25 @@ const DIVIDER = ` ${SYMBOLS.DIVIDER} `;
20
20
  * conversions are only ever done once and only "one-direction-ally". The
21
21
  * "one-direction" concept is to avoid the problem of encountering rounding
22
22
  * errors when converting between multiple formats.
23
- * */
23
+ *
24
+ * @param format - The coordinate format (LATLON or LONLAT) for the provided value.
25
+ * @param value - The formatted coordinate string to cache.
26
+ * @returns Cache object with both LATLON and LONLAT format strings.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * createCache('LATLON', '37.7749 N / 122.4194 W');
31
+ * // { LATLON: '37.7749 N / 122.4194 W', LONLAT: '122.4194 W / 37.7749 N' }
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * createCache('LONLAT', '122° W / 37° N');
37
+ * // { LONLAT: '122° W / 37° N', LATLON: '37° N / 122° W' }
38
+ * ```
39
+ */
24
40
  function createCache(format, value) {
25
- const [alternate] = FORMATS.filter((o) => o !== format);
41
+ const alternate = format === "LATLON" ? "LONLAT" : "LATLON";
26
42
  return {
27
43
  [format]: value,
28
44
  [alternate]: value.includes(SYMBOLS.DIVIDER) ? value.split(DIVIDER).reverse().join(DIVIDER).trim() : value
@@ -1 +1 @@
1
- {"version":3,"file":"create-cache.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/create-cache.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { FORMATS, type Format, SYMBOLS } from '.';\n\nexport type CoordinateCache = Record<Format, string>;\n\nconst DIVIDER = ` ${SYMBOLS.DIVIDER} `;\n\n/**\n * Create, and initialize, a cache object for coordinate conversions so that\n * conversions are only ever done once and only \"one-direction-ally\". The\n * \"one-direction\" concept is to avoid the problem of encountering rounding\n * errors when converting between multiple formats.\n * */\nexport function createCache(format: Format, value: string) {\n const [alternate] = FORMATS.filter((o) => o !== format) as [Format];\n\n return {\n [format]: value,\n [alternate]: value.includes(SYMBOLS.DIVIDER)\n ? value.split(DIVIDER).reverse().join(DIVIDER).trim()\n : value,\n } as CoordinateCache;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,UAAU,IAAI,QAAQ,QAAQ;;;;;;;AAQpC,SAAgB,YAAY,QAAgB,OAAe;CACzD,MAAM,CAAC,aAAa,QAAQ,QAAQ,MAAM,MAAM,OAAO;AAEvD,QAAO;GACJ,SAAS;GACT,YAAY,MAAM,SAAS,QAAQ,QAAQ,GACxC,MAAM,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,MAAM,GACnD;EACL"}
1
+ {"version":3,"file":"create-cache.js","names":["alternate: Format"],"sources":["../../../../src/coordinates/latlon/internal/create-cache.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Format, SYMBOLS } from '.';\n\nexport type CoordinateCache = Record<Format, string>;\n\nconst DIVIDER = ` ${SYMBOLS.DIVIDER} `;\n\n/**\n * Create, and initialize, a cache object for coordinate conversions so that\n * conversions are only ever done once and only \"one-direction-ally\". The\n * \"one-direction\" concept is to avoid the problem of encountering rounding\n * errors when converting between multiple formats.\n *\n * @param format - The coordinate format (LATLON or LONLAT) for the provided value.\n * @param value - The formatted coordinate string to cache.\n * @returns Cache object with both LATLON and LONLAT format strings.\n *\n * @example\n * ```typescript\n * createCache('LATLON', '37.7749 N / 122.4194 W');\n * // { LATLON: '37.7749 N / 122.4194 W', LONLAT: '122.4194 W / 37.7749 N' }\n * ```\n *\n * @example\n * ```typescript\n * createCache('LONLAT', '122° W / 37° N');\n * // { LONLAT: '122° W / 37° N', LATLON: '37° N / 122° W' }\n * ```\n */\nexport function createCache(format: Format, value: string) {\n const alternate: Format = format === 'LATLON' ? 'LONLAT' : 'LATLON';\n\n return {\n [format]: value,\n [alternate]: value.includes(SYMBOLS.DIVIDER)\n ? value.split(DIVIDER).reverse().join(DIVIDER).trim()\n : value,\n } as CoordinateCache;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,UAAU,IAAI,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;AAwBpC,SAAgB,YAAY,QAAgB,OAAe;CACzD,MAAMA,YAAoB,WAAW,WAAW,WAAW;AAE3D,QAAO;GACJ,SAAS;GACT,YAAY,MAAM,SAAS,QAAQ,QAAQ,GACxC,MAAM,MAAM,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,MAAM,GACnD;EACL"}
@@ -2,6 +2,21 @@
2
2
  /**
3
3
  * A collection of input strings each with exactly one error in a unique
4
4
  * position for each format (LATLON and LONLAT) in each system (DD, DDM, DMS).
5
+ *
6
+ * Used for comprehensive error validation testing. Each entry contains coordinate
7
+ * strings with systematic errors across different notation systems.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * EXHAUSTIVE_ERRORS.DD.LATLON;
12
+ * // Array of decimal degrees strings with errors like '91 N / 179 E'
13
+ * ```
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * EXHAUSTIVE_ERRORS.DMS.LONLAT;
18
+ * // Array of degrees-minutes-seconds strings with errors
19
+ * ```
5
20
  */
6
21
  declare const EXHAUSTIVE_ERRORS: {
7
22
  [k: string]: any;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -95,11 +95,39 @@ const systems = [
95
95
  /**
96
96
  * A collection of input strings each with exactly one error in a unique
97
97
  * position for each format (LATLON and LONLAT) in each system (DD, DDM, DMS).
98
+ *
99
+ * Used for comprehensive error validation testing. Each entry contains coordinate
100
+ * strings with systematic errors across different notation systems.
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * EXHAUSTIVE_ERRORS.DD.LATLON;
105
+ * // Array of decimal degrees strings with errors like '91 N / 179 E'
106
+ * ```
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * EXHAUSTIVE_ERRORS.DMS.LONLAT;
111
+ * // Array of degrees-minutes-seconds strings with errors
112
+ * ```
98
113
  */
99
114
  const EXHAUSTIVE_ERRORS = Object.fromEntries(systems.map(({ designation, ...system }) => {
100
115
  const options = ["LAT LON", "LON LAT"].map((format) => [format.replace(" ", ""), cartesian(...format.split(" ").map((key) => system[key])).map((pair) => pair.join(" / ")).flatMap((t) => fillTemplate(t, values))]);
101
116
  return [designation, Object.fromEntries(options)];
102
117
  }));
118
+ /**
119
+ * Fills a coordinate template with test values, generating variations with errors.
120
+ *
121
+ * @param template - Template string with placeholders like 'DLAT MM BLAT / DLON MM BLON'.
122
+ * @param values - Object containing valid and invalid test values for each placeholder.
123
+ * @returns Array of coordinate strings with systematic errors injected.
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * fillTemplate('DLAT MM BLAT / DLON MM BLON', values);
128
+ * // ['91 30 N / 179 30 E', 'nope 30 N / 179 30 E', ...]
129
+ * ```
130
+ */
103
131
  function fillTemplate(template, values$1) {
104
132
  return template.split(" ").flatMap((key, i, original) => {
105
133
  if (!values$1.invalid[key]) return "";
@@ -1 +1 @@
1
- {"version":3,"file":"exhaustive-errors.js","names":["values: Values","values"],"sources":["../../../../src/coordinates/latlon/internal/exhaustive-errors.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { cartesian } from '@/cartesian';\n\ntype Values = {\n invalid: Record<string, string[]>;\n valid: Record<string, string>;\n};\n\nconst values: Values = {\n invalid: {\n BLAT: ['X', 'random garbage'],\n BLON: ['X', 'random garbage'],\n DLAT: ['91', 'nope'],\n DDLAT: ['90.1', 'nope'],\n DLON: ['181', 'nope'],\n DDLON: ['180.1', 'nope'],\n M: ['-1', '61', 'nope'],\n MM: ['-0.1', '60.1', 'nope'],\n SS: ['-0.1', '60.1', 'nope'],\n },\n valid: {\n '/': '/',\n BLAT: 'N',\n BLON: 'E',\n DLAT: '89',\n DDLAT: '89.999999999',\n DLON: '179',\n DDLON: '179.999999999',\n M: '59',\n MM: '59.999999999',\n SS: '59.999999999',\n },\n};\n\nconst systems = [\n {\n designation: 'DD',\n LAT: ['DDLAT', 'BLAT DDLAT', 'DDLAT BLAT'],\n LON: ['DDLON', 'BLON DDLON', 'DDLON BLON'],\n },\n {\n designation: 'DDM',\n LAT: ['DLAT MM', 'BLAT DLAT MM', 'DLAT MM BLAT'],\n LON: ['DLON MM', 'BLON DLON MM', 'DLON MM BLON'],\n },\n {\n designation: 'DMS',\n LAT: ['DLAT M SS', 'BLAT DLAT M SS', 'DLAT M SS BLAT'],\n LON: ['DLON M SS', 'BLON DLON M SS', 'DLON M SS BLON'],\n },\n];\n\n/**\n * A collection of input strings each with exactly one error in a unique\n * position for each format (LATLON and LONLAT) in each system (DD, DDM, DMS).\n */\nexport const EXHAUSTIVE_ERRORS = Object.fromEntries(\n systems.map(({ designation, ...system }) => {\n // for both format options\n const options = ['LAT LON', 'LON LAT'].map((format) => [\n // create object key: 'LATLON' or 'LONLAT'\n format.replace(' ', ''),\n\n // cross-join each variation of LAT with each variation of LON in the system\n cartesian(\n ...format.split(' ').map((key) => system[key as keyof typeof system]),\n )\n // input not including this isn't an error so no need for variation\n .map((pair) => pair.join(' / '))\n // fill the generated template with actual values\n .flatMap((t) => fillTemplate(t, values)),\n ]);\n\n return [designation, Object.fromEntries(options)];\n }),\n);\n\nfunction fillTemplate(template: string, values: Values) {\n return template\n .split(' ')\n .flatMap((key, i, original) => {\n if (!values.invalid[key]) {\n return '';\n }\n\n return (values.invalid[key] as string[]).map((opt) =>\n [...original.slice(0, i), opt, ...original.slice(i + 1)]\n .map((token) => (token in values.valid ? values.valid[token] : token))\n .join(' '),\n );\n })\n .filter(Boolean);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,MAAMA,SAAiB;CACrB,SAAS;EACP,MAAM,CAAC,KAAK,iBAAiB;EAC7B,MAAM,CAAC,KAAK,iBAAiB;EAC7B,MAAM,CAAC,MAAM,OAAO;EACpB,OAAO,CAAC,QAAQ,OAAO;EACvB,MAAM,CAAC,OAAO,OAAO;EACrB,OAAO,CAAC,SAAS,OAAO;EACxB,GAAG;GAAC;GAAM;GAAM;GAAO;EACvB,IAAI;GAAC;GAAQ;GAAQ;GAAO;EAC5B,IAAI;GAAC;GAAQ;GAAQ;GAAO;EAC7B;CACD,OAAO;EACL,KAAK;EACL,MAAM;EACN,MAAM;EACN,MAAM;EACN,OAAO;EACP,MAAM;EACN,OAAO;EACP,GAAG;EACH,IAAI;EACJ,IAAI;EACL;CACF;AAED,MAAM,UAAU;CACd;EACE,aAAa;EACb,KAAK;GAAC;GAAS;GAAc;GAAa;EAC1C,KAAK;GAAC;GAAS;GAAc;GAAa;EAC3C;CACD;EACE,aAAa;EACb,KAAK;GAAC;GAAW;GAAgB;GAAe;EAChD,KAAK;GAAC;GAAW;GAAgB;GAAe;EACjD;CACD;EACE,aAAa;EACb,KAAK;GAAC;GAAa;GAAkB;GAAiB;EACtD,KAAK;GAAC;GAAa;GAAkB;GAAiB;EACvD;CACF;;;;;AAMD,MAAa,oBAAoB,OAAO,YACtC,QAAQ,KAAK,EAAE,aAAa,GAAG,aAAa;CAE1C,MAAM,UAAU,CAAC,WAAW,UAAU,CAAC,KAAK,WAAW,CAErD,OAAO,QAAQ,KAAK,GAAG,EAGvB,UACE,GAAG,OAAO,MAAM,IAAI,CAAC,KAAK,QAAQ,OAAO,KAA4B,CACtE,CAEE,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAE/B,SAAS,MAAM,aAAa,GAAG,OAAO,CAAC,CAC3C,CAAC;AAEF,QAAO,CAAC,aAAa,OAAO,YAAY,QAAQ,CAAC;EACjD,CACH;AAED,SAAS,aAAa,UAAkB,UAAgB;AACtD,QAAO,SACJ,MAAM,IAAI,CACV,SAAS,KAAK,GAAG,aAAa;AAC7B,MAAI,CAACC,SAAO,QAAQ,KAClB,QAAO;AAGT,SAAQA,SAAO,QAAQ,KAAkB,KAAK,QAC5C;GAAC,GAAG,SAAS,MAAM,GAAG,EAAE;GAAE;GAAK,GAAG,SAAS,MAAM,IAAI,EAAE;GAAC,CACrD,KAAK,UAAW,SAASA,SAAO,QAAQA,SAAO,MAAM,SAAS,MAAO,CACrE,KAAK,IAAI,CACb;GACD,CACD,OAAO,QAAQ"}
1
+ {"version":3,"file":"exhaustive-errors.js","names":["values: Values","values"],"sources":["../../../../src/coordinates/latlon/internal/exhaustive-errors.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { cartesian } from '@/cartesian';\n\ntype Values = {\n invalid: Record<string, string[]>;\n valid: Record<string, string>;\n};\n\nconst values: Values = {\n invalid: {\n BLAT: ['X', 'random garbage'],\n BLON: ['X', 'random garbage'],\n DLAT: ['91', 'nope'],\n DDLAT: ['90.1', 'nope'],\n DLON: ['181', 'nope'],\n DDLON: ['180.1', 'nope'],\n M: ['-1', '61', 'nope'],\n MM: ['-0.1', '60.1', 'nope'],\n SS: ['-0.1', '60.1', 'nope'],\n },\n valid: {\n '/': '/',\n BLAT: 'N',\n BLON: 'E',\n DLAT: '89',\n DDLAT: '89.999999999',\n DLON: '179',\n DDLON: '179.999999999',\n M: '59',\n MM: '59.999999999',\n SS: '59.999999999',\n },\n};\n\nconst systems = [\n {\n designation: 'DD',\n LAT: ['DDLAT', 'BLAT DDLAT', 'DDLAT BLAT'],\n LON: ['DDLON', 'BLON DDLON', 'DDLON BLON'],\n },\n {\n designation: 'DDM',\n LAT: ['DLAT MM', 'BLAT DLAT MM', 'DLAT MM BLAT'],\n LON: ['DLON MM', 'BLON DLON MM', 'DLON MM BLON'],\n },\n {\n designation: 'DMS',\n LAT: ['DLAT M SS', 'BLAT DLAT M SS', 'DLAT M SS BLAT'],\n LON: ['DLON M SS', 'BLON DLON M SS', 'DLON M SS BLON'],\n },\n];\n\n/**\n * A collection of input strings each with exactly one error in a unique\n * position for each format (LATLON and LONLAT) in each system (DD, DDM, DMS).\n *\n * Used for comprehensive error validation testing. Each entry contains coordinate\n * strings with systematic errors across different notation systems.\n *\n * @example\n * ```typescript\n * EXHAUSTIVE_ERRORS.DD.LATLON;\n * // Array of decimal degrees strings with errors like '91 N / 179 E'\n * ```\n *\n * @example\n * ```typescript\n * EXHAUSTIVE_ERRORS.DMS.LONLAT;\n * // Array of degrees-minutes-seconds strings with errors\n * ```\n */\nexport const EXHAUSTIVE_ERRORS = Object.fromEntries(\n systems.map(({ designation, ...system }) => {\n // for both format options\n const options = ['LAT LON', 'LON LAT'].map((format) => [\n // create object key: 'LATLON' or 'LONLAT'\n format.replace(' ', ''),\n\n // cross-join each variation of LAT with each variation of LON in the system\n cartesian(\n ...format.split(' ').map((key) => system[key as keyof typeof system]),\n )\n // input not including this isn't an error so no need for variation\n .map((pair) => pair.join(' / '))\n // fill the generated template with actual values\n .flatMap((t) => fillTemplate(t, values)),\n ]);\n\n return [designation, Object.fromEntries(options)];\n }),\n);\n\n/**\n * Fills a coordinate template with test values, generating variations with errors.\n *\n * @param template - Template string with placeholders like 'DLAT MM BLAT / DLON MM BLON'.\n * @param values - Object containing valid and invalid test values for each placeholder.\n * @returns Array of coordinate strings with systematic errors injected.\n *\n * @example\n * ```typescript\n * fillTemplate('DLAT MM BLAT / DLON MM BLON', values);\n * // ['91 30 N / 179 30 E', 'nope 30 N / 179 30 E', ...]\n * ```\n */\nfunction fillTemplate(template: string, values: Values) {\n return template\n .split(' ')\n .flatMap((key, i, original) => {\n if (!values.invalid[key]) {\n return '';\n }\n\n return (values.invalid[key] as string[]).map((opt) =>\n [...original.slice(0, i), opt, ...original.slice(i + 1)]\n .map((token) => (token in values.valid ? values.valid[token] : token))\n .join(' '),\n );\n })\n .filter(Boolean);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,MAAMA,SAAiB;CACrB,SAAS;EACP,MAAM,CAAC,KAAK,iBAAiB;EAC7B,MAAM,CAAC,KAAK,iBAAiB;EAC7B,MAAM,CAAC,MAAM,OAAO;EACpB,OAAO,CAAC,QAAQ,OAAO;EACvB,MAAM,CAAC,OAAO,OAAO;EACrB,OAAO,CAAC,SAAS,OAAO;EACxB,GAAG;GAAC;GAAM;GAAM;GAAO;EACvB,IAAI;GAAC;GAAQ;GAAQ;GAAO;EAC5B,IAAI;GAAC;GAAQ;GAAQ;GAAO;EAC7B;CACD,OAAO;EACL,KAAK;EACL,MAAM;EACN,MAAM;EACN,MAAM;EACN,OAAO;EACP,MAAM;EACN,OAAO;EACP,GAAG;EACH,IAAI;EACJ,IAAI;EACL;CACF;AAED,MAAM,UAAU;CACd;EACE,aAAa;EACb,KAAK;GAAC;GAAS;GAAc;GAAa;EAC1C,KAAK;GAAC;GAAS;GAAc;GAAa;EAC3C;CACD;EACE,aAAa;EACb,KAAK;GAAC;GAAW;GAAgB;GAAe;EAChD,KAAK;GAAC;GAAW;GAAgB;GAAe;EACjD;CACD;EACE,aAAa;EACb,KAAK;GAAC;GAAa;GAAkB;GAAiB;EACtD,KAAK;GAAC;GAAa;GAAkB;GAAiB;EACvD;CACF;;;;;;;;;;;;;;;;;;;;AAqBD,MAAa,oBAAoB,OAAO,YACtC,QAAQ,KAAK,EAAE,aAAa,GAAG,aAAa;CAE1C,MAAM,UAAU,CAAC,WAAW,UAAU,CAAC,KAAK,WAAW,CAErD,OAAO,QAAQ,KAAK,GAAG,EAGvB,UACE,GAAG,OAAO,MAAM,IAAI,CAAC,KAAK,QAAQ,OAAO,KAA4B,CACtE,CAEE,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,CAE/B,SAAS,MAAM,aAAa,GAAG,OAAO,CAAC,CAC3C,CAAC;AAEF,QAAO,CAAC,aAAa,OAAO,YAAY,QAAQ,CAAC;EACjD,CACH;;;;;;;;;;;;;;AAeD,SAAS,aAAa,UAAkB,UAAgB;AACtD,QAAO,SACJ,MAAM,IAAI,CACV,SAAS,KAAK,GAAG,aAAa;AAC7B,MAAI,CAACC,SAAO,QAAQ,KAClB,QAAO;AAGT,SAAQA,SAAO,QAAQ,KAAkB,KAAK,QAC5C;GAAC,GAAG,SAAS,MAAM,GAAG,EAAE;GAAE;GAAK,GAAG,SAAS,MAAM,IAAI,EAAE;GAAC,CACrD,KAAK,UAAW,SAASA,SAAO,QAAQA,SAAO,MAAM,SAAS,MAAO,CACrE,KAAK,IAAI,CACb;GACD,CACD,OAAO,QAAQ"}
@@ -5,6 +5,26 @@ interface FormatOptions {
5
5
  separator: string;
6
6
  withOrdinal?: boolean;
7
7
  }
8
+ /**
9
+ * Creates a coordinate formatter function from a coordinate conversion function.
10
+ *
11
+ * @param fn - Function that converts a single coordinate value to a formatted string.
12
+ * @returns Formatter function that takes coordinate pair and optional config.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);
17
+ * formatDD([37.7749, -122.4194]);
18
+ * // '37.774900° N, 122.419400° W'
19
+ * ```
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const formatDMS = createFormatter(toDegreesMinutesSeconds);
24
+ * formatDMS([37.7749, -122.4194], { separator: ' / ', withOrdinal: true });
25
+ * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'
26
+ * ```
27
+ */
8
28
  declare const createFormatter: (fn: (coord: number, withOrdinal?: boolean) => string) => (coordinates: [number, number], config?: FormatOptions) => string;
9
29
  //#endregion
10
30
  export { FormatOptions, createFormatter };
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -14,6 +14,26 @@
14
14
  import { getOrdinal } from "./ordinal.js";
15
15
 
16
16
  //#region src/coordinates/latlon/internal/format.ts
17
+ /**
18
+ * Creates a coordinate formatter function from a coordinate conversion function.
19
+ *
20
+ * @param fn - Function that converts a single coordinate value to a formatted string.
21
+ * @returns Formatter function that takes coordinate pair and optional config.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);
26
+ * formatDD([37.7749, -122.4194]);
27
+ * // '37.774900° N, 122.419400° W'
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const formatDMS = createFormatter(toDegreesMinutesSeconds);
33
+ * formatDMS([37.7749, -122.4194], { separator: ' / ', withOrdinal: true });
34
+ * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'
35
+ * ```
36
+ */
17
37
  const createFormatter = (fn) => (coordinates, config) => {
18
38
  const [latitude, longitude] = coordinates;
19
39
  const latOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(latitude, true)}` : ""}`;
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/format.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n// __private-exports\n\nimport { getOrdinal } from './ordinal';\n\nexport interface FormatOptions {\n prefix: string;\n suffix: string;\n separator: string;\n withOrdinal?: boolean;\n}\n\nexport const createFormatter =\n (fn: (coord: number, withOrdinal?: boolean) => string) =>\n (coordinates: [number, number], config?: FormatOptions): string => {\n const [latitude, longitude] = coordinates;\n const latOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(latitude, true)}` : ''}`;\n const lonOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(longitude, false)}` : ''}`;\n const lat = fn(latitude, config?.withOrdinal);\n const lon = fn(longitude, config?.withOrdinal);\n const prefix = config?.prefix ?? '';\n const suffix = config?.suffix ?? '';\n const separator = config?.separator ?? ', ';\n\n return `${prefix}${lat}${latOrdinal}${separator}${lon}${lonOrdinal}${suffix}`;\n };\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAa,mBACV,QACA,aAA+B,WAAmC;CACjE,MAAM,CAAC,UAAU,aAAa;CAC9B,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,UAAU,KAAK,KAAK;CAC/E,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,WAAW,MAAM,KAAK;CACjF,MAAM,MAAM,GAAG,UAAU,QAAQ,YAAY;CAC7C,MAAM,MAAM,GAAG,WAAW,QAAQ,YAAY;CAC9C,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,QAAQ,UAAU;AAGjC,QAAO,GAAG,SAAS,MAAM,aAFP,QAAQ,aAAa,OAEW,MAAM,aAAa"}
1
+ {"version":3,"file":"format.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/format.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n// __private-exports\n\nimport { getOrdinal } from './ordinal';\n\nexport interface FormatOptions {\n prefix: string;\n suffix: string;\n separator: string;\n withOrdinal?: boolean;\n}\n\n/**\n * Creates a coordinate formatter function from a coordinate conversion function.\n *\n * @param fn - Function that converts a single coordinate value to a formatted string.\n * @returns Formatter function that takes coordinate pair and optional config.\n *\n * @example\n * ```typescript\n * const formatDD = createFormatter((num) => `${num.toFixed(6)}°`);\n * formatDD([37.7749, -122.4194]);\n * // '37.774900° N, 122.419400° W'\n * ```\n *\n * @example\n * ```typescript\n * const formatDMS = createFormatter(toDegreesMinutesSeconds);\n * formatDMS([37.7749, -122.4194], { separator: ' / ', withOrdinal: true });\n * // '37° 46' 29.64″ N / 122° 25' 9.84″ W'\n * ```\n */\nexport const createFormatter =\n (fn: (coord: number, withOrdinal?: boolean) => string) =>\n (coordinates: [number, number], config?: FormatOptions): string => {\n const [latitude, longitude] = coordinates;\n const latOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(latitude, true)}` : ''}`;\n const lonOrdinal = `${config?.withOrdinal ? ` ${getOrdinal(longitude, false)}` : ''}`;\n const lat = fn(latitude, config?.withOrdinal);\n const lon = fn(longitude, config?.withOrdinal);\n const prefix = config?.prefix ?? '';\n const suffix = config?.suffix ?? '';\n const separator = config?.separator ?? ', ';\n\n return `${prefix}${lat}${latOrdinal}${separator}${lon}${lonOrdinal}${suffix}`;\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAa,mBACV,QACA,aAA+B,WAAmC;CACjE,MAAM,CAAC,UAAU,aAAa;CAC9B,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,UAAU,KAAK,KAAK;CAC/E,MAAM,aAAa,GAAG,QAAQ,cAAc,IAAI,WAAW,WAAW,MAAM,KAAK;CACjF,MAAM,MAAM,GAAG,UAAU,QAAQ,YAAY;CAC7C,MAAM,MAAM,GAAG,WAAW,QAAQ,YAAY;CAC9C,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,SAAS,QAAQ,UAAU;AAGjC,QAAO,GAAG,SAAS,MAAM,aAFP,QAAQ,aAAa,OAEW,MAAM,aAAa"}
@@ -2,6 +2,29 @@
2
2
  /**
3
3
  * Return an error string if the value is outside the range where the limits
4
4
  * are 0-limit.
5
+ *
6
+ * @param label - Descriptive label for the value being validated (e.g., "Minutes", "Seconds").
7
+ * @param value - String representation of the numeric value to validate.
8
+ * @param limit - Maximum allowed value (minimum is always 0).
9
+ * @returns Error message string if out of range, undefined if valid.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * inRange('Minutes', '45', 59);
14
+ * // undefined (valid)
15
+ * ```
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * inRange('Minutes', '61', 59);
20
+ * // 'Minutes value (61) exceeds max value (59).'
21
+ * ```
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * inRange('Seconds', '-5', 59);
26
+ * // 'Seconds value (-5) must be positive.'
27
+ * ```
5
28
  */
6
29
  declare const inRange: (label: string, value: string, limit: number) => string | undefined;
7
30
  //#endregion
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -15,9 +15,33 @@
15
15
  /**
16
16
  * Return an error string if the value is outside the range where the limits
17
17
  * are 0-limit.
18
+ *
19
+ * @param label - Descriptive label for the value being validated (e.g., "Minutes", "Seconds").
20
+ * @param value - String representation of the numeric value to validate.
21
+ * @param limit - Maximum allowed value (minimum is always 0).
22
+ * @returns Error message string if out of range, undefined if valid.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * inRange('Minutes', '45', 59);
27
+ * // undefined (valid)
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * inRange('Minutes', '61', 59);
33
+ * // 'Minutes value (61) exceeds max value (59).'
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * inRange('Seconds', '-5', 59);
39
+ * // 'Seconds value (-5) must be positive.'
40
+ * ```
18
41
  */
19
42
  const inRange = (label, value, limit) => {
20
43
  const num = Number.parseFloat(value);
44
+ if (value !== "" && Number.isNaN(num)) return `${label} value (${value}) is not a valid number.`;
21
45
  if (limit < num) return `${label} value (${value}) exceeds max value (${limit}).`;
22
46
  if (num < 0) return `${label} value (${value}) must be positive.`;
23
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"in-range.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/in-range.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Return an error string if the value is outside the range where the limits\n * are 0-limit.\n */\nexport const inRange = (label: string, value: string, limit: number) => {\n const num = Number.parseFloat(value);\n\n if (limit < num) {\n return `${label} value (${value}) exceeds max value (${limit}).`;\n }\n\n if (num < 0) {\n return `${label} value (${value}) must be positive.`;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,MAAa,WAAW,OAAe,OAAe,UAAkB;CACtE,MAAM,MAAM,OAAO,WAAW,MAAM;AAEpC,KAAI,QAAQ,IACV,QAAO,GAAG,MAAM,UAAU,MAAM,uBAAuB,MAAM;AAG/D,KAAI,MAAM,EACR,QAAO,GAAG,MAAM,UAAU,MAAM"}
1
+ {"version":3,"file":"in-range.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/in-range.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Return an error string if the value is outside the range where the limits\n * are 0-limit.\n *\n * @param label - Descriptive label for the value being validated (e.g., \"Minutes\", \"Seconds\").\n * @param value - String representation of the numeric value to validate.\n * @param limit - Maximum allowed value (minimum is always 0).\n * @returns Error message string if out of range, undefined if valid.\n *\n * @example\n * ```typescript\n * inRange('Minutes', '45', 59);\n * // undefined (valid)\n * ```\n *\n * @example\n * ```typescript\n * inRange('Minutes', '61', 59);\n * // 'Minutes value (61) exceeds max value (59).'\n * ```\n *\n * @example\n * ```typescript\n * inRange('Seconds', '-5', 59);\n * // 'Seconds value (-5) must be positive.'\n * ```\n */\nexport const inRange = (label: string, value: string, limit: number) => {\n const num = Number.parseFloat(value);\n\n if (value !== '' && Number.isNaN(num)) {\n return `${label} value (${value}) is not a valid number.`;\n }\n\n if (limit < num) {\n return `${label} value (${value}) exceeds max value (${limit}).`;\n }\n\n if (num < 0) {\n return `${label} value (${value}) must be positive.`;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAa,WAAW,OAAe,OAAe,UAAkB;CACtE,MAAM,MAAM,OAAO,WAAW,MAAM;AAEpC,KAAI,UAAU,MAAM,OAAO,MAAM,IAAI,CACnC,QAAO,GAAG,MAAM,UAAU,MAAM;AAGlC,KAAI,QAAQ,IACV,QAAO,GAAG,MAAM,UAAU,MAAM,uBAAuB,MAAM;AAG/D,KAAI,MAAM,EACR,QAAO,GAAG,MAAM,UAAU,MAAM"}
@@ -1,3 +1,18 @@
1
+ /*
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { CoordinateInput, CoordinateInternalValue, CoordinateObject, CoordinateTuple, LatLonTuple, LonLatTuple, isCoordinateObject, isCoordinateTuple, normalizeObjectToLatLon, tupleToLatLon } from "./normalize.js";
14
+ import { isFiniteNumber, validateNumericCoordinate, validateSignedRange } from "./validate.js";
15
+
1
16
  //#region src/coordinates/latlon/internal/index.d.ts
2
17
  type Axes = 'LAT' | 'LON';
3
18
  type Compass = 'N' | 'S' | 'E' | 'W';
@@ -57,5 +72,5 @@ declare const PARTIAL_PATTERNS: {
57
72
  readonly secDec: RegExp;
58
73
  };
59
74
  //#endregion
60
- export { Axes, BEARINGS, Compass, Errors, FORMATS, FORMATS_DEFAULT, Format, LIMITS, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS };
75
+ export { Axes, BEARINGS, Compass, type CoordinateInput, type CoordinateInternalValue, type CoordinateObject, type CoordinateTuple, Errors, FORMATS, FORMATS_DEFAULT, Format, LIMITS, type LatLonTuple, type LonLatTuple, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, normalizeObjectToLatLon, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
61
76
  //# sourceMappingURL=index.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -12,6 +12,8 @@
12
12
 
13
13
 
14
14
  import { capture, merge, optional } from "../../../patterning.js";
15
+ import { isCoordinateObject, isCoordinateTuple, normalizeObjectToLatLon, tupleToLatLon } from "./normalize.js";
16
+ import { isFiniteNumber, validateNumericCoordinate, validateSignedRange } from "./validate.js";
15
17
 
16
18
  //#region src/coordinates/latlon/internal/index.ts
17
19
  /**
@@ -58,6 +60,28 @@ const SYMBOL_PATTERNS = {
58
60
  SYMBOLS.SECONDS
59
61
  ].join("")}]`)
60
62
  };
63
+ /**
64
+ * Creates a regex pattern for matching decimal minutes or seconds values.
65
+ *
66
+ * Generates a pattern that matches numeric values in the range 0-59.999... with optional
67
+ * leading zeros, decimal points, and symbol indicators, using lookbehind and lookahead
68
+ * to prevent partial matches within larger numbers.
69
+ *
70
+ * @param symbol - Regular expression for the symbol (minutes ' or seconds " indicator).
71
+ * @returns Combined regex pattern with precise boundary matching.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const minutesPattern = decimalSecAndMin(SYMBOL_PATTERNS.MINUTES);
76
+ * // Matches: "30.5'", "59.999999999", ".5'", "001'", etc.
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const secondsPattern = decimalSecAndMin(SYMBOL_PATTERNS.SECONDS);
82
+ * // Matches: '45.23"', '0.5', '59.9999999999"', etc.
83
+ * ```
84
+ */
61
85
  const decimalSecAndMin = (symbol) => optional(/(?<!\d)/, /([-+]?0*(?:[0-5]?\d|\.\d{1,10})(?:\.\d{1,10})?)/, optional(symbol), /(?!\d)/);
62
86
  const PARTIAL_PATTERNS = {
63
87
  " ": /\s*/,
@@ -74,5 +98,5 @@ const PARTIAL_PATTERNS = {
74
98
  };
75
99
 
76
100
  //#endregion
77
- export { BEARINGS, FORMATS, FORMATS_DEFAULT, LIMITS, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS };
101
+ export { BEARINGS, FORMATS, FORMATS_DEFAULT, LIMITS, PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, isCoordinateObject, isCoordinateTuple, isFiniteNumber, normalizeObjectToLatLon, tupleToLatLon, validateNumericCoordinate, validateSignedRange };
78
102
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Patterning.optional","Patterning.capture","Patterning.merge"],"sources":["../../../../src/coordinates/latlon/internal/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport * as Patterning from '@/patterning';\n\nexport type Axes = 'LAT' | 'LON';\nexport type Compass = 'N' | 'S' | 'E' | 'W';\nexport type Errors = string[];\nexport type Format = (typeof FORMATS)[number];\n\n/**\n * Bearings are the consistent/explicit identifiers of directionality of a\n * coordinate component; this library has opted for these over implicit\n * indication by number sign not because there is an inherent superiority\n * but because something had to be chosen.\n *\n * NOTE: these arrays are position-important; negative values are [1] and\n * positive values are [0] so that they can be consistently indexed using\n * an `isNegative` boolean to reference the negative bearing of each axis\n */\nexport const BEARINGS = {\n LAT: ['N', 'S'],\n LON: ['E', 'W'],\n LATLON: [\n ['N', 'S'],\n ['E', 'W'],\n ],\n LONLAT: [\n ['E', 'W'],\n ['N', 'S'],\n ],\n} as const;\n\nexport const FORMATS = ['LATLON', 'LONLAT'] as const;\nexport const FORMATS_DEFAULT = FORMATS[0];\n\nexport const LIMITS = { LATLON: [90, 180], LONLAT: [180, 90] } as const;\n\nexport const SYMBOLS = {\n DEGREES: '°',\n MINUTES: \"'\",\n SECONDS: '\"',\n DIVIDER: '/',\n};\n\nexport const SYMBOL_PATTERNS = {\n LAT: new RegExp(`[${BEARINGS.LAT.join('')}]`),\n LON: new RegExp(`[${BEARINGS.LON.join('')}]`),\n NSEW: new RegExp(`[${[...BEARINGS.LAT, ...BEARINGS.LON].join('')}]`),\n NEGATIVE_BEARINGS: /[SW]/i,\n NEGATIVE_SIGN: /-/,\n\n DEGREES: new RegExp(SYMBOLS.DEGREES),\n MINUTES: new RegExp(SYMBOLS.MINUTES),\n SECONDS: new RegExp(SYMBOLS.SECONDS),\n\n DIVIDER: new RegExp(SYMBOLS.DIVIDER),\n\n DMS: new RegExp(\n `[${[SYMBOLS.DEGREES, SYMBOLS.MINUTES, SYMBOLS.SECONDS].join('')}]`,\n ),\n\n // divider: {\n // first: /(?<NAMED_SEPARATOR>:?)/,\n // follow: new RegExp(`\\\\s?\\\\k<${'NAMED_SEPARATOR'}>\\\\s?`),\n // },\n} as const;\n\nconst decimalSecAndMin = (symbol: RegExp) =>\n Patterning.optional(\n // Negative lookbehind\n // to ensure that the match is not preceded by a digit,\n // avoiding partial matches within larger numbers.\n /(?<!\\d)/,\n\n // 0-59 including 10 decimal places and leading zeros or no number before\n // acceptable values: 0, 0.1234567890, .9876543210, 001, 59.9999999999\n /([-+]?0*(?:[0-5]?\\d|\\.\\d{1,10})(?:\\.\\d{1,10})?)/,\n\n Patterning.optional(symbol),\n\n // Negative lookahead\n // to ensure that the match is not followed by a digit,\n // avoiding partial matches within larger numbers.\n /(?!\\d)/,\n );\n\nexport const PARTIAL_PATTERNS = {\n ' ': /\\s*/,\n '/': Patterning.capture(SYMBOL_PATTERNS.DIVIDER),\n NS: Patterning.optional(Patterning.capture(SYMBOL_PATTERNS.LAT)),\n EW: Patterning.optional(Patterning.capture(SYMBOL_PATTERNS.LON)),\n\n degLatDec: Patterning.merge(\n Patterning.capture(\n /0*(?:90(?:\\.0{1,10})?)/, // 90[.0]\n /|/,\n /(?:0?[0-8]?\\d(?:\\.\\d{1,10})?)/, // [0]0[.0]-89[.9]\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLonDec: Patterning.merge(\n Patterning.capture(\n /(?:180(?:\\.0{1,10})?)/, // 180[.0]\n /|/,\n /(?:0*(?:\\d{1,2}|1[0-7]\\d)(?:\\.\\d{1,10})?)/, // [00]0[.0]-179[.9]\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLat: Patterning.merge(\n Patterning.capture(\n /(?:0?90)/, // 90\n /|/,\n /(?:0?[0-8]?\\d)/, // [0]0-89\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLon: Patterning.merge(\n Patterning.capture(\n /(?:180)/, // 180\n /|/,\n /(?:0*(?:\\d{1,2}|1[0-7]\\d))/, // [00]0-179\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n min: Patterning.merge(\n Patterning.optional(\n Patterning.capture(\n /(?:0?[0-5]?\\d)?/, // [0]0-59\n ),\n Patterning.optional(SYMBOL_PATTERNS.MINUTES),\n ),\n ),\n minDec: decimalSecAndMin(SYMBOL_PATTERNS.MINUTES),\n secDec: decimalSecAndMin(SYMBOL_PATTERNS.SECONDS),\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,WAAW;CACtB,KAAK,CAAC,KAAK,IAAI;CACf,KAAK,CAAC,KAAK,IAAI;CACf,QAAQ,CACN,CAAC,KAAK,IAAI,EACV,CAAC,KAAK,IAAI,CACX;CACD,QAAQ,CACN,CAAC,KAAK,IAAI,EACV,CAAC,KAAK,IAAI,CACX;CACF;AAED,MAAa,UAAU,CAAC,UAAU,SAAS;AAC3C,MAAa,kBAAkB,QAAQ;AAEvC,MAAa,SAAS;CAAE,QAAQ,CAAC,IAAI,IAAI;CAAE,QAAQ,CAAC,KAAK,GAAG;CAAE;AAE9D,MAAa,UAAU;CACrB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACV;AAED,MAAa,kBAAkB;CAC7B,qBAAK,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,GAAG;CAC7C,qBAAK,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,GAAG;CAC7C,sBAAM,IAAI,OAAO,IAAI,CAAC,GAAG,SAAS,KAAK,GAAG,SAAS,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG;CACpE,mBAAmB;CACnB,eAAe;CAEf,SAAS,IAAI,OAAO,QAAQ,QAAQ;CACpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CACpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CAEpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CAEpC,qBAAK,IAAI,OACP,IAAI;EAAC,QAAQ;EAAS,QAAQ;EAAS,QAAQ;EAAQ,CAAC,KAAK,GAAG,CAAC,GAClE;CAMF;AAED,MAAM,oBAAoB,WACxBA,SAIE,WAIA,mDAEAA,SAAoB,OAAO,EAK3B,SACD;AAEH,MAAa,mBAAmB;CAC9B,KAAK;CACL,KAAKC,QAAmB,gBAAgB,QAAQ;CAChD,IAAID,SAAoBC,QAAmB,gBAAgB,IAAI,CAAC;CAChE,IAAID,SAAoBC,QAAmB,gBAAgB,IAAI,CAAC;CAEhE,WAAWC,MACTD,QACE,0BACA,KACA,gCACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,WAAWE,MACTD,QACE,yBACA,KACA,4CACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,QAAQE,MACND,QACE,YACA,KACA,iBACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,QAAQE,MACND,QACE,WACA,KACA,6BACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,KAAKE,MACHF,SACEC,QACE,kBACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C,CACF;CACD,QAAQ,iBAAiB,gBAAgB,QAAQ;CACjD,QAAQ,iBAAiB,gBAAgB,QAAQ;CAClD"}
1
+ {"version":3,"file":"index.js","names":["Patterning.optional","Patterning.capture","Patterning.merge"],"sources":["../../../../src/coordinates/latlon/internal/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport * as Patterning from '@/patterning';\n\nexport type Axes = 'LAT' | 'LON';\nexport type Compass = 'N' | 'S' | 'E' | 'W';\nexport type Errors = string[];\nexport type Format = (typeof FORMATS)[number];\n\n/**\n * Bearings are the consistent/explicit identifiers of directionality of a\n * coordinate component; this library has opted for these over implicit\n * indication by number sign not because there is an inherent superiority\n * but because something had to be chosen.\n *\n * NOTE: these arrays are position-important; negative values are [1] and\n * positive values are [0] so that they can be consistently indexed using\n * an `isNegative` boolean to reference the negative bearing of each axis\n */\nexport const BEARINGS = {\n LAT: ['N', 'S'],\n LON: ['E', 'W'],\n LATLON: [\n ['N', 'S'],\n ['E', 'W'],\n ],\n LONLAT: [\n ['E', 'W'],\n ['N', 'S'],\n ],\n} as const;\n\nexport const FORMATS = ['LATLON', 'LONLAT'] as const;\nexport const FORMATS_DEFAULT = FORMATS[0];\n\nexport const LIMITS = { LATLON: [90, 180], LONLAT: [180, 90] } as const;\n\nexport const SYMBOLS = {\n DEGREES: '°',\n MINUTES: \"'\",\n SECONDS: '\"',\n DIVIDER: '/',\n};\n\nexport const SYMBOL_PATTERNS = {\n LAT: new RegExp(`[${BEARINGS.LAT.join('')}]`),\n LON: new RegExp(`[${BEARINGS.LON.join('')}]`),\n NSEW: new RegExp(`[${[...BEARINGS.LAT, ...BEARINGS.LON].join('')}]`),\n NEGATIVE_BEARINGS: /[SW]/i,\n NEGATIVE_SIGN: /-/,\n\n DEGREES: new RegExp(SYMBOLS.DEGREES),\n MINUTES: new RegExp(SYMBOLS.MINUTES),\n SECONDS: new RegExp(SYMBOLS.SECONDS),\n\n DIVIDER: new RegExp(SYMBOLS.DIVIDER),\n\n DMS: new RegExp(\n `[${[SYMBOLS.DEGREES, SYMBOLS.MINUTES, SYMBOLS.SECONDS].join('')}]`,\n ),\n\n // divider: {\n // first: /(?<NAMED_SEPARATOR>:?)/,\n // follow: new RegExp(`\\\\s?\\\\k<${'NAMED_SEPARATOR'}>\\\\s?`),\n // },\n} as const;\n\n/**\n * Creates a regex pattern for matching decimal minutes or seconds values.\n *\n * Generates a pattern that matches numeric values in the range 0-59.999... with optional\n * leading zeros, decimal points, and symbol indicators, using lookbehind and lookahead\n * to prevent partial matches within larger numbers.\n *\n * @param symbol - Regular expression for the symbol (minutes ' or seconds \" indicator).\n * @returns Combined regex pattern with precise boundary matching.\n *\n * @example\n * ```typescript\n * const minutesPattern = decimalSecAndMin(SYMBOL_PATTERNS.MINUTES);\n * // Matches: \"30.5'\", \"59.999999999\", \".5'\", \"001'\", etc.\n * ```\n *\n * @example\n * ```typescript\n * const secondsPattern = decimalSecAndMin(SYMBOL_PATTERNS.SECONDS);\n * // Matches: '45.23\"', '0.5', '59.9999999999\"', etc.\n * ```\n */\nconst decimalSecAndMin = (symbol: RegExp) =>\n Patterning.optional(\n // Negative lookbehind\n // to ensure that the match is not preceded by a digit,\n // avoiding partial matches within larger numbers.\n /(?<!\\d)/,\n\n // 0-59 including 10 decimal places and leading zeros or no number before\n // acceptable values: 0, 0.1234567890, .9876543210, 001, 59.9999999999\n /([-+]?0*(?:[0-5]?\\d|\\.\\d{1,10})(?:\\.\\d{1,10})?)/,\n\n Patterning.optional(symbol),\n\n // Negative lookahead\n // to ensure that the match is not followed by a digit,\n // avoiding partial matches within larger numbers.\n /(?!\\d)/,\n );\n\nexport const PARTIAL_PATTERNS = {\n ' ': /\\s*/,\n '/': Patterning.capture(SYMBOL_PATTERNS.DIVIDER),\n NS: Patterning.optional(Patterning.capture(SYMBOL_PATTERNS.LAT)),\n EW: Patterning.optional(Patterning.capture(SYMBOL_PATTERNS.LON)),\n\n degLatDec: Patterning.merge(\n Patterning.capture(\n /0*(?:90(?:\\.0{1,10})?)/, // 90[.0]\n /|/,\n /(?:0?[0-8]?\\d(?:\\.\\d{1,10})?)/, // [0]0[.0]-89[.9]\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLonDec: Patterning.merge(\n Patterning.capture(\n /(?:180(?:\\.0{1,10})?)/, // 180[.0]\n /|/,\n /(?:0*(?:\\d{1,2}|1[0-7]\\d)(?:\\.\\d{1,10})?)/, // [00]0[.0]-179[.9]\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLat: Patterning.merge(\n Patterning.capture(\n /(?:0?90)/, // 90\n /|/,\n /(?:0?[0-8]?\\d)/, // [0]0-89\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n degLon: Patterning.merge(\n Patterning.capture(\n /(?:180)/, // 180\n /|/,\n /(?:0*(?:\\d{1,2}|1[0-7]\\d))/, // [00]0-179\n ),\n Patterning.optional(SYMBOL_PATTERNS.DEGREES),\n ),\n min: Patterning.merge(\n Patterning.optional(\n Patterning.capture(\n /(?:0?[0-5]?\\d)?/, // [0]0-59\n ),\n Patterning.optional(SYMBOL_PATTERNS.MINUTES),\n ),\n ),\n minDec: decimalSecAndMin(SYMBOL_PATTERNS.MINUTES),\n secDec: decimalSecAndMin(SYMBOL_PATTERNS.SECONDS),\n} as const;\n\nexport {\n type CoordinateInput,\n type CoordinateInternalValue,\n type CoordinateObject,\n type CoordinateTuple,\n type LatLonTuple,\n type LonLatTuple,\n isCoordinateObject,\n isCoordinateTuple,\n normalizeObjectToLatLon,\n tupleToLatLon,\n} from './normalize';\nexport {\n isFiniteNumber,\n validateNumericCoordinate,\n validateSignedRange,\n} from './validate';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,WAAW;CACtB,KAAK,CAAC,KAAK,IAAI;CACf,KAAK,CAAC,KAAK,IAAI;CACf,QAAQ,CACN,CAAC,KAAK,IAAI,EACV,CAAC,KAAK,IAAI,CACX;CACD,QAAQ,CACN,CAAC,KAAK,IAAI,EACV,CAAC,KAAK,IAAI,CACX;CACF;AAED,MAAa,UAAU,CAAC,UAAU,SAAS;AAC3C,MAAa,kBAAkB,QAAQ;AAEvC,MAAa,SAAS;CAAE,QAAQ,CAAC,IAAI,IAAI;CAAE,QAAQ,CAAC,KAAK,GAAG;CAAE;AAE9D,MAAa,UAAU;CACrB,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACV;AAED,MAAa,kBAAkB;CAC7B,qBAAK,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,GAAG;CAC7C,qBAAK,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,GAAG;CAC7C,sBAAM,IAAI,OAAO,IAAI,CAAC,GAAG,SAAS,KAAK,GAAG,SAAS,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG;CACpE,mBAAmB;CACnB,eAAe;CAEf,SAAS,IAAI,OAAO,QAAQ,QAAQ;CACpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CACpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CAEpC,SAAS,IAAI,OAAO,QAAQ,QAAQ;CAEpC,qBAAK,IAAI,OACP,IAAI;EAAC,QAAQ;EAAS,QAAQ;EAAS,QAAQ;EAAQ,CAAC,KAAK,GAAG,CAAC,GAClE;CAMF;;;;;;;;;;;;;;;;;;;;;;;AAwBD,MAAM,oBAAoB,WACxBA,SAIE,WAIA,mDAEAA,SAAoB,OAAO,EAK3B,SACD;AAEH,MAAa,mBAAmB;CAC9B,KAAK;CACL,KAAKC,QAAmB,gBAAgB,QAAQ;CAChD,IAAID,SAAoBC,QAAmB,gBAAgB,IAAI,CAAC;CAChE,IAAID,SAAoBC,QAAmB,gBAAgB,IAAI,CAAC;CAEhE,WAAWC,MACTD,QACE,0BACA,KACA,gCACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,WAAWE,MACTD,QACE,yBACA,KACA,4CACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,QAAQE,MACND,QACE,YACA,KACA,iBACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,QAAQE,MACND,QACE,WACA,KACA,6BACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C;CACD,KAAKE,MACHF,SACEC,QACE,kBACD,EACDD,SAAoB,gBAAgB,QAAQ,CAC7C,CACF;CACD,QAAQ,iBAAiB,gBAAgB,QAAQ;CACjD,QAAQ,iBAAiB,gBAAgB,QAAQ;CAClD"}