view src/test/tiny.html @ 36:b54e9e2212b7

try sceditor
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 03 Aug 2022 23:55:17 -0600
parents 1ce75c5ab0f7
children 3354d4ac89f8
line wrap: on
line source

<!doctype html>
<html>
	<head>
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<script src="/site.js"></script>
		<script src="http://tinymce.luan.software/tinymce.min.js" xreferrerpolicy="origin"></script>
		<style>
			input[type="file"] {
				display: none;
			}
		</style>
		<script>
			function videoIframe(url) {
				return '<iframe data-video="'+url+'" width="560" height="315" frameborder="0" allowfullscreen src="'+url+'"></iframe>';
			}

			// fucking moronic javascript doesn't have \Q \E in regex
			var videoHandlers = {};
			{
				let ptn1 = /^https:\/\/youtu\.be\/([a-zA-Z0-9_-]+)(?:\?t=([0-9]+))?/;
				let ptn2 = /^https:\/\/www\.youtube\.com\/watch\?v=([a-zA-Z0-9_-]+)(?:&t=([0-9]+)s)?/;
				videoHandlers.youtube = function(url) {
					let result = url.match(ptn1) || url.match(ptn2);
					if( result ) {
						url = 'https://www.youtube.com/embed/' + result[1];
						if( result[2] )
							url += '?start=' + result[2];
						return videoIframe(url);
					}
				}
			}
			{
				let ptn = /^https:\/\/rumble\.com\/embed\/[a-z0-9]+\/\?pub=[a-z0-9]+/;
				videoHandlers.rumble = function(url) {
					if( url.match(ptn) ) {
						return videoIframe(url);
					}
				}
			}
			{
				let ptn = /^https:\/\/www\.bitchute\.com\/video\/([a-zA-Z0-9]+)\//;
				videoHandlers.bitchute = function(url) {
					let result = url.match(ptn);
					if( result ) {
						url = 'https://www.bitchute.com/embed/' + result[1];
						return videoIframe(url);
					}
				}
			}
			{
				let ptn = /^https:\/\/vimeo\.com\/([0-9]+)/;
				videoHandlers.vimeo = function(url) {
					let result = url.match(ptn);
					if( result ) {
						url = 'https://player.vimeo.com/video/' + result[1];
						return videoIframe(url);
					}
				}
			}
			{
				let ptn = /^https:\/\/dai\.ly\/([a-z0-9]+)/;
				videoHandlers.dailymotion = function(url) {
					let result = url.match(ptn);
					if( result ) {
						url = 'https://www.dailymotion.com/embed/video/' + result[1];
						return videoIframe(url);
					}
				}
			}
			{
				let ptn = /^https:\/\/www\.tiktok\.com\/[^/]+\/video\/([0-9]+)/;
				videoHandlers.tiktok = function(url) {
					let result = url.match(ptn);
					if( result ) {
						//let html = '<blockquote class="tiktok-embed" data-video="'+result[1]+'" style="max-width: 560px; margin-left: 0;"><section></section></blockquote>';
						//html += '<script async src="https://www.tiktok.com/embed.js"></'+'script>';
						let html = '<img data-video="'+result[1]+'" src="whataever">';
						return html;
					}
				}
			}
			{
				let ptn = /\.[a-zA-Z0-9]+$/;
				videoHandlers.file = function(url) {
					if( url.match(ptn) ) {
						return '<video controls width="560" height><source src="'+url+'"></video>';
					}
				}
			}

			function videoUrlToHtml(url) {
				for (let key in videoHandlers) {
					let handle = videoHandlers[key];
					let html = handle(url);
					if(html) return html;
				}
				return '<a data-video="'+url+'" href="'+url+'">'+url+'</a>';
			}

			function uploaded(input,url,filename) {
				input.parentNode.parentNode.querySelector('input[type="url"]').value = url;
			}

			let imageFileHtml = '<input type=file accept="image/*" onchange="upload(this,uploaded)">';
			imageFileHtml += '<button class="tox-button tox-button--secondary" onclick="fileButtonClick(this)">Upload Image</button>';

			let videoFileHtml = '<input type=file accept="video/*" onchange="upload(this,uploaded)">';
			videoFileHtml += '<button class="tox-button tox-button--secondary" onclick="fileButtonClick(this)">Upload Video</button>';

			function tinymceSetup(editor) {

				editor.ui.registry.addButton('insertLink', {
					icon: 'link',
					tooltip: 'Insert link',
					onAction: function(api) {
						editor.windowManager.open({
							title: 'Insert Link',
							body: {
								type: 'panel',
								items: [
									{
										type: 'urlinput',
										name: 'src',
										label: 'URL'
									},
									{
										type: 'input',
										name: 'text',
										label: 'Text to display'
									},
								]
							},
							buttons: [
								{
									type: 'cancel',
									text: 'Cancel'
								},
								{
									type: 'submit',
									text: 'Save',
									buttonType: 'primary'
								}
							],
							onSubmit: function(dialogApi) {
								let data = dialogApi.getData();
								let src = data.src.value;
								if(!src) return;
								src = tinymce.DOM.encode(src);
								let text = data.text;
								let html = '<a href="' + src + '">' + text + '</a>';
								dialogApi.close();
								editor.insertContent(html);
							}
						});
					},
				});

				editor.ui.registry.addButton('insertImage', {
					icon: 'image',
					tooltip: 'Insert image',
					onAction: function(api) {
						editor.windowManager.open({
							title: 'Insert Image',
							body: {
								type: 'panel',
								items: [
									{
										type: 'urlinput',
										name: 'src',
										filetype: 'image',
										label: 'Source URL'
									},
									{
										type: 'htmlpanel',
										html: imageFileHtml
									},
								]
							},
							buttons: [
								{
									type: 'cancel',
									text: 'Cancel'
								},
								{
									type: 'submit',
									text: 'Save',
									buttonType: 'primary'
								}
							],
							onSubmit: function(dialogApi) {
								let src = dialogApi.getData().src.value;
								if(!src) return;
								src = tinymce.DOM.encode(src);
								let html = '<img src="' + src + '">';
								dialogApi.close();
								editor.insertContent(html);
							}
						});
					},
				});

				editor.ui.registry.addButton('insertVideo', {
					icon: 'embed',
					tooltip: 'Insert video',
					onAction: function(api) {
						editor.windowManager.open({
							title: 'Insert Video',
							body: {
								type: 'panel',
								items: [
									{
										type: 'urlinput',
										name: 'src',
										filetype: 'media',
										label: 'Source URL'
									},
									{
										type: 'htmlpanel',
										html: videoFileHtml
									},
								]
							},
							buttons: [
								{
									type: 'cancel',
									text: 'Cancel'
								},
								{
									type: 'submit',
									text: 'Save',
									buttonType: 'primary'
								}
							],
							onSubmit: function(dialogApi) {
								let src = dialogApi.getData().src.value;
								if(!src) return;
								let html = videoUrlToHtml(src);
								//alert(html);
								dialogApi.close();
								editor.insertContent(html);
							}
						});
					},
				});

				editor.ui.registry.addToggleButton('styleCode', {
					icon: 'code-sample',
					tooltip: 'Code',
					onAction: function(api) {
						editor.execCommand('mceToggleFormat', false, 'code');
					},
					onSetup: function(api) {
						api.setActive(editor.formatter.match('code'));
						let changed = editor.formatter.formatChanged('code', api.setActive);
						return function() { changed.unbind(); };
					}
				});

				editor.ui.registry.addMenuButton('styleText', {
					icon: 'format',
					tooltip: 'Text',
					fetch: function(callback) {
						callback([
							'fontsize',
							'forecolor',
						])
					}
				});

				editor.on( 'init', function(e) {
					editor.focus();
				} );
			}

			tinymce.init({
				selector: 'textarea',
				setup: tinymceSetup,
				//menubar: false,
				statusbar: false,
				plugins: ['link', 'image', 'media', 'lists', 'code', 'autoresize'],
				toolbar: 'link insertLink insertImage insertVideo | styleCode bold italic underline strikethrough superscript styleText | blockquote numlist bullist',
				autoresize_bottom_margin: 0,
				link_target_list: false,
				link_title: false,
				object_resizing: false,
				contextmenu: false,
				text_patterns: false,
				content_style: 'img {max-width: 500px;} p {margin: 0}',
				extended_valid_elements: 'b,i',
				formats: {
					bold: { inline: 'b' },
					italic: {inline: 'i'},
					underline: {inline: 'u'},
				},
			});

			function log() {
				console.log(tinymce.activeEditor.getContent());
			}
		</script>
	</head>
	<body>
		<p>
			<a href="https://www.tiny.cloud/">TinyMCE</a>
			<a href="https://github.com/tinymce/tinymce">source</a>
		</p>
		<textarea></textarea>
		<p><button onclick="log()">log</button></p>
	</body>
</html>