@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,8 +13,33 @@
13
13
  import { Tokens } from "../lexer.js";
14
14
 
15
15
  //#region src/coordinates/latlon/internal/pipes/check-numbers.d.ts
16
+
16
17
  /**
17
18
  * Check for problems in the numeric values.
19
+ *
20
+ * Validates that there are at least 2 numbers, no more than 6 numbers total,
21
+ * and that negative values only appear in the first position (degrees).
22
+ *
23
+ * @param tokens - Array of parsed coordinate tokens.
24
+ * @returns Pipe result with tokens and error message (or false if valid).
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * checkNumberValues(['45', '30']);
29
+ * // Returns tokens with error=false (valid number count)
30
+ * ```
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * checkNumberValues(['45']);
35
+ * // Returns error: 'Too few numbers.'
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * checkNumberValues(['1', '2', '3', '4', '5', '6', '7']);
41
+ * // Returns error: 'Too many numbers.'
42
+ * ```
18
43
  */
19
44
  declare function checkNumberValues(tokens: Tokens): [string[], string | boolean];
20
45
  //#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
@@ -11,12 +11,37 @@
11
11
  */
12
12
 
13
13
 
14
+ import { SYMBOLS } from "../index.js";
14
15
  import { simpler } from "./simpler.js";
15
16
  import { pipesResult } from "./index.js";
16
17
 
17
18
  //#region src/coordinates/latlon/internal/pipes/check-numbers.ts
18
19
  /**
19
20
  * Check for problems in the numeric values.
21
+ *
22
+ * Validates that there are at least 2 numbers, no more than 6 numbers total,
23
+ * and that negative values only appear in the first position (degrees).
24
+ *
25
+ * @param tokens - Array of parsed coordinate tokens.
26
+ * @returns Pipe result with tokens and error message (or false if valid).
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * checkNumberValues(['45', '30']);
31
+ * // Returns tokens with error=false (valid number count)
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * checkNumberValues(['45']);
37
+ * // Returns error: 'Too few numbers.'
38
+ * ```
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * checkNumberValues(['1', '2', '3', '4', '5', '6', '7']);
43
+ * // Returns error: 'Too many numbers.'
44
+ * ```
20
45
  */
21
46
  function checkNumberValues(tokens) {
22
47
  const simple = simpler(tokens);
@@ -28,6 +53,14 @@ function checkNumberValues(tokens) {
28
53
  return acc;
29
54
  }, []).join("");
30
55
  if (!!pattern.match(/[^_]-./) && pattern !== "_--_") return pipesResult(tokens, "Negative value for non-degrees value found.");
56
+ if (tokens.includes(SYMBOLS.DIVIDER)) {
57
+ const divIdx = tokens.indexOf(SYMBOLS.DIVIDER);
58
+ const halves = [tokens.slice(0, divIdx), tokens.slice(divIdx + 1)];
59
+ for (const half of halves) {
60
+ const nums = half.filter((t) => /\d/.test(t));
61
+ if (nums.length > 1 && nums.some((n, i) => i > 0 && Number.parseFloat(n) < 0)) return pipesResult(tokens, "Negative value for non-degrees value found.");
62
+ }
63
+ }
31
64
  return pipesResult(tokens, false);
32
65
  }
33
66
 
@@ -1 +1 @@
1
- {"version":3,"file":"check-numbers.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/check-numbers.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 { pipesResult } from '../pipes';\nimport { simpler } from './simpler';\nimport type { Tokens } from '../lexer';\n\n/**\n * Check for problems in the numeric values.\n */\nexport function checkNumberValues(tokens: Tokens) {\n const simple = simpler(tokens);\n\n if ((simple.match(/N/g) ?? []).length < 2) {\n return pipesResult(tokens, 'Too few numbers.');\n }\n\n const error =\n // 4 consecutive numbers in specific formation is not going to be valid\n /(?:N{4,}BN+)|(?:N+BN{4,})/.test(simple) ||\n // more than 6 numbers total\n (simple.match(/N/g) ?? []).length > 6;\n\n if (error) {\n return pipesResult(tokens, 'Too many numbers.');\n }\n\n const pattern = tokens\n .reduce((acc, t) => {\n if (/\\d/.test(t)) {\n acc.push(Number.parseFloat(t) < 0 ? '-' : '+');\n } else {\n acc.push('_');\n }\n\n return acc;\n }, [] as string[])\n .join('');\n\n const matches = pattern.match(/[^_]-./);\n\n // special case '_--_' when the input is something like 'S -1 -1 W'\n // which is invalid for other reasons and will be caught elsewhere\n if (!!matches && pattern !== '_--_') {\n return pipesResult(tokens, 'Negative value for non-degrees value found.');\n }\n\n return pipesResult(tokens, false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,kBAAkB,QAAgB;CAChD,MAAM,SAAS,QAAQ,OAAO;AAE9B,MAAK,OAAO,MAAM,KAAK,IAAI,EAAE,EAAE,SAAS,EACtC,QAAO,YAAY,QAAQ,mBAAmB;AAShD,KAJE,4BAA4B,KAAK,OAAO,KAEvC,OAAO,MAAM,KAAK,IAAI,EAAE,EAAE,SAAS,EAGpC,QAAO,YAAY,QAAQ,oBAAoB;CAGjD,MAAM,UAAU,OACb,QAAQ,KAAK,MAAM;AAClB,MAAI,KAAK,KAAK,EAAE,CACd,KAAI,KAAK,OAAO,WAAW,EAAE,GAAG,IAAI,MAAM,IAAI;MAE9C,KAAI,KAAK,IAAI;AAGf,SAAO;IACN,EAAE,CAAa,CACjB,KAAK,GAAG;AAMX,KAAI,CAAC,CAJW,QAAQ,MAAM,SAAS,IAItB,YAAY,OAC3B,QAAO,YAAY,QAAQ,8CAA8C;AAG3E,QAAO,YAAY,QAAQ,MAAM"}
1
+ {"version":3,"file":"check-numbers.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/check-numbers.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 { SYMBOLS } from '..';\nimport { pipesResult } from '../pipes';\nimport { simpler } from './simpler';\nimport type { Tokens } from '../lexer';\n\n/**\n * Check for problems in the numeric values.\n *\n * Validates that there are at least 2 numbers, no more than 6 numbers total,\n * and that negative values only appear in the first position (degrees).\n *\n * @param tokens - Array of parsed coordinate tokens.\n * @returns Pipe result with tokens and error message (or false if valid).\n *\n * @example\n * ```typescript\n * checkNumberValues(['45', '30']);\n * // Returns tokens with error=false (valid number count)\n * ```\n *\n * @example\n * ```typescript\n * checkNumberValues(['45']);\n * // Returns error: 'Too few numbers.'\n * ```\n *\n * @example\n * ```typescript\n * checkNumberValues(['1', '2', '3', '4', '5', '6', '7']);\n * // Returns error: 'Too many numbers.'\n * ```\n */\nexport function checkNumberValues(tokens: Tokens) {\n const simple = simpler(tokens);\n\n if ((simple.match(/N/g) ?? []).length < 2) {\n return pipesResult(tokens, 'Too few numbers.');\n }\n\n const error =\n // 4 consecutive numbers in specific formation is not going to be valid\n /(?:N{4,}BN+)|(?:N+BN{4,})/.test(simple) ||\n // more than 6 numbers total\n (simple.match(/N/g) ?? []).length > 6;\n\n if (error) {\n return pipesResult(tokens, 'Too many numbers.');\n }\n\n const pattern = tokens\n .reduce((acc, t) => {\n if (/\\d/.test(t)) {\n acc.push(Number.parseFloat(t) < 0 ? '-' : '+');\n } else {\n acc.push('_');\n }\n\n return acc;\n }, [] as string[])\n .join('');\n\n const matches = pattern.match(/[^_]-./);\n\n // special case '_--_' when the input is something like 'S -1 -1 W'\n // which is invalid for other reasons and will be caught elsewhere\n if (!!matches && pattern !== '_--_') {\n return pipesResult(tokens, 'Negative value for non-degrees value found.');\n }\n\n if (tokens.includes(SYMBOLS.DIVIDER)) {\n const divIdx = tokens.indexOf(SYMBOLS.DIVIDER);\n const halves = [tokens.slice(0, divIdx), tokens.slice(divIdx + 1)];\n\n for (const half of halves) {\n const nums = half.filter((t) => /\\d/.test(t));\n\n if (\n nums.length > 1 &&\n nums.some((n, i) => i > 0 && Number.parseFloat(n) < 0)\n ) {\n return pipesResult(\n tokens,\n 'Negative value for non-degrees value found.',\n );\n }\n }\n }\n\n return pipesResult(tokens, false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,kBAAkB,QAAgB;CAChD,MAAM,SAAS,QAAQ,OAAO;AAE9B,MAAK,OAAO,MAAM,KAAK,IAAI,EAAE,EAAE,SAAS,EACtC,QAAO,YAAY,QAAQ,mBAAmB;AAShD,KAJE,4BAA4B,KAAK,OAAO,KAEvC,OAAO,MAAM,KAAK,IAAI,EAAE,EAAE,SAAS,EAGpC,QAAO,YAAY,QAAQ,oBAAoB;CAGjD,MAAM,UAAU,OACb,QAAQ,KAAK,MAAM;AAClB,MAAI,KAAK,KAAK,EAAE,CACd,KAAI,KAAK,OAAO,WAAW,EAAE,GAAG,IAAI,MAAM,IAAI;MAE9C,KAAI,KAAK,IAAI;AAGf,SAAO;IACN,EAAE,CAAa,CACjB,KAAK,GAAG;AAMX,KAAI,CAAC,CAJW,QAAQ,MAAM,SAAS,IAItB,YAAY,OAC3B,QAAO,YAAY,QAAQ,8CAA8C;AAG3E,KAAI,OAAO,SAAS,QAAQ,QAAQ,EAAE;EACpC,MAAM,SAAS,OAAO,QAAQ,QAAQ,QAAQ;EAC9C,MAAM,SAAS,CAAC,OAAO,MAAM,GAAG,OAAO,EAAE,OAAO,MAAM,SAAS,EAAE,CAAC;AAElE,OAAK,MAAM,QAAQ,QAAQ;GACzB,MAAM,OAAO,KAAK,QAAQ,MAAM,KAAK,KAAK,EAAE,CAAC;AAE7C,OACE,KAAK,SAAS,KACd,KAAK,MAAM,GAAG,MAAM,IAAI,KAAK,OAAO,WAAW,EAAE,GAAG,EAAE,CAEtD,QAAO,YACL,QACA,8CACD;;;AAKP,QAAO,YAAY,QAAQ,MAAM"}
@@ -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,10 +15,27 @@ import { Tokens } from "../lexer.js";
15
15
  import { PipeResult } from "./index.js";
