mirror of https://github.com/docusealco/docuseal
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							81 lines
						
					
					
						
							2.0 KiB
						
					
					
				
			
		
		
	
	
							81 lines
						
					
					
						
							2.0 KiB
						
					
					
				| <template>
 | |
|   <span>
 | |
|     <span v-if="textOnly">
 | |
|       {{ dom.body.textContent }}
 | |
|     </span>
 | |
|     <template v-else>
 | |
|       <template
 | |
|         v-for="(item, index) in nodes || dom.body.childNodes"
 | |
|         :key="index"
 | |
|       >
 | |
|         <a
 | |
|           v-if="item.tagName === 'A' && item.getAttribute('href') !== 'undefined'"
 | |
|           :href="sanitizeUrl(item.getAttribute('href'))"
 | |
|           rel="noopener noreferrer nofollow"
 | |
|           :class="item.getAttribute('class') || 'link'"
 | |
|           target="_blank"
 | |
|         >
 | |
|           <MarkdownContent :nodes="item.childNodes" />
 | |
|         </a>
 | |
|         <component
 | |
|           :is="item.tagName"
 | |
|           v-else-if="safeTags.includes(item.tagName)"
 | |
|         >
 | |
|           <MarkdownContent :nodes="item.childNodes" />
 | |
|         </component>
 | |
|         <br v-else-if="item.tagName === 'BR' || item.nodeValue === '\n'">
 | |
|         <template v-else>
 | |
|           {{ item.textContent }}
 | |
|         </template>
 | |
|       </template>
 | |
|     </template>
 | |
|   </span>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import snarkdown from 'snarkdown'
 | |
| import { sanitizeUrl } from '@braintree/sanitize-url'
 | |
| 
 | |
| export default {
 | |
|   name: 'MarkdownContent',
 | |
|   props: {
 | |
|     string: {
 | |
|       type: String,
 | |
|       required: false,
 | |
|       default: ''
 | |
|     },
 | |
|     nodes: {
 | |
|       type: [Array, Object],
 | |
|       require: false,
 | |
|       default: null
 | |
|     },
 | |
|     textOnly: {
 | |
|       type: Boolean,
 | |
|       required: false,
 | |
|       default: false
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     safeTags () {
 | |
|       return ['UL', 'I', 'EM', 'B', 'STRONG', 'P']
 | |
|     },
 | |
|     dom () {
 | |
|       const linkParts = this.string.split(/(https?:\/\/[^\s)]+)/g)
 | |
| 
 | |
|       const text = linkParts.map((part, index) => {
 | |
|         if (part.match(/^https?:\/\//) && !linkParts[index - 1]?.match(/\(\s*$/) && !linkParts[index + 1]?.match(/^\s*\)/)) {
 | |
|           return `[${part}](${part})`
 | |
|         } else {
 | |
|           return part
 | |
|         }
 | |
|       }).join('')
 | |
| 
 | |
|       return new DOMParser().parseFromString(snarkdown(text.replace(/\n/g, '<br>')), 'text/html')
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     sanitizeUrl
 | |
|   }
 | |
| }
 | |
| </script>
 |