Skip to content

Commit a2d6961

Browse files
erichschroeterErich Schroeter
authored andcommitted
feat: Integer Base Converter space separator support (#481)
Fix #480 Co-authored-by: Erich Schroeter <erich.schroeter@gmail.com>
1 parent e1de52b commit a2d6961

4 files changed

Lines changed: 110 additions & 10 deletions

File tree

locales/en.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5768,6 +5768,13 @@ tools:
57685768
label-base64-64: Base64 (64)
57695769
placeholder-base64-version-will-be-here: Base64 version will be here...
57705770
tag-custom: "Custom:"
5771+
label-space-separation: Space separation
5772+
label-binary-size: Binary size
5773+
label-octal-size: Octal size
5774+
label-decimal-size: Decimal size
5775+
label-hexadecimal-size: Hex size
5776+
label-base64-size: Base64 size
5777+
label-custom-size: Custom size
57715778
model:
57725779
text:
57735780
invalid-digit-digit-for-base-finalfrombase: Invalid digit "{0}" for base {1}.

src/tools/integer-base-converter/integer-base-converter.model.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest';
2-
import { convertBase } from './integer-base-converter.model';
2+
import { convertBase, formatWithSpaces } from './integer-base-converter.model';
33

44
describe('integer-base-converter', () => {
55
describe('convertBase', () => {
@@ -30,6 +30,30 @@ describe('integer-base-converter', () => {
3030
expect(convertBase({ value: '42540766411283223938465490632011909384', fromBase: 10, toBase: 16 })).toEqual('20010db8000085a300000000ac1f8908');
3131
expect(convertBase({ value: '20010db8000085a300000000ac1f8908', fromBase: 16, toBase: 10 })).toEqual('42540766411283223938465490632011909384');
3232
});
33+
34+
it('should convert integers even when containing spaces', () => {
35+
expect(convertBase({ value: '1010 0101', fromBase: 2, toBase: 16 })).toEqual('a5');
36+
expect(convertBase({ value: '192 654', fromBase: 10, toBase: 8 })).toEqual('570216');
37+
});
38+
});
39+
});
40+
41+
describe('formatWithSpaces', () => {
42+
it('should format numbers with spaces correctly from right to left', () => {
43+
expect(formatWithSpaces('10100000000000001111000000000000', 8)).toEqual('10100000 00000000 11110000 00000000');
44+
expect(formatWithSpaces('a000f000', 4)).toEqual('a000 f000');
45+
expect(formatWithSpaces('24000170000', 3)).toEqual('24 000 170 000');
46+
});
47+
48+
it('should handle edge cases', () => {
49+
expect(formatWithSpaces('', 3)).toEqual('');
50+
expect(formatWithSpaces('12', 3)).toEqual('12');
51+
expect(formatWithSpaces('123', 3)).toEqual('123');
52+
expect(formatWithSpaces('1234', 3)).toEqual('1 234');
53+
expect(formatWithSpaces('12345', 3)).toEqual('12 345');
54+
expect(formatWithSpaces('123456', 3)).toEqual('123 456');
55+
expect(formatWithSpaces('123', 0)).toEqual('123');
56+
expect(formatWithSpaces('123', -1)).toEqual('123');
3357
});
3458
});
3559
});

src/tools/integer-base-converter/integer-base-converter.model.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,15 @@ export function convertBase(
6161
}
6262
return newValue || '0';
6363
}
64+
65+
export function formatWithSpaces(value: string, groupSize: number): string {
66+
if (groupSize <= 0 || !value) {
67+
return value;
68+
}
69+
const chunks: string[] = [];
70+
for (let i = value.length; i > 0; i -= groupSize) {
71+
const start = Math.max(0, i - groupSize);
72+
chunks.unshift(value.slice(start, i));
73+
}
74+
return chunks.join(' ');
75+
}

