Skip to content

Commit

Permalink
Merge pull request #309 from pratikb64/add-markdown-editor
Browse files Browse the repository at this point in the history
feat: add markdown editor toolbar
  • Loading branch information
pratikb64 authored Jan 3, 2025
2 parents d4a22f8 + 82ad4dc commit f0ca7ca
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 49 deletions.
143 changes: 138 additions & 5 deletions wiki/public/js/editor.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as Ace from "ace-builds";
import "ace-builds/src-noconflict/theme-tomorrow_night";
import "ace-builds/src-noconflict/mode-markdown";
import "ace-builds/src-noconflict/theme-tomorrow_night";

const editorContainer = document.getElementById("wiki-editor");
const previewContainer = $("#preview-container");
const previewToggleBtn = $("#toggle-btn");
const wikiTitleInput = $(".wiki-title-input");
const editWikiBtn = $(".edit-wiki-btn, .sidebar-edit-mode-btn");
const saveWikiPageBtn = document.querySelector(
'[data-wiki-button="saveWikiPage"]',
'[data-wiki-button="saveWikiPage"]'
);
const draftWikiPageBtn = document.querySelector(
'[data-wiki-button="draftWikiPage"]',
'[data-wiki-button="draftWikiPage"]'
);
let showPreview = false;

Expand Down Expand Up @@ -125,7 +125,7 @@ editorContainer.addEventListener(
e.preventDefault();
e.stopPropagation();
},
500,
500
);

editorContainer.addEventListener("drop", function (e) {
Expand Down Expand Up @@ -162,8 +162,141 @@ editorContainer.addEventListener("drop", function (e) {
}
editor.session.insert(
editor.getCursorPosition(),
`![](${encodeURI(file_doc.file_url)})`,
`![](${encodeURI(file_doc.file_url)})`
);
},
});
});

function insertMarkdown(type) {
const selection = editor.getSelectedText();
let insertion = "";

switch (type) {
case "bold":
insertion = `**${selection || "bold text"}**`;
break;
case "italic":
insertion = `*${selection || "italic text"}*`;
break;
case "heading":
insertion = `\n# ${selection || "Heading"}`;
break;
case "quote":
insertion = `\n> ${selection || "Quote"}`;
break;
case "olist":
insertion = `\n1. ${selection || "List item"}`;
break;
case "ulist":
insertion = `\n* ${selection || "List item"}`;
break;
case "link":
insertion = `[${selection || "link text"}](url)`;
break;
case "image":
new frappe.ui.FileUploader({
dialog_title: __("Insert Image in Markdown"),
doctype: this.doctype,
docname: this.docname,
frm: this.frm,
folder: "Home/Attachments",
allow_multiple: false,
restrictions: {
allowed_file_types: ["image/*"],
},
on_success: (file_doc) => {
if (this.frm && !this.frm.is_new()) {
this.frm.attachments.attachment_uploaded(file_doc);
}
editor.session.insert(
editor.getCursorPosition(),
`\n![](${encodeURI(file_doc.file_url)})`
);
},
});
break;
case "table":
insertion = `${selection}\n| Header 1 | Header 2 |\n| -------- | -------- |\n| Row 1 | Row 1 |\n| Row 2 | Row 2 |`;
break;
}

editor.insert(insertion);
editor.focus();
}

const mdeBoldBtn = document.querySelector('[data-mde-button="bold"]');
const mdeItalicBtn = document.querySelector('[data-mde-button="italic"]');
const mdeHeadingBtn = document.querySelector('[data-mde-button="heading"]');
const mdeQuoteBtn = document.querySelector('[data-mde-button="quote"]');
const mdeOlistBtn = document.querySelector('[data-mde-button="olist"]');
const mdeUlistBtn = document.querySelector('[data-mde-button="ulist"]');
const mdeLinkBtn = document.querySelector('[data-mde-button="link"]');
const mdeImageBtn = document.querySelector('[data-mde-button="image"]');
const mdeTableBtn = document.querySelector('[data-mde-button="table"]');

