/ src / common.ts
common.ts
 1  import { createContext } from 'react'
 2  import { z } from 'zod'
 3  
 4  import { createRadix, type Radix } from './radixes.ts'
 5  import { getErrorMessage } from 'react-error-boundary'
 6  
 7  
 8  export const LS_CHARS = 'chars'
 9  export const LS_RADIXES = 'radixes'
10  
11  const ExportRadixes = z.array(z.object({
12  	name: z.string(),
13  	radix: z.number(),
14  	system: z.enum([ 'standard', 'bijective', 'balanced', 'clock', 'sum', 'balsum' ]),
15  	chars: z.string(),
16  	enabled: z.boolean(),
17  }))
18  
19  export const AppContext = createContext<{ updateError: (error: unknown) => void }>({ updateError: () => {} })
20  
21  export function getCharsLS(): string | undefined {
22  	return localStorage.getItem(LS_CHARS) ?? undefined
23  }
24  
25  export function sanitizeInput(input: string, radix: Radix): string[] {
26  	input = input.toUpperCase()
27  	const chars = radix.system === 'balanced' ? radix.chars : `-${radix.chars}`
28  	const sanitizedInput = input.replaceAll(new RegExp(`[^${chars}]`, 'g'), '')
29  	const rest = input.replaceAll(new RegExp(`[${chars}]`, 'g'), '')
30  	return [ sanitizedInput, rest ]
31  }
32  
33  export function serializeRadixes(radixes: Radix[]) {
34  	return JSON.stringify(
35  		radixes.map(r => ({ name: r.name, radix: Number(r.radix), system: r.system, chars: r.chars, enabled: r.enabled })),
36  		undefined,
37  		'\t',
38  	)
39  }
40  
41  export function unserializeRadixes(content: string): Radix[] {
42  	try {
43  		const radixes = ExportRadixes.parse(JSON.parse(content), { reportInput: true })
44  		return radixes.map(r => createRadix(r.radix, r.system, r.chars, r.enabled, r.name, false))
45  	} catch (error) {
46  		if (error instanceof z.ZodError) throw new Error(`Error validating input file:\n\n${z.prettifyError(error)}`, { cause: error })
47  		throw new Error(`Error parsing input file:\n\n${getErrorMessage(error)}`, { cause: error })
48  	}
49  }