mirror of
				https://github.com/CorentinTh/it-tools.git
				synced 2025-10-31 10:07:00 -04:00 
			
		
		
		
	feat: added MarkdownEditor.vue
Signed-off-by: Corentin Thomasset <corentin.thomasset74@gmail.com>
This commit is contained in:
		
							parent
							
								
									0631a7f750
								
							
						
					
					
						commit
						507d961cd8
					
				| @ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||||||
| - [fix] [GithubContributors] ordered contributors by contribution count | - [fix] [GithubContributors] ordered contributors by contribution count | ||||||
| - [refactor] used vue-typecasting for number inputs | - [refactor] used vue-typecasting for number inputs | ||||||
| - [feat] lazy loading tools routes | - [feat] lazy loading tools routes | ||||||
|  | - [feat] added [markdown editor](/#/markdown-editor) | ||||||
| 
 | 
 | ||||||
| ## 1.2.1 | ## 1.2.1 | ||||||
| - [fix] [UuidGenerator] added quantity validation rules | - [fix] [UuidGenerator] added quantity validation rules | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										22
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -3139,6 +3139,12 @@ | |||||||
|           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", |           "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", | ||||||
|           "dev": true |           "dev": true | ||||||
|         }, |         }, | ||||||
|  |         "highlight.js": { | ||||||
|  |           "version": "9.18.1", | ||||||
|  |           "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz", | ||||||
|  |           "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==", | ||||||
|  |           "dev": true | ||||||
|  |         }, | ||||||
|         "supports-color": { |         "supports-color": { | ||||||
|           "version": "7.1.0", |           "version": "7.1.0", | ||||||
|           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", |           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", | ||||||
| @ -4373,6 +4379,11 @@ | |||||||
|         "domelementtype": "1" |         "domelementtype": "1" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "dompurify": { | ||||||
|  |       "version": "2.0.11", | ||||||
|  |       "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.11.tgz", | ||||||
|  |       "integrity": "sha512-qVoGPjIW9IqxRij7klDQQ2j6nSe4UNWANBhZNLnsS7ScTtLb+3YdxkRY8brNTpkUiTtcXsCJO+jS0UCDfenLuA==" | ||||||
|  |     }, | ||||||
|     "domutils": { |     "domutils": { | ||||||
|       "version": "1.7.0", |       "version": "1.7.0", | ||||||
|       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", |       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", | ||||||
| @ -6253,12 +6264,6 @@ | |||||||
|       "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", |       "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "highlight.js": { |  | ||||||
|       "version": "9.18.1", |  | ||||||
|       "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz", |  | ||||||
|       "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==", |  | ||||||
|       "dev": true |  | ||||||
|     }, |  | ||||||
|     "hmac-drbg": { |     "hmac-drbg": { | ||||||
|       "version": "1.0.1", |       "version": "1.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", |       "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", | ||||||
| @ -8103,6 +8108,11 @@ | |||||||
|         "object-visit": "^1.0.0" |         "object-visit": "^1.0.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "marked": { | ||||||
|  |       "version": "1.1.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/marked/-/marked-1.1.0.tgz", | ||||||
|  |       "integrity": "sha512-EkE7RW6KcXfMHy2PA7Jg0YJE1l8UPEZE8k45tylzmZM30/r1M1MUXWQfJlrSbsTeh7m/XTwHbWUENvAJZpp1YA==" | ||||||
|  |     }, | ||||||
|     "md5.js": { |     "md5.js": { | ||||||
|       "version": "1.3.5", |       "version": "1.3.5", | ||||||
|       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", |       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", | ||||||
|  | |||||||
| @ -13,6 +13,8 @@ | |||||||
|     "color-convert": "^2.0.1", |     "color-convert": "^2.0.1", | ||||||
|     "color-name": "^1.1.4", |     "color-name": "^1.1.4", | ||||||
|     "core-js": "^3.6.4", |     "core-js": "^3.6.4", | ||||||
|  |     "dompurify": "^2.0.11", | ||||||
|  |     "marked": "^1.1.0", | ||||||
|     "register-service-worker": "^1.7.1", |     "register-service-worker": "^1.7.1", | ||||||
|     "roboto-fontface": "*", |     "roboto-fontface": "*", | ||||||
|     "vue": "^2.6.11", |     "vue": "^2.6.11", | ||||||
|  | |||||||
| @ -85,15 +85,22 @@ const toolsComponents = [ | |||||||
|         ], |         ], | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         title: 'Miscellaneous', |         title: 'Text', | ||||||
|         child: [ |         child: [ | ||||||
|             { |             { | ||||||
|                 icon: 'fa-align-left\n', |                 icon: 'fa-align-left', | ||||||
|                 text: 'Text stats', |                 text: 'Text stats', | ||||||
|                 path: '/text-stats', |                 path: '/text-stats', | ||||||
|                 component: () => import('./routes/tools/TextStats'), |                 component: () => import('./routes/tools/TextStats'), | ||||||
|                 keywords: ['word', 'count', 'size', 'bytes', 'length'] |                 keywords: ['word', 'count', 'size', 'bytes', 'length'] | ||||||
|             }, |             }, | ||||||
|  |             { | ||||||
|  |                 icon: 'fab fa-markdown', | ||||||
|  |                 text: 'Markdown editor', | ||||||
|  |                 path: '/markdown-editor', | ||||||
|  |                 component: () => import('./routes/tools/MarkdownEditor'), | ||||||
|  |                 keywords: ['text', 'html', 'markdown'] | ||||||
|  |             }, | ||||||
|         ], |         ], | ||||||
|     } |     } | ||||||
| ]; | ]; | ||||||
|  | |||||||
							
								
								
									
										77
									
								
								src/routes/tools/MarkdownEditor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/routes/tools/MarkdownEditor.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | <template> | ||||||
|  |     <v-row justify="center" align="center"> | ||||||
|  |         <v-col cols="12" xl="5" lg="6" md="12"> | ||||||
|  |             <v-card> | ||||||
|  |                 <v-card-text> | ||||||
|  |                     <v-textarea v-model="markdown" auto-grow outlined label="Markdown editor"/> | ||||||
|  |                     <div class="text-center"> | ||||||
|  |                         <v-btn @click="copy(markdown)">copy markdown</v-btn> | ||||||
|  |                     </div> | ||||||
|  |                 </v-card-text> | ||||||
|  |             </v-card> | ||||||
|  |         </v-col> | ||||||
|  |         <v-col cols="12" xl="5" lg="6" md="12"> | ||||||
|  |             <v-card> | ||||||
|  |                 <v-card-text > | ||||||
|  |                     <div class="preview" v-html="html"></div> | ||||||
|  |                     <div class="text-center"> | ||||||
|  |                         <v-divider /> | ||||||
|  |                         <br> | ||||||
|  |                         <v-btn @click="copy(html)">copy html</v-btn> | ||||||
|  |                     </div> | ||||||
|  |                 </v-card-text> | ||||||
|  |             </v-card> | ||||||
|  |         </v-col> | ||||||
|  |     </v-row> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  |     // import {debounce} from "../../utils/helpers"; | ||||||
|  |     import marked from 'marked' | ||||||
|  |     import DOMPurify from 'dompurify'; | ||||||
|  |     import {copyToClipboard} from "../../utils/helpers"; | ||||||
|  | 
 | ||||||
|  |     export default { | ||||||
|  |         name: "MarkdownEditor", | ||||||
|  |         data: () => ({ | ||||||
|  |             markdown: '# Hello, World!\nLorem ipsum **dolor** sit *amet*, consectetur adipisicing elit. A aspernatur commodi consequuntur distinctio dolore doloribus eaque earum est ipsum nobis numquam pariatur perspiciatis quasi quis, sed, sunt tempore tenetur, veniam!\n', | ||||||
|  |         }), | ||||||
|  |         methods: { | ||||||
|  |             copy(text){ | ||||||
|  |                 copyToClipboard(text) | ||||||
|  |                 this.$toast.success('Copied to clipboard.') | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         computed: { | ||||||
|  |             html() { | ||||||
|  |                 return DOMPurify.sanitize(marked(this.markdown)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang="less"> | ||||||
|  |     ::v-deep { | ||||||
|  |         .preview { | ||||||
|  |             padding: 20px; | ||||||
|  | 
 | ||||||
|  |             h1{ | ||||||
|  |                 margin-bottom: 15px; | ||||||
|  |             } | ||||||
|  |             code{ | ||||||
|  |                 background-color: rgba(0, 0, 0, 0.3) !important; | ||||||
|  |                 box-shadow: none; | ||||||
|  |                 color: #9a9a9a; | ||||||
|  |                 font-weight: normal; | ||||||
|  |             } | ||||||
|  |             pre { | ||||||
|  |                 width: 100%; | ||||||
|  | 
 | ||||||
|  |                 code { | ||||||
|  |                     width: 100% !important; | ||||||
|  |                     padding: 10px; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | </style> | ||||||
| @ -28,9 +28,19 @@ const isInt = (value) => { | |||||||
|     return Number.isInteger(value); |     return Number.isInteger(value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const debounce = (callback, delay = 300) => { | ||||||
|  |     let timer; | ||||||
|  | 
 | ||||||
|  |     return function(...args) { | ||||||
|  |         clearTimeout(timer); | ||||||
|  |         timer = setTimeout(() => callback(...args), delay); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export { | export { | ||||||
|     copyToClipboard, |     copyToClipboard, | ||||||
|     fileIsImage, |     fileIsImage, | ||||||
|     formatBytes, |     formatBytes, | ||||||
|     isInt |     isInt, | ||||||
|  |     debounce | ||||||
| } | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user