Skip to content

Commit

Permalink
Add parse_si_float inverse function to pretty_num in labels.ts (#…
Browse files Browse the repository at this point in the history
…50)

* add parse_si_float

* add parse_si_float

basically the inverse to pretty_num

* test parse_si_float

* update deps
  • Loading branch information
janosh authored Jul 19, 2024
1 parent 05d091a commit 5414367
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ repos:
exclude: ^changelog.md|.*/(structures|molecules)/.*\.json|.py$

- repo: https://github.com/pre-commit/mirrors-eslint
rev: v9.5.0
rev: v9.7.0
hooks:
- id: eslint
types: [file]
Expand Down
30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"dependencies": {
"@iconify/svelte": "^4.0.2",
"@sveltejs/kit": "^2.5.17",
"@sveltejs/kit": "^2.5.18",
"@threlte/core": "7.3.1",
"d3": "^7.9.0",
"d3-array": "^3.2.4",
Expand All @@ -34,14 +34,14 @@
"d3-scale": "^4.0.2",
"d3-scale-chromatic": "^3.1.0",
"d3-shape": "^3.2.0",
"highlight.js": "^11.9.0",
"highlight.js": "^11.10.0",
"svelte": "4.2.18",
"svelte-multiselect": "^10.3.0",
"svelte-zoo": "^0.4.10",
"three": "^0.165.0"
"three": "^0.166.1"
},
"devDependencies": {
"@playwright/test": "^1.45.0",
"@playwright/test": "^1.45.2",
"@sveltejs/adapter-static": "3.0.2",
"@sveltejs/package": "^2.3.2",
"@sveltejs/vite-plugin-svelte": "^3.1.1",
Expand All @@ -52,29 +52,29 @@
"@types/d3-scale": "^4.0.8",
"@types/d3-scale-chromatic": "^3.0.3",
"@types/d3-shape": "^3.1.6",
"@types/three": "^0.165.0",
"@vitest/coverage-v8": "^1.6.0",
"eslint": "^9.5.0",
"eslint-plugin-svelte": "^2.41.0",
"@types/three": "^0.166.0",
"@vitest/coverage-v8": "^2.0.3",
"eslint": "^9.7.0",
"eslint-plugin-svelte": "^2.43.0",
"hastscript": "^9.0.0",
"jsdom": "^24.1.0",
"mdsvex": "^0.11.2",
"mdsvexamples": "^0.4.1",
"prettier": "^3.3.2",
"prettier-plugin-svelte": "^3.2.5",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.6",
"rehype-autolink-headings": "^7.1.0",
"rehype-katex-svelte": "^1.2.0",
"rehype-slug": "^6.0.0",
"remark-math": "3.0.0",
"sharp": "^0.33.4",
"svelte-check": "^3.8.4",
"svelte-preprocess": "^6.0.1",
"svelte-preprocess": "^6.0.2",
"svelte-toc": "^0.5.9",
"svelte2tsx": "^0.7.13",
"typescript": "5.5.2",
"typescript-eslint": "^7.14.1",
"vite": "^5.3.2",
"vitest": "^1.6.0"
"typescript": "5.5.3",
"typescript-eslint": "^7.16.1",
"vite": "^5.3.4",
"vitest": "^2.0.3"
},
"keywords": [
"svelte",
Expand Down
31 changes: 31 additions & 0 deletions src/lib/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,37 @@ export const pretty_num = (num: number, fmt?: string | number) => {
}
return format(fmt)(num)
}
export function parse_si_float<T extends string | number | null | undefined>(
value: T,
): T | number | string {
// if not string, return as is
if (typeof value !== `string`) return value
// Remove whitespace and commas
const cleaned = value.trim().replace(/(\d),(\d)/g, `$1$2`)

// Check if the value is a SI-formatted number (e.g., "1.23k", "4.56M", "789µ", "12n")
const match = cleaned.match(/^([-+]?\d*\.?\d+)\s*([yzafpnµmkMGTPEZY])?$/i)
if (match) {
const [, num_part, suffix] = match
let multiplier = 1
if (suffix) {
const suffixes = `yzafpnµm kMGTPEZY`
const index = suffixes.indexOf(suffix)
if (index !== -1) {
multiplier = Math.pow(1000, index - 8)
}
}
return parseFloat(num_part) * multiplier
}

// If it's a number without SI suffix, try parsing it
if (/^[-+]?[\d,]+\.?\d*$/.test(cleaned)) {
return parseFloat(cleaned)
}

// If the value is not a formatted number, return as is
return value
}

export const category_counts: Record<Category, number> = {
actinide: 15,
Expand Down
48 changes: 47 additions & 1 deletion tests/unit/labels.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { element_data } from '$lib'
import {
default_fmt,
heatmap_keys,
parse_si_float,
pretty_num,
property_labels,
superscript_digits,
} from '$lib/labels'
import { expect, test } from 'vitest'
import { describe, expect, test } from 'vitest'

test(`pretty_num`, () => {
expect(pretty_num(0)).toBe(`0`)
Expand Down Expand Up @@ -61,3 +62,48 @@ test(`superscript_digits`, () => {
expect(superscript_digits(`+123-456+789-0`)).toBe(`⁺¹²³⁻⁴⁵⁶⁺⁷⁸⁹⁻⁰`)
expect(superscript_digits(`No digits here`)).toBe(`No digits here`)
})

describe(`parse_si_float function`, () => {
test.each([
[`123`, 123], // int
[`123.45`, 123.45], // float
[`1,234.45`, 1234.45], // with comma
[`1,234,567.89`, 1234567.89], // 2 commas
[`1k`, 1000],
[`1.5k`, 1500],
[`2M`, 2000000],
[`3.14G`, 3140000000],
[`5T`, 5000000000000],
[`1m`, 0.001],
[`500µ `, 0.0005],
[`10n`, 1e-8],
[`2p`, 2e-12],
[`3f`, 3e-15],
[`4a`, 4e-18],
[` 5z`, 5e-21], // leading whitespace
[`6y`, 6e-24],
[`-1.5k`, -1500],
[`-500µ`, -0.0005],
[`abc`, `abc`],
[``, ``],
[` 123 `, 123], // leading/trailing whitespace
[`-123`, -123],
[`1 k`, 1000], // with space
[`2 µ`, 0.000002], // with space
[`foo`, `foo`],
[`123foo`, `123foo`],
[-12, -12], // int -> int
[124.847321, 124.847321], // float -> float
[``, ``], // empty string
[undefined, undefined], // undefined
[null, null], // null
[`123.456.789`, `123.456.789`], // phone number
])(`parseValue(%s) should return %s`, (input, expected) => {
const result = parse_si_float(input as string)
if (typeof expected === `number`) {
expect(result).toBeCloseTo(expected, 15) // Increased precision for very small numbers
} else {
expect(result).toEqual(expected)
}
})
})

0 comments on commit 5414367

Please sign in to comment.