mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-25 01:06:15 -04:00
fix(integer-base-converter): handle non-decimal char and better error message
This commit is contained in:
parent
0ff853437b
commit
8476cf319b
4 changed files with 93 additions and 11 deletions
|
@ -7,7 +7,7 @@ export function convertBase({ value, fromBase, toBase }: { value: string; fromBa
|
||||||
.reverse()
|
.reverse()
|
||||||
.reduce((carry: number, digit: string, index: number) => {
|
.reduce((carry: number, digit: string, index: number) => {
|
||||||
if (!fromRange.includes(digit)) {
|
if (!fromRange.includes(digit)) {
|
||||||
throw new Error('Invalid digit `' + digit + '` for base ' + fromBase + '.');
|
throw new Error('Invalid digit "' + digit + '" for base ' + fromBase + '.');
|
||||||
}
|
}
|
||||||
return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index));
|
return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index));
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div v-if="styleStore.isSmallScreen">
|
<div v-if="styleStore.isSmallScreen">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
|
||||||
<n-input-number v-model:value="inputNumber" min="0" style="width: 100%" />
|
<n-input v-model:value="input" style="width: 100%" :status="error ? 'error' : undefined" />
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
|
||||||
|
@ -14,51 +14,65 @@
|
||||||
|
|
||||||
<n-input-group v-else>
|
<n-input-group v-else>
|
||||||
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 120px"> Input number: </n-input-group-label>
|
||||||
<n-input-number v-model:value="inputNumber" min="0" />
|
<n-input v-model:value="input" :status="error ? 'error' : undefined" />
|
||||||
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 120px"> Input base: </n-input-group-label>
|
||||||
<n-input-number v-model:value="inputBase" max="64" min="2" />
|
<n-input-number v-model:value="inputBase" max="64" min="2" />
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
||||||
|
<n-alert v-if="error" style="margin-top: 25px" type="error">{{ error }}</n-alert>
|
||||||
<n-divider />
|
<n-divider />
|
||||||
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 170px"> Binary (2): </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 170px"> Binary (2): </n-input-group-label>
|
||||||
<input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 2 })" readonly />
|
<input-copyable
|
||||||
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 2 })"
|
||||||
|
readonly
|
||||||
|
placeholder="Binary version will be here..."
|
||||||
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 170px"> Octal (8): </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 170px"> Octal (8): </n-input-group-label>
|
||||||
<input-copyable :value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 8 })" readonly />
|
<input-copyable
|
||||||
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 8 })"
|
||||||
|
readonly
|
||||||
|
placeholder="Octal version will be here..."
|
||||||
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 170px"> Decimal (10): </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 170px"> Decimal (10): </n-input-group-label>
|
||||||
<input-copyable
|
<input-copyable
|
||||||
:value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 10 })"
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 10 })"
|
||||||
readonly
|
readonly
|
||||||
|
placeholder="Decimal version will be here..."
|
||||||
/>
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 170px"> Hexadecimal (16): </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 170px"> Hexadecimal (16): </n-input-group-label>
|
||||||
<input-copyable
|
<input-copyable
|
||||||
:value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 16 })"
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 16 })"
|
||||||
readonly
|
readonly
|
||||||
|
placeholder="Decimal version will be here..."
|
||||||
/>
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 170px"> Base64 (64): </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 170px"> Base64 (64): </n-input-group-label>
|
||||||
<input-copyable
|
<input-copyable
|
||||||
:value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: 64 })"
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 64 })"
|
||||||
readonly
|
readonly
|
||||||
|
placeholder="Base64 version will be here..."
|
||||||
/>
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input-group-label style="flex: 0 0 85px"> Custom: </n-input-group-label>
|
<n-input-group-label style="flex: 0 0 85px"> Custom: </n-input-group-label>
|
||||||
<n-input-number v-model:value="outputBase" style="flex: 0 0 86px" max="64" min="2" />
|
<n-input-number v-model:value="outputBase" style="flex: 0 0 86px" max="64" min="2" />
|
||||||
<input-copyable
|
<input-copyable
|
||||||
:value="convertBase({ value: String(inputNumber), fromBase: inputBase, toBase: outputBase })"
|
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: outputBase })"
|
||||||
readonly
|
readonly
|
||||||
|
:placeholder="`Base ${outputBase} will be here...`"
|
||||||
/>
|
/>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
@ -66,16 +80,31 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useStyleStore } from '@/stores/style.store';
|
import { useStyleStore } from '@/stores/style.store';
|
||||||
|
import { getErrorMessageIfThrows } from '@/utils/error';
|
||||||
import { convertBase } from './integer-base-converter.model';
|
import { convertBase } from './integer-base-converter.model';
|
||||||
import InputCopyable from '../../components/InputCopyable.vue';
|
import InputCopyable from '../../components/InputCopyable.vue';
|
||||||
|
|
||||||
const styleStore = useStyleStore();
|
const styleStore = useStyleStore();
|
||||||
|
|
||||||
const inputNumber = ref(42);
|
const input = ref('42');
|
||||||
const inputBase = ref(10);
|
const inputBase = ref(10);
|
||||||
const outputBase = ref(42);
|
const outputBase = ref(42);
|
||||||
|
|
||||||
|
function errorlessConvert(...args: Parameters<typeof convertBase>) {
|
||||||
|
try {
|
||||||
|
return convertBase(...args);
|
||||||
|
} catch (err) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = computed(() =>
|
||||||
|
getErrorMessageIfThrows(() =>
|
||||||
|
convertBase({ value: input.value, fromBase: inputBase.value, toBase: outputBase.value }),
|
||||||
|
),
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
29
src/utils/error.test.ts
Normal file
29
src/utils/error.test.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { getErrorMessageIfThrows } from './error';
|
||||||
|
|
||||||
|
describe('error util', () => {
|
||||||
|
describe('getErrorMessageIfThrows', () => {
|
||||||
|
it('get an error message if the callback throws, undefined instead', () => {
|
||||||
|
expect(
|
||||||
|
getErrorMessageIfThrows(() => {
|
||||||
|
throw 'message';
|
||||||
|
}),
|
||||||
|
).to.equal('message');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getErrorMessageIfThrows(() => {
|
||||||
|
throw new Error('message');
|
||||||
|
}),
|
||||||
|
).to.equal('message');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getErrorMessageIfThrows(() => {
|
||||||
|
throw { message: 'message' };
|
||||||
|
}),
|
||||||
|
).to.equal('message');
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
expect(getErrorMessageIfThrows(() => {})).to.equal(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
24
src/utils/error.ts
Normal file
24
src/utils/error.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export { getErrorMessageIfThrows };
|
||||||
|
|
||||||
|
function getErrorMessageIfThrows(cb: () => unknown) {
|
||||||
|
try {
|
||||||
|
cb();
|
||||||
|
return undefined;
|
||||||
|
} catch (err) {
|
||||||
|
if (_.isString(err)) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isError(err)) {
|
||||||
|
return err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isObject(err) && _.has(err, 'message')) {
|
||||||
|
return (err as { message: string }).message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'An error as occurred.';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue