• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nerdstep / react-coordinate-input / 4329094450

pending completion
4329094450

Pull #69

github

GitHub
Merge dfbdd3f36 into 7230f418c
Pull Request #69: build(deps): bump minimist from 1.2.5 to 1.2.8 in /example

63 of 66 branches covered (95.45%)

Branch coverage included in aggregate %.

118 of 120 relevant lines covered (98.33%)

29.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.65
/src/utils.js
1
// @ts-check
2
import { SEPARATOR } from './constants'
3
import { RE_DD, RE_DMS } from './regex'
4

5
/**
6
 * fill
7
 *
8
 * Fills an array with the provided value X number of times
9
 *
10
 * @param {any[]} arr Array to fill
11
 * @param {any} value Value to push to the array
12
 * @param {number} count Number of items to add
13
 * @returns {any[]} Array filled with values
14
 */
15
export function fill(arr, value, count) {
16
  for (let i = 0; i < count; i++) {
13✔
17
    arr.push(value)
14✔
18
  }
19
  return arr
13✔
20
}
21

22
/**
23
 * normalizeInput
24
 *
25
 * Returns a normalized DMS input value
26
 *
27
 * @param {string} value Input value
28
 * @param {string} [sep] Value separator
29
 * @returns {string} Normalized value
30
 */
31
export function normalizeInput(value, sep = SEPARATOR) {
32✔
32
  return value?.replace(/[^0-9.NSEW]/gi, sep).replace(/:{2,}/g, sep) || ''
32✔
33
}
34

35
/**
36
 * convertInput
37
 *
38
 * Converts a DD string into a DMS string
39
 *
40
 * @param {string} value Input value
41
 * @param {number} precision DMS decimal places
42
 *  @param {string} [sep] Value separator
43
 * @returns {string} Normalized DMS string
44
 */
45
export function convertInput(value, precision, sep = SEPARATOR) {
29✔
46
  if (validateDD(value)) {
38✔
47
    const dd = value.split(',')
29✔
48
    const lat = parseFloat(dd[0])
29✔
49
    const lon = parseFloat(dd[1])
29✔
50
    const latArr = decimalToDMS(lat, false, precision)
29✔
51
    const lonArr = decimalToDMS(lon, true, precision)
29✔
52
    value = serializeDMS(latArr, lonArr, sep)
29✔
53
  }
54
  return value || ''
38✔
55
}
56

57
/**
58
 * validateDD
59
 *
60
 * Returns true if the provided value is a valid DD string
61
 *
62
 * @param {string} value Input value
63
 * @returns {boolean} Is valid DD?
64
 */
65
export function validateDD(value) {
66
  return RE_DD.test(value)
38✔
67
}
68

69
/**
70
 * Returns true if the provided value is a valid (normalized) DMS string
71
 *
72
 * @param {string} value Input value
73
 * @returns {boolean} Is valid DMS?
74
 */
75
export function validateDMS(value) {
76
  return RE_DMS.test(value)
31✔
77
}
78

79
/**
80
 * parseDMS
81
 *
82
 * Parses a DMS string into an array of lat/lon arrays
83
 *
84
 * @param {string} value DMS value, e.g. '04:08:15:N:162:03:42:E'
85
 * @param {string} [sep] Separator
86
 * @returns {((string|number)[])[]} [[D, M, S, 'N|S'], [D, M, S, 'E|W']]
87
 */
88
export function parseDMS(value, sep = SEPARATOR) {
31✔
89
  const match = value.match(RE_DMS).slice(1)
31✔
90

91
  const lat = match[0].split(sep).map((n) => parseFloat(n))
93✔
92
  const lon = match[2].split(sep).map((n) => parseFloat(n))
93✔
93

94
  return [
31✔
95
    [lat[0], lat[1], lat[2], match[1]],
96
    [lon[0], lon[1], lon[2], match[3]],
97
  ]
98
}
99

