From 7e3f80863da41fd5f4407639ca534b346d95f25b Mon Sep 17 00:00:00 2001 From: Antal Orcsik Date: Tue, 27 Aug 2024 16:08:12 +0200 Subject: [PATCH] editor fixes and markdown demo doc --- src/css/blog.css | 9 +- src/css/client.css | 16 ++-- src/css/editor.css | 2 +- src/ejs/editor.ejs | 2 +- src/js/client/editor.js | 82 +++++++++------- src/md/blog/markdown-it-demo.md | 164 ++++++++++++++++++++++++++++++++ 6 files changed, 225 insertions(+), 50 deletions(-) create mode 100644 src/md/blog/markdown-it-demo.md diff --git a/src/css/blog.css b/src/css/blog.css index d3bab92..de3aae5 100644 --- a/src/css/blog.css +++ b/src/css/blog.css @@ -6,7 +6,7 @@ body { display: flex; align-items: center; flex-direction: column; - min-height: 400px; + min-height: 300px; padding-top: var(--header-height); padding-bottom: 2rem; background-size: cover; @@ -17,9 +17,8 @@ body { } @media only screen and (min-width: 992px) { .blog-header { - min-height: 350px; border-radius: 1rem 1rem 0 0; - margin: calc(-1 * var(--header-height) + .5rem) 0 0 0; + /* margin: calc(-1 * var(--header-height) + 1rem) 0 0 0; */ } } .blog-header:before { @@ -53,6 +52,7 @@ body { width: 64px; z-index: 2; margin: .5rem auto 0 auto; + display: none; } .blog-header .blog-title, @@ -229,6 +229,9 @@ body.tag-elden-ring #header.sticky #logo span.logo-head::after { body.tag-elden-ring #logo span.logo-head { filter: blur(4px); } +body.tag-elden-ring .blog-header { + min-height: 400px; +} body.tag-elden-ring .blog-header:before { background-image: url("https://static.aorcsik.com/blog/elden-ring-background2.webp"); background-position: center bottom; diff --git a/src/css/client.css b/src/css/client.css index 8c4e62f..6f66502 100644 --- a/src/css/client.css +++ b/src/css/client.css @@ -398,20 +398,20 @@ p { } } -#menu-toggle:checked + #header nav ul li, -#menu-toggle:checked + #header nav ul li a, -#header.sticky nav ul li, -#header.sticky nav ul li a { +#menu-toggle:checked + header#header nav ul li, +#menu-toggle:checked + header#header nav ul li a, +header#header.sticky nav ul li, +header#header.sticky nav ul li a { color: var(--nav-color); } -#menu-toggle:checked + #header #logo span.logo-head::after, -#header.sticky #logo span.logo-head::after { +#menu-toggle:checked + header#header #logo span.logo-head::after, +header#header.sticky #logo span.logo-head::after { opacity: 0; } -#menu-toggle:checked + #header #logo span.logo-tail, -#header.sticky #logo span.logo-tail { +#menu-toggle:checked + header#header #logo span.logo-tail, +header#header.sticky #logo span.logo-tail { color: var(--nav-color); } diff --git a/src/css/editor.css b/src/css/editor.css index e0bec2d..e67afcc 100644 --- a/src/css/editor.css +++ b/src/css/editor.css @@ -397,7 +397,7 @@ body.dragging .container .preview-container .drag-overlay { color: var(--syntax-color-1); } .mdHr { - + color: var(--syntax-color-4); } diff --git a/src/ejs/editor.ejs b/src/ejs/editor.ejs index f84ed0b..388fbcc 100644 --- a/src/ejs/editor.ejs +++ b/src/ejs/editor.ejs @@ -37,7 +37,7 @@
- +
diff --git a/src/js/client/editor.js b/src/js/client/editor.js index 783c753..1abc486 100644 --- a/src/js/client/editor.js +++ b/src/js/client/editor.js @@ -47,7 +47,7 @@ const textareaContentScrollHandler = (event) => { previewScrollMatcher(textareaContent.scrollTop, textareaContent.scrollHeight, textareaContent.offsetHeight); }; -let savedContent = null; +window.savedContent = window.savedContent || null; let updateStatusThrottle = null; const updateStatus = () => { if (updateStatusThrottle) window.clearTimeout(updateStatusThrottle); @@ -58,7 +58,7 @@ const updateStatus = () => { let status; if (isLoading > 1) { status = "loading"; - } else if (savedContent !== markdownText) { + } else if (window.savedContent !== markdownText) { status = "changed"; } else { status = "saved"; @@ -162,7 +162,7 @@ const changeHandler = (event) => { }); } - if (!savedContent) savedContent = markdownText; + if (!window.savedContent) window.savedContent = markdownText; updateStatus(); @@ -245,7 +245,7 @@ const changeHandler = (event) => { markdownText = markdownText.replace(match[0], markupMap.heading.replace("%%", `${markup}${match[2]}`)); }); - const mdHeadingMatch2 = markdownText.matchAll(/^(\s*[^\s]+\n)(-+\n|=+\n)/gm); + const mdHeadingMatch2 = markdownText.matchAll(/^(\s*[^\s].*\n)(-+\n|=+\n)/gm); if (mdHeadingMatch2) [...mdHeadingMatch2].forEach(match => { const markup = match[2].replaceAll("=", markupMap["="]).replaceAll("-", markupMap["-"]); markdownText = markdownText.replace(match[0], markupMap.heading.replace("%%", `${match[1]}${markup}`)); @@ -257,13 +257,30 @@ const changeHandler = (event) => { markdownText = markdownText.replace(match[0], markupMap.hr.replace("%%", `${markup}`)); }); - const mdCodeBlockMatch = markdownText.matchAll(/(```)(\s*[^\s]?)(.*?)(\1(\n\n|\n?$))/gms); - if (mdCodeBlockMatch) [...mdCodeBlockMatch].forEach(match => { + 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.list_bullet.replace("%%", markupMap[match[2]] ? markupMap[match[2]] : match[2]); + markdownText = markdownText.replace(match[0], `${markupMap.list.replace("%%", `${match[1]}${markup}${content}`)}`); + }); + return markdownText; + } + markdownText = listMatch(markdownText); + + const mdFencedCodeBlockMatch = markdownText.matchAll(/(```)(\s*[^\s]?)(.*?)(\1(\n\n|\n?$))/gms); + if (mdFencedCodeBlockMatch) [...mdFencedCodeBlockMatch].forEach(match => { const markupStart = match[1].split("").map((m) => markupMap[m] || m).join(""); const markupEnd = match[4].split("").map((m) => markupMap[m] || m).join(""); markdownText = markdownText.replaceAll(match[0], markupMap.code_block.replace("%%", `${markupStart}${match[2] || ''}${match[3]}${markupEnd}`)); }); + const mdIndentedCodeBlockMatch = markdownText.matchAll(/^ .+/gm); + if (mdIndentedCodeBlockMatch) [...mdIndentedCodeBlockMatch].forEach(match => { + markdownText = markdownText.replaceAll(match[0], markupMap.code_block.replace("%%", match[0])); + }); + const mdCodeMatch = markdownText.matchAll(/(`)(.+?)\1/gms); if (mdCodeMatch) [...mdCodeMatch].forEach(match => { if (match[2].match(/\n\n/)) return; @@ -271,6 +288,23 @@ const changeHandler = (event) => { markdownText = markdownText.replace(match[0], markupMap.code.replace("%%", `${markup}${match[2]}${markup}`)); }); + const references = {}; + const mdReferenceMatch = markdownText.matchAll(/^(\s*)\[([^\^\]][^\]]*?)\]:(\s*)([^\s]+)(\s+".*?")?/gm); + if (mdReferenceMatch) [...mdReferenceMatch].forEach(match => { + if (!match[1].match(/mdImage/)) { // Image markup inside link markup is not supported + markdownText = markdownText.replaceAll(match[0], (match[1] || '') + markupMap.reference + .replace("%1", match[2]) + .replace("%2", match[3] || '') + .replace("%3", match[4]) + .replace("%4", match[5] || '') + ); + references[match[2]] = { + url: match[4], + title: match[5] + }; + } + }); + const mdImageMatch = markdownText.matchAll(/!\[([^\]]+?)\]\(([^\s]*?)(\s+".*?")?\)/gm); if (mdImageMatch) [...mdImageMatch].forEach(match => { markdownText = markdownText.replaceAll(match[0], markupMap.image @@ -279,9 +313,9 @@ const changeHandler = (event) => { .replace("%3", match[3] || '') ); }); - const mdImageReferenceMatch = markdownText.matchAll(/!\[([^\]]+?)\]\[([^\]]+?)\]/gm); + const mdImageReferenceMatch = markdownText.matchAll(/!\[([^\]]+?)\]\[([^\^\]][^\]]*?)\]/gm); if (mdImageReferenceMatch) [...mdImageReferenceMatch].forEach(match => { - markdownText = markdownText.replaceAll(match[0], markupMap.imageRef + if (references[match[2]]) markdownText = markdownText.replaceAll(match[0], markupMap.imageRef .replace("%1", match[1]) .replace("%2", match[2]) ); @@ -296,28 +330,14 @@ const changeHandler = (event) => { ); } }); - const mdLinkReferenceMatch = markdownText.matchAll(/\[([^\]]+?)\]\[([^\]]+?)\]/gm); + const mdLinkReferenceMatch = markdownText.matchAll(/\[([^\]]+?)\]\[([^\^\]][^\]]*?)\]/gm); if (mdLinkReferenceMatch) [...mdLinkReferenceMatch].forEach(match => { - markdownText = markdownText.replaceAll(match[0], markupMap.linkRef + if (references[match[2]]) markdownText = markdownText.replaceAll(match[0], markupMap.linkRef .replace("%1", match[1]) .replace("%2", match[2]) ); }); - const mdReferenceMatch = markdownText.matchAll(/\[([^\]]+?)\]:(\s*)([^\s]+)(\s+".*?")?/gm); - if (mdReferenceMatch) [...mdReferenceMatch].forEach(match => { - if (!match[1].match(/mdImage/)) { // Image markup inside link markup is not supported - markdownText = markdownText.replaceAll(match[0], markupMap.reference - .replace("%1", match[1]) - .replace("%2", match[2] || '') - .replace("%3", match[3]) - .replace("%4", match[4] || '') - ); - } - }); - - - const mdQuoteMatch = markdownText.matchAll(/^([ \t]*)(>(\s*>)*)(.*?\n\n)/gms); if (mdQuoteMatch) [...mdQuoteMatch].forEach(match => { const markup = match[2].replaceAll(">", markupMap['>']); @@ -331,18 +351,6 @@ const changeHandler = (event) => { markdownText = markdownText.replace(match[0], `${match[1]}${markupMap.quote.replace("%%", `${markup}${content}`)}`); }); - 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.list_bullet.replace("%%", markupMap[match[2]] ? markupMap[match[2]] : match[2]); - markdownText = markdownText.replace(match[0], `${match[1]}${markupMap.list.replace("%%", `${markup}${content}`)}`); - }); - return markdownText; - } - markdownText = listMatch(markdownText); - const mdStrikethroughMatch = markdownText.matchAll(/(~~)(.+?)\1/gms); if (mdStrikethroughMatch) [...mdStrikethroughMatch].forEach(match => { if (match[2].match(/\n\n/)) return; @@ -437,7 +445,7 @@ textareaContentScrollHandler(); const submitHandler = (event) => { if (event.submitter.name === "save") { console.log("Saving..."); - savedContent = event.target.content.value; + window.savedContent = event.target.content.value; // changeHandler(); } else { console.log("Previewing..."); diff --git a/src/md/blog/markdown-it-demo.md b/src/md/blog/markdown-it-demo.md new file mode 100644 index 0000000..ac64809 --- /dev/null +++ b/src/md/blog/markdown-it-demo.md @@ -0,0 +1,164 @@ +--- +published_at: 2024.08.23 +author: aorcsik +draft: true +--- + +## markdown-it let's make this title long + +### demo + +# h1 Heading 8-) +## h2 Heading +### h3 Heading +#### h4 Heading +##### h5 Heading +###### h6 Heading + + +h1 Heading +=== + +h2 Heading +--- + + +## Horizontal Rules + +___ + +--- + +*** + +## Typographic replacements + +Enable typographer option to see result. + +(c) (C) (r) (R) (tm) (TM) (p) (P) +- + +test.. test... test..... test?..... test!.... + +!!!!!! ???? ,, -- --- + +"Smartypants, double quotes" and 'single quotes' + + +## Emphasis + +**This is bold text** + +__This is bold text__ + +*This is italic text* + +_This is italic text_ + +~~Strikethrough~~ + + +## Blockquotes + + +> Blockquotes can also be nested... +>> ...by using additional greater-than signs right next to each other... +> > > ...or with spaces between arrows. + + +## Lists + +Unordered + ++ Create a list by starting a line with `+`, `-`, or `*` ++ Sub-lists are made by indenting 2 spaces: + - Marker character change forces new list start: + * Ac tristique libero volutpat at + + Facilisis in pretium nisl aliquet + - Nulla volutpat aliquam velit ++ Very easy! + +Ordered + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + + +1. You can use sequential numbers... +1. ...or keep all the numbers as `1.` + +Start numbering with offset: + +57. foo +1. bar + + +## Code + +Inline `code` + +Indented code + + // Some comments + + line 1 of code + line 2 of code + line 3 of code + + +Block code "fences" + +``` +Sample text here... +``` + +Syntax highlighting + +``` js +var foo = function (bar) { + return bar++; +}; + +console.log(foo(5)); +``` + +## Tables + +| Option | Description | +| ------ | ----------- | +| data | path to data files to supply the data that will be passed into templates.hhh | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + +Right aligned columns + +| Option | Description | +| ------:| -----------:| +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + + + +## Links + +[link text](http://dev.nodeca.com) + +[link with title](http://nodeca.github.io/pica/demo/ "title text!") + +Autoconverted link https://github.com/nodeca/pica (enable linkify to see) + + +## Images + +![Minion](https://octodex.github.com/images/minion.png) +![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") + +Like links, Images also have a footnote style syntax + +![Alt text][id] + +With a reference later in the document defining the URL location: + +[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" +