Implement markdown emoji, youtube, clipboard

This commit is contained in:
cuom1999 2024-03-19 23:51:12 -05:00
parent 5e72b472e6
commit e923d1b2fe
12 changed files with 381 additions and 27 deletions

View file

@ -726,7 +726,7 @@ noscript #noscript {
}
.featherlight {
z-index: 1000 !important;
z-index: 1001 !important;
}
// @media (max-width: 500px) {

View file

@ -27,7 +27,7 @@
margin-top: 1em;
}
.big-emoji {
font-size: 16px;
font-size: 1.2em;
}
#chat-online {
border-right: 1px solid #ccc;

View file

@ -311,17 +311,49 @@ function populateCopyButton() {
});
}
function register_markdown_editors() {
if (!("Markdown" in window)) {
return;
}
$('textarea.wmd-input').each(function() {
let id = this.id.substr(9); // remove prefix "wmd-input"
var $buttonBar = $(this).prevAll('div[id^="wmd-button-bar"]').first();
if (!$buttonBar.length || !$buttonBar.html().trim()) {
let converter = new Markdown.Converter();
let editor = new Markdown.Editor(converter, id);
editor.run();
function register_copy_clipboard($elements, callback) {
$elements.on('paste', function(event) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (const index in items) {
const item = items[index];
if (item.kind === 'file' && item.type.indexOf('image') !== -1) {
const blob = item.getAsFile();
const formData = new FormData();
formData.append('image', blob);
$(this).prop('disabled', true);
$.ajax({
url: '/pagedown/image-upload/',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
// Assuming the server returns the URL of the image
const imageUrl = data.url;
const editor = $(event.target); // Get the textarea where the event was triggered
let currentMarkdown = editor.val();
const markdownImageText = '![](' + imageUrl + ')'; // Markdown for an image
if (currentMarkdown) currentMarkdown += "\n";
currentMarkdown += markdownImageText;
editor.val(currentMarkdown);
callback?.();
},
error: function() {
alert('There was an error uploading the image.');
},
complete: () => {
// Re-enable the editor
$(this).prop('disabled', false);
}
});
// We only handle the first image in the clipboard data
break;
}
}
});
}
@ -399,9 +431,7 @@ function onWindowReady() {
}
});
setTimeout(() => {
register_markdown_editors();
}, 100);
register_copy_clipboard($('textarea.wmd-input'));
$('form').submit(function (evt) {
// Prevent multiple submissions of forms, see #565

View file

@ -4129,17 +4129,20 @@ html .md-typeset .footnote-ref{
.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji){
display:inline-flex;
height:1.125em;
vertical-align:text-top
vertical-align:text-top;
font-size: 1.2em;
}
.md-typeset :-moz-any(.emojione,.twemoji,.gemoji){
display:inline-flex;
height:1.125em;
vertical-align:text-top
vertical-align:text-top;
font-size: 1.2em;
}
.md-typeset :is(.emojione,.twemoji,.gemoji){
display:inline-flex;
height:1.125em;
vertical-align:text-top
vertical-align:text-top;
font-size: 1.2em;
}
.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji) svg{
fill:currentcolor;
@ -4149,12 +4152,14 @@ html .md-typeset .footnote-ref{
.md-typeset :-moz-any(.emojione,.twemoji,.gemoji) svg{
fill:currentcolor;
max-height:100%;
width:1.125em
width:1.125em;
font-size: 1.2em;
}
.md-typeset :is(.emojione,.twemoji,.gemoji) svg{
fill:currentcolor;
max-height:100%;
width:1.125em
width:1.125em;
font-size: 1.2em;
}
.highlight :-webkit-any(.o,.ow){
color:var(--md-code-hl-operator-color)

158
resources/pagedown_init.js Normal file
View file

@ -0,0 +1,158 @@
var DjangoPagedown = DjangoPagedown | {};
DjangoPagedown = (function() {
var converter = Markdown.getSanitizingConverter();
var editors = {};
var elements;
Markdown.Extra.init(converter, {
extensions: "all"
});
var createEditor = function(element) {
var input = element.getElementsByClassName("wmd-input")[0];
if (input === undefined) {
return
}
var id = input.id.substr(9);
if (!editors.hasOwnProperty(id)) {
var editor = new Markdown.Editor(converter, id, {});
// Handle image upload
if (element.classList.contains("image-upload-enabled")) {
var upload = element.getElementsByClassName("pagedown-image-upload")[0];
var url = upload.getElementsByClassName("url-input")[0];
var file = upload.getElementsByClassName("file-input")[0];
var cancel = upload.getElementsByClassName("deletelink")[0];
var submit = upload.getElementsByClassName("submit-input")[0];
var loading = upload.getElementsByClassName("submit-loading")[0];
var close = function(value, callback = undefined) {
upload.classList.remove("show");
url.value = "";
file.value = "";
document.removeEventListener('click', outsideClickListener);
if (callback) callback(value);
};
var outsideClickListener = function(event) {
if (!upload.contains(event.target) && upload.classList.contains("show")) {
cancel.click();
}
};
editor.hooks.set("insertImageDialog", function(callback) {
upload.classList.add("show");
setTimeout(function() {
document.addEventListener('click', outsideClickListener);
}, 0);
cancel.addEventListener(
"click",
function(event) {
close(null, callback);
event.preventDefault();
},
{ once: true }
);
submit.addEventListener(
"click",
function() {
// Regular URL
if (url.value.length > 0) {
close(url.value, callback);
}
// File upload
else if (file.files.length > 0) {
loading.classList.add("show");
submit.classList.remove("show");
var data = new FormData();
var xhr = new XMLHttpRequest();
data.append("image", file.files[0]);
xhr.open("POST", file.dataset.action, true);
xhr.addEventListener(
"load",
function() {
loading.classList.remove("show");
submit.classList.add("show");
if (xhr.status !== 200) {
alert(xhr.statusText);
} else {
var response = JSON.parse(xhr.response);
if (response.success) {
close(response.url, callback);
} else {
if (response.error) {
var error = "";
for (var key in response.error) {
if (response.error.hasOwnProperty(key)) {
error += key + ":" + response.error[key];
}
}
alert(error);
}
close(null, callback);
}
}
},
{
once: true
}
);
xhr.send(data);
} else {
// Nothing
close(null, callback);
}
event.preventDefault();
},
{ once: true }
);
return true;
});
}
editor.run();
editors[id] = editor;
}
};
var destroyEditor = function(element) {
var input = element.getElementsByClassName("wmd-input")[0];
if (input === undefined) {
return
}
var id = input.id.substr(9);
if (editors.hasOwnProperty(id)) {
delete editors[id];
return true;
}
return false;
};
var init = function() {
elements = document.getElementsByClassName("wmd-wrapper");
for (var i = 0; i < elements.length; ++i) {
createEditor(elements[i]);
}
};
return {
init: function() {
return init();
},
createEditor: function(element) {
return createEditor(element);
},
destroyEditor: function(element) {
return destroyEditor(element);
}
};
})();
window.onload = DjangoPagedown.init;