refactor(dx): generic data transformer
This commit is contained in:
		
							parent
							
								
									9fa4c26929
								
							
						
					
					
						commit
						05f06f6a07
					
				
							
								
								
									
										1
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -12,6 +12,7 @@ declare module '@vue/runtime-core' { | ||||
|     CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default'] | ||||
|     ColoredCard: typeof import('./src/components/ColoredCard.vue')['default'] | ||||
|     FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default'] | ||||
|     FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default'] | ||||
|     InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] | ||||
|     MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] | ||||
|     MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] | ||||
|  | ||||
							
								
								
									
										57
									
								
								src/components/FormatTransformer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/components/FormatTransformer.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| <template> | ||||
|   <n-form-item :label="inputLabel" v-bind="validationAttrs"> | ||||
|     <n-input | ||||
|       ref="inputElement" | ||||
|       v-model:value="input" | ||||
|       :placeholder="inputPlaceholder" | ||||
|       type="textarea" | ||||
|       rows="20" | ||||
|       autocomplete="off" | ||||
|       autocorrect="off" | ||||
|       autocapitalize="off" | ||||
|       spellcheck="false" | ||||
|       :input-props="{ 'data-test-id': 'input' }" | ||||
|     /> | ||||
|   </n-form-item> | ||||
|   <n-form-item :label="outputLabel"> | ||||
|     <textarea-copyable :value="output" :language="outputLanguage" :follow-height-of="inputElement" /> | ||||
|   </n-form-item> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useValidation, type UseValidationRule } from '@/composable/validation'; | ||||
| import _ from 'lodash'; | ||||
| 
 | ||||
| const props = withDefaults( | ||||
|   defineProps<{ | ||||
|     transformer?: (v: string) => string; | ||||
|     inputValidationRules?: UseValidationRule<string>[]; | ||||
|     inputLabel?: string; | ||||
|     inputPlaceholder?: string; | ||||
|     inputDefault?: string; | ||||
|     outputLabel?: string; | ||||
|     outputLanguage?: string; | ||||
|   }>(), | ||||
|   { | ||||
|     transformer: _.identity, | ||||
|     inputValidationRules: () => [], | ||||
|     inputLabel: 'Input', | ||||
|     inputDefault: '', | ||||
|     inputPlaceholder: 'Input...', | ||||
|     outputLabel: 'Output', | ||||
|     outputLanguage: '', | ||||
|   }, | ||||
| ); | ||||
| 
 | ||||
| const { transformer, inputValidationRules, inputLabel, outputLabel, outputLanguage, inputPlaceholder, inputDefault } = | ||||
|   toRefs(props); | ||||
| 
 | ||||
| const inputElement = ref(); | ||||
| 
 | ||||
| const input = ref(inputDefault.value); | ||||
| const output = computed(() => transformer.value(input.value)); | ||||
| 
 | ||||
| const { attrs: validationAttrs } = useValidation({ source: input, rules: inputValidationRules.value }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped></style> | ||||
| @ -7,7 +7,7 @@ | ||||
|         :style="height ? `min-height: ${height - 40 /* card padding */ + 10 /* negative margin compensation */}px` : ''" | ||||
|       > | ||||
|         <n-config-provider :hljs="hljs"> | ||||
|           <n-code :code="value" :language="language" :trim="false" /> | ||||
|           <n-code :code="value" :language="language" :trim="false" data-test-id="area-content" /> | ||||
|         </n-config-provider> | ||||
|       </n-scrollbar> | ||||
|       <n-tooltip v-if="value" trigger="hover"> | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { reactive, watch, type Ref } from 'vue'; | ||||
| 
 | ||||
| type ValidatorReturnType = unknown; | ||||
| 
 | ||||
| interface UseValidationRule<T> { | ||||
| export interface UseValidationRule<T> { | ||||
|   validator: (value: T) => ValidatorReturnType; | ||||
|   message: string; | ||||
| } | ||||
|  | ||||
| @ -1,57 +1,27 @@ | ||||
| <template> | ||||
|   <n-form-item | ||||
|     label="Your raw json" | ||||
|     :feedback="rawJsonValidation.message" | ||||
|     :validation-status="rawJsonValidation.status" | ||||
|   > | ||||
|     <n-input | ||||
|       ref="inputElement" | ||||
|       v-model:value="rawJson" | ||||
|       placeholder="Paste your raw json here..." | ||||
|       type="textarea" | ||||
|       rows="20" | ||||
|       autocomplete="off" | ||||
|       autocorrect="off" | ||||
|       autocapitalize="off" | ||||
|       spellcheck="false" | ||||
|     /> | ||||
|   </n-form-item> | ||||
|   <n-form-item label="Minify version of your JSON"> | ||||
|     <textarea-copyable :value="cleanJson" language="json" :follow-height-of="inputElement" /> | ||||
|   </n-form-item> | ||||
|   <format-transformer | ||||
|     input-label="Your raw json" | ||||
|     :input-default="defaultValue" | ||||
|     input-placeholder="Paste your raw json here..." | ||||
|     output-label="Minify version of your JSON" | ||||
|     output-language="json" | ||||
|     :input-validation-rules="rules" | ||||
|     :transformer="transformer" | ||||
|   /> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import TextareaCopyable from '@/components/TextareaCopyable.vue'; | ||||
| import { useValidation } from '@/composable/validation'; | ||||
| import type { UseValidationRule } from '@/composable/validation'; | ||||
| import { withDefaultOnError } from '@/utils/defaults'; | ||||
| import JSON5 from 'json5'; | ||||
| import { computed, ref } from 'vue'; | ||||
| 
 | ||||
| const inputElement = ref<HTMLElement>(); | ||||
| const defaultValue = '{\n\t"hello": [\n\t\t"world"\n\t]\n}'; | ||||
| const transformer = (value: string) => withDefaultOnError(() => JSON.stringify(JSON5.parse(value), null, 0), ''); | ||||
| 
 | ||||
| const rawJson = ref('{\n\t"hello": [\n\t\t"world"\n\t]\n}'); | ||||
| const cleanJson = computed(() => withDefaultOnError(() => JSON.stringify(JSON5.parse(rawJson.value), null, 0), '')); | ||||
| 
 | ||||
| const rawJsonValidation = useValidation({ | ||||
|   source: rawJson, | ||||
|   rules: [ | ||||
|     { | ||||
|       validator: (v) => v === '' || JSON5.parse(v), | ||||
|       message: 'Provided JSON is not valid.', | ||||
|     }, | ||||
|   ], | ||||
| }); | ||||
| const rules: UseValidationRule<string>[] = [ | ||||
|   { | ||||
|     validator: (v: string) => v === '' || JSON5.parse(v), | ||||
|     message: 'Provided JSON is not valid.', | ||||
|   }, | ||||
| ]; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
| .result-card { | ||||
|   position: relative; | ||||
| 
 | ||||
|   .copy-button { | ||||
|     position: absolute; | ||||
|     top: 10px; | ||||
|     right: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user