mdeBoldBtn.addEventListener("click", () => insertMarkdown("bold"));
mdeItalicBtn.addEventListener("click", () => insertMarkdown("italic"));
mdeHeadingBtn.addEventListener("click", () => insertMarkdown("heading"));
mdeQuoteBtn.addEventListener("click", () => insertMarkdown("quote"));
mdeOlistBtn.addEventListener("click", () => insertMarkdown("olist"));
mdeUlistBtn.addEventListener("click", () => insertMarkdown("ulist"));
mdeLinkBtn.addEventListener("click", () => insertMarkdown("link"));
mdeImageBtn.addEventListener("click", () => insertMarkdown("image"));
mdeTableBtn.addEventListener("click", () => insertMarkdown("table"));

editor.commands.addCommand({
name: "bold",
bindKey: { win: "Ctrl-B", mac: "Command-B" },
exec: () => insertMarkdown("bold"),
readOnly: false,
});

editor.commands.addCommand({
name: "italic",
bindKey: { win: "Ctrl-I", mac: "Command-I" },
exec: () => insertMarkdown("italic"),
readOnly: false,
});

editor.commands.addCommand({
name: "heading",
bindKey: { win: "Ctrl-H", mac: "Command-H" },
exec: () => insertMarkdown("heading"),
readOnly: false,
});

editor.commands.addCommand({
name: "quote",
bindKey: { win: "Ctrl-Shift-.", mac: "Command-Shift-." },
exec: () => insertMarkdown("quote"),
readOnly: false,
});

editor.commands.addCommand({
name: "orderedList",
bindKey: { win: "Ctrl-Shift-7", mac: "Command-Shift-7" },
exec: () => insertMarkdown("olist"),
readOnly: false,
});

editor.commands.addCommand({
name: "unorderedList",
bindKey: { win: "Ctrl-Shift-8", mac: "Command-Shift-8" },
exec: () => insertMarkdown("ulist"),
readOnly: false,
});

editor.commands.addCommand({
name: "link",
bindKey: { win: "Ctrl-K", mac: "Command-K" },
exec: () => insertMarkdown("link"),
readOnly: false,
});

editor.commands.addCommand({
name: "image",
bindKey: { win: "Ctrl-P", mac: "Command-P" },
exec: () => insertMarkdown("image"),
readOnly: false,
});
62 changes: 31 additions & 31 deletions wiki/public/js/render_wiki.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,34 +121,32 @@ window.RenderWiki = class RenderWiki extends Wiki {

if (urlParams.get("editWiki") && $(".wiki-options").length) {
toggleEditor();
$("html").css({ overflow: "hidden" });
} else if (urlParams.get("newWiki")) {
toggleEditor();
$("html").css({ overflow: "hidden" });

if (
!$(
`.doc-sidebar .sidebar-group[data-title="${urlParams.get(
"newWiki",
)}"] .add-sidebar-page`,
"newWiki"
)}"] .add-sidebar-page`
).length
) {
this.add_wiki_sidebar(urlParams.get("newWiki"));

$(
$(
`.sidebar-items > .list-unstyled .h6:contains(${urlParams.get(
"newWiki",
)}) + .add-sidebar-page`,
)[0],
"newWiki"
)}) + .add-sidebar-page`
)[0]
).trigger("click");
} else
$(
$(
`.sidebar-items > .list-unstyled .h6:contains(${urlParams.get(
"newWiki",
)}) + .add-sidebar-page`,
)[1],
"newWiki"
)}) + .add-sidebar-page`
)[1]
).trigger("click");
}
$(".wiki-footer, .wiki-page-meta").toggleClass("hide");
Expand All @@ -171,7 +169,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
{
scrollTop: offset,
},
100,
100
);
});
});
Expand Down Expand Up @@ -260,7 +258,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(".edit-wiki-btn, .sidebar-edit-mode-btn").on("click", function () {
if (frappe.session.user === "Guest")
window.location.assign(
`/login?redirect-to=${window.location.pathname}`,
`/login?redirect-to=${window.location.pathname}`
);
else {
const urlParams = new URLSearchParams(window.location.search);
Expand All @@ -285,7 +283,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
const groupName = $(".sidebar-item.active").data("group-name");
$(".edit-wiki-btn").trigger("click");
$(
`.doc-sidebar .add-sidebar-page[data-group-name="${groupName}"]`,
`.doc-sidebar .add-sidebar-page[data-group-name="${groupName}"]`
).trigger("click");
});

Expand All @@ -310,7 +308,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
if (newWikiPage.data("group-name") !== groupName) {
// when new item is created in a different group as earlier
newSidebarItem.appendTo(
$(this).parent().parent().children(".list-unstyled"),
$(this).parent().parent().children(".list-unstyled")
);
if (urlParams.get("newWiki") !== groupName)
set_search_params("newWiki", groupName);
Expand All @@ -327,11 +325,11 @@ window.RenderWiki = class RenderWiki extends Wiki {
} else {
// fresh new item
active_items = $(
".sidebar-item.active, .sidebar-item.active .active",
".sidebar-item.active, .sidebar-item.active .active"
).removeClass("active");

newSidebarItem.appendTo(
$(this).parent().parent().children(".list-unstyled"),
$(this).parent().parent().children(".list-unstyled")
);
if (!$(".wiki-editor").is(":visible")) toggleEditor();
if (urlParams.get("newWiki") !== groupName)
Expand All @@ -340,7 +338,7 @@ window.RenderWiki = class RenderWiki extends Wiki {

$(this).parent().parent().each(setSortable);
e.stopPropagation();
},
}
);
}