src/tools/integer-base-converter/integer-base-converter.vue

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { useI18n } from 'vue-i18n';
33
import InputCopyable from '../../components/InputCopyable.vue';
4-
import { convertBase, hasNumberPrefix } from './integer-base-converter.model';
4+
import { convertBase, hasNumberPrefix, formatWithSpaces } from './integer-base-converter.model';
55
import { getErrorMessageIfThrows } from '@/utils/error';
66
import { useQueryParam } from '@/composable/queryParams';
77
@@ -21,9 +21,39 @@ const outputBase = useQueryParam({ tool: 'int-base-conv', name: 'outbase', defau
2121
2222
const hasInputNumberPrefix = computed(() => hasNumberPrefix(input.value));
2323
24-
function errorlessConvert(...args: Parameters<typeof convertBase>) {
24+
const useSpaceSeparation = ref(false);
25+
const groupSizes = ref({
26+
binary: 8,
27+
octal: 3,
28+
decimal: 3,
29+
hex: 4,
30+
base64: 4,
31+
custom: 4,
32+
});
33+
34+
function getGroupSizeForBase(base: number): number {
35+
if (!useSpaceSeparation.value) {
36+
return 0;
37+
}
38+
switch (base) {
39+
case 2: return groupSizes.value.binary;
40+
case 8: return groupSizes.value.octal;
41+
case 10: return groupSizes.value.decimal;
42+
case 16: return groupSizes.value.hex;
43+
case 64: return groupSizes.value.base64;
44+
default:
45+
return base === outputBase.value ? groupSizes.value.custom : 4;
46+
}
47+
}
48+
49+
function formattedConvert(args: Parameters<typeof convertBase>[0]) {
2550
try {
26-
return convertBase(...args);
51+
const converted = convertBase(args);
52+
const size = getGroupSizeForBase(args.toBase);
53+
if (useSpaceSeparation.value && size > 0) {
54+
return formatWithSpaces(converted, size);
55+
}
56+
return converted;
2757
}
2858
catch (err) {
2959
return '';
@@ -46,6 +76,33 @@ const error = computed(() =>
4676
<n-input-number-i18n v-model:value="inputBase" max="64" min="2" :placeholder="t('tools.integer-base-converter.texts.placeholder-put-your-input-base-here-ex-10')" w-full />
4777
</n-form-item>
4878

79+
<n-form-item :label="t('tools.integer-base-converter.texts.label-space-separation')" label-placement="left" label-width="110" :show-feedback="false" style="margin-top: 10px;">
80+
<n-switch v-model:value="useSpaceSeparation" />
81+
</n-form-item>
82+
83+
<div v-if="useSpaceSeparation" style="margin-top: 10px; margin-bottom: 20px; padding-left: 20px; border-left: 2px solid var(--n-border-color)">
84+
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px;">
85+
<n-form-item :label="t('tools.integer-base-converter.texts.label-binary-size')" label-placement="top" :show-feedback="false">
86+
<n-input-number v-model:value="groupSizes.binary" :min="1" :max="64" size="small" />
87+
</n-form-item>
88+
<n-form-item :label="t('tools.integer-base-converter.texts.label-octal-size')" label-placement="top" :show-feedback="false">
89+
<n-input-number v-model:value="groupSizes.octal" :min="1" :max="64" size="small" />
90+
</n-form-item>
91+
<n-form-item :label="t('tools.integer-base-converter.texts.label-decimal-size')" label-placement="top" :show-feedback="false">
92+
<n-input-number v-model:value="groupSizes.decimal" :min="1" :max="64" size="small" />
93+
</n-form-item>
94+
<n-form-item :label="t('tools.integer-base-converter.texts.label-hexadecimal-size')" label-placement="top" :show-feedback="false">
95+
<n-input-number v-model:value="groupSizes.hex" :min="1" :max="64" size="small" />
96+
</n-form-item>
97+
<n-form-item :label="t('tools.integer-base-converter.texts.label-base64-size')" label-placement="top" :show-feedback="false">
98+
<n-input-number v-model:value="groupSizes.base64" :min="1" :max="64" size="small" />
99+
</n-form-item>
100+
<n-form-item :label="t('tools.integer-base-converter.texts.label-custom-size')" label-placement="top" :show-feedback="false">
101+
<n-input-number v-model:value="groupSizes.custom" :min="1" :max="64" size="small" />
102+
</n-form-item>
103+
</div>
104+
</div>
105+
49106
<n-alert v-if="error" style="margin-top: 25px" type="error">
50107
{{ error }}
51108
</n-alert>
@@ -54,35 +111,35 @@ const error = computed(() =>
54111
<InputCopyable
55112
:label="t('tools.integer-base-converter.texts.label-binary-2')"
56113
v-bind="inputProps"
57-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 2 })"
114+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: 2 })"
58115
:placeholder="t('tools.integer-base-converter.texts.placeholder-binary-version-will-be-here')"
59116
/>
60117

61118
<InputCopyable
62119
:label="t('tools.integer-base-converter.texts.label-octal-8')"
63120
v-bind="inputProps"
64-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 8 })"
121+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: 8 })"
65122
:placeholder="t('tools.integer-base-converter.texts.placeholder-octal-version-will-be-here')"
66123
/>
67124

68125
<InputCopyable
69126
:label="t('tools.integer-base-converter.texts.label-decimal-10')"
70127
v-bind="inputProps"
71-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 10 })"
128+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: 10 })"
72129
:placeholder="t('tools.integer-base-converter.texts.placeholder-decimal-version-will-be-here')"
73130
/>
74131

75132
<InputCopyable
76133
:label="t('tools.integer-base-converter.texts.label-hexadecimal-16')"
77134
v-bind="inputProps"
78-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 16 })"
135+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: 16 })"
79136
:placeholder="t('tools.integer-base-converter.texts.placeholder-hexadecimal-version-will-be-here')"
80137
/>
81138

82139
<InputCopyable
83140
:label="t('tools.integer-base-converter.texts.label-base64-64')"
84141
v-bind="inputProps"
85-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: 64 })"
142+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: 64 })"
86143
:placeholder="t('tools.integer-base-converter.texts.placeholder-base64-version-will-be-here')"
87144
/>
88145

@@ -95,7 +152,7 @@ const error = computed(() =>
95152
<InputCopyable
96153
flex-1
97154
v-bind="inputProps"
98-
:value="errorlessConvert({ value: input, fromBase: inputBase, toBase: outputBase })"
155+
:value="formattedConvert({ value: input, fromBase: inputBase, toBase: outputBase })"
99156
:placeholder="`Base ${outputBase} will be here...`"
100157
/>
101158
</div>

0 commit comments

Comments
 (0)