Skip to content

Commit

Permalink
feat(string-utils): export looksLikeNumber helper (#324)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoe authored Sep 20, 2020
1 parent c653b22 commit c8580a2
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 21 deletions.
3 changes: 2 additions & 1 deletion browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// specific libraries, such as "path".
//
// TODO: figure out reasonable web equivalents for "resolve", "normalize", etc.
import { camelCase, decamelize } from './build/lib/string-utils.js'
import { camelCase, decamelize, looksLikeNumber } from './build/lib/string-utils.js'
import { YargsParser } from './build/lib/yargs-parser.js'
const parser = new YargsParser({
cwd: () => { return '' },
Expand All @@ -24,5 +24,6 @@ yargsParser.detailed = function (args, opts) {
}
yargsParser.camelCase = camelCase
yargsParser.decamelize = decamelize
yargsParser.looksLikeNumber = looksLikeNumber

export default yargsParser
3 changes: 2 additions & 1 deletion deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
// TODO: find reasonable replacement for require logic.
import * as path from 'https://deno.land/std/path/mod.ts'
import { camelCase, decamelize } from './build/lib/string-utils.js'
import { camelCase, decamelize, looksLikeNumber } from './build/lib/string-utils.js'
import { YargsParser } from './build/lib/yargs-parser.js'
import { Arguments, ArgsInput, Parser, Options, DetailedArguments } from './build/lib/yargs-parser-types.d.ts'

Expand Down Expand Up @@ -33,5 +33,6 @@ yargsParser.detailed = function (args: ArgsInput, opts?: Partial<Options>): Deta
}
yargsParser.camelCase = camelCase
yargsParser.decamelize = decamelize
yargsParser.looksLikeNumber = looksLikeNumber

export default yargsParser
3 changes: 2 additions & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { format } from 'util'
import { readFileSync } from 'fs'
import { normalize, resolve } from 'path'
import { ArgsInput, Arguments, Parser, Options, DetailedArguments } from './yargs-parser-types.js'
import { camelCase, decamelize } from './string-utils.js'
import { camelCase, decamelize, looksLikeNumber } from './string-utils.js'
import { YargsParser } from './yargs-parser.js'

// See https://github.com/yargs/yargs-parser#supported-nodejs-versions for our
Expand Down Expand Up @@ -49,4 +49,5 @@ yargsParser.detailed = function (args: ArgsInput, opts?: Partial<Options>): Deta
}
yargsParser.camelCase = camelCase
yargsParser.decamelize = decamelize
yargsParser.looksLikeNumber = looksLikeNumber
export default yargsParser
11 changes: 11 additions & 0 deletions lib/string-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,14 @@ export function decamelize (str: string, joinString?: string): string {
}
return notCamelcase
}

export function looksLikeNumber (x: null | undefined | number | string): boolean {
if (x === null || x === undefined) return false
// if loaded from config, may already be a number.
if (typeof x === 'number') return true
// hexadecimal.
if (/^0x[0-9a-f]+$/i.test(x)) return true
// don't treat 0123 as a number; as it drops the leading '0'.
if (x.length > 1 && x[0] === '0') return false
return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
}
1 change: 1 addition & 0 deletions lib/yargs-parser-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export interface Parser {
detailed(args: ArgsInput, opts?: Partial<Options>): DetailedArguments;
camelCase(str: string): string;
decamelize(str: string, joinString?: string): string;
looksLikeNumber(x: null | undefined | number | string): boolean;
}

export type StringFlag = Dictionary<string[]>;
Expand Down
15 changes: 2 additions & 13 deletions lib/yargs-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type {
YargsParserMixin
} from './yargs-parser-types.js'
import type { Dictionary, ValueOf } from './common-types.js'
import { camelCase, decamelize } from './string-utils.js'
import { camelCase, decamelize, looksLikeNumber } from './string-utils.js'

let mixin: YargsParserMixin
export class YargsParser {
Expand Down Expand Up @@ -621,7 +621,7 @@ export class YargsParser {
function maybeCoerceNumber (key: string, value: string | number | null | undefined) {
if (!configuration['parse-positional-numbers'] && key === '_') return value
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.bools) && !Array.isArray(value)) {
const shouldCoerceNumber = isNumber(value) && configuration['parse-numbers'] && (
const shouldCoerceNumber = looksLikeNumber(value) && configuration['parse-numbers'] && (
Number.isSafeInteger(Math.floor(parseFloat(`${value}`)))
)
if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) {
Expand Down Expand Up @@ -1004,17 +1004,6 @@ export class YargsParser {
return type
}

function isNumber (x: null | undefined | number | string): boolean {
if (x === null || x === undefined) return false
// if loaded from config, may already be a number.
if (typeof x === 'number') return true
// hexadecimal.
if (/^0x[0-9a-f]+$/i.test(x)) return true
// don't treat 0123 as a number; as it drops the leading '0'.
if (x.length > 1 && x[0] === '0') return false
return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
}

function isUndefined (num: any): num is undefined {
return num === undefined
}
Expand Down
9 changes: 9 additions & 0 deletions test/deno/yargs-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,12 @@ Deno.test('convert hyphenated string to camelcase', () => {
Deno.test('convert camelcase string to hyphenated', () => {
assertEquals(parser.decamelize('helloWorld'), 'hello-world')
})

Deno.test('it detects strings that could be parsed as numbers', () => {
assertEquals(parser.looksLikeNumber('3293'), true)
assertEquals(parser.looksLikeNumber('0x10'), true)
assertEquals(parser.looksLikeNumber('0x10'), true)

assertEquals(parser.looksLikeNumber('0100'), false)
assertEquals(parser.looksLikeNumber('apple'), false)
})
20 changes: 15 additions & 5 deletions test/string-utils.cjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
/* global describe, it */

const { expect } = require('chai')
const { camelCase, decamelize } = require('../build/index.cjs')
const { strictEqual } = require('assert')
const { camelCase, decamelize, looksLikeNumber } = require('../build/index.cjs')

describe('string-utils', function () {
describe('camelCase', () => {
it('converts string with hypen in middle to camel case', () => {
expect(camelCase('hello-world')).to.equal('helloWorld')
strictEqual(camelCase('hello-world'), 'helloWorld')
})
it('removes leading hyphens', () => {
expect(camelCase('-goodnight-moon')).to.equal('goodnightMoon')
strictEqual(camelCase('-goodnight-moon'), 'goodnightMoon')
})
})
describe('decamelize', () => {
it('adds hyphens back to camelcase string', () => {
expect(decamelize('helloWorld')).to.equal('hello-world')
strictEqual(decamelize('helloWorld'), 'hello-world')
})
})
describe('looksLikeNumber', () => {
it('it detects strings that could be parsed as numbers', () => {
strictEqual(looksLikeNumber('3293'), true)
strictEqual(looksLikeNumber('0x10'), true)
strictEqual(looksLikeNumber('0x10'), true)

strictEqual(looksLikeNumber('0100'), false)
strictEqual(looksLikeNumber('apple'), false)
})
})
})

0 comments on commit c8580a2

Please # to comment.