From 81bfe57cb85690f4153683754ffb09f35a816dac Mon Sep 17 00:00:00 2001 From: Corentin THOMASSET Date: Sat, 26 Aug 2023 16:43:47 +0200 Subject: [PATCH] feat(new tool): text diff and comparator (#588) * feat(new tool): text diff and comparator * chore(ci): increased memory in CI --- .github/workflows/ci.yml | 2 + components.d.ts | 2 + package.json | 1 + pnpm-lock.yaml | 71 +++++++++++++------------- src/tools/index.ts | 3 +- src/tools/text-diff/index.ts | 12 +++++ src/tools/text-diff/text-diff.vue | 5 ++ src/ui/c-diff-editor/c-diff-editor.vue | 68 ++++++++++++++++++++++++ 8 files changed, 127 insertions(+), 37 deletions(-) create mode 100644 src/tools/text-diff/index.ts create mode 100644 src/tools/text-diff/text-diff.vue create mode 100644 src/ui/c-diff-editor/c-diff-editor.vue diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f5a9b6a..611b7e6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,4 +31,6 @@ jobs: run: pnpm typecheck - name: Build the app + env: + NODE_OPTIONS: --max-old-space-size=4096 run: pnpm build diff --git a/components.d.ts b/components.d.ts index 33ae6d50..076fc061 100644 --- a/components.d.ts +++ b/components.d.ts @@ -27,6 +27,7 @@ declare module '@vue/runtime-core' { 'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default'] CCard: typeof import('./src/ui/c-card/c-card.vue')['default'] 'CCard.demo': typeof import('./src/ui/c-card/c-card.demo.vue')['default'] + CDiffEditor: typeof import('./src/ui/c-diff-editor/c-diff-editor.vue')['default'] ChmodCalculator: typeof import('./src/tools/chmod-calculator/chmod-calculator.vue')['default'] Chronometer: typeof import('./src/tools/chronometer/chronometer.vue')['default'] CInputText: typeof import('./src/ui/c-input-text/c-input-text.vue')['default'] @@ -166,6 +167,7 @@ declare module '@vue/runtime-core' { SvgPlaceholderGenerator: typeof import('./src/tools/svg-placeholder-generator/svg-placeholder-generator.vue')['default'] TemperatureConverter: typeof import('./src/tools/temperature-converter/temperature-converter.vue')['default'] TextareaCopyable: typeof import('./src/components/TextareaCopyable.vue')['default'] + TextDiff: typeof import('./src/tools/text-diff/text-diff.vue')['default'] TextStatistics: typeof import('./src/tools/text-statistics/text-statistics.vue')['default'] TextToNatoAlphabet: typeof import('./src/tools/text-to-nato-alphabet/text-to-nato-alphabet.vue')['default'] TokenDisplay: typeof import('./src/tools/otp-code-generator-and-validator/token-display.vue')['default'] diff --git a/package.json b/package.json index 716c9d26..b68e04f7 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "lodash": "^4.17.21", "mathjs": "^11.9.1", "mime-types": "^2.1.35", + "monaco-editor": "^0.41.0", "naive-ui": "^2.34.3", "netmask": "^2.0.2", "node-forge": "^1.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65e29afd..9ceb775e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ dependencies: mime-types: specifier: ^2.1.35 version: 2.1.35 + monaco-editor: + specifier: ^0.41.0 + version: 0.41.0 naive-ui: specifier: ^2.34.3 version: 2.34.3(vue@3.3.4) @@ -429,6 +432,13 @@ packages: dependencies: '@babel/highlight': 7.22.10 chalk: 2.4.2 + dev: true + + /@babel/code-frame@7.22.5: + resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.5 /@babel/compat-data@7.22.5: resolution: {integrity: sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==} @@ -468,7 +478,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.5 '@babel/generator': 7.22.5 '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.5) '@babel/helper-module-transforms': 7.22.5 @@ -759,6 +769,15 @@ packages: '@babel/helper-validator-identifier': 7.22.5 chalk: 2.4.2 js-tokens: 4.0.0 + dev: true + + /@babel/highlight@7.22.5: + resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: 2.4.2 + js-tokens: 4.0.0 /@babel/parser@7.21.4: resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} @@ -770,7 +789,6 @@ packages: /@babel/parser@7.22.10: resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==} engines: {node: '>=6.0.0'} - hasBin: true dependencies: '@babel/types': 7.22.10 @@ -1713,7 +1731,7 @@ packages: resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.5 '@babel/parser': 7.22.5 '@babel/types': 7.22.5 @@ -1739,7 +1757,7 @@ packages: resolution: {integrity: sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.22.5 '@babel/generator': 7.22.5 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-function-name': 7.22.5 @@ -3837,12 +3855,12 @@ packages: acorn: 7.4.1 dev: true - /acorn-jsx@5.3.2(acorn@8.10.0): + /acorn-jsx@5.3.2(acorn@8.9.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.10.0 + acorn: 8.9.0 dev: true /acorn-walk@8.2.0: @@ -3853,19 +3871,16 @@ packages: /acorn@7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} engines: {node: '>=0.4.0'} - hasBin: true dev: true /acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} - hasBin: true + dev: true /acorn@8.9.0: resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} engines: {node: '>=0.4.0'} - hasBin: true - dev: true /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} @@ -4833,7 +4848,6 @@ packages: /esbuild@0.18.20: resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} engines: {node: '>=12'} - hasBin: true requiresBuild: true optionalDependencies: '@esbuild/android-arm': 0.18.20 @@ -4884,7 +4898,6 @@ packages: /escodegen@2.0.0: resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} engines: {node: '>=6.0'} - hasBin: true dependencies: esprima: 4.0.1 estraverse: 5.3.0 @@ -5183,7 +5196,6 @@ packages: /eslint@8.47.0: resolution: {integrity: sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) '@eslint-community/regexpp': 4.6.2 @@ -5239,8 +5251,8 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) + acorn: 8.9.0 + acorn-jsx: 5.3.2(acorn@8.9.0) eslint-visitor-keys: 3.4.3 dev: true @@ -6216,7 +6228,6 @@ packages: /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true dependencies: argparse: 2.0.1 dev: true @@ -6271,7 +6282,6 @@ packages: /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} - hasBin: true /jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} @@ -6537,7 +6547,6 @@ packages: /mathjs@11.9.1: resolution: {integrity: sha512-VdB9ELZ6Dwda13j5d1eCBETmPO8m9qIJETUdfZmTA9cPnXUiIk7UuoAmvxFqtfAe32XYuRugAec2Ndv0/RfRhg==} engines: {node: '>= 14'} - hasBin: true dependencies: '@babel/runtime': 7.22.10 complex.js: 2.1.1 @@ -6652,11 +6661,15 @@ packages: /mlly@1.4.0: resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==} dependencies: - acorn: 8.10.0 + acorn: 8.9.0 pathe: 1.1.1 pkg-types: 1.0.3 ufo: 1.1.2 + /monaco-editor@0.41.0: + resolution: {integrity: sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==} + dev: false + /moo@0.5.2: resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} dev: false @@ -6705,7 +6718,6 @@ packages: /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -6713,7 +6725,6 @@ packages: /nearley@2.20.1: resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} - hasBin: true dependencies: commander: 2.20.3 moo: 0.5.2 @@ -7077,7 +7088,6 @@ packages: /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - requiresBuild: true dev: true optional: true @@ -7341,7 +7351,6 @@ packages: /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - requiresBuild: true dev: true optional: true @@ -7578,7 +7587,6 @@ packages: /rollup@3.28.0: resolution: {integrity: sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true optionalDependencies: fsevents: 2.3.3 dev: true @@ -7619,12 +7627,10 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - requiresBuild: true dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} - requiresBuild: true dev: true optional: true @@ -7657,12 +7663,10 @@ packages: /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true dev: true /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true /semver@7.5.1: resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} @@ -7826,7 +7830,6 @@ packages: /sql-formatter@12.0.0: resolution: {integrity: sha512-LR2m7BEvkyNAPzmcSCZ2b4Qzm5ySiiXS9Juc73VguTqCWIbYv7ZFV4LaDM7jNNZqHPfrqFssO7WWpITsAuLOuQ==} - hasBin: true dependencies: argparse: 2.0.1 nearley: 2.20.1 @@ -7943,7 +7946,7 @@ packages: /strip-literal@1.0.1: resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} dependencies: - acorn: 8.10.0 + acorn: 8.9.0 /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} @@ -8477,7 +8480,7 @@ packages: /unplugin@1.3.1: resolution: {integrity: sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==} dependencies: - acorn: 8.10.0 + acorn: 8.9.0 chokidar: 3.5.3 webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 @@ -8485,7 +8488,7 @@ packages: /unplugin@1.4.0: resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==} dependencies: - acorn: 8.10.0 + acorn: 8.9.0 chokidar: 3.5.3 webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 @@ -8548,7 +8551,6 @@ packages: /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} - hasBin: true dev: false /v8-to-istanbul@9.1.0: @@ -8579,7 +8581,6 @@ packages: /vite-node@0.34.0(@types/node@18.15.11)(less@4.1.3): resolution: {integrity: sha512-rGZMvpb052rjUwJA/a17xMfOibzNF7byMdRSTcN2Lw8uxX08s5EfjWW5mBkm3MSFTPctMSVtT2yC+8ShrZbT5g==} engines: {node: '>=v14.18.0'} - hasBin: true dependencies: cac: 6.7.14 debug: 4.3.4 @@ -8967,7 +8968,6 @@ packages: /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} - hasBin: true dependencies: isexe: 2.0.0 dev: true @@ -8982,7 +8982,6 @@ packages: /why-is-node-running@2.2.2: resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} engines: {node: '>=8'} - hasBin: true dependencies: siginfo: 2.0.0 stackback: 0.0.2 diff --git a/src/tools/index.ts b/src/tools/index.ts index c5686a48..39b34ad6 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -2,6 +2,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; import { tool as stringObfuscator } from './string-obfuscator'; +import { tool as textDiff } from './text-diff'; import { tool as emojiPicker } from './emoji-picker'; import { tool as passwordStrengthAnalyser } from './password-strength-analyser'; import { tool as yamlToToml } from './yaml-to-toml'; @@ -146,7 +147,7 @@ export const toolsByCategory: ToolCategory[] = [ }, { name: 'Text', - components: [loremIpsumGenerator, textStatistics, emojiPicker, stringObfuscator], + components: [loremIpsumGenerator, textStatistics, emojiPicker, stringObfuscator, textDiff], }, { name: 'Data', diff --git a/src/tools/text-diff/index.ts b/src/tools/text-diff/index.ts new file mode 100644 index 00000000..992acbae --- /dev/null +++ b/src/tools/text-diff/index.ts @@ -0,0 +1,12 @@ +import { FileDiff } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Text diff', + path: '/text-diff', + description: 'Compare two texts and see the differences between them.', + keywords: ['text', 'diff', 'compare', 'string', 'text diff', 'code'], + component: () => import('./text-diff.vue'), + icon: FileDiff, + createdAt: new Date('2023-08-16'), +}); diff --git a/src/tools/text-diff/text-diff.vue b/src/tools/text-diff/text-diff.vue new file mode 100644 index 00000000..990f05b1 --- /dev/null +++ b/src/tools/text-diff/text-diff.vue @@ -0,0 +1,5 @@ + diff --git a/src/ui/c-diff-editor/c-diff-editor.vue b/src/ui/c-diff-editor/c-diff-editor.vue new file mode 100644 index 00000000..2aa29475 --- /dev/null +++ b/src/ui/c-diff-editor/c-diff-editor.vue @@ -0,0 +1,68 @@ + + +