100
/**
101
 * serializeDMS
102
 *
103
 * Serializes DMS lat/lon arrays into a normalized DMS string
104
 *
105
 * @param {(string|number)[]} lat DMS latitude, e.g. [4, 8, 15, 'N']
106
 * @param {(string|number)[]} lon DMS longitude, e.g. [162, 3, 42, 'E']
107
 * @param {string} [sep] Separator
108
 * @returns {string}
109
 * @example `04:08:15:N:162:03:42:E`
110
 */
111
export function serializeDMS(lat, lon, sep = SEPARATOR) {
27✔
112
  const res = []
56✔
113

114
  res[0] = lat
56✔
115
    .map((item) => item.toString().replace(/^(\d)(\.\d+)?$/, '0$1$2'))
224✔
116
    .join(sep)
117

118
  res[1] = lon
56✔
119
    .map((item, i) =>
120
      i === 0
224✔
121
        ? item
122
            .toString()
123
            .replace(/^(\d)$/, '00$1')
124
            .replace(/^(\d\d)$/, '0$1')
125
        : item.toString().replace(/^(\d)(\.\d+)?$/, '0$1$2')
126
    )
127
    .join(sep)
128

129
  return res.join(sep)
56✔
130
}
131

132
/**
133
 * dmsToDecimal
134
 *
135
 * Converts Degrees Minutes Seconds to Decimal Degrees
136
 *
137
 * Formula:
138
 * DD = D + M / 60 + S / 3600
139
 *
140
 * @param {number} degrees
141
 * @param {number} minutes
142
 * @param {number} seconds
143
 * @param {string} direction Compass direction, e.g. N|S|E|W
144
 * @param {number} [precision]  Decimal places (default: 6)
145
 * @returns {number} Decimal degrees, e.g. 42.451
146
 */
147
export function dmsToDecimal(
148
  degrees,
149
  minutes,
150
  seconds,
151
  direction,
152
  precision = 6
60✔
153
) {
154
  const factor = Math.pow(10, precision)
62✔
155
  let dd = degrees + minutes / 60 + seconds / 3600
62✔
156
  // Round the result to the given precision
157
  dd = Math.round(dd * factor) / factor
62✔
158
  // If direction is South or West then value is negative
159
  return /S|W/.test(direction) ? dd * -1 : dd
62✔
160
}
161

162
/**
163
 * decimalToDMS
164
 *
165
 * Converts Decimal Degress to Degrees Minutes Seconds
166
 *
167
 * @param {number} dd Decimal degree value
168
 * @param {boolean} isLon Is longitude?
169
 * @param {number} [precision] Decimal places for seconds (default: 0)
170
 * @returns {(string|number)[]} DMS values, e.g. [D, M, S, 'N|S|E|W']
171
 */
172
export function decimalToDMS(dd, isLon, precision = 0) {
5✔
173
  const factor = Math.pow(10, precision)
113✔
174
  const direction = dd < 0 ? (isLon ? 'W' : 'S') : isLon ? 'E' : 'N'
113✔
175

176
  // Ensure degrees is a positive value
177
  const absolute = Math.abs(dd)
113✔
178
  let degrees = Math.floor(absolute)
113✔
179
  const minutesFloat = (absolute - degrees) * 60
113✔
180
  let minutes = Math.floor(minutesFloat)
113✔
181
  let seconds = (minutesFloat - minutes) * 60
113✔
182

183
  // Round seconds to the given precision
184
  seconds = Math.round(seconds * factor) / factor
113✔
185

186
  // Ensure minutes & seconds are not 60
187
  if (seconds === 60) {
113✔
188
    minutes++
2✔
189
    seconds = 0
2✔
190
  }
191

192
  if (minutes === 60) {
113!
193
    degrees++
×
194
    minutes = 0
×
195
  }
196

197
  return [degrees, minutes, seconds, direction]
113✔
198
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc