| 22 | 1 <!doctype html> | 
|  | 2 <html> | 
|  | 3 	<head> | 
|  | 4 		<meta name="viewport" content="width=device-width, initial-scale=1"> | 
| 24 | 5 		<script src="http://tinymce.luan.software/tinymce.min.js" xreferrerpolicy="origin"></script> | 
| 22 | 6 		<style> | 
|  | 7 		</style> | 
|  | 8 		<script> | 
| 28 | 9 			function videoIframe(url) { | 
|  | 10 				return '<iframe data-video="'+url+'" width="560" height="315" frameborder="0" allowfullscreen src="'+url+'"></iframe>'; | 
|  | 11 			} | 
|  | 12 | 
|  | 13 			var videoHandlers = {}; | 
|  | 14 			{ | 
|  | 15 				let ptn1 = new RegExp('https://youtu.be/([a-zA-Z0-9_-]+)(?:\\?t=([0-9]+))?'); | 
|  | 16 				let ptn2 = new RegExp('https://www.youtube.com/watch\\?v=([a-zA-Z0-9_-]+)(?:\\?t=([0-9]+)s)?'); | 
|  | 17 				videoHandlers.youtube = function(url) { | 
|  | 18 					let result = url.match(ptn1) || url.match(ptn2); | 
|  | 19 					if( result ) { | 
|  | 20 						url = 'https://www.youtube.com/embed/' + result[1]; | 
|  | 21 						if( result[2] ) | 
|  | 22 							url += '?start=' + result[2]; | 
|  | 23 						return videoIframe(url); | 
|  | 24 					} | 
|  | 25 				} | 
|  | 26 			} | 
|  | 27 			{ | 
|  | 28 				let ptn = new RegExp('https://rumble.com/embed/[a-z0-9]+/\\?pub=[a-z0-9]+'); | 
|  | 29 				videoHandlers.rumble = function(url) { | 
|  | 30 					if( url.match(ptn) ) { | 
|  | 31 						return videoIframe(url); | 
|  | 32 					} | 
|  | 33 				} | 
|  | 34 			} | 
|  | 35 			{ | 
|  | 36 				let ptn = new RegExp('https://www.bitchute.com/video/([a-zA-Z0-9]+)/'); | 
|  | 37 				videoHandlers.bitchute = function(url) { | 
|  | 38 					let result = url.match(ptn); | 
|  | 39 					if( result ) { | 
|  | 40 						url = 'https://www.bitchute.com/embed/' + result[1]; | 
|  | 41 						return videoIframe(url); | 
|  | 42 					} | 
|  | 43 				} | 
|  | 44 			} | 
|  | 45 			{ | 
|  | 46 				let ptn = new RegExp('https://vimeo.com/([0-9]+)'); | 
|  | 47 				videoHandlers.vimeo = function(url) { | 
|  | 48 					let result = url.match(ptn); | 
|  | 49 					if( result ) { | 
|  | 50 						url = 'https://player.vimeo.com/video/' + result[1]; | 
|  | 51 						return videoIframe(url); | 
|  | 52 					} | 
|  | 53 				} | 
|  | 54 			} | 
|  | 55 			{ | 
|  | 56 				let ptn = new RegExp('https://dai.ly/([a-z0-9]+)'); | 
|  | 57 				videoHandlers.dailymotion = function(url) { | 
|  | 58 					let result = url.match(ptn); | 
|  | 59 					if( result ) { | 
|  | 60 						url = 'https://www.dailymotion.com/embed/video/' + result[1]; | 
|  | 61 						return videoIframe(url); | 
|  | 62 					} | 
|  | 63 				} | 
|  | 64 			} | 
|  | 65 			{ | 
|  | 66 				let ptn = new RegExp('https://www.tiktok.com/[^/]+/video/([0-9]+)'); | 
|  | 67 				videoHandlers.tiktok = function(url) { | 
|  | 68 					let result = url.match(ptn); | 
|  | 69 					if( result ) { | 
|  | 70 						let html = '<blockquote class="tiktok-embed" data-video-id="'+result[1]+'" style="max-width: 560px; margin-left: 0;"><section></section></blockquote>'; | 
|  | 71 						//html += '<script async src="https://www.tiktok.com/embed.js"></'+'script>'; | 
|  | 72 						return html; | 
|  | 73 					} | 
|  | 74 				} | 
|  | 75 			} | 
|  | 76 			{ | 
|  | 77 				let ptn = new RegExp('\\.[a-zA-Z0-9]+$'); | 
|  | 78 				videoHandlers.file = function(url) { | 
|  | 79 					if( url.match(ptn) ) { | 
|  | 80 						return '<video controls width="560" height><source src="'+url+'"></video>'; | 
|  | 81 					} | 
|  | 82 				} | 
|  | 83 			} | 
|  | 84 | 
|  | 85 			function videoUrlToHtml(url) { | 
|  | 86 				for (let key in videoHandlers) { | 
|  | 87 					let handle = videoHandlers[key]; | 
|  | 88 					let html = handle(url); | 
|  | 89 					if(html) return html; | 
|  | 90 				} | 
|  | 91 				return '<a data-video="'+url+'" href="'+url+'">'+url+'</a>'; | 
|  | 92 			} | 
|  | 93 			console.log(videoUrlToHtml('https://www.tiktok.com/@chantelleef/video/7112118342181276933?is_from_webapp=1&sender_device=pc&web_id=7073254106622838318')); | 
| 22 | 94 | 
|  | 95 			function media_url_resolver(data,resolve,reject) { | 
| 28 | 96 				let html = videoUrlToHtml(data.url); | 
| 22 | 97 				resolve({ html: html }); | 
|  | 98 			} | 
|  | 99 | 
| 24 | 100 | 
| 23 | 101 			function tinymceSetup(editor) { | 
| 24 | 102 | 
|  | 103 				editor.ui.registry.addToggleButton('styleCode', { | 
|  | 104 					icon: 'sourcecode', | 
|  | 105 					tooltip: 'Code', | 
|  | 106 					onAction: function(api) { | 
|  | 107 						editor.execCommand('mceToggleFormat', false, 'code') | 
|  | 108 					}, | 
|  | 109 					onSetup: function(api) { | 
|  | 110 						api.setActive(editor.formatter.match('code')); | 
|  | 111 						let changed = editor.formatter.formatChanged('code', api.setActive); | 
|  | 112 						return function() { changed.unbind(); }; | 
|  | 113 					} | 
|  | 114 				}); | 
|  | 115 | 
|  | 116 				editor.ui.registry.addMenuButton('styleText', { | 
|  | 117 					icon: 'format', | 
|  | 118 					tooltip: 'Text', | 
|  | 119 					fetch: function(callback) { | 
|  | 120 						callback([ | 
|  | 121 							'fontsize', | 
|  | 122 							'forecolor', | 
|  | 123 						]) | 
|  | 124 					} | 
| 23 | 125 				}); | 
| 26 | 126 | 
|  | 127 				editor.on( 'init', function(e) {editor.focus()} ); | 
| 23 | 128 			} | 
|  | 129 | 
| 22 | 130 			tinymce.init({ | 
|  | 131 				selector: 'textarea', | 
| 23 | 132 				setup: tinymceSetup, | 
| 27 | 133 				//menubar: false, | 
| 26 | 134 				statusbar: false, | 
| 24 | 135 				toolbar: 'link image media | styleCode bold italic underline strikethrough superscript styleText | blockquote numlist bullist', | 
| 26 | 136 				plugins: ['link', 'image', 'media', 'lists', 'code', 'autoresize'], | 
|  | 137 				autoresize_bottom_margin: 0, | 
| 22 | 138 				link_target_list: false, | 
|  | 139 				link_title: false, | 
|  | 140 				image_description: false, | 
|  | 141 				image_dimensions: false, | 
|  | 142 				object_resizing: false, | 
|  | 143 				contextmenu: false, | 
|  | 144 				media_alt_source: false, | 
|  | 145 				media_dimensions: false, | 
|  | 146 				media_poster: false, | 
|  | 147 				media_url_resolver: media_url_resolver, | 
|  | 148 				text_patterns: false, | 
| 26 | 149 				content_style: 'img {max-width: 500px;} p {margin: 0}', | 
| 23 | 150 				//newline_behavior: 'linebreak', | 
| 22 | 151 				extended_valid_elements: 'b,i', | 
|  | 152 				formats: { | 
|  | 153 					bold: { inline: 'b' }, | 
|  | 154 					italic: {inline: 'i'}, | 
|  | 155 					underline: {inline: 'u'}, | 
|  | 156 				}, | 
|  | 157 			}); | 
|  | 158 | 
|  | 159 			function log() { | 
|  | 160 				console.log(tinymce.activeEditor.getContent()); | 
|  | 161 			} | 
|  | 162 		</script> | 
|  | 163 	</head> | 
|  | 164 	<body> | 
| 23 | 165 		<p><a href="https://www.tiny.cloud/">TinyMCE</a></p> | 
| 22 | 166 		<textarea></textarea> | 
|  | 167 		<p><button onclick="log()">log</button></p> | 
|  | 168 	</body> | 
|  | 169 </html> |