Skip to content

Commit

Permalink
auto pagination, editor enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
aorcsik committed Aug 10, 2024
1 parent edbc3b6 commit db7550f
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 24 deletions.
53 changes: 49 additions & 4 deletions src/css/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,24 @@ body.dragging .container .separator {
display: flex;
padding: .5rem;
background: #ddd;
align-items: center;
}
.container .editor-header .status {
padding-right: .5rem;
display: none;
}
.container.status-loading .editor-header .status-loading {
display: block;
}
.container.status-saved .editor-header .status-saved {
display: block;
}
.container.status-changed .editor-header .status-changed {
display: block;
}

.container .editor-header input[name="filename"] {
border: 0;
width: 100%;
display: block;
background-color: transparent;
color: var(--text-secondary-color);
Expand All @@ -90,11 +104,18 @@ body.dragging .container .separator {
background: var(--accent);
color: #fff;
border-radius: .25rem;
margin-left: auto;
}
.container .editor-header button[name="save"] i {
display: none;
}
.container .editor-header button[name="save"]:disabled {
background: rgba(0,0,0,0.3);
cursor: not-allowed;
}
.container .editor-header button[name="save"].saving i {
display: inline-block;
}

.container .editor-container {
width: 50%;
Expand Down Expand Up @@ -135,6 +156,9 @@ body.dragging .container .separator {
flex-grow: 1;
color: var(--text-color);
background-color: var(--background-color);

--token-color: #999;

}
.container .editor-container pre.contentPre #content {
outline: 0;
Expand Down Expand Up @@ -199,16 +223,37 @@ body.dragging .container .preview-container .drag-overlay {
}
.mdAsterisk::after {
content: "*";
color: var(--text-secondary-color);
color: var(--token-color);
}
.mdUnderscore::after {
content: "_";
color: var(--text-secondary-color);
color: var(--token-color);
}
.mdHashmark::after {
content: "#";
color: var(--text-secondary-color);
color: var(--token-color);
}
.mdHtml {
color: #fe7b00;
}
.mdQuote {
color: var(--text-secondary-color);
}
.mdGreaterThan::after {
content: ">";
color: var(--token-color);
}
.mdDash::after {
content: "-";
color: var(--token-color);
}
.mdListBullet {
color: var(--token-color);
}
.mdList {
color: darkgreen;
}
.mdEqual::after {
content: "=";
color: var(--token-color);
}
3 changes: 3 additions & 0 deletions src/ejs/editor.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<div class="container">
<form method="post" action="/preview" target="temp_iframe" class="editor-container">
<div class="editor-header">
<span class="status status-saved"><i class="fa-regular fa-circle-check"></i></span>
<span class="status status-changed"><i class="fa-regular fa-circle-exclamation"></i></span>
<span class="status status-loading"><i class="fa-regular fa-spinner-third fa-spin"></i></span>
<input type="text" name="filename" readonly value="<%= context.filename %>">
<input type="hidden" name="content" value="">
<button type="submit" name="save" value="1">Save</button>
Expand Down
92 changes: 81 additions & 11 deletions src/js/client/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,59 @@ import { calculateReadingTime, countWords } from "../server/shared";

import "../../css/editor.css";

let savedContent = null;
let isLoading = 0;
const updateStatus = () => {
const markdownText = document.getElementById("content").innerText;

let status = "saved";
if (isLoading > 0) {
status = "loading";
} else if (savedContent !== markdownText) {
status = "changed";
} else {
status = "saved";
}

document.querySelector(".container").className = document.querySelector(".container").className.replaceAll(/( status-loading| status-saved| status-changed)/gm, "");
document.querySelector(".container").className += ` status-${status}`;

return status;
};

let iframeId = (new Date()).getTime();
let changeThrottle = null;
const changeHandler = (event) => {
let markdownText = document.getElementById("content").innerText;

const savedContent = document.getElementById("savedContent").innerText;
if (!savedContent) savedContent = markdownText;

let markdownText = document.getElementById("content").innerText;

if (savedContent !== markdownText) {
document.querySelector("form.editor-container button[name=save]").removeAttribute("disabled");
} else {
const status = updateStatus();

if (status === "loading" || status === "saved") {
document.querySelector("form.editor-container button[name=save]").setAttribute("disabled", true);
} else {
document.querySelector("form.editor-container button[name=save]").removeAttribute("disabled");
}

const markupMap = {
"*": "<span class='mdAsterisk'></span>",
"_": "<span class='mdUnderscore'></span>",
"#": "<span class='mdHashmark'></span>",
">": "<span class='mdGreaterThan'></span>",
"-": "<span class='mdDash'></span>",
"=": "<span class='mdEqual'></span>",
"list_bullet": "<span class='mdListBullet'>%%</span>",
"heading_open": "<span class='mdHeading'>",
"heading_close": "</span>",
"em_open": "<span class='mdEm'>",
"em_close": "</span>",
"strong_open": "<span class='mdStrong'>",
"strong_close": "</span>",
"quote_open": "<span class='mdQuote'>",
"quote_close": "</span>",
"list_open": "<span class='mdList'>",
"list_close": "</span>",
};

let frontMatter = '';
Expand All @@ -41,25 +70,55 @@ const changeHandler = (event) => {
const readingTime = calculateReadingTime(markdownText);
document.querySelector(".editor-footer").innerHTML = `${wordCount} words | ${readingTime} minute${readingTime > 1 ? "s" : ""}`;

const mdHeadingMatch = markdownText.matchAll(/^(#+)(\s+.*)/gm);
const mdHeadingMatch = markdownText.matchAll(/^(#{1,6})(\s+.*)/gm);
if (mdHeadingMatch) [...mdHeadingMatch].forEach(match => {
const markup = match[1].split("").map((m) => markupMap[m]).join("");
markdownText = markdownText.replace(match[0], `${markupMap.heading_open}${markup}${match[2]}${markupMap.heading_close}`);
});

const mdHeadingMatch2 = markdownText.matchAll(/^(.*\n)(-+\n|=+\n)/gm);
if (mdHeadingMatch2) [...mdHeadingMatch2].forEach(match => {
const markup = match[2].replaceAll("=", markupMap["="]).replaceAll("-", markupMap["-"]);
markdownText = markdownText.replace(match[0], `${markupMap.heading_open}${match[1]}${markup}${markupMap.heading_close}`);
});

const mdLinkMatch = markdownText.matchAll(/!?\[[^\]]+?\]\([^\s]+?\)/gm);
if (mdLinkMatch) [...mdLinkMatch].forEach(match => {
markdownText = markdownText.replaceAll(match[0], `<span class='mdLink'>${match[0]}</span>`);
});
const mdStrongMatch = markdownText.matchAll(/(\*\*|__)(.+?)\1/gm);

const mdQuoteMatch = markdownText.matchAll(/^([ \t]*)(&gt;(\s*&gt;)*)(.*?\n\n)/gms);
if (mdQuoteMatch) [...mdQuoteMatch].forEach(match => {
const markup = match[2].replaceAll("&gt;", markupMap['>']);
markdownText = markdownText.replace(match[0], `${match[1]}${markupMap.quote_open}${markup}${match[4]}${markupMap.quote_close}`);
});

const listMatch = (markdownText) => {
const mdListMatch = markdownText.matchAll(/^([ \t]*)(\*|-|\d+\.)(\s+.*?\n\n)/gms);
if (mdListMatch) [...mdListMatch].forEach(match => {
let content = match[3];
if (content.match(/^([ \t]*)(\*|-|\d+\.)(\s+.*?\n\n)/ms)) content = listMatch(content);
const markup = markupMap[match[2]] ? markupMap[match[2]] : markupMap.list_bullet.replace("%%", match[2]);
markdownText = markdownText.replace(match[0], `${match[1]}${markupMap.list_open}${markup}${content}${markupMap.list_close}`);
});
return markdownText;
}
markdownText = listMatch(markdownText);

const mdStrongMatch = markdownText.matchAll(/(\*\*|__)(.+?)\1/gms);
if (mdStrongMatch) [...mdStrongMatch].forEach(match => {
if (match[2].match(/\n\n/)) return;
const markup = match[1].split("").map(m => markupMap[m]).join("");
markdownText = markdownText.replace(match[0], `${markupMap.strong_open}${markup}${match[2]}${markup}${markupMap.strong_close}`);
});
const mdEmMatch = markdownText.matchAll(/(\*|_)(.+?)\1/gm);

const mdEmMatch = markdownText.matchAll(/(\*|_)(.+?)\1/gms);
if (mdEmMatch) [...mdEmMatch].forEach(match => {
if (match[2].match(/\n\n/)) return;
const markup = match[1].split("").map(m => markupMap[m]).join("");
markdownText = markdownText.replace(match[0], `${markupMap.em_open}${markup}${match[2]}${markup}${markupMap.em_close}`);
});

const mdHtmlMatch = markdownText.matchAll(/&lt;[a-z/].*?&gt;/gm);
if (mdHtmlMatch) [...mdHtmlMatch].forEach(match => {
markdownText = markdownText.replace(match[0], `<span class='mdHtml'>${match[0]}</span>`);
Expand All @@ -73,6 +132,9 @@ const changeHandler = (event) => {
if (document.querySelector("form.editor-container input[name=content]").value !== markdownText) {
document.querySelector("form.editor-container input[name=content]").value = markdownText;

isLoading++;
updateStatus();

const newIframe = document.createElement("iframe");
newIframe.setAttribute("name", `temp_iframe_${iframeId}`);
document.querySelector(".preview-container").appendChild(newIframe);
Expand All @@ -82,7 +144,14 @@ const changeHandler = (event) => {
if (iframe.getAttribute("name") < event.target.getAttribute("name")) {
iframe.remove();
}
})
});

isLoading--;
updateStatus();

});
newIframe.addEventListener("error", (event) => {
console.log(error);
});

document.querySelector("form.editor-container").setAttribute("target", `temp_iframe_${iframeId}`);
Expand All @@ -97,7 +166,8 @@ changeHandler();

const submitHandler = (event) => {
if (event.submitter.name === "save") {
document.getElementById("savedContent").innerHTML = event.target.content.value;
savedContent = event.target.content.value;
changeHandler();
}
};

Expand Down
18 changes: 17 additions & 1 deletion src/js/server/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,27 @@ const renderHtml = async (config, templateName, basePath, skipDraft=false) => {

if (blogPage.collection) {
context.pages = context.blogPages.filter(bP => bP.collection === blogPage.collection).sort(BlogPage.compare);

let previous;
let current;
let next;
context.pages.forEach((bP) => {
if (bP.path === blogPage.path) {
current = bP;
} else if (current && !next) {
next = bP;
blogPage.next = next.path;
} else if (!current) {
previous = bP;
blogPage.previous = previous.path;
}
});
}
context = {...context, ...blogPage};
templateName = "/_blog_post";
} catch (error) {
// console.log(error);
// "ENOENT: no such file or directory" is expected when the page has no markdown file
if (!error.message.match(/ENOENT: no such file or directory/)) throw error;
}

const templatePath = `${config.templateDir}${templateName}.ejs`;
Expand Down
2 changes: 0 additions & 2 deletions src/md/blog/elden-ring-part-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ author: aorcsik
published_at: 2024.07.11
tags:
- elden-ring
previous: /blog/elden-ring.html
next: /blog/elden-ring-part-3.html
collection: elden-ring
---

Expand Down
4 changes: 1 addition & 3 deletions src/md/blog/elden-ring-part-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ author: aorcsik
published_at: 2024.07.16
tags:
- elden-ring
previous: /blog/elden-ring-part-2.html
next: /blog/elden-ring-part-4.html
draft: true
collection: elden-ring
draft: true
---

## I'm not strong enough
Expand Down
4 changes: 1 addition & 3 deletions src/md/blog/elden-ring.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ author: aorcsik
published_at: 2024.07.08
tags:
- elden-ring
next: /blog/elden-ring-part-2.html
collection: elden-ring

---

## First Steps
## First Stepss

### Adventures in Elden Ring - Part 1

Expand Down

0 comments on commit db7550f

Please sign in to comment.