16
16
 
17
17
  //#region src/coordinates/latlon/internal/pipes/fix-bearings.d.ts
18
+
18
19
  /**
19
20
  * Normalize bearings - negative and positive numeric values to NSEW - and
20
21
  * positioning of bearings - after the numeric values - and fill in any missing
21
22
  * bearings if only one is provided.
23
+ *
24
+ * @param tokens - Array of parsed coordinate tokens containing a divider.
25
+ * @param format - Optional coordinate format (LATLON or LONLAT) to infer missing bearings.
26
+ * @returns Pipe result with normalized tokens and error status.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * fixBearings(['45', 'N', '/', '122', 'W'], 'LATLON');
31
+ * // Returns ['45', 'N', '/', '122', 'W'] with error=false
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * fixBearings(['-45', '/', '122'], 'LATLON');
37
+ * // Returns ['45', 'S', '/', '122', 'E'] with error=false
38
+ * ```
22
39
  */
23
40
  declare function fixBearings(tokens: Tokens, format?: Format): PipeResult;
24
41
  //#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
@@ -27,6 +27,22 @@ const conflict = ([a, b]) => `Bearing (${a}) conflicts with negative number (${b
27
27
  * Normalize bearings - negative and positive numeric values to NSEW - and
28
28
  * positioning of bearings - after the numeric values - and fill in any missing
29
29
  * bearings if only one is provided.
30
+ *
31
+ * @param tokens - Array of parsed coordinate tokens containing a divider.
32
+ * @param format - Optional coordinate format (LATLON or LONLAT) to infer missing bearings.
33
+ * @returns Pipe result with normalized tokens and error status.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * fixBearings(['45', 'N', '/', '122', 'W'], 'LATLON');
38
+ * // Returns ['45', 'N', '/', '122', 'W'] with error=false
39
+ * ```
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * fixBearings(['-45', '/', '122'], 'LATLON');
44
+ * // Returns ['45', 'S', '/', '122', 'E'] with error=false
45
+ * ```
30
46
  */
31
47
  function fixBearings(tokens, format) {
32
48
  const [left, right] = [tokens.slice(0, tokens.indexOf(SYMBOLS.DIVIDER)), tokens.slice(1 + tokens.indexOf(SYMBOLS.DIVIDER))].map(moveBearingsToHead);
@@ -65,6 +81,21 @@ function fixBearings(tokens, format) {
65
81
  * module only - so that it is easier to work with; moving a bearing to the
66
82
  * "head" allows for `push()` of subsequent number processing will keep the
67
83
  * order of the numeric values intact.
84
+ *
85
+ * @param coord - Array of tokens for one coordinate half (before or after divider).
86
+ * @returns New array with bearing moved to first position.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * moveBearingsToHead(['45', '30', 'N']);
91
+ * // ['N', '45', '30']
92
+ * ```
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * moveBearingsToHead(['122', '15']);
97
+ * // ['122', '15']
98
+ * ```
68
99
  */
69
100
  function moveBearingsToHead(coord) {
70
101
  return coord.reduce((acc, t) => {
@@ -1 +1 @@
1
- {"version":3,"file":"fix-bearings.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/fix-bearings.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 { BEARINGS, type Format, SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\nimport type { PipeResult } from '../pipes';\n\nconst orthogonal = {\n N: BEARINGS.LON,\n S: BEARINGS.LON,\n E: BEARINGS.LAT,\n W: BEARINGS.LAT,\n};\n\nconst bearingConflictsWithNumber = (tokens: Tokens) =>\n tokens[0] &&\n tokens[1] &&\n SYMBOL_PATTERNS.NEGATIVE_SIGN.test(tokens[1]) &&\n SYMBOL_PATTERNS.NSEW.test(tokens[0]) &&\n !SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(tokens[0]);\n\nconst bePositive = (n: string) => n.replace(SYMBOL_PATTERNS.NEGATIVE_SIGN, '');\n\nconst conflict = ([a, b]: Tokens) =>\n `Bearing (${a}) conflicts with negative number (${b}).`;\n\n/**\n * Normalize bearings - negative and positive numeric values to NSEW - and\n * positioning of bearings - after the numeric values - and fill in any missing\n * bearings if only one is provided.\n */\nexport function fixBearings(tokens: Tokens, format?: Format): PipeResult {\n const [left, right] = [\n tokens.slice(0, tokens.indexOf(SYMBOLS.DIVIDER)),\n tokens.slice(1 + tokens.indexOf(SYMBOLS.DIVIDER)),\n ].map(moveBearingsToHead) as [Tokens, Tokens];\n\n if (bearingConflictsWithNumber(left)) {\n return [[], conflict(left)];\n }\n\n if (bearingConflictsWithNumber(right)) {\n return [[], conflict(right)];\n }\n\n const [leftHasBearing, rightHasBearing] = [left, right].map(\n (list) => !!(list?.[0] && SYMBOL_PATTERNS.NSEW.test(list[0])),\n );\n\n let leftBearing = '';\n let rightBearing = '';\n\n if (leftHasBearing && rightHasBearing) {\n leftBearing = left.shift() ?? '';\n rightBearing = right.shift() ?? '';\n } else if (leftHasBearing) {\n leftBearing = left.shift() ?? '';\n rightBearing =\n orthogonal[leftBearing as keyof typeof orthogonal][\n +SYMBOL_PATTERNS.NEGATIVE_SIGN.test(right[0] ?? '') as 0 | 1\n ];\n } else if (rightHasBearing) {\n rightBearing = right.shift() ?? '';\n leftBearing =\n orthogonal[rightBearing as keyof typeof orthogonal][\n +SYMBOL_PATTERNS.NEGATIVE_SIGN.test(right[0] ?? '') as 0 | 1\n ];\n } else if (format) {\n leftBearing = `${BEARINGS[format][0][+SYMBOL_PATTERNS.NEGATIVE_SIGN.test(`${left[0]}`)]}`;\n rightBearing = `${BEARINGS[format][1][+SYMBOL_PATTERNS.NEGATIVE_SIGN.test(`${right[0]}`)]}`;\n } else {\n // neither exist\n return [[...left, SYMBOLS.DIVIDER, ...right], false];\n }\n\n return [\n [\n ...left.map(bePositive),\n leftBearing,\n SYMBOLS.DIVIDER,\n ...right.map(bePositive),\n rightBearing,\n ],\n false,\n ];\n}\n\n/**\n * Move the bearings indicators to the first element in the list - in this\n * module only - so that it is easier to work with; moving a bearing to the\n * \"head\" allows for `push()` of subsequent number processing will keep the\n * order of the numeric values intact.\n */\nfunction moveBearingsToHead(coord: Tokens) {\n return coord.reduce((acc, t) => {\n if (/\\d/.test(t)) {\n acc.push(t);\n } else {\n acc.unshift(t);\n }\n\n return acc;\n }, [] as Tokens);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,aAAa;CACjB,GAAG,SAAS;CACZ,GAAG,SAAS;CACZ,GAAG,SAAS;CACZ,GAAG,SAAS;CACb;AAED,MAAM,8BAA8B,WAClC,OAAO,MACP,OAAO,MACP,gBAAgB,cAAc,KAAK,OAAO,GAAG,IAC7C,gBAAgB,KAAK,KAAK,OAAO,GAAG,IACpC,CAAC,gBAAgB,kBAAkB,KAAK,OAAO,GAAG;AAEpD,MAAM,cAAc,MAAc,EAAE,QAAQ,gBAAgB,eAAe,GAAG;AAE9E,MAAM,YAAY,CAAC,GAAG,OACpB,YAAY,EAAE,oCAAoC,EAAE;;;;;;AAOtD,SAAgB,YAAY,QAAgB,QAA6B;CACvE,MAAM,CAAC,MAAM,SAAS,CACpB,OAAO,MAAM,GAAG,OAAO,QAAQ,QAAQ,QAAQ,CAAC,EAChD,OAAO,MAAM,IAAI,OAAO,QAAQ,QAAQ,QAAQ,CAAC,CAClD,CAAC,IAAI,mBAAmB;AAEzB,KAAI,2BAA2B,KAAK,CAClC,QAAO,CAAC,EAAE,EAAE,SAAS,KAAK,CAAC;AAG7B,KAAI,2BAA2B,MAAM,CACnC,QAAO,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC;CAG9B,MAAM,CAAC,gBAAgB,mBAAmB,CAAC,MAAM,MAAM,CAAC,KACrD,SAAS,CAAC,EAAE,OAAO,MAAM,gBAAgB,KAAK,KAAK,KAAK,GAAG,EAC7D;CAED,IAAI,cAAc;CAClB,IAAI,eAAe;AAEnB,KAAI,kBAAkB,iBAAiB;AACrC,gBAAc,KAAK,OAAO,IAAI;AAC9B,iBAAe,MAAM,OAAO,IAAI;YACvB,gBAAgB;AACzB,gBAAc,KAAK,OAAO,IAAI;AAC9B,iBACE,WAAW,aACT,CAAC,gBAAgB,cAAc,KAAK,MAAM,MAAM,GAAG;YAE9C,iBAAiB;AAC1B,iBAAe,MAAM,OAAO,IAAI;AAChC,gBACE,WAAW,cACT,CAAC,gBAAgB,cAAc,KAAK,MAAM,MAAM,GAAG;YAE9C,QAAQ;AACjB,gBAAc,GAAG,SAAS,QAAQ,GAAG,CAAC,gBAAgB,cAAc,KAAK,GAAG,KAAK,KAAK;AACtF,iBAAe,GAAG,SAAS,QAAQ,GAAG,CAAC,gBAAgB,cAAc,KAAK,GAAG,MAAM,KAAK;OAGxF,QAAO,CAAC;EAAC,GAAG;EAAM,QAAQ;EAAS,GAAG;EAAM,EAAE,MAAM;AAGtD,QAAO,CACL;EACE,GAAG,KAAK,IAAI,WAAW;EACvB;EACA,QAAQ;EACR,GAAG,MAAM,IAAI,WAAW;EACxB;EACD,EACD,MACD;;;;;;;;AASH,SAAS,mBAAmB,OAAe;AACzC,QAAO,MAAM,QAAQ,KAAK,MAAM;AAC9B,MAAI,KAAK,KAAK,EAAE,CACd,KAAI,KAAK,EAAE;MAEX,KAAI,QAAQ,EAAE;AAGhB,SAAO;IACN,EAAE,CAAW"}
1
+ {"version":3,"file":"fix-bearings.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/fix-bearings.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 { BEARINGS, type Format, SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\nimport type { PipeResult } from '../pipes';\n\nconst orthogonal = {\n N: BEARINGS.LON,\n S: BEARINGS.LON,\n E: BEARINGS.LAT,\n W: BEARINGS.LAT,\n};\n\nconst bearingConflictsWithNumber = (tokens: Tokens) =>\n tokens[0] &&\n tokens[1] &&\n SYMBOL_PATTERNS.NEGATIVE_SIGN.test(tokens[1]) &&\n SYMBOL_PATTERNS.NSEW.test(tokens[0]) &&\n !SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(tokens[0]);\n\nconst bePositive = (n: string) => n.replace(SYMBOL_PATTERNS.NEGATIVE_SIGN, '');\n\nconst conflict = ([a, b]: Tokens) =>\n `Bearing (${a}) conflicts with negative number (${b}).`;\n\n/**\n * Normalize bearings - negative and positive numeric values to NSEW - and\n * positioning of bearings - after the numeric values - and fill in any missing\n * bearings if only one is provided.\n *\n * @param tokens - Array of parsed coordinate tokens containing a divider.\n * @param format - Optional coordinate format (LATLON or LONLAT) to infer missing bearings.\n * @returns Pipe result with normalized tokens and error status.\n *\n * @example\n * ```typescript\n * fixBearings(['45', 'N', '/', '122', 'W'], 'LATLON');\n * // Returns ['45', 'N', '/', '122', 'W'] with error=false\n * ```\n *\n * @example\n * ```typescript\n * fixBearings(['-45', '/', '122'], 'LATLON');\n * // Returns ['45', 'S', '/', '122', 'E'] with error=false\n * ```\n */\nexport function fixBearings(tokens: Tokens, format?: Format): PipeResult {\n const [left, right] = [\n tokens.slice(0, tokens.indexOf(SYMBOLS.DIVIDER)),\n tokens.slice(1 + tokens.indexOf(SYMBOLS.DIVIDER)),\n ].map(moveBearingsToHead) as [Tokens, Tokens];\n\n if (bearingConflictsWithNumber(left)) {\n return [[], conflict(left)];\n }\n\n if (bearingConflictsWithNumber(right)) {\n return [[], conflict(right)];\n }\n\n const [leftHasBearing, rightHasBearing] = [left, right].map(\n (list) => !!(list?.[0] && SYMBOL_PATTERNS.NSEW.test(list[0])),\n );\n\n let leftBearing = '';\n let rightBearing = '';\n\n if (leftHasBearing && rightHasBearing) {\n leftBearing = left.shift() ?? '';\n rightBearing = right.shift() ?? '';\n } else if (leftHasBearing) {\n leftBearing = left.shift() ?? '';\n rightBearing =\n orthogonal[leftBearing as keyof typeof orthogonal][\n +SYMBOL_PATTERNS.NEGATIVE_SIGN.test(right[0] ?? '') as 0 | 1\n ];\n } else if (rightHasBearing) {\n rightBearing = right.shift() ?? '';\n leftBearing =\n orthogonal[rightBearing as keyof typeof orthogonal][\n +SYMBOL_PATTERNS.NEGATIVE_SIGN.test(right[0] ?? '') as 0 | 1\n ];\n } else if (format) {\n leftBearing = `${BEARINGS[format][0][+SYMBOL_PATTERNS.NEGATIVE_SIGN.test(`${left[0]}`)]}`;\n rightBearing = `${BEARINGS[format][1][+SYMBOL_PATTERNS.NEGATIVE_SIGN.test(`${right[0]}`)]}`;\n } else {\n // neither exist\n return [[...left, SYMBOLS.DIVIDER, ...right], false];\n }\n\n return [\n [\n ...left.map(bePositive),\n leftBearing,\n SYMBOLS.DIVIDER,\n ...right.map(bePositive),\n rightBearing,\n ],\n false,\n ];\n}\n\n/**\n * Move the bearings indicators to the first element in the list - in this\n * module only - so that it is easier to work with; moving a bearing to the\n * \"head\" allows for `push()` of subsequent number processing will keep the\n * order of the numeric values intact.\n *\n * @param coord - Array of tokens for one coordinate half (before or after divider).\n * @returns New array with bearing moved to first position.\n *\n * @example\n * ```typescript\n * moveBearingsToHead(['45', '30', 'N']);\n * // ['N', '45', '30']\n * ```\n *\n * @example\n * ```typescript\n * moveBearingsToHead(['122', '15']);\n * // ['122', '15']\n * ```\n */\nfunction moveBearingsToHead(coord: Tokens) {\n return coord.reduce((acc, t) => {\n if (/\\d/.test(t)) {\n acc.push(t);\n } else {\n acc.unshift(t);\n }\n\n return acc;\n }, [] as Tokens);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,MAAM,aAAa;CACjB,GAAG,SAAS;CACZ,GAAG,SAAS;CACZ,GAAG,SAAS;CACZ,GAAG,SAAS;CACb;AAED,MAAM,8BAA8B,WAClC,OAAO,MACP,OAAO,MACP,gBAAgB,cAAc,KAAK,OAAO,GAAG,IAC7C,gBAAgB,KAAK,KAAK,OAAO,GAAG,IACpC,CAAC,gBAAgB,kBAAkB,KAAK,OAAO,GAAG;AAEpD,MAAM,cAAc,MAAc,EAAE,QAAQ,gBAAgB,eAAe,GAAG;AAE9E,MAAM,YAAY,CAAC,GAAG,OACpB,YAAY,EAAE,oCAAoC,EAAE;;;;;;;;;;;;;;;;;;;;;;AAuBtD,SAAgB,YAAY,QAAgB,QAA6B;CACvE,MAAM,CAAC,MAAM,SAAS,CACpB,OAAO,MAAM,GAAG,OAAO,QAAQ,QAAQ,QAAQ,CAAC,EAChD,OAAO,MAAM,IAAI,OAAO,QAAQ,QAAQ,QAAQ,CAAC,CAClD,CAAC,IAAI,mBAAmB;AAEzB,KAAI,2BAA2B,KAAK,CAClC,QAAO,CAAC,EAAE,EAAE,SAAS,KAAK,CAAC;AAG7B,KAAI,2BAA2B,MAAM,CACnC,QAAO,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC;CAG9B,MAAM,CAAC,gBAAgB,mBAAmB,CAAC,MAAM,MAAM,CAAC,KACrD,SAAS,CAAC,EAAE,OAAO,MAAM,gBAAgB,KAAK,KAAK,KAAK,GAAG,EAC7D;CAED,IAAI,cAAc;CAClB,IAAI,eAAe;AAEnB,KAAI,kBAAkB,iBAAiB;AACrC,gBAAc,KAAK,OAAO,IAAI;AAC9B,iBAAe,MAAM,OAAO,IAAI;YACvB,gBAAgB;AACzB,gBAAc,KAAK,OAAO,IAAI;AAC9B,iBACE,WAAW,aACT,CAAC,gBAAgB,cAAc,KAAK,MAAM,MAAM,GAAG;YAE9C,iBAAiB;AAC1B,iBAAe,MAAM,OAAO,IAAI;AAChC,gBACE,WAAW,cACT,CAAC,gBAAgB,cAAc,KAAK,MAAM,MAAM,GAAG;YAE9C,QAAQ;AACjB,gBAAc,GAAG,SAAS,QAAQ,GAAG,CAAC,gBAAgB,cAAc,KAAK,GAAG,KAAK,KAAK;AACtF,iBAAe,GAAG,SAAS,QAAQ,GAAG,CAAC,gBAAgB,cAAc,KAAK,GAAG,MAAM,KAAK;OAGxF,QAAO,CAAC;EAAC,GAAG;EAAM,QAAQ;EAAS,GAAG;EAAM,EAAE,MAAM;AAGtD,QAAO,CACL;EACE,GAAG,KAAK,IAAI,WAAW;EACvB;EACA,QAAQ;EACR,GAAG,MAAM,IAAI,WAAW;EACxB;EACD,EACD,MACD;;;;;;;;;;;;;;;;;;;;;;;AAwBH,SAAS,mBAAmB,OAAe;AACzC,QAAO,MAAM,QAAQ,KAAK,MAAM;AAC9B,MAAI,KAAK,KAAK,EAAE,CACd,KAAI,KAAK,EAAE;MAEX,KAAI,QAAQ,EAAE;AAGhB,SAAO;IACN,EAAE,CAAW"}
@@ -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,11 +15,28 @@ import { Tokens } from "../lexer.js";
15
15
  import { PipeResult } from "./index.js";