Expand Down Expand Up @@ -369,7 +367,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
title: __("Delete Wiki Page"),
indicator: "red",
message: __(
`Are you sure you want to <b>delete</b> the Wiki Page <b>${title}</b>?`,
`Are you sure you want to <b>delete</b> the Wiki Page <b>${title}</b>?`
),
primary_action: {
label: "Yes",
Expand All @@ -395,7 +393,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
},
},
});
},
}
);
}

Expand All @@ -410,7 +408,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(".revision-content").html(),
$(".from-markdown .wiki-content")
.html()
.replaceAll(/<br class="ProseMirror-trailingBreak">/g, ""),
.replaceAll(/<br class="ProseMirror-trailingBreak">/g, "")
);
$(".previous-revision").removeClass("hide");
} else {
Expand Down Expand Up @@ -452,11 +450,12 @@ window.RenderWiki = class RenderWiki extends Wiki {
if (previousRevision.content)
$(".revision-content")[0].innerHTML = HtmlDiff.execute(
previousRevision.content,
currentRevision.content,
currentRevision.content
);
else $(".revision-content")[0].innerHTML = currentRevision.content;
$(".revision-time")[0].innerHTML =
`${currentRevision.author} edited ${currentRevision.revision_time}`;
$(
".revision-time"
)[0].innerHTML = `${currentRevision.author} edited ${currentRevision.revision_time}`;
currentRevisionIndex++;
addHljsClass();
});
Expand All @@ -473,10 +472,11 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(".previous-revision").removeClass("hide");
$(".revision-content")[0].innerHTML = HtmlDiff.execute(
nextRevision.content,
currentRevision.content,
currentRevision.content
);
$(".revision-time")[0].innerHTML =
`${currentRevision.author} edited ${currentRevision.revision_time}`;
$(
".revision-time"
)[0].innerHTML = `${currentRevision.author} edited ${currentRevision.revision_time}`;
currentRevisionIndex--;
addHljsClass();
});
Expand Down Expand Up @@ -505,7 +505,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(".doc-sidebar .sidebar-items")
.children(".list-unstyled")
.not(".hidden")
.first(),
.first()
);

$(".web-sidebar ul").each(setSortable);
Expand Down Expand Up @@ -537,7 +537,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(this)
.parent()
.append(
$(`<ul class="list-unstyled" style="min-height:20px;"> </ul`),
$(`<ul class="list-unstyled" style="min-height:20px;"> </ul`)
);
}
});
Expand Down Expand Up @@ -568,7 +568,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
// fixes html tags when they are sliced
return new DOMParser().parseFromString(
content.slice(start, end),
"text/html",
"text/html"
).body.innerHTML;
}

Expand Down Expand Up @@ -630,7 +630,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$dropdown_menu.addClass("show");
dropdownItems = $dropdown_menu.find(".dropdown-item");
});
}, 500),
}, 500)
);

$("#dropdownMenuSearch, .mobile-search-icon").on("click", () => {
Expand Down Expand Up @@ -726,7 +726,7 @@ window.RenderWiki = class RenderWiki extends Wiki {
$(".update-page-settings-button").on("click", function () {
const name = $('[name="wiki-page-name"]').val();
const hideOnSidebar = $('input[name="pageHideOnSidebar"]').prop(
"checked",
"checked"
);
const route =
$(".wiki-space-route-block").text().trim() +
Expand Down
Loading

0 comments on commit f0ca7ca

Please sign in to comment.