Skip to content

Commit bc0c344

Browse files
committed
feat(new tool): Math Formula format converter
Fix part of CorentinTh#1009
1 parent e876d03 commit bc0c344

File tree

7 files changed

+150
-8
lines changed

7 files changed

+150
-8
lines changed

components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ declare module '@vue/runtime-core' {
120120
MacAddressGenerator: typeof import('./src/tools/mac-address-generator/mac-address-generator.vue')['default']
121121
MacAddressLookup: typeof import('./src/tools/mac-address-lookup/mac-address-lookup.vue')['default']
122122
MathEvaluator: typeof import('./src/tools/math-evaluator/math-evaluator.vue')['default']
123+
MathFormatsConverter: typeof import('./src/tools/math-formats-converter/math-formats-converter.vue')['default']
123124
MenuBar: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar.vue')['default']
124125
MenuBarItem: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar-item.vue')['default']
125126
MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default']

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"dependencies": {
3838
"@it-tools/bip39": "^0.0.4",
3939
"@it-tools/oggen": "^1.3.0",
40+
"@plurimath/plurimath": "^0.2.0",
4041
"@sindresorhus/slugify": "^2.2.1",
4142
"@tiptap/pm": "2.1.6",
4243
"@tiptap/starter-kit": "2.1.6",

pnpm-lock.yaml

Lines changed: 14 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/composable/queryParams.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useRouteQuery } from '@vueuse/router';
22
import { computed } from 'vue';
3+
import { useStorage } from '@vueuse/core';
34

4-
export { useQueryParam };
5+
export { useQueryParam, useQueryParamOrStorage };
56

67
const transformers = {
78
number: {
@@ -33,3 +34,31 @@ function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue:
3334
},
3435
});
3536
}
37+
38+
function useQueryParamOrStorage<T>({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) {
39+
const type = typeof defaultValue;
40+
const transformer = transformers[type as keyof typeof transformers] ?? transformers.string;
41+
42+
const storageRef = useStorage(storageName, defaultValue);
43+
const storageDefaultValue = storageRef.value ?? defaultValue;
44+
45+
const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never));
46+
47+
const ref = computed<T>({
48+
get() {
49+
return transformer.fromQuery(proxy.value) as unknown as T;
50+
},
51+
set(value) {
52+
proxy.value = transformer.toQuery(value as never);
53+
},
54+
});
55+
56+
watch(
57+
ref,
58+
(newValue) => {
59+
storageRef.value = newValue;
60+
},
61+
);
62+
63+
return ref;
64+
}

src/tools/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { tool as base64FileConverter } from './base64-file-converter';
22
import { tool as base64StringConverter } from './base64-string-converter';
33
import { tool as basicAuthGenerator } from './basic-auth-generator';
4+
import { tool as mathFormatsConverter } from './math-formats-converter';
45

56
import { tool as asciiTextDrawer } from './ascii-text-drawer';
67

@@ -156,7 +157,12 @@ export const toolsByCategory: ToolCategory[] = [
156157
},
157158
{
158159
name: 'Math',
159-
components: [mathEvaluator, etaCalculator, percentageCalculator],
160+
components: [
161+
mathEvaluator,
162+
etaCalculator,
163+
percentageCalculator,
164+
mathFormatsConverter,
165+
],
160166
},
161167
{
162168
name: 'Measurement',
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { EqualNot } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Math Formats Converter',
6+
path: '/math-formats-converter',
7+
description: 'Convert mathematical expression between formats',
8+
keywords: ['math', 'formats', 'converter', 'latex', 'mathml', 'asciimath', 'omml', 'html'],
9+
component: () => import('./math-formats-converter.vue'),
10+
icon: EqualNot,
11+
createdAt: new Date('2024-05-11'),
12+
});
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<script setup lang="ts">
2+
import Plurimath from '@plurimath/plurimath';
3+
import { useQueryParamOrStorage } from '@/composable/queryParams';
4+
5+
const formats = [
6+
{ value: 'asciimath', label: 'AsciiMath' },
7+
{ value: 'latex', label: 'Latex' },
8+
{ value: 'mathml', label: 'MathML' },
9+
{ value: 'html', label: 'Html' },
10+
{ value: 'omml', label: 'OOML' },
11+
];
12+
13+
const source = ref('');
14+
const sourceFormat = useQueryParamOrStorage({ name: 'src', storageName: 'math-fmts-conv:src', defaultValue: 'latex' });
15+
const targetFormat = useQueryParamOrStorage({ name: 'target', storageName: 'math-fmts-conv:target', defaultValue: 'mathml' });
16+
const target = computedAsync(async () => {
17+
const sourceValue = source.value;
18+
const sourceFormatValue = sourceFormat.value;
19+
const targetFormatValue = targetFormat.value;
20+
if (sourceValue === '') {
21+
return '';
22+
}
23+
if (sourceFormatValue === targetFormatValue) {
24+
return sourceValue;
25+
}
26+
return new Promise<string>((resolve, _reject) => {
27+
try {
28+
const formula = new Plurimath(sourceValue, sourceFormatValue);
29+
let result;
30+
switch (targetFormatValue) {
31+
case 'asciimath':
32+
result = formula.toAsciimath();
33+
break;
34+
case 'latex':
35+
result = formula.toLatex();
36+
break;
37+
case 'mathml':
38+
result = formula.toMathml();
39+
break;
40+
case 'html':
41+
result = formula.toHtml();
42+
break;
43+
case 'omml':
44+
result = formula.toOmml();
45+
break;
46+
default:
47+
result = '# unknown format';
48+
break;
49+
}
50+
resolve(result);
51+
}
52+
catch (e: any) {
53+
resolve(`# error converting formula: ${e.toString()}`);
54+
}
55+
});
56+
});
57+
</script>
58+
59+
<template>
60+
<div>
61+
<c-input-text
62+
v-model:value="source"
63+
multiline
64+
placeholder="Put your math expression here..."
65+
rows="5"
66+
label="Mathematical expression to convert"
67+
raw-text
68+
mb-5
69+
/>
70+
<c-select
71+
v-model:value="sourceFormat"
72+
:options="formats"
73+
placeholder="Source format"
74+
/>
75+
76+
<n-divider />
77+
78+
<c-select
79+
v-model:value="targetFormat"
80+
:options="formats"
81+
placeholder="Source format"
82+
/>
83+
<textarea-copyable v-if="target !== ''" :value="target" :language="targetFormat" />
84+
</div>
85+
</template>

0 commit comments

Comments
 (0)