16
16
 
17
17
  //#region src/coordinates/latlon/internal/pipes/fix-dividers.d.ts
18
+
18
19
  /**
19
20
  * For tokens lists without a divider, `fixDivider` attempts to determine the
20
21
  * __safe__ location to add a divider based on the existing formatting of the
21
22
  * coordinate: numbers, number positions, and number indicators.
22
23
  *
24
+ * @param original - Array of coordinate tokens without a divider.
25
+ * @param _format - Optional coordinate format (LATLON or LONLAT), currently unused.
26
+ * @returns Pipe result with divider inserted, or error=true if no safe location found.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * fixDivider(['45°', '30'', 'N', '122°', '15'', 'W']);
31
+ * // Returns tokens with divider inserted between latitude and longitude
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * fixDivider(['45', '30', 'N']);
37
+ * // Returns error=true (cannot safely determine divider position)
38
+ * ```
39
+ *
23
40
  * @remarks
24
41
  * pure function
25
42
  */
@@ -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
@@ -22,6 +22,19 @@ const SIMPLER_PATTERNS = {
22
22
  BNNB: 2,
23
23
  BNN: 2
24
24
  };
25
+ /**
26
+ * Inserts a divider token at the specified index in the tokens array.
27
+ *
28
+ * @param tokens - Array of coordinate tokens without a divider.
29
+ * @param index - Position where the divider should be inserted.
30
+ * @returns Pipe result with divider inserted and error=false.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * insertDivider(['45', '30', 'N', '122', '15', 'W'], 3);
35
+ * // [['45', '30', 'N', '/', '122', '15', 'W'], false]
36
+ * ```
37
+ */
25
38
  const insertDivider = (tokens, index) => [[
26
39
  ...tokens.slice(0, index),
27
40
  SYMBOLS.DIVIDER,
@@ -32,6 +45,22 @@ const insertDivider = (tokens, index) => [[
32
45
  * __safe__ location to add a divider based on the existing formatting of the
33
46
  * coordinate: numbers, number positions, and number indicators.
34
47
  *
48
+ * @param original - Array of coordinate tokens without a divider.
49
+ * @param _format - Optional coordinate format (LATLON or LONLAT), currently unused.
50
+ * @returns Pipe result with divider inserted, or error=true if no safe location found.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * fixDivider(['45°', '30'', 'N', '122°', '15'', 'W']);
55
+ * // Returns tokens with divider inserted between latitude and longitude
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * fixDivider(['45', '30', 'N']);
61
+ * // Returns error=true (cannot safely determine divider position)
62
+ * ```
63
+ *
35
64
  * @remarks
36
65
  * pure function
37
66
  */
@@ -1 +1 @@
1
- {"version":3,"file":"fix-dividers.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/fix-dividers.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 '..';\nimport { getGenomeIndex } from './genome';\nimport { simpler } from './simpler';\nimport type { Tokens } from '../lexer';\nimport type { PipeResult } from '../pipes';\n\n// N = number\n// B = bearing\nconst SIMPLER_PATTERNS = {\n NN: 1,\n NNB: 1,\n BNNB: 2,\n BNN: 2,\n};\n\nconst insertDivider = (tokens: Tokens, index: number): PipeResult => [\n [...tokens.slice(0, index), SYMBOLS.DIVIDER, ...tokens.slice(index)],\n false,\n];\n\n/**\n * For tokens lists without a divider, `fixDivider` attempts to determine the\n * __safe__ location to add a divider based on the existing formatting of the\n * coordinate: numbers, number positions, and number indicators.\n *\n * @remarks\n * pure function\n */\nexport function fixDivider(original: Tokens, _format?: Format): PipeResult {\n // if there is already a divider then there is nothing to do\n if (original.includes(SYMBOLS.DIVIDER)) {\n return [original, false];\n }\n\n // disconnect from argument memory space so we aren't working on shared memory\n const tokens = original.slice(0);\n\n const genomeIndex = getGenomeIndex(tokens);\n\n if (genomeIndex) {\n return insertDivider(tokens, genomeIndex);\n }\n\n const simple = simpler(tokens) as keyof typeof SIMPLER_PATTERNS;\n\n if (SIMPLER_PATTERNS[simple]) {\n return insertDivider(tokens, SIMPLER_PATTERNS[simple]);\n }\n\n // no position is found to be a safe location to insert a divider; any placement\n // would be a guess and therefor only has a 50% chance of being wrong or right\n return [[], true];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,MAAM,mBAAmB;CACvB,IAAI;CACJ,KAAK;CACL,MAAM;CACN,KAAK;CACN;AAED,MAAM,iBAAiB,QAAgB,UAA8B,CACnE;CAAC,GAAG,OAAO,MAAM,GAAG,MAAM;CAAE,QAAQ;CAAS,GAAG,OAAO,MAAM,MAAM;CAAC,EACpE,MACD;;;;;;;;;AAUD,SAAgB,WAAW,UAAkB,SAA8B;AAEzE,KAAI,SAAS,SAAS,QAAQ,QAAQ,CACpC,QAAO,CAAC,UAAU,MAAM;CAI1B,MAAM,SAAS,SAAS,MAAM,EAAE;CAEhC,MAAM,cAAc,eAAe,OAAO;AAE1C,KAAI,YACF,QAAO,cAAc,QAAQ,YAAY;CAG3C,MAAM,SAAS,QAAQ,OAAO;AAE9B,KAAI,iBAAiB,QACnB,QAAO,cAAc,QAAQ,iBAAiB,QAAQ;AAKxD,QAAO,CAAC,EAAE,EAAE,KAAK"}
1
+ {"version":3,"file":"fix-dividers.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/fix-dividers.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 '..';\nimport { getGenomeIndex } from './genome';\nimport { simpler } from './simpler';\nimport type { Tokens } from '../lexer';\nimport type { PipeResult } from '../pipes';\n\n// N = number\n// B = bearing\nconst SIMPLER_PATTERNS = {\n NN: 1,\n NNB: 1,\n BNNB: 2,\n BNN: 2,\n};\n\n/**\n * Inserts a divider token at the specified index in the tokens array.\n *\n * @param tokens - Array of coordinate tokens without a divider.\n * @param index - Position where the divider should be inserted.\n * @returns Pipe result with divider inserted and error=false.\n *\n * @example\n * ```typescript\n * insertDivider(['45', '30', 'N', '122', '15', 'W'], 3);\n * // [['45', '30', 'N', '/', '122', '15', 'W'], false]\n * ```\n */\nconst insertDivider = (tokens: Tokens, index: number): PipeResult => [\n [...tokens.slice(0, index), SYMBOLS.DIVIDER, ...tokens.slice(index)],\n false,\n];\n\n/**\n * For tokens lists without a divider, `fixDivider` attempts to determine the\n * __safe__ location to add a divider based on the existing formatting of the\n * coordinate: numbers, number positions, and number indicators.\n *\n * @param original - Array of coordinate tokens without a divider.\n * @param _format - Optional coordinate format (LATLON or LONLAT), currently unused.\n * @returns Pipe result with divider inserted, or error=true if no safe location found.\n *\n * @example\n * ```typescript\n * fixDivider(['45°', '30'', 'N', '122°', '15'', 'W']);\n * // Returns tokens with divider inserted between latitude and longitude\n * ```\n *\n * @example\n * ```typescript\n * fixDivider(['45', '30', 'N']);\n * // Returns error=true (cannot safely determine divider position)\n * ```\n *\n * @remarks\n * pure function\n */\nexport function fixDivider(original: Tokens, _format?: Format): PipeResult {\n // if there is already a divider then there is nothing to do\n if (original.includes(SYMBOLS.DIVIDER)) {\n return [original, false];\n }\n\n // disconnect from argument memory space so we aren't working on shared memory\n const tokens = original.slice(0);\n\n const genomeIndex = getGenomeIndex(tokens);\n\n if (genomeIndex) {\n return insertDivider(tokens, genomeIndex);\n }\n\n const simple = simpler(tokens) as keyof typeof SIMPLER_PATTERNS;\n\n if (SIMPLER_PATTERNS[simple]) {\n return insertDivider(tokens, SIMPLER_PATTERNS[simple]);\n }\n\n // no position is found to be a safe location to insert a divider; any placement\n // would be a guess and therefor only has a 50% chance of being wrong or right\n return [[], true];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,MAAM,mBAAmB;CACvB,IAAI;CACJ,KAAK;CACL,MAAM;CACN,KAAK;CACN;;;;;;;;;;;;;;AAeD,MAAM,iBAAiB,QAAgB,UAA8B,CACnE;CAAC,GAAG,OAAO,MAAM,GAAG,MAAM;CAAE,QAAQ;CAAS,GAAG,OAAO,MAAM,MAAM;CAAC,EACpE,MACD;;;;;;;;;;;;;;;;;;;;;;;;;AA0BD,SAAgB,WAAW,UAAkB,SAA8B;AAEzE,KAAI,SAAS,SAAS,QAAQ,QAAQ,CACpC,QAAO,CAAC,UAAU,MAAM;CAI1B,MAAM,SAAS,SAAS,MAAM,EAAE;CAEhC,MAAM,cAAc,eAAe,OAAO;AAE1C,KAAI,YACF,QAAO,cAAc,QAAQ,YAAY;CAG3C,MAAM,SAAS,QAAQ,OAAO;AAE9B,KAAI,iBAAiB,QACnB,QAAO,cAAc,QAAQ,iBAAiB,QAAQ;AAKxD,QAAO,CAAC,EAAE,EAAE,KAAK"}
@@ -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,9 +13,25 @@
13
13
  import { Tokens } from "../lexer.js";
14
14
 
15
15
  //#region src/coordinates/latlon/internal/pipes/genome.d.ts
16
+
16
17
  /**
17
18
  * Use the "genome" sequence of the token list to find the index for inserting
18
19
  * a missing divider token.
20
+ *
21
+ * @param tokens - Array of coordinate tokens to analyze.
22
+ * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);
27
+ * // 3 (insert divider after latitude components)
28
+ * ```
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * getGenomeIndex(['45', '30', '15']);
33
+ * // 0 (pattern doesn't match genome sequence)
34
+ * ```
19
35
  */
20
36
  declare function getGenomeIndex(tokens: Tokens): number;
21
37
  //#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
@@ -19,6 +19,16 @@ const GENOME_PATTERN = /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$
19
19
  * Get the position (index) of where to insert a divider into the token list;
20
20
  * basically, the count of numeric components (left-of-divider position) plus
21
21
  * 1 if there is a bearing identifier (left-of-divider).
22
+ *
23
+ * @param _full - Full regex match string (unused).
24
+ * @param args - Regex capture groups: [bearing1, number1, bearing2, number2].
25
+ * @returns String representation of the divider index position.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');
30
+ * // '3' (bearing + 2 numeric components)
31
+ * ```
22
32
  */
23
33
  function dividerIndexer(_full, ...args) {
24
34
  const [bearing1 = "", number1, bearing2 = "", number2] = args;
@@ -34,6 +44,22 @@ function dividerIndexer(_full, ...args) {
34
44
  * - S = seconds (number with seconds character following)
35
45
  * - N = number (no identifying character following)
36
46
  * - X = for unmatched token types
47
+ *
48
+ * @param acc - Accumulated genome sequence string.
49
+ * @param t - Current token to classify.
50
+ * @returns Updated genome sequence with new character appended.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * genomeSequencer('', '45°');
55
+ * // 'D'
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * genomeSequencer('D', 'N');
61
+ * // 'DB'
62
+ * ```
37
63
  */
38
64
  function genomeSequencer(acc, t) {
39
65
  if (t.includes(SYMBOLS.DEGREES)) return `${acc}D`;
@@ -46,6 +72,21 @@ function genomeSequencer(acc, t) {
46
72
  /**
47
73
  * Use the "genome" sequence of the token list to find the index for inserting
48
74
  * a missing divider token.
75
+ *
76
+ * @param tokens - Array of coordinate tokens to analyze.
77
+ * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);
82
+ * // 3 (insert divider after latitude components)
83
+ * ```
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * getGenomeIndex(['45', '30', '15']);
88
+ * // 0 (pattern doesn't match genome sequence)
89
+ * ```
49
90
  */
50
91
  function getGenomeIndex(tokens) {
51
92
  const seq = tokens.reduce(genomeSequencer, "");
@@ -1 +1 @@
1
- {"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.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 { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ;;;;;;AAOF,SAAS,eAAe,OAAe,GAAG,MAAgB;CACxD,MAAM,CAAC,WAAW,IAAI,SAAS,WAAW,IAAI,WAAW;AAGzD,KAAI,EAAE,SAAS,UAAU,SAAS,QAChC,QAAO;AAGT,QAAO,GAAG,QAAQ,UAAU,SAAS,UAAU,SAAS;;;;;;;;;;;;AAa1D,SAAS,gBAAgB,KAAa,GAAW;AAC/C,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,gBAAgB,KAAK,KAAK,EAAE,CAC9B,QAAO,GAAG,IAAI;AAGhB,KAAI,KAAK,KAAK,EAAE,CACd,QAAO,GAAG,IAAI;AAGhB,QAAO,GAAG,IAAI;;;;;;AAOhB,SAAgB,eAAe,QAAgB;CAC7C,MAAM,MAAM,OAAO,OAAO,iBAAiB,GAAG;AAE9C,QAAO,eAAe,KAAK,IAAI,GAC3B,OAAO,SAAS,IAAI,QAAQ,gBAAgB,eAAe,EAAE,GAAG,GAChE"}
1
+ {"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.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 { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n *\n * @param _full - Full regex match string (unused).\n * @param args - Regex capture groups: [bearing1, number1, bearing2, number2].\n * @returns String representation of the divider index position.\n *\n * @example\n * ```typescript\n * dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');\n * // '3' (bearing + 2 numeric components)\n * ```\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n *\n * @param acc - Accumulated genome sequence string.\n * @param t - Current token to classify.\n * @returns Updated genome sequence with new character appended.\n *\n * @example\n * ```typescript\n * genomeSequencer('', '45°');\n * // 'D'\n * ```\n *\n * @example\n * ```typescript\n * genomeSequencer('D', 'N');\n * // 'DB'\n * ```\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n *\n * @param tokens - Array of coordinate tokens to analyze.\n * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);\n * // 3 (insert divider after latitude components)\n * ```\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45', '30', '15']);\n * // 0 (pattern doesn't match genome sequence)\n * ```\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ;;;;;;;;;;;;;;;;AAiBF,SAAS,eAAe,OAAe,GAAG,MAAgB;CACxD,MAAM,CAAC,WAAW,IAAI,SAAS,WAAW,IAAI,WAAW;AAGzD,KAAI,EAAE,SAAS,UAAU,SAAS,QAChC,QAAO;AAGT,QAAO,GAAG,QAAQ,UAAU,SAAS,UAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B1D,SAAS,gBAAgB,KAAa,GAAW;AAC/C,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,gBAAgB,KAAK,KAAK,EAAE,CAC9B,QAAO,GAAG,IAAI;AAGhB,KAAI,KAAK,KAAK,EAAE,CACd,QAAO,GAAG,IAAI;AAGhB,QAAO,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;AAsBhB,SAAgB,eAAe,QAAgB;CAC7C,MAAM,MAAM,OAAO,OAAO,iBAAiB,GAAG;AAE9C,QAAO,eAAe,KAAK,IAAI,GAC3B,OAAO,SAAS,IAAI,QAAQ,gBAAgB,eAAe,EAAE,GAAG,GAChE"}
@@ -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
@@ -20,7 +20,21 @@ type PipeResult = ReturnType<Pipe>;
20
20
  * Consistently create a PipesResult array to return. Use this instead of
21
21
  * casting to PipesResult everywhere.
22
22
  *
23
- * @param e true = has error, false = no error
23
+ * @param t - Array of coordinate tokens.
24
+ * @param e - Error status: true = has error, false = no error, or error message string.
25
+ * @returns Pipe result tuple with tokens (empty if error) and error status.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * pipesResult(['45', 'N', '/', '122', 'W'], false);
30
+ * // [['45', 'N', '/', '122', 'W'], false]
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * pipesResult(['45'], 'Too few numbers.');
36
+ * // [[], 'Too few numbers.']
37
+ * ```
24
38
  *
25
39
  * @remarks
26
40
  * pure function
@@ -30,7 +44,23 @@ declare const pipesResult: (t: Tokens, e: boolean | string) => PipeResult;
30
44
  * Run the tokens through a preset pipeline of violations checks exiting the
31
45
  * process as early as possible when violations are found because violations
32
46
  * will make further violations checks less accurate and could return inaccurate
33
- * violations that could be misleading or hide the most important violation
47
+ * violations that could be misleading or hide the most important violation.
48
+ *
49
+ * @param tokens - Array of parsed coordinate tokens to validate and normalize.
50
+ * @param format - Optional coordinate format (LATLON or LONLAT) for inference.
51
+ * @returns Tuple of [processed tokens, array of error messages].
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
56
+ * // [['45', 'N', '/', '122', 'W'], []]
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * pipesRunner(['45'], 'LATLON');
62
+ * // [[], ['Too few numbers.']]
63
+ * ```
34
64
  */
35
65
  declare function pipesRunner(tokens: Tokens, format?: Format): [Tokens, string[]];
36
66
  //#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
@@ -18,19 +18,56 @@ import { fixBearings } from "./fix-bearings.js";
18
18
  import { fixDivider } from "./fix-dividers.js";
19
19
 
20
20
  //#region src/coordinates/latlon/internal/pipes/index.ts
21
- /** Make a RegExp global. */
21
+ /**
22
+ * Make a RegExp global.
23
+ *
24
+ * @param k - Key of the SYMBOL_PATTERNS object.
25
+ * @returns New global RegExp based on the pattern.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * makeGlobal('NSEW');
30
+ * // /[NSEW]/g
31
+ * ```
32
+ */
22
33
  const makeGlobal = (k) => new RegExp(SYMBOL_PATTERNS[k], "g");
23
34
  /**
24
35
  * Consistently create a PipesResult array to return. Use this instead of
25
36
  * casting to PipesResult everywhere.
26
37
  *
27
- * @param e true = has error, false = no error
38
+ * @param t - Array of coordinate tokens.
39
+ * @param e - Error status: true = has error, false = no error, or error message string.
40
+ * @returns Pipe result tuple with tokens (empty if error) and error status.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * pipesResult(['45', 'N', '/', '122', 'W'], false);
45
+ * // [['45', 'N', '/', '122', 'W'], false]
46
+ * ```
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * pipesResult(['45'], 'Too few numbers.');
51
+ * // [[], 'Too few numbers.']
52
+ * ```
28
53
  *
29
54
  * @remarks
30
55
  * pure function
31
56
  */
32
57
  const pipesResult = (t, e) => [e ? [] : t, e];
33
- /** Check if there are more than 2 of something. */
58
+ /**
59
+ * Check if there are more than 2 of something.
60
+ *
61
+ * @param p - Regular expression pattern to match.
62
+ * @returns Function that takes tokens and returns pipe result with error if >2 matches found.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const checkBearings = tooMany(/[NSEW]/g);
67
+ * checkBearings(['N', 'S', 'E', 'W']);
68
+ * // Returns error=true (more than 2 bearings)
69
+ * ```
70
+ */
34
71
  const tooMany = (p) => (t) => pipesResult(t, (t.join("").match(p) ?? []).length > 2);
35
72
  const pipes = [
36
73
  ["Too many bearings.", tooMany(makeGlobal("NSEW"))],
@@ -47,7 +84,23 @@ const pipes = [
47
84
  * Run the tokens through a preset pipeline of violations checks exiting the
48
85
  * process as early as possible when violations are found because violations
49
86
  * will make further violations checks less accurate and could return inaccurate
50
- * violations that could be misleading or hide the most important violation
87
+ * violations that could be misleading or hide the most important violation.
88
+ *
89
+ * @param tokens - Array of parsed coordinate tokens to validate and normalize.
90
+ * @param format - Optional coordinate format (LATLON or LONLAT) for inference.
91
+ * @returns Tuple of [processed tokens, array of error messages].
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
96
+ * // [['45', 'N', '/', '122', 'W'], []]
97
+ * ```
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * pipesRunner(['45'], 'LATLON');
102
+ * // [[], ['Too few numbers.']]
103
+ * ```
51
104
  */
52
105
  function pipesRunner(tokens, format) {
53
106
  let copy = tokens.slice(0);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/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 { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n/** Make a RegExp global. */\nconst makeGlobal = (k: keyof typeof SYMBOL_PATTERNS) =>\n new RegExp(SYMBOL_PATTERNS[k], 'g');\n\n/**\n * Consistently create a PipesResult array to return. Use this instead of\n * casting to PipesResult everywhere.\n *\n * @param e true = has error, false = no error\n *\n * @remarks\n * pure function\n */\nexport const pipesResult = (t: Tokens, e: boolean | string): PipeResult => [\n // if there are errors do NOT return the tokens\n e ? [] : t,\n e,\n];\n\n/** Check if there are more than 2 of something. */\nconst tooMany = (p: RegExp) => (t: Tokens) =>\n pipesResult(t, (t.join('').match(p) ?? []).length > 2);\n\nconst pipes: [string, Pipe][] = [\n // Unrecoverable violations\n ['Too many bearings.', tooMany(makeGlobal('NSEW'))],\n ['Too many numeric signs.', tooMany(/[-+]/g)],\n ['Too many degrees indicators.', tooMany(makeGlobal('DEGREES'))],\n ['Too many minutes indicators.', tooMany(makeGlobal('MINUTES'))],\n ['Too many seconds indicators.', tooMany(makeGlobal('SECONDS'))],\n ['Number values checks.', checkNumberValues],\n ['Ambiguous grouping of numbers with no divider.', checkAmbiguousGrouping],\n\n // fix values and formatting to be consistent\n ['Unable to identify latitude from longitude.', fixDivider],\n ['Unable to identify bearings.', fixBearings],\n];\n\n/**\n * Run the tokens through a preset pipeline of violations checks exiting the\n * process as early as possible when violations are found because violations\n * will make further violations checks less accurate and could return inaccurate\n * violations that could be misleading or hide the most important violation\n */\nexport function pipesRunner(\n tokens: Tokens,\n format?: Format,\n): [Tokens, string[]] {\n let copy = tokens.slice(0);\n let error: PipeResult[1] = false;\n const errors = [] as string[];\n\n for (const [message, op] of pipes) {\n [copy, error] = op(copy, format);\n\n if (error) {\n // accumulate the \"errors\" because if tokens are returned\n // the errors are only warnings and are recoverable\n errors.push(error === true ? message : error);\n\n if (!copy.length) {\n return [copy, [error === true ? message : error]];\n }\n }\n }\n\n return [copy, errors];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,cAAc,MAClB,IAAI,OAAO,gBAAgB,IAAI,IAAI;;;;;;;;;;AAWrC,MAAa,eAAe,GAAW,MAAoC,CAEzE,IAAI,EAAE,GAAG,GACT,EACD;;AAGD,MAAM,WAAW,OAAe,MAC9B,YAAY,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE;AAExD,MAAMA,QAA0B;CAE9B,CAAC,sBAAsB,QAAQ,WAAW,OAAO,CAAC,CAAC;CACnD,CAAC,2BAA2B,QAAQ,QAAQ,CAAC;CAC7C,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,yBAAyB,kBAAkB;CAC5C,CAAC,kDAAkD,uBAAuB;CAG1E,CAAC,+CAA+C,WAAW;CAC3D,CAAC,gCAAgC,YAAY;CAC9C;;;;;;;AAQD,SAAgB,YACd,QACA,QACoB;CACpB,IAAI,OAAO,OAAO,MAAM,EAAE;CAC1B,IAAIC,QAAuB;CAC3B,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,CAAC,SAAS,OAAO,OAAO;AACjC,GAAC,MAAM,SAAS,GAAG,MAAM,OAAO;AAEhC,MAAI,OAAO;AAGT,UAAO,KAAK,UAAU,OAAO,UAAU,MAAM;AAE7C,OAAI,CAAC,KAAK,OACR,QAAO,CAAC,MAAM,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC;;;AAKvD,QAAO,CAAC,MAAM,OAAO"}
1
+ {"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/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 { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n/**\n * Make a RegExp global.\n *\n * @param k - Key of the SYMBOL_PATTERNS object.\n * @returns New global RegExp based on the pattern.\n *\n * @example\n * ```typescript\n * makeGlobal('NSEW');\n * // /[NSEW]/g\n * ```\n */\nconst makeGlobal = (k: keyof typeof SYMBOL_PATTERNS) =>\n new RegExp(SYMBOL_PATTERNS[k], 'g');\n\n/**\n * Consistently create a PipesResult array to return. Use this instead of\n * casting to PipesResult everywhere.\n *\n * @param t - Array of coordinate tokens.\n * @param e - Error status: true = has error, false = no error, or error message string.\n * @returns Pipe result tuple with tokens (empty if error) and error status.\n *\n * @example\n * ```typescript\n * pipesResult(['45', 'N', '/', '122', 'W'], false);\n * // [['45', 'N', '/', '122', 'W'], false]\n * ```\n *\n * @example\n * ```typescript\n * pipesResult(['45'], 'Too few numbers.');\n * // [[], 'Too few numbers.']\n * ```\n *\n * @remarks\n * pure function\n */\nexport const pipesResult = (t: Tokens, e: boolean | string): PipeResult => [\n // if there are errors do NOT return the tokens\n e ? [] : t,\n e,\n];\n\n/**\n * Check if there are more than 2 of something.\n *\n * @param p - Regular expression pattern to match.\n * @returns Function that takes tokens and returns pipe result with error if >2 matches found.\n *\n * @example\n * ```typescript\n * const checkBearings = tooMany(/[NSEW]/g);\n * checkBearings(['N', 'S', 'E', 'W']);\n * // Returns error=true (more than 2 bearings)\n * ```\n */\nconst tooMany = (p: RegExp) => (t: Tokens) =>\n pipesResult(t, (t.join('').match(p) ?? []).length > 2);\n\nconst pipes: [string, Pipe][] = [\n // Unrecoverable violations\n ['Too many bearings.', tooMany(makeGlobal('NSEW'))],\n ['Too many numeric signs.', tooMany(/[-+]/g)],\n ['Too many degrees indicators.', tooMany(makeGlobal('DEGREES'))],\n ['Too many minutes indicators.', tooMany(makeGlobal('MINUTES'))],\n ['Too many seconds indicators.', tooMany(makeGlobal('SECONDS'))],\n ['Number values checks.', checkNumberValues],\n ['Ambiguous grouping of numbers with no divider.', checkAmbiguousGrouping],\n\n // fix values and formatting to be consistent\n ['Unable to identify latitude from longitude.', fixDivider],\n ['Unable to identify bearings.', fixBearings],\n];\n\n/**\n * Run the tokens through a preset pipeline of violations checks exiting the\n * process as early as possible when violations are found because violations\n * will make further violations checks less accurate and could return inaccurate\n * violations that could be misleading or hide the most important violation.\n *\n * @param tokens - Array of parsed coordinate tokens to validate and normalize.\n * @param format - Optional coordinate format (LATLON or LONLAT) for inference.\n * @returns Tuple of [processed tokens, array of error messages].\n *\n * @example\n * ```typescript\n * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');\n * // [['45', 'N', '/', '122', 'W'], []]\n * ```\n *\n * @example\n * ```typescript\n * pipesRunner(['45'], 'LATLON');\n * // [[], ['Too few numbers.']]\n * ```\n */\nexport function pipesRunner(\n tokens: Tokens,\n format?: Format,\n): [Tokens, string[]] {\n let copy = tokens.slice(0);\n let error: PipeResult[1] = false;\n const errors = [] as string[];\n\n for (const [message, op] of pipes) {\n [copy, error] = op(copy, format);\n\n if (error) {\n // accumulate the \"errors\" because if tokens are returned\n // the errors are only warnings and are recoverable\n errors.push(error === true ? message : error);\n\n if (!copy.length) {\n return [copy, [error === true ? message : error]];\n }\n }\n }\n\n return [copy, errors];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAM,cAAc,MAClB,IAAI,OAAO,gBAAgB,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;AAyBrC,MAAa,eAAe,GAAW,MAAoC,CAEzE,IAAI,EAAE,GAAG,GACT,EACD;;;;;;;;;;;;;;AAeD,MAAM,WAAW,OAAe,MAC9B,YAAY,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE;AAExD,MAAMA,QAA0B;CAE9B,CAAC,sBAAsB,QAAQ,WAAW,OAAO,CAAC,CAAC;CACnD,CAAC,2BAA2B,QAAQ,QAAQ,CAAC;CAC7C,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,yBAAyB,kBAAkB;CAC5C,CAAC,kDAAkD,uBAAuB;CAG1E,CAAC,+CAA+C,WAAW;CAC3D,CAAC,gCAAgC,YAAY;CAC9C;;;;;;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,YACd,QACA,QACoB;CACpB,IAAI,OAAO,OAAO,MAAM,EAAE;CAC1B,IAAIC,QAAuB;CAC3B,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,CAAC,SAAS,OAAO,OAAO;AACjC,GAAC,MAAM,SAAS,GAAG,MAAM,OAAO;AAEhC,MAAI,OAAO;AAGT,UAAO,KAAK,UAAU,OAAO,UAAU,MAAM;AAE7C,OAAI,CAAC,KAAK,OACR,QAAO,CAAC,MAAM,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC;;;AAKvD,QAAO,CAAC,MAAM,OAAO"}