cleand up text editor layout, tweaked editor colors, re-activated editor options

This commit is contained in:
Ro 2021-12-28 14:48:54 -08:00
parent 682406515d
commit 0742e06c45
11 changed files with 212 additions and 152 deletions

View file

@ -32,7 +32,7 @@
{% endblock %} {% endblock %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfdfd"> <link rel="stylesheet" type="text/css" href="/assets/css/dash.css?=dfeef">
{% endblock %} {% endblock %}
{% block mainContent %} {% block mainContent %}
@ -106,7 +106,12 @@
{{ include("dash/partials/editor.twig") }} {{ include("dash/partials/editor.twig") }}
{% endapply %} {% endapply %}
<div id="edit-post-wrapper"> <div id="edit-post-wrapper">
<pre><code spellcheck="false" id="edit-post-text" contenteditable="true" class="language-markdown"> {{- content -}}</code></pre> <textarea id="edit" spellcheck="false">{{- content -}}</textarea>
<pre id="highlight">
<code id="highlight-content" class="language-md">
</code>
</pre>
</div> </div>
</div> </div>
</div> </div>

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "fipamo-dash", "name": "fipamo-dash",
"version": "1.2.4", "version": "2.5.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "fipamo-dash", "name": "fipamo-dash",
"version": "1.2.4", "version": "2.5.0",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@babel/core": "^7.16.5", "@babel/core": "^7.16.5",

View file

@ -7,7 +7,6 @@
"version": "1.0.0", "version": "1.0.0",
"description": "The most chill API for the most chill blog framework" "description": "The most chill API for the most chill blog framework"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-env": "^7.16.5", "@babel/preset-env": "^7.16.5",
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",

View file

@ -1712,7 +1712,6 @@ strong {
font-weight: bolder; font-weight: bolder;
} }
code,
kbd, kbd,
samp { samp {
font-family: monospace, monospace; font-family: monospace, monospace;
@ -3192,33 +3191,44 @@ select {
margin: 0 auto; margin: 0 auto;
} }
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper { #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper {
width: 100%;
max-width: 900px; max-width: 900px;
border-radius: 5px; border-radius: 5px;
margin: 40px 0 40px 0; margin: 10px 0 50px 0;
overflow: hidden; position: relative;
} }
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper pre { #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #edit, #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight {
margin: 0; /* Both elements need the same text and space styling so they are directly on top of each other */
} border: 0;
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper pre code { width: 100%;
font-family: "Lucida Console", Monaco, monospace; height: auto;
padding: 5px; position: absolute;
border-radius: 5px; top: 0;
line-height: 1.6em; left: 0;
font-size: 1.25em; overflow: auto;
color: #fde3a7;
word-wrap: normal; word-wrap: normal;
white-space: pre-wrap; white-space: pre-wrap;
line-break: normal; line-break: normal;
-webkit-line-break: normal; }
-o-line-break: normal; #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight-content {
-moz-line-break: normal; word-wrap: normal;
display: inline-block; white-space: pre-wrap;
width: 100%; line-break: normal;
max-width: 900px; }
min-height: 200px; #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #edit, #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight, #post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #hightlight * {
font-size: 1.2em;
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
line-height: 22pt;
}
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #edit {
z-index: 1;
color: transparent;
background: transparent;
caret-color: #fc6399; caret-color: #fc6399;
} }
#post-edit-index #post-edit-index-wrapper #edit-post #edit-post-wrapper #highlight {
z-index: 0;
}
@media only screen and (max-width: 800px) { @media only screen and (max-width: 800px) {
#post-edit-index #post-edit-index-wrapper #post-header #post-title #post-date { #post-edit-index #post-edit-index-wrapper #post-header #post-title #post-date {
@ -3680,7 +3690,7 @@ select {
code[class*=language-], code[class*=language-],
pre[class*=language-] { pre[class*=language-] {
color: #f8f8f2; color: #fde3a7;
background: none; background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3); text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
@ -3701,8 +3711,7 @@ pre[class*=language-] {
} }
pre[class*=language-] { pre[class*=language-] {
padding: 1em; margin: 0.1em 0;
margin: 0.5em 0;
overflow: auto; overflow: auto;
border-radius: 0.3em; border-radius: 0.3em;
} }
@ -3726,7 +3735,7 @@ pre[class*=language-] {
} }
.token.punctuation { .token.punctuation {
color: #ffa07a; color: #e7903c;
} }
.token.namespace { .token.namespace {
opacity: 0.7; opacity: 0.7;
@ -3741,7 +3750,7 @@ pre[class*=language-] {
cursor: help; cursor: help;
} }
.token.content { .token.content {
color: #89c4f4; color: #6bb9f0;
} }
.token.property, .token.property,
@ -3749,7 +3758,7 @@ pre[class*=language-] {
.token.constant, .token.constant,
.token.symbol, .token.symbol,
.token.deleted { .token.deleted {
color: #f92672; color: #e73c4e;
} }
.token.boolean, .token.boolean,
@ -3772,7 +3781,7 @@ pre[class*=language-] {
.language-css .token.string, .language-css .token.string,
.style .token.string, .style .token.string,
.token.variable { .token.variable {
color: #f8f8f2; color: #dcc6e0;
} }
.token.atrule, .token.atrule,
@ -3784,7 +3793,7 @@ pre[class*=language-] {
.token.regex, .token.regex,
.token.important { .token.important {
color: #fd971f; color: #e7903c;
} }
.token.important, .token.important,

View file

@ -11,9 +11,9 @@ export default class PostActions {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let pageInfo = new FormData(); let pageInfo = new FormData();
let txt = document.createElement("textarea"); let txt = document.createElement("textarea");
txt.innerHTML = document.getElementById("edit-post-text").innerHTML; txt.innerHTML = document.getElementById("highlight-content").innerHTML;
let html = txt.value; let html = txt.value;
html = html.replace(/<\/?span[^>]*>/g, ''); //removes prism styling html = html.replace(/<\/?span[^>]*>/g, ""); //removes prism styling
html = html.replace(/<\/?br[^>]*>/g, "\n"); //convert back to encoded line break for storage html = html.replace(/<\/?br[^>]*>/g, "\n"); //convert back to encoded line break for storage
pageInfo.append( pageInfo.append(
"id", "id",

View file

@ -37,9 +37,9 @@ export default class PostEditor {
.getElementById("post-edit-index") .getElementById("post-edit-index")
.getAttribute("data-layout"); .getAttribute("data-layout");
} }
if (document.getElementById("edit-post-text")) { if (document.getElementById("edit")) {
this.editor = new TextEditor( this.editor = new TextEditor(
document.getElementById("edit-post-text"), document.getElementById("edit"),
document.getElementById("header").offsetHeight + document.getElementById("header").offsetHeight +
document.getElementById("post-header").offsetHeight + document.getElementById("post-header").offsetHeight +
document.getElementById("post-feature").offsetHeight document.getElementById("post-feature").offsetHeight

View file

@ -15,11 +15,30 @@ class TextEditor extends EventEmitter {
//-------------------------- //--------------------------
constructor(textEditor, scrollLimit) { constructor(textEditor, scrollLimit) {
super(); super();
//hljs.initHighlightingOnLoad();
this.textEditor = textEditor; document.getElementById("edit").addEventListener("input", (e) => {
this.fixLimit = scrollLimit; let result_element = document.querySelector("#highlight-content");
this.caretPos = null; this.textEditor = textEditor;
this.url = ""; // Update code
let text = e.target.value;
result_element.innerHTML = text
.replace(new RegExp("&", "g"), "&amp;")
.replace(new RegExp("<", "g"), "&lt;");
let editorHeight = document.getElementById("highlight").offsetHeight;
document.getElementById("edit-post-wrapper").style.height =
editorHeight + "px";
e.target.style.height = editorHeight + "px";
// Syntax Highlight
Prism.highlightElement(result_element);
});
document.getElementById("edit").addEventListener("scroll", (e) => {
/* Scroll result to scroll coords of event - sync with textarea */
let result_element = document.querySelector("#highlight");
// Get and set x and y
result_element.scrollTop = e.scrollTop;
result_element.scrollLeft = e.scrollLeft;
});
document.getElementById("edit").dispatchEvent(new Event("input"));
this.setInputs(); this.setInputs();
window.addEventListener("scroll", () => { window.addEventListener("scroll", () => {
//var fixLimit = this.fixLimit; //var fixLimit = this.fixLimit;
@ -32,7 +51,7 @@ class TextEditor extends EventEmitter {
} }
*/ */
}); });
this.refresh(); //this.refresh();
} }
//-------------------------- //--------------------------
// methods // methods
@ -47,32 +66,6 @@ class TextEditor extends EventEmitter {
false false
); );
} }
this.textEditor.addEventListener("input", (e) => {
let htmlTagRe = /<[a-z][\s\S]*>/g;
let text = this.textEditor.innerText;
if (e.inputType == "insertParagraph") return; //cursor setting gets weird on return, so just back out
if (text.search(htmlTagRe) > -1) {
let caret = position(this.textEditor).pos;
self.refresh();
position(this.textEditor, caret);
}
});
}
refresh() {
var spiffed = Prism.highlight(
this.textEditor.innerText,
Prism.languages.md,
"md"
);
//var spiffed = this.textEditor.innerText;
spiffed = spiffed.replace(new RegExp("\r?\n", "g"), "<br>");
var temp = document.createElement("div");
temp.innerText = spiffed;
this.textEditor.innerHTML = temp.innerText;
this.textEditor.style.maxWidth = "900px";
} }
notify(type, data) { notify(type, data) {
switch (type) { switch (type) {
@ -96,22 +89,16 @@ class TextEditor extends EventEmitter {
// do nothing // do nothing
break; break;
case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: case EditorEvent.EDITOR_UPLOAD_POST_IMAGE:
position(this.textEditor, this.caretPos); let len = this.textEditor.value.length;
var sel, range; let start = this.textEditor.selectionStart;
//var pulled; let end = this.textEditor.selectionEnd;
sel = window.getSelection(); //console.log(sel) let insert = "![image alt text](" + data + " 'image title')";
//console.log(note.message)
if (sel.rangeCount) { this.textEditor.value =
range = sel.getRangeAt(0); this.textEditor.value.substring(0, start) +
//pulled = sel.getRangeAt(0).toString(); insert +
range.deleteContents(); this.textEditor.value.substring(end, len);
range.insertNode( document.getElementById("edit").dispatchEvent(new Event("input"));
document.createTextNode(
"![image alt text](" + data + " 'image title')"
)
);
}
this.refresh();
break; break;
} }
} }
@ -120,59 +107,86 @@ class TextEditor extends EventEmitter {
//-------------------------- //--------------------------
handleEditorOption(e) { handleEditorOption(e) {
e.preventDefault(); e.preventDefault();
var sel, range, pulled; let len = this.textEditor.value.length;
sel = window.getSelection(); //console.log(sel) let start = this.textEditor.selectionStart;
if (sel.rangeCount) { let end = this.textEditor.selectionEnd;
range = sel.getRangeAt(0);
pulled = sel.getRangeAt(0).toString(); let selectedText = this.textEditor.value.substring(start, end);
range.deleteContents(); let insert = "";
switch (e.target.id) { switch (e.target.id) {
case "edit-bold": case "edit-bold":
range.insertNode(document.createTextNode("**" + pulled + "**")); insert = "**" + selectedText + "**";
break; this.textEditor.value =
case "edit-italic": this.textEditor.value.substring(0, start) +
range.insertNode(document.createTextNode("*" + pulled + "*")); insert +
break; this.textEditor.value.substring(end, len);
case "edit-strikethrough":
range.insertNode( break;
document.createTextNode("<del>" + pulled + "</del>") case "edit-italic":
); insert = "*" + selectedText + "*";
break; //console.log(this.textEditor);
case "edit-header1": this.textEditor.value =
range.insertNode(document.createTextNode("# " + pulled + "\n")); this.textEditor.value.substring(0, start) +
break; insert +
case "edit-header2": this.textEditor.value.substring(end, len);
range.insertNode(document.createTextNode("## " + pulled + "\n")); break;
break; case "edit-strikethrough":
case "edit-header3": insert = "~~" + selectedText + "~~";
range.insertNode(document.createTextNode("### " + pulled + "\n")); this.textEditor.value =
break; this.textEditor.value.substring(0, start) +
case "edit-image": insert +
this.caretPos = position(this.textEditor).pos; this.textEditor.value.substring(end, len);
this.emitEvent(EditorEvent.EDITOR_UPLOAD_POST_IMAGE); break;
break; case "edit-header1":
case "submit-save": insert = "# " + selectedText + "\n";
case "edit-save": this.textEditor.value =
this.emitEvent(EditorEvent.EDITOR_SAVE); this.textEditor.value.substring(0, start) +
break; insert +
case "submit-update": this.textEditor.value.substring(end, len);
case "edit-update": break;
this.emitEvent(EditorEvent.EDITOR_UPDATE); case "edit-header2":
break; insert = "## " + selectedText + "\n";
case "edit-link": this.textEditor.value =
range.insertNode( this.textEditor.value.substring(0, start) +
document.createTextNode("[" + pulled + "](PASTE URL HERE)") insert +
); this.textEditor.value.substring(end, len);
break; break;
case "edit-delete": case "edit-header3":
this.emitEvent(EditorEvent.EDITOR_DELETE); insert = "### " + selectedText + "\n";
break; this.textEditor.value =
default: this.textEditor.value.substring(0, start) +
//range.insertNode(document.createTextNode("[" + self.url + "](PASTE URL HERE)")); insert +
break; this.textEditor.value.substring(end, len);
} break;
case "edit-link":
let url = prompt("Let's get that url, boss");
let link = url.toLowerCase();
insert = "[" + selectedText + "](" + link + ")";
this.textEditor.value =
this.textEditor.value.substring(0, start) +
insert +
this.textEditor.value.substring(end, len);
break;
case "edit-image":
this.caretPos = position(this.textEditor).pos;
this.emitEvent(EditorEvent.EDITOR_UPLOAD_POST_IMAGE);
break;
case "submit-save":
case "edit-save":
this.emitEvent(EditorEvent.EDITOR_SAVE);
break;
case "submit-update":
case "edit-update":
this.emitEvent(EditorEvent.EDITOR_UPDATE);
break;
case "edit-delete":
this.emitEvent(EditorEvent.EDITOR_DELETE);
break;
default:
//do stuff
break;
} }
this.refresh(); document.getElementById("edit").dispatchEvent(new Event("input"));
} }
} }
export default TextEditor; export default TextEditor;

View file

@ -12,6 +12,7 @@ $eventCool: #32cd32
$eventLame: #F64747 $eventLame: #F64747
$editorPrimary: #fde3a7 $editorPrimary: #fde3a7
$editorSecondary: #ffa07a $editorSecondary: #e7903c
$editorTertiary: #89c4f4 $editorTertiary: #6bb9f0
$editorString: #f6dd74 $editorString: #dcc6e0
$editorTag: #e73c4e

View file

@ -1,6 +1,6 @@
code[class*="language-"], code[class*="language-"],
pre[class*="language-"] pre[class*="language-"]
color: #f8f8f2 color: $editorPrimary
background: none background: none
text-shadow: 0 1px rgba(0, 0, 0, 0.3) text-shadow: 0 1px rgba(0, 0, 0, 0.3)
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace
@ -19,8 +19,8 @@ pre[class*="language-"]
-ms-hyphens: none -ms-hyphens: none
hyphens: none hyphens: none
pre[class*="language-"] pre[class*="language-"]
padding: 1em //padding: 1em
margin: .5em 0 margin: .1em 0
overflow: auto overflow: auto
border-radius: 0.3em border-radius: 0.3em
:not(pre) > code[class*="language-"], :not(pre) > code[class*="language-"],
@ -54,7 +54,7 @@ pre[class*="language-"]
.token.constant, .token.constant,
.token.symbol, .token.symbol,
.token.deleted .token.deleted
color: #f92672 color: $editorTag
.token.boolean, .token.boolean,
.token.number .token.number
color: #ae81ff color: #ae81ff
@ -71,7 +71,7 @@ pre[class*="language-"]
.language-css .token.string, .language-css .token.string,
.style .token.string, .style .token.string,
.token.variable .token.variable
color: #f8f8f2 color: $editorString
.token.atrule, .token.atrule,
.token.attr-value, .token.attr-value,
.token.function, .token.function,
@ -79,7 +79,7 @@ pre[class*="language-"]
color: #e6db74 color: #e6db74
.token.regex, .token.regex,
.token.important .token.important
color: #fd971f color: $editorSecondary
.token.important, .token.important,
.token.bold .token.bold
font-weight: bold font-weight: bold

View file

@ -53,7 +53,7 @@ strong
font-weight: inherit font-weight: inherit
font-weight: bolder font-weight: bolder
code, //code,
kbd, kbd,
samp samp
font-family: monospace, monospace font-family: monospace, monospace

View file

@ -159,7 +159,6 @@
#post-edit-index-wrapper #post-edit-index-wrapper
width: 100% width: 100%
#post-header #post-header
// width 100% // width 100%
@ -301,14 +300,47 @@
margin: 0 auto margin: 0 auto
#edit-post-wrapper #edit-post-wrapper
//width 98.7% width: 100%
max-width: 900px max-width: 900px
border-radius: 5px border-radius: 5px
//background $primary - 10% //background $primary - 10%
margin: 40px 0 40px 0 margin: 10px 0 50px 0
overflow: hidden position: relative
pre #edit, #highlight
/* Both elements need the same text and space styling so they are directly on top of each other */
//margin: 10px
//padding: 10px
border: 0
width: 100%
height: auto
position: absolute
top: 0
left: 0
overflow: auto
word-wrap: normal
white-space: pre-wrap
line-break: normal
#highlight-content
word-wrap: normal
white-space: pre-wrap
line-break: normal
#edit, #highlight, #hightlight *
font-size: 1.2em
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace
line-height: 22pt
#edit
z-index: 1
color: transparent
background: transparent
caret-color: $highlight
#highlight
z-index: 0
//pre
margin: 0 margin: 0
code code
font-family: $monoType font-family: $monoType