Skip to content

Commit

Permalink
Merge pull request #61 from jkroso/fix-regex
Browse files Browse the repository at this point in the history
Safeguard RE
  • Loading branch information
dy authored Feb 11, 2025
2 parents 2c0c072 + 2a340b5 commit 9e88421
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 19 deletions.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ declare module './locale/*.js' {
declare const durationRE: RegExp;

declare namespace parse {
const unit: Units;
let unit: Units;
}

/**
Expand Down
21 changes: 10 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import en from './locale/en.js'

const durationRE = /(-?(?:\d+\.?\d*|\d*\.?\d+)(?:e[-+]?\d+)?)\s*([\p{L}]*)/uig
const durationRE = /((?:\d{1,16}(?:\.\d{1,16})?|\.\d{1,16})(?:[eE][-+]?\d{1,4})?)\s?([\p{L}]{0,14})/gu

parse.unit = en

/**
* convert `str` to ms
*
* @param {String} str
* @param {String} format
* @return {Number}
* @param {string} str
* @param {string} format
* @return {number}
*/
export default function parse(str = '', format = 'ms') {
let result = null, prevUnits

(str + '')
.replace(/(\d)[_ ](\d)/g, '$1$2') // ignore placeholders
.replaceAll(parse.unit.group, '') // remove group separator
.replaceAll(parse.unit.decimal, '.') // normalize decimal separator
String(str)
.replace(new RegExp(`(\\d)[${parse.unit.placeholder}${parse.unit.group}](\\d)`, 'g'), '$1$2') // clean up group separators / placeholders
.replace(parse.unit.decimal, '.') // normalize decimal separator
.replace(durationRE, (_, n, units) => {
// if no units, find next smallest units or fall back to format value
// eg. 1h30 -> 1h30m
if (!units) {
if (prevUnits) {
for (var u in parse.unit) if (parse.unit[u] < prevUnits) { units = u; break }
for (const u in parse.unit) if (parse.unit[u] < prevUnits) { units = u; break }
}
else units = format
}
else units = units.toLowerCase()

units = parse.unit[units] || parse.unit[units.replace(/s$/, '')]
prevUnits = units = parse.unit[units] || parse.unit[units.replace(/s$/, '')]

if (units) result = (result || 0) + Math.abs(parseFloat(n, 10)) * units, prevUnits = units
if (units) result = (result || 0) + n * units
})

return result && ((result / (parse.unit[format] || 1)) * (str[0] === '-' ? -1 : 1))
Expand Down
1 change: 1 addition & 0 deletions locale/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ unit.nanosecond = unit.nanosec = unit.ns = 1e-6

unit.group = ','
unit.decimal = '.'
unit.placeholder = ' _'

export default unit
14 changes: 7 additions & 7 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ t('locales', t => {
t('locale separators', t => {
parse.unit = en
t.equal(parse('3.14 seconds'), 3140)
t.equal(parse('"1,23,456.789 seconds'), 123456789)
t.equal(parse('"1,23,456.789s'), 123456789)
t.equal(parse('"30,000.65 seconds'), 30000650)
t.equal(parse('1,23,456.789 seconds'), 123456789)
t.equal(parse('1,23,456.789s'), 123456789)
t.equal(parse('30,000.65 seconds'), 30000650)

parse.unit = de
t.equal(parse('3,14 seconds'), 3140)
t.equal(parse('"123.456,789 seconds'), 123456789)
t.equal(parse('"30.000,65 seconds'), 30000650)
t.equal(parse('"30 000,65 seconds'), 30000650)
t.equal(parse('"30_000,65 seconds'), 30000650)
t.equal(parse('123.456,789 seconds'), 123456789)
t.equal(parse('30.000,65 seconds'), 30000650)
t.equal(parse('30 000,65 seconds'), 30000650)
t.equal(parse('30_000,65 seconds'), 30000650)
t.end()
})

0 comments on commit 9e88421

Please sign in to comment.