diff --git a/dist/api/blog/blogData.php b/dist/api/blog/blogData.php
index 95dd912..a8f8c6f 100644
--- a/dist/api/blog/blogData.php
+++ b/dist/api/blog/blogData.php
@@ -444,22 +444,87 @@ class blogData
if ($result)
{
- $bodyText = array_column($result, "bodyText");
- // go through each body plain text and get the sentence before, the sentence with the search term and the sentence after and append it to a new array
- foreach ($bodyText as $key => $text)
+ for ($i = 0; $i < count($result); $i++)
{
- $text = strtolower($text);
- $searchTerm = strtolower($searchTerm);
- $pos = strpos($text, $searchTerm);
- $start = strrpos(substr($text, 0, $pos), ".") + 1;
- $end = strpos($text, ".", $pos);
- $result[$key]["bodyText"] = substr($text, $start, $end - $start);
+ $result[$i]["abstract"] = $this->getShortPost($searchTerm, stripcslashes($result[$i]["bodyText"]));
}
-
return $result;
}
return array("errorMessage" => "Error, could not find posts");
}
+
+ /**
+ * Get the short post with the search term
+ * @param string $searchTerm - Search term
+ * @param $text - Body of the post as plain text
+ * @return string - Short post with the search term
+ */
+ private function getShortPost(string $searchTerm, $text): string
+ {
+ $pattern = '/([,:;!?.-]+)/u';
+ $parts = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+
+ $cleanedParts = [];
+
+ foreach ($parts as $part)
+ {
+ $part = trim($part); // Remove leading/trailing spaces and newline characters
+ if (!empty($part))
+ {
+ $cleanedParts[] = $part;
+ }
+ }
+
+ $combinedParts = [];
+ $currentPart = '';
+
+ foreach ($cleanedParts as $part)
+ {
+ if (preg_match('/[,:;!?.-]/u', $part))
+ {
+ $currentPart .= $part;
+ }
+ else
+ {
+ if (!empty($currentPart))
+ {
+ $combinedParts[] = trim($currentPart);
+ }
+ $currentPart = rtrim($part);
+ }
+ }
+
+ if (!empty($currentPart))
+ {
+ $combinedParts[] = trim($currentPart);
+ }
+
+ $result = "";
+
+
+ for ($i = 0; $i < count($combinedParts); $i++)
+ {
+ $part = $combinedParts[$i];
+
+ if (stripos($part, $searchTerm) !== false)
+ {
+ $before = ($i > 0) ? $combinedParts[$i - 1] : "";
+ $after = ($i < count($combinedParts) - 1) ? $combinedParts[$i + 1] : "";
+
+ if ($before === "" && $i > 0)
+ {
+ $before = $combinedParts[$i - 1];
+ }
+
+ $result = $before . " " . $part . " " . $after;
+
+ // If the search term is found, we don't need to continue checking subsequent parts
+ break;
+ }
+ }
+
+ return $result;
+ }
}
\ No newline at end of file
diff --git a/dist/api/blog/blogRoutes.php b/dist/api/blog/blogRoutes.php
index 7a7933a..d3c4201 100644
--- a/dist/api/blog/blogRoutes.php
+++ b/dist/api/blog/blogRoutes.php
@@ -254,7 +254,7 @@ class blogRoutes implements routesInterface
}
$featured = $data["featured"] === "true";
- $insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
+ $insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
if (!is_int($insertedID))
{
// uh oh something went wrong
diff --git a/dist/blog/index.html b/dist/blog/index.html
index e67e83f..471db0e 100644
--- a/dist/blog/index.html
+++ b/dist/blog/index.html
@@ -1 +1 @@
-
Rohit Pai - Blog
\ No newline at end of file
+Rohit Pai - Blog
\ No newline at end of file
diff --git a/dist/blog/js/index.js b/dist/blog/js/index.js
index be84bfc..dc5f439 100644
--- a/dist/blog/js/index.js
+++ b/dist/blog/js/index.js
@@ -1 +1 @@
-const scrollLimit=150;function goToURL(e){let t=e.split("/");if("/blog/"!==e&&"/blog"!==e){if("post"!==t[2])return"category"===t[2]?t[3]?void loadPostsByCategory(t[t.length-1]):void loadAllCategories():void show404();loadIndividualPost(t[t.length-1]).catch((e=>console.log(e)))}else loadHomeContent()}function createLargePost(e){let t=document.createElement("div");t.classList.add("outerContent");let n=document.createElement("img");n.className="banner",n.src=e.headerImg,n.alt=e.title,t.appendChild(n);let a=document.createElement("div");a.classList.add("content");let o=document.createElement("div");o.classList.add("postContent");let s="";return e.categories.split(", ").forEach((t=>{s+=`${t} `,e.categories.split(", ").length>1&&(s+=", ")})),s.endsWith(", ")&&(s=s.substring(0,s.length-2)),o.innerHTML=`\n ${e.title} \n Last updated: ${e.dateModified} | ${s} \n ${e.abstract}
\n See Post \n `,a.appendChild(o),t.appendChild(a),t}function loadHomeContent(){let e=document.createElement("div");e.classList.add("menuBar"),e.innerHTML='\n \n\t',document.querySelector("#main").appendChild(e),fetch("/api/blog/post").then((e=>e.json().then((e=>{for(let t=0;te.json())),await fetch("/api/blog/post/featured").then((e=>e.json()))]}function csvToArray(e){let t="",n=[""],a=0,o=!0,s=null;for(s of e)'"'===s?(o&&s===t&&(n[a]+=s),o=!o):","===s&&o?s=n[++a]="":"\n"===s&&o?("\r"===t&&(row[a]=row[a].slice(0,-1)),n=n[++r]=[s=""],a=0):n[a]+=s,t=s;return n}async function getCategories(){let e=await fetch("/api/blog/categories").then((e=>e.json())),t=[];return e.forEach((e=>t=t.concat(csvToArray(e.categories.replace(/\s*,\s*/g,","))))),[...new Set(t)]}function createCategories(e){let t="";return e.forEach((e=>t+=`${e} `)),t}function createButtonCategories(e){let t="";return e.forEach((e=>e.forEach((e=>t+=`${e} `)))),t}async function createSideContent(){let e=await getLatestAndFeaturedPosts(),t=e[0],n=e[1],a=createCategories(await getCategories()),o=document.createElement("aside");return o.classList.add("sideContent"),o.innerHTML=`\n \n \n
latest post \n
${t.title} \n
${t.abstract}
\n
See Post \n
\n \n
featured post \n
${n.title} \n
${n.abstract}
\n
See Post \n
\n \n
categories \n ${a}\n \n `,o}async function loadIndividualPost(e){document.title="Rohit Pai - "+decodeURI(e),await fetch(`/api/blog/post/${e}`).then((async e=>{e.ok?await e.json().then((async e=>{let t=document.createElement("section");t.classList.add("post"),t.id="individualPost";let n=document.createElement("div");n.classList.add("mainContent");let a=document.createElement("article");a.innerHTML=`\n ${e.title} \n \n
Last updated: ${e.dateModified} \n ${createButtonCategories([csvToArray(e.categories.replace(/\s*,\s*/g,","))])} \n \n
\n ${e.body}\n `;let o=document.createElement("section");o.classList.add("comments"),o.innerHTML='Comments \n \n ',n.appendChild(a),n.appendChild(o);let s=await createSideContent();t.appendChild(n),t.appendChild(s),document.querySelector("#main").appendChild(t);var c,i;c=document,(i=c.createElement("script")).src="https://rohitpaiportfolio.disqus.com/embed.js",i.setAttribute("data-timestamp",+new Date),c.body.appendChild(i)})):show404()}))}async function loadAllCategories(){document.title="Rohit Pai - Categories";let e=await getCategories(),t=document.querySelector("#main"),n=document.createElement("section");n.classList.add("categories"),n.id="allCategories";let a=document.createElement("h1");a.innerHTML="Categories",t.appendChild(a);for(let t of e){let e=document.createElement("div");e.classList.add("btnContainer");let a=document.createElement("a");a.classList.add("btn"),a.classList.add("btnPrimary"),a.innerHTML=t,a.href=`/blog/category/${t}`,e.appendChild(a),n.appendChild(e)}t.appendChild(n)}function loadPostsByCategory(e){document.title="Rohit Pai - "+decodeURI(e),fetch(`/api/blog/categories/${e}`).then((t=>t.json().then((t=>{let n=document.querySelector("#main"),a=document.createElement("section");a.classList.add("catPosts"),a.id="postsByCategory";let o=document.createElement("h1");o.innerHTML=decodeURI(e),n.appendChild(o);for(let e=0;e\n \n \n '}document.addEventListener("DOMContentLoaded",(()=>{goToURL(window.location.pathname)})),window.addEventListener("popstate",(e=>{goToURL(window.history.state)})),window.onscroll=()=>{document.body.scrollTop>=150||document.documentElement.scrollTop>=150?document.querySelector("nav").classList.add("scrolled"):document.querySelector("nav").classList.remove("scrolled")};
\ No newline at end of file
+const scrollLimit=150;function goToURL(e){let t=e.split("/");if("/blog/"!==e&&"/blog"!==e){if("post"!==t[2])return"category"===t[2]?t[3]?void loadPostsByCategory(t[t.length-1]):void loadAllCategories().catch((e=>console.log(e))):void("search"===t[2]&&t[3]?loadSearchResults(t[t.length-1]):show404());loadIndividualPost(t[t.length-1]).catch((e=>console.log(e)))}else loadHomeContent()}function createLargePost(e){let t=document.createElement("div");t.classList.add("outerContent");let n=document.createElement("img");n.className="banner",n.src=e.headerImg,n.alt=e.title,t.appendChild(n);let a=document.createElement("div");a.classList.add("content");let o=document.createElement("div");o.classList.add("postContent");let s="";return e.categories.split(", ").forEach((t=>{s+=`${t} `,e.categories.split(", ").length>1&&(s+=", ")})),s.endsWith(", ")&&(s=s.substring(0,s.length-2)),o.innerHTML=`\n ${e.title} \n Last updated: ${e.dateModified} | ${s} \n ${e.abstract}
\n See Post \n `,a.appendChild(o),t.appendChild(a),t}function loadHomeContent(){fetch("/api/blog/post").then((e=>e.json().then((e=>{for(let t=0;te.json())),await fetch("/api/blog/post/featured").then((e=>e.json()))]}function csvToArray(e){let t="",n=[""],a=0,o=!0,s=null;for(s of e)'"'===s?(o&&s===t&&(n[a]+=s),o=!o):","===s&&o?s=n[++a]="":"\n"===s&&o?("\r"===t&&(row[a]=row[a].slice(0,-1)),n=n[++r]=[s=""],a=0):n[a]+=s,t=s;return n}async function getCategories(){let e=await fetch("/api/blog/categories").then((e=>e.json())),t=[];return e.forEach((e=>t=t.concat(csvToArray(e.categories.replace(/\s*,\s*/g,","))))),[...new Set(t)]}function createCategories(e){let t="";return e.forEach((e=>t+=`${e} `)),t}function createButtonCategories(e){let t="";return e.forEach((e=>e.forEach((e=>t+=`${e} `)))),t}async function createSideContent(){let e=await getLatestAndFeaturedPosts(),t=e[0],n=e[1],a=createCategories(await getCategories()),o=document.createElement("aside");return o.classList.add("sideContent"),o.innerHTML=`\n \n \n
latest post \n
${t.title} \n
${t.abstract}
\n
See Post \n
\n \n
featured post \n
${n.title} \n
${n.abstract}
\n
See Post \n
\n \n
categories \n ${a}\n \n `,o}async function loadIndividualPost(e){document.title="Rohit Pai - "+decodeURI(e),await fetch(`/api/blog/post/${e}`).then((async e=>{e.ok?await e.json().then((async e=>{let t=document.createElement("section");t.classList.add("post"),t.id="individualPost";let n=document.createElement("div");n.classList.add("mainContent");let a=document.createElement("article");a.innerHTML=`\n ${e.title} \n \n
Last updated: ${e.dateModified} \n ${createButtonCategories([csvToArray(e.categories.replace(/\s*,\s*/g,","))])} \n \n
\n ${e.body}\n `;let o=document.createElement("section");o.classList.add("comments"),o.innerHTML='Comments \n \n ',n.appendChild(a),n.appendChild(o);let s=await createSideContent();t.appendChild(n),t.appendChild(s),document.querySelector("#main").appendChild(t);var c,l;c=document,(l=c.createElement("script")).src="https://rohitpaiportfolio.disqus.com/embed.js",l.setAttribute("data-timestamp",+new Date),c.body.appendChild(l)})):show404()}))}async function loadAllCategories(){document.title="Rohit Pai - Categories";let e=await getCategories(),t=document.querySelector("#main"),n=document.createElement("section");n.classList.add("categories"),n.id="allCategories";let a=document.createElement("h1");a.innerHTML="Categories",t.appendChild(a);for(let t of e){let e=document.createElement("div");e.classList.add("btnContainer");let a=document.createElement("a");a.classList.add("btn"),a.classList.add("btnPrimary"),a.innerHTML=t,a.href=`/blog/category/${t}`,e.appendChild(a),n.appendChild(e)}t.appendChild(n)}function loadPostsByCategory(e){document.title="Rohit Pai - "+decodeURI(e),fetch(`/api/blog/categories/${e}`).then((t=>t.json().then((t=>{let n=document.querySelector("#main"),a=document.createElement("section");a.classList.add("catPosts"),a.id="postsByCategory";let o=document.createElement("h1");o.innerHTML=decodeURI(e),n.appendChild(o);for(let e=0;ee.json().then((e=>{let t=document.querySelector("#main"),n=document.createElement("section");n.classList.add("catPosts"),n.id="searchResults";let a=document.createElement("h1");a.innerHTML="Search Results",t.appendChild(a);for(let t=0;t\n \n \n '}document.addEventListener("DOMContentLoaded",(()=>{goToURL(window.location.pathname)})),window.addEventListener("popstate",(e=>{goToURL(window.history.state)})),window.onscroll=()=>{document.body.scrollTop>=150||document.documentElement.scrollTop>=150?document.querySelector("nav").classList.add("scrolled"):document.querySelector("nav").classList.remove("scrolled")},document.querySelector("#searchBtn").addEventListener("click",(e=>{let t=document.querySelector("#searchField").value;t.length>0&&(window.history.pushState(null,null,`/blog/search/${t}`),document.querySelector("#searchField").value="",document.querySelector("#main").innerHTML="",goToURL(`/blog/search/${t}`))})),document.querySelector("#searchField").addEventListener("keyup",(e=>{"Enter"===e.key&&document.querySelector("#searchBtn").click()}));
\ No newline at end of file
diff --git a/dist/editor/editor.html b/dist/editor/editor.html
index 4b91781..89aea41 100644
--- a/dist/editor/editor.html
+++ b/dist/editor/editor.html
@@ -1 +1 @@
-Editor × ☰
Editor
\ No newline at end of file
+Editor × ☰
Editor
\ No newline at end of file
diff --git a/dist/editor/js/editor.js b/dist/editor/js/editor.js
index 912e97d..a88e6e3 100644
--- a/dist/editor/js/editor.js
+++ b/dist/editor/js/editor.js
@@ -1 +1 @@
-let dateOptions={month:"short",year:"numeric"},textareaLoaded=!1,editors={},posts=null;const smallPaddingElements=["figcaption","li"];function goToPage(e){document.querySelectorAll(".editor section").forEach((t=>{t.style.display="none",t.id===e&&(t.style.display="flex")}))}function viewToPlainText(e){let t="";if(e.is("$text")||e.is("$textProxy"))t=e.data;else if(e.is("element","img")&&e.hasAttribute("alt"))t=e.getAttribute("alt");else if(e.is("element","br"))t="\n";else{let a=null;for(const l of e.getChildren()){const e=viewToPlainText(l);a&&(a.is("containerElement")||l.is("containerElement"))&&(smallPaddingElements.includes(a.name)||smallPaddingElements.includes(l.name)?t+="\n":t+="\n\n"),t+=e,a=l}}return t}function addActiveClass(e){document.querySelectorAll("nav.sideNav ul li a").forEach((t=>{t.classList.remove("active"),t.id===e&&t.classList.add("active")}))}function editProjectItem(e){document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}proj`).toggleAttribute("disabled"),document.querySelector(`#info${e}proj`).toggleAttribute("disabled")}function createEditors(...e){e.forEach((e=>{ClassicEditor.create(document.querySelector(`#${e}`),{placeholder:"Write something amazing...",simpleUpload:{uploadUrl:"/api/blog/uploadPostImage",headers:{Authorization:"Bearer "+localStorage.getItem("token")}},style:{definitions:[{name:"Button Primary",element:"a",classes:["btn","btnPrimary"]},{name:"Button Primary",element:"button",classes:["btn","btnPrimary"]}]},codeBlock:{languages:[{language:"plaintext",label:"Plain text"},{language:"abap",label:"ABAP"},{language:"abnf",label:"ABNF"},{language:"actionscript",label:"ActionScript"},{language:"ada",label:"Ada"},{language:"agda",label:"Agda"},{language:"al",label:"AL"},{language:"antlr4",label:"ANTLR4"},{language:"apacheconf",label:"Apache Configuration"},{language:"apex",label:"Apex"},{language:"apl",label:"APL"},{language:"applescript",label:"AppleScript"},{language:"aql",label:"AQL"},{language:"arduino",label:"Arduino"},{language:"arff",label:"ARFF"},{language:"asciidoc",label:"AsciiDoc"},{language:"aspnet",label:"ASP.NET (C#)"},{language:"asm6502",label:"6502 Assembly"},{language:"autohotkey",label:"AutoHotkey"},{language:"autoit",label:"AutoIt"},{language:"bash",label:"Bash"},{language:"basic",label:"BASIC"},{language:"batch",label:"Batch"},{language:"bbcode",label:"BBcode"},{language:"bison",label:"Bison"},{language:"bnf",label:"BNF"},{language:"brainfuck",label:"Brainfuck"},{language:"brightscript",label:"BrightScript"},{language:"bro",label:"Bro"},{language:"c",label:"C"},{language:"concurnas",label:"Concurnas"},{language:"csharp",label:"C#"},{language:"cpp",label:"C++"},{language:"cil",label:"CIL"},{language:"clojure",label:"Clojure"},{language:"cmake",label:"CMake"},{language:"coffeescript",label:"CoffeeScript"},{language:"concurnas",label:"Concurnas"},{language:"crystal",label:"Crystal"},{language:"css-extras",label:"CSS Extras"},{language:"css",label:"CSS"},{language:"d",label:"D"},{language:"dart",label:"Dart"},{language:"dax",label:"DAX"},{language:"dhall",label:"Dhall"},{language:"diff",label:"Diff"},{language:"django",label:"Django/Jinja2"},{language:"dns-zone-file",label:"DNS zone file"},{language:"docker",label:"Docker"},{language:"ebnf",label:"EBNF"},{language:"editorconfig",label:"EditorConfig"},{language:"eiffel",label:"Eiffel"},{language:"ejs",label:"EJS"},{language:"elixir",label:"Elixir"},{language:"elm",label:"Elm"},{language:"etlua",label:"Embedded Lua"},{language:"erb",label:"ERB"},{language:"erlang",label:"Erlang"},{language:"excel-formula",label:"Excel Formula"},{language:"fsharp",label:"F#"},{language:"factor",label:"Factor"},{language:"firestore-security-rules",label:"Firestore security rules"},{language:"flow",label:"Flow"},{language:"fortran",label:"Fortran"},{language:"ftl",label:"FreeMarker Template Language"},{language:"gcode",label:"G-code"},{language:"gdscript",label:"GDScript"},{language:"gedcom",label:"GEDCOM"},{language:"gherkin",label:"Gherkin"},{language:"git",label:"Git"},{language:"glsl",label:"GLSL"},{language:"gml",label:"GameMaker Language"},{language:"go",label:"Go"},{language:"graphql",label:"GraphQL"},{language:"groovy",label:"Groovy"},{language:"haml",label:"Haml"},{language:"handlebars",label:"Handlebars"},{language:"haskell",label:"Haskell"},{language:"haxe",label:"Haxe"},{language:"hcl",label:"HCL"},{language:"hlsl",label:"HLSL"},{language:"http",label:"HTTP"},{language:"hpkp",label:"HTTP Public-Key-Pins"},{language:"hsts",label:"HTTP Strict-Transport-Security"},{language:"ichigojam",label:"IchigoJam"},{language:"icon",label:"Icon"},{language:"ignore",label:"Ignore"},{language:"inform7",label:"Inform 7"},{language:"ini",label:"Ini"},{language:"io",label:"Io"},{language:"j",label:"J"},{language:"java",label:"Java"},{language:"javadoc",label:"JavaDoc"},{language:"javadoclike",label:"JavaDoc-like"},{language:"javascript",label:"JavaScript"},{language:"javastacktrace",label:"Java stack trace"},{language:"jolie",label:"Jolie"},{language:"jq",label:"JQ"},{language:"js-extras",label:"JS Extras"},{language:"js-templates",label:"JS Templates"},{language:"jsdoc",label:"JSDoc"},{language:"json",label:"JSON"},{language:"json5",label:"JSON5"},{language:"jsonp",label:"JSONP"},{language:"jsstacktrace",label:"JS stack trace"},{language:"jsx",label:"React JSX"},{language:"julia",label:"Julia"},{language:"keyman",label:"Keyman"},{language:"kotlin",label:"Kotlin"},{language:"latex",label:"LaTeX"},{language:"latte",label:"Latte"},{language:"less",label:"Less"},{language:"lilypond",label:"LilyPond"},{language:"liquid",label:"Liquid"},{language:"lisp",label:"Lisp"},{language:"livescript",label:"LiveScript"},{language:"llvm",label:"LLVM IR"},{language:"log",label:"Log file"},{language:"lolcode",label:"LOLCODE"},{language:"lua",label:"Lua"},{language:"makefile",label:"Makefile"},{language:"markdown",label:"Markdown"},{language:"markup-templating",label:"Markup templating"},{language:"matlab",label:"MATLAB"},{language:"mel",label:"MEL"},{language:"mizar",label:"Mizar"},{language:"mongodb",label:"MongoDB"},{language:"monkey",label:"Monkey"},{language:"moonscript",label:"MoonScript"},{language:"n1ql",label:"N1QL"},{language:"n4js",label:"N4JS"},{language:"nand2tetris-hdl",label:"Nand To Tetris HDL"},{language:"nasm",label:"NASM"},{language:"neon",label:"NEON"},{language:"nginx",label:"nginx"},{language:"nim",label:"Nim"},{language:"nix",label:"Nix"},{language:"nsis",label:"NSIS"},{language:"objectivec",label:"Objective-C"},{language:"ocaml",label:"OCaml"},{language:"opencl",label:"OpenCL"},{language:"oz",label:"Oz"},{language:"parigp",label:"PARI/GP"},{language:"parser",label:"Parser"},{language:"pascal",label:"Pascal"},{language:"pascaligo",label:"Pascaligo"},{language:"pcaxis",label:"PC-Axis"},{language:"peoplecode",label:"PeopleCode"},{language:"perl",label:"Perl"},{language:"php",label:"PHP"},{language:"phpdoc",label:"PHPDoc"},{language:"php-extras",label:"PHP Extras"},{language:"plsql",label:"PL/SQL"},{language:"powerquery",label:"PowerQuery"},{language:"powershell",label:"PowerShell"},{language:"processing",label:"Processing"},{language:"prolog",label:"Prolog"},{language:"properties",label:".properties"},{language:"protobuf",label:"Protocol Buffers"},{language:"pug",label:"Pug"},{language:"puppet",label:"Puppet"},{language:"pure",label:"Pure"},{language:"purebasic",label:"PureBasic"},{language:"python",label:"Python"},{language:"q",label:"Q (kdb+ database)"},{language:"qml",label:"QML"},{language:"qore",label:"Qore"},{language:"r",label:"R"},{language:"racket",label:"Racket"},{language:"jsx",label:"React JSX"},{language:"tsx",label:"React TSX"},{language:"reason",label:"Reason"},{language:"regex",label:"Regex"},{language:"renpy",label:"Ren'py"},{language:"rest",label:"reST (reStructuredText)"},{language:"rip",label:"Rip"},{language:"roboconf",label:"Roboconf"},{language:"robotframework",label:"Robot Framework"},{language:"ruby",label:"Ruby"},{language:"rust",label:"Rust"},{language:"sas",label:"SAS"},{language:"sass",label:"Sass (Sass)"},{language:"scss",label:"Sass (Scss)"},{language:"scala",label:"Scala"},{language:"scheme",label:"Scheme"},{language:"shell-session",label:"Shell session"},{language:"smali",label:"Smali"},{language:"smalltalk",label:"Smalltalk"},{language:"smarty",label:"Smarty"},{language:"solidity",label:"Solidity (Ethereum)"},{language:"solution-file",label:"Solution file"},{language:"soy",label:"Soy (Closure Template)"},{language:"sparql",label:"SPARQL"},{language:"splunk-spl",label:"Splunk SPL"},{language:"sqf",label:"SQF: Status Quo Function (Arma 3)"},{language:"sql",label:"SQL"},{language:"stan",label:"Stan"},{language:"stata",label:"Stata"},{language:"step21",label:"STEP Part 21"},{language:"stylus",label:"Stylus"},{language:"swift",label:"Swift"},{language:"tap",label:"TAP"},{language:"tcl",label:"Tcl"},{language:"textile",label:"Textile"},{language:"toml",label:"TOML"},{language:"tt2",label:"Template Toolkit 2"},{language:"turtle",label:"Turtle"},{language:"twig",label:"Twig"},{language:"typescript",label:"TypeScript"},{language:"t4-cs",label:"T4 Text Templates (C#)"},{language:"t4-vb",label:"T4 Text Templates (VB)"},{language:"t4-templating",label:"T4 templating"},{language:"unrealscript",label:"UnrealScript"},{language:"vala",label:"Vala"},{language:"vbnet",label:"VB.Net"},{language:"velocity",label:"Velocity"},{language:"verilog",label:"Verilog"},{language:"vhdl",label:"VHDL"},{language:"vim",label:"vim"},{language:"visual-basic",label:"Visual Basic"},{language:"warpscript",label:"WarpScript"},{language:"wasm",label:"WebAssembly"},{language:"wiki",label:"Wiki markup"},{language:"xeora",label:"Xeora"},{language:"xojo",label:"Xojo (REALbasic)"},{language:"xquery",label:"XQuery"},{language:"yaml",label:"YAML"},{language:"zephir",label:"Zephir"}]}}).then((t=>{editors[e]=t})).catch((e=>{console.error("Oops, something went wrong!"),console.error("Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:"),console.warn("Build id: 1eo8ioyje2om-vgar4aghypdm"),console.error(e)}))}))}function editPostItem(e){posts.forEach((t=>{t.ID===e&&(document.querySelector("#editPostTitle").value=t.title,document.querySelector("#editIsFeatured").checked=1===t.featured,document.querySelector("#editPostCategories").value=t.categories,document.querySelector("#editPostAbstract").value=t.abstract,editors.CKEditorEditPost.setData(t.body),document.querySelector("#editPostForm input[type='submit']").id=e)}))}function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function showSuccessMessage(e,t){document.querySelector(`#${t}Success`).classList.remove("hidden"),document.querySelector(`#${t}Success div`).innerText=e}function editCVItem(e){if(textareaLoaded=!1,document.querySelector(`#timelineItem${e}`).classList.toggle("editing"),e.includes("e"))return document.querySelector(`#grade${e}`).toggleAttribute("disabled"),void document.querySelector(`#course${e}`).toggleAttribute("disabled");document.querySelector(`#companyName${e}`).toggleAttribute("disabled"),document.querySelector(`#area${e}`).toggleAttribute("disabled"),document.querySelector(`#jobTitle${e}`).toggleAttribute("disabled")}function addEduData(e,t,a,l,o,n=!1){let r=e+"e",i=document.createElement("form");i.id="timelineItem"+r,i.classList.add("timelineItem"),i.onsubmit=t=>updateEduItem(e,t),i.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n Grade: \n \n
\n \n ${o} \n
\n \n \n \n `,n?document.querySelector("#edu").prepend(i):document.getElementById("edu").appendChild(i)}function addWorkData(e,t,a,l,o,n,r=!1){let i=e+"w",d=document.createElement("form");d.id="timelineItem"+i,d.classList.add("timelineItem"),d.onsubmit=t=>updateWorkItem(e,t),d.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n -\n \n
\n \n ${n} \n
\n \n \n \n\t`,r?document.querySelector("#work").prepend(d):document.getElementById("work").appendChild(d)}function updateEduItem(e,t){t.preventDefault();let a={};a.dateFrom=document.querySelector(`#dateFrom${e}e`).value,a.dateTo=document.querySelector(`#dateTo${e}e`).value,a.grade=document.querySelector(`#grade${e}e`).value,a.course=document.querySelector(`#course${e}e`).value,fetch("/api/timelineData/edu/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}e`).innerHTML=new Date(document.querySelector(`#dateFrom${e}e`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}e`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}e`).classList.toggle("editing"),document.querySelector(`#grade${e}e`).setAttribute("disabled",""),void document.querySelector(`#course${e}e`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#eduError${e}e`).classList.remove("hidden"),document.querySelector(`#eduError${e}e div`).innerHTML=t.error})):window.location.href="./"}))}function updateWorkItem(e,t){t.preventDefault();let a={};a.dateFrom=document.querySelector(`#dateFrom${e}w`).value,a.dateTo=document.querySelector(`#dateTo${e}w`).value,a.companyName=document.querySelector(`#companyName${e}w`).value,a.area=document.querySelector(`#area${e}w`).value,a.title=document.querySelector(`#jobTitle${e}w`).value,fetch("/api/timelineData/work/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}w`).innerHTML=new Date(document.querySelector(`#dateFrom${e}w`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}w`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}w`).classList.toggle("editing"),document.querySelector(`#companyName${e}w`).setAttribute("disabled",""),document.querySelector(`#area${e}w`).setAttribute("disabled",""),void document.querySelector(`#jobTitle${e}w`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#workError${e}w`).classList.remove("hidden"),document.querySelector(`#workError${e}w div`).innerHTML=t.error})):window.location.href="./"}))}function deleteEduItem(e){fetch("/api/timelineData/edu/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}e`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function deleteWorkItem(e){fetch("/api/timelineData/work/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}w`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function updateProjectItem(e,t){t.preventDefault();let a={};a.title=document.querySelector(`#title${e}`).value,a.isMainProject=document.querySelector(`#isMainProject${e}`).checked?"true":"false",a.information=document.querySelector(`#info${e}`).value,a.projectLink=document.querySelector(`#viewProj${e}`).value,a.gitLink=document.querySelector(`#git${e}`).value;let l=new FormData;l.append("img",document.querySelector(`#img${e}`).files[0]),fetch("/api/projectData/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return"undefined"===l.get("img")?("true"===a.isMainProject&&(document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),document.querySelector(`#isMainProject${e}`).checked=!0,document.querySelector("#projList").prepend(document.querySelector(`#projectItem${e}`))),document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).setAttribute("disabled",""),void document.querySelector(`#info${e}`).setAttribute("disabled","")):(console.log("updating image"),fetch("/api/projectImage/"+e,{method:"POST",body:l,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}));401!==t.status?t.json().then((t=>{document.querySelector(`#projError${e}`).classList.remove("hidden"),document.querySelector(`#projError${e} div`).innerHTML=t.error})):window.location.href="./"})).then((t=>t.json().then((a=>{if(t.ok)return"true"===a.isMainProject&&(document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),document.querySelector(`#isMainProject${e}`).checked=!0,document.querySelector("#projList").prepend(document.querySelector(`#projectItem${e}`))),document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).setAttribute("disabled",""),document.querySelector(`#info${e}`).setAttribute("disabled",""),void(document.querySelector(`#projectImage${e}`).src=a.imgLocation);401!==t.status?(document.querySelector(`#projError${e}`).classList.remove("hidden"),document.querySelector(`#projError${e} div`).innerHTML=a.error):window.location.href="./"}))))}function deleteProjectItem(e){fetch("/api/projectData/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#projectItem${e}`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function addProject(e,t,a,l,o,n,r){let i=document.createElement("form"),d=e+"proj";if(i.id="projectItem"+e,i.classList.add("projItem"),i.onsubmit=t=>updateProjectItem(e,t),i.innerHTML=`\n \n \n \n
\n \n \n \n
\n \n \n
\n \n Is It The Main Project\n \n \n \n
\n \n ${o} \n
\n \n \n
\n \n \n
\n \n \n \n `,"true"===t)return document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),void document.querySelector("#projList").prepend(i);document.querySelector("#projList").appendChild(i)}function deletePostItem(e){fetch("/api/blog/post/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#postInfo${e}`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function addPostInfo(e,t,a,l){let o=document.createElement("tr"),n=e+"post";o.id="postInfo"+e,o.innerHTML=`\n \n ${t}\n \n \n ${new Date(a).toLocaleDateString()}\n \n \n ${new Date(l).toLocaleDateString()}\n \n \n \n \n \n `,document.querySelector("#editPost table tbody").appendChild(o)}document.addEventListener("DOMContentLoaded",(()=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok||(window.location.href="./")})),document.querySelector("#dateFromE").max=(new Date).toISOString().split("T")[0],document.querySelector("#dateFromW").max=(new Date).toISOString().split("T")[0],fetch("/api/timelineData/edu").then((e=>e.json().then((t=>{if(e.ok)for(let e=0;ee.json().then((t=>{if(e.ok)for(let e=0;ee.json().then((t=>{e.ok?t.forEach((e=>{addProject(e.ID,1===e.isMainProject?"true":"false",""===e.imgLocation?"../imgs/placeholder.png":e.imgLocation,e.title,e.information,e.projectLink,e.gitLink)})):document.querySelector("#projList").innerHTML="No project data found"})))),fetch("/api/blog/post").then((e=>e.json().then((t=>{e.ok&&(posts=t,t.forEach((e=>{addPostInfo(e.ID,e.title,e.dateCreated,e.dateModified)})))})))),createEditors("CKEditorAddPost","CKEditorEditPost")})),document.querySelector("body").addEventListener("click",(()=>{if(textareaLoaded)return;const e=document.querySelectorAll("main.editor textarea");for(let t=0;t{e.target.style.height="0",e.target.style.height=e.target.scrollHeight+15+"px"};textareaLoaded=!0})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(()=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"})),document.querySelector("#addEdu").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromE").value),t.append("dateTo",document.querySelector("#dateToE").value),t.append("grade",document.querySelector("#grade").value),t.append("course",document.querySelector("#courseTitle").value),fetch("/api/timelineData/edu",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok)return addEduData(a.ID,t.get("dateFrom"),t.get("dateTo"),t.get("grade"),t.get("course"),!0),void document.querySelector("#addEdu").reset();401!==e.status?showErrorMessage(a.error,"edu"):window.location.href="./"}))))})),document.querySelector("#addWork").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromW").value),t.append("dateTo",document.querySelector("#dateToW").value),t.append("companyName",document.querySelector("#company").value),t.append("area",document.querySelector("#area").value),t.append("title",document.querySelector("#jobTitle").value),fetch("/api/timelineData/work",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok){let e=""===t.get("dateTo")?"Present":t.get("dateTo ");return addWorkData(a.ID,t.get("dateFrom"),e,t.get("companyName"),t.get("area"),t.get("title"),!0),void document.querySelector("#addWork").reset()}401!==e.status?showErrorMessage(a.error,"work"):window.location.href="./"}))))})),document.querySelector("#addProj").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("title",document.querySelector("#projTitle").value),t.append("isMainProject",document.querySelector("#isMainProject").checked?"true":"false"),t.append("information",document.querySelector("#projInfo").value),t.append("projectLink",document.querySelector("#projLink").value?document.querySelector("#projLink").value:"N/A"),t.append("gitLink",document.querySelector("#gitLink").value);let a=new FormData;a.append("img",document.querySelector("#projImg").files[0]);let l=0;fetch("/api/projectData",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok)return"undefined"===a.get("img")?(addProject(o.ID,t.get("isMainProject"),"../imgs/placeholder.png",t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset()):(l=o.ID,fetch("/api/projectImage/"+o.ID,{method:"POST",body:a,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}));401!==e.status?showErrorMessage(o.error,"proj"):window.location.href="./"})).then((e=>e.json().then((a=>{if(e.ok)return addProject(l,t.get("isMainProject"),a.imgLocation,t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset();401!==e.status?showErrorMessage(a.error,"proj"):window.location.href="./"}))))))})),document.querySelector("#addPostForm").addEventListener("submit",(e=>{if(e.preventDefault(),""===editors.CKEditorAddPost.getData())return void showErrorMessage("Post body cannot be empty","addPost");let t=new FormData;t.append("title",document.querySelector("#postTitle").value),t.append("featured",document.querySelector("#isFeatured").checked?"1":"0"),t.append("abstract",document.querySelector("#postAbstract").value),t.append("body",editors.CKEditorAddPost.getData()),t.append("bodyText",viewToPlainText(editors.CKEditorAddPost.editing.view.document.getRoot())),t.append("dateCreated",(new Date).toISOString().slice(0,19).replace("T"," ")),t.append("categories",document.querySelector("#postCategories").value.toLowerCase()),t.append("headerImg",document.querySelector("#headerImg").files[0]),fetch("/api/blog/post",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok)return document.querySelector("#addPostForm").reset(),editors.CKEditorAddPost.setData(""),addPostInfo(a.ID,t.get("title"),t.get("dateCreated"),t.get("dateModified")),void showSuccessMessage("Post added successfully","addPost");401!==e.status?e.json().then((e=>showErrorMessage(e.error,"addPost"))):window.location.href="./"}))))})),document.querySelector("#editPostForm").addEventListener("submit",(e=>{e.preventDefault();let t=document.querySelector("#editPostForm input[type='submit']").id;if(""===t)return void showErrorMessage("Currently not editing any post","editPost");if(""===editors.CKEditorEditPost.getData())return void showErrorMessage("Post body cannot be empty","editPost");let a={};a.title=document.querySelector("#editPostTitle").value,a.featured=document.querySelector("#editIsFeatured").checked?"1":"0",a.abstract=document.querySelector("#editPostAbstract").value,a.body=editors.CKEditorEditPost.getData(),a.bodyText=viewToPlainText(editors.CKEditorEditPost.editing.view.document.getRoot()),a.dateModified=(new Date).toISOString().slice(0,19).replace("T"," "),a.categories=document.querySelector("#editPostCategories").value.toLowerCase();let l=new FormData;l.append("headerImg",document.querySelector("#editHeaderImg").files[0]),fetch("/api/blog/post/"+t,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>{if(e.ok)return"undefined"===l.get("headerImg")?(document.querySelector("#editPostForm").reset(),document.querySelector("#editPostForm input[type='submit']").id="",editors.CKEditorEditPost.setData(""),void showSuccessMessage("Post edited successfully","editPost")):fetch("/api/blog/headerImage/"+t,{method:"POST",body:l,headers:{Authorization:"Bearer "+localStorage.getItem("token")}});401!==e.status?e.json().then((e=>showErrorMessage(e.error,"editPost"))):window.location.href="./"})).then((e=>e.json().then((t=>{if(e.ok)return document.querySelector("#editPostForm").reset(),document.querySelector("#editPostForm input[type='submit']").id="",console.log(),editors.CKEditorEditPost.setData(""),void showSuccessMessage("Post edited successfully","editPost");401!==e.status?showErrorMessage(t.error.message,"editPost"):window.location.href="./"}))))})),document.querySelector("#goToCV").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToCV"),goToPage("curriculumVitae")})),document.querySelector("#goToProjects").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToProjects"),goToPage("projects")})),document.querySelector("#blog").addEventListener("click",(()=>{document.querySelector("nav.sideNav ul li.dropdown ul").classList.toggle("active"),document.querySelector("#blog i.fa").classList.toggle("fa-caret-down"),document.querySelector("#blog i.fa").classList.toggle("fa-caret-right")})),document.querySelector("#goToAddPost").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToAddPost"),goToPage("addPost"),document.querySelector("#blog").classList.add("active")})),document.querySelector("#goToEditPost").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToEditPost"),goToPage("editPost"),document.querySelector("#blog").classList.add("active")})),document.querySelector("#logout").addEventListener("click",(()=>{fetch("/api/user/logout").then((e=>{e.ok&&window.location.reload()}))})),document.querySelector("#eduError .close").addEventListener("click",(()=>document.querySelector("#eduError").classList.toggle("hidden"))),document.querySelector("#workError .close").addEventListener("click",(()=>document.querySelector("#workError").classList.toggle("hidden"))),document.querySelector("#projError .close").addEventListener("click",(()=>document.querySelector("#projError").classList.toggle("hidden"))),document.querySelector("#addPostError .close").addEventListener("click",(()=>document.querySelector("#addPostError").classList.toggle("hidden"))),document.querySelector("#addPostSuccess .close").addEventListener("click",(()=>document.querySelector("#addPostSuccess").classList.toggle("hidden"))),document.querySelector("#editPostError .close").addEventListener("click",(()=>document.querySelector("#editPostError").classList.toggle("hidden"))),document.querySelector("#editPostSuccess .close").addEventListener("click",(()=>document.querySelector("#editPostSuccess").classList.toggle("hidden")));
\ No newline at end of file
+let dateOptions={month:"short",year:"numeric"},textareaLoaded=!1,editors={},posts=null;const smallPaddingElements=["figcaption","li"];function goToPage(e){document.querySelectorAll(".editor section").forEach((t=>{t.style.display="none",t.id===e&&(t.style.display="flex")}))}function viewToPlainText(e){let t="";if(e.is("$text")||e.is("$textProxy"))t=e.data;else if(e.is("element","br"))t="\n";else{let a=null;for(const l of e.getChildren()){const e=viewToPlainText(l);a&&(a.is("containerElement")||l.is("containerElement"))&&(smallPaddingElements.includes(a.name)||smallPaddingElements.includes(l.name)?t+="\n":t+="\n\n"),t+=e,a=l}}return t}function addActiveClass(e){document.querySelectorAll("nav.sideNav ul li a").forEach((t=>{t.classList.remove("active"),t.id===e&&t.classList.add("active")}))}function editProjectItem(e){document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}proj`).toggleAttribute("disabled"),document.querySelector(`#info${e}proj`).toggleAttribute("disabled")}function createEditors(...e){e.forEach((e=>{ClassicEditor.create(document.querySelector(`#${e}`),{placeholder:"Write something amazing...",simpleUpload:{uploadUrl:"/api/blog/uploadPostImage",headers:{Authorization:"Bearer "+localStorage.getItem("token")}},style:{definitions:[{name:"Button Primary",element:"a",classes:["btn","btnPrimary"]},{name:"Button Primary",element:"button",classes:["btn","btnPrimary"]}]},codeBlock:{languages:[{language:"plaintext",label:"Plain text"},{language:"abap",label:"ABAP"},{language:"abnf",label:"ABNF"},{language:"actionscript",label:"ActionScript"},{language:"ada",label:"Ada"},{language:"agda",label:"Agda"},{language:"al",label:"AL"},{language:"antlr4",label:"ANTLR4"},{language:"apacheconf",label:"Apache Configuration"},{language:"apex",label:"Apex"},{language:"apl",label:"APL"},{language:"applescript",label:"AppleScript"},{language:"aql",label:"AQL"},{language:"arduino",label:"Arduino"},{language:"arff",label:"ARFF"},{language:"asciidoc",label:"AsciiDoc"},{language:"aspnet",label:"ASP.NET (C#)"},{language:"asm6502",label:"6502 Assembly"},{language:"autohotkey",label:"AutoHotkey"},{language:"autoit",label:"AutoIt"},{language:"bash",label:"Bash"},{language:"basic",label:"BASIC"},{language:"batch",label:"Batch"},{language:"bbcode",label:"BBcode"},{language:"bison",label:"Bison"},{language:"bnf",label:"BNF"},{language:"brainfuck",label:"Brainfuck"},{language:"brightscript",label:"BrightScript"},{language:"bro",label:"Bro"},{language:"c",label:"C"},{language:"concurnas",label:"Concurnas"},{language:"csharp",label:"C#"},{language:"cpp",label:"C++"},{language:"cil",label:"CIL"},{language:"clojure",label:"Clojure"},{language:"cmake",label:"CMake"},{language:"coffeescript",label:"CoffeeScript"},{language:"concurnas",label:"Concurnas"},{language:"crystal",label:"Crystal"},{language:"css-extras",label:"CSS Extras"},{language:"css",label:"CSS"},{language:"d",label:"D"},{language:"dart",label:"Dart"},{language:"dax",label:"DAX"},{language:"dhall",label:"Dhall"},{language:"diff",label:"Diff"},{language:"django",label:"Django/Jinja2"},{language:"dns-zone-file",label:"DNS zone file"},{language:"docker",label:"Docker"},{language:"ebnf",label:"EBNF"},{language:"editorconfig",label:"EditorConfig"},{language:"eiffel",label:"Eiffel"},{language:"ejs",label:"EJS"},{language:"elixir",label:"Elixir"},{language:"elm",label:"Elm"},{language:"etlua",label:"Embedded Lua"},{language:"erb",label:"ERB"},{language:"erlang",label:"Erlang"},{language:"excel-formula",label:"Excel Formula"},{language:"fsharp",label:"F#"},{language:"factor",label:"Factor"},{language:"firestore-security-rules",label:"Firestore security rules"},{language:"flow",label:"Flow"},{language:"fortran",label:"Fortran"},{language:"ftl",label:"FreeMarker Template Language"},{language:"gcode",label:"G-code"},{language:"gdscript",label:"GDScript"},{language:"gedcom",label:"GEDCOM"},{language:"gherkin",label:"Gherkin"},{language:"git",label:"Git"},{language:"glsl",label:"GLSL"},{language:"gml",label:"GameMaker Language"},{language:"go",label:"Go"},{language:"graphql",label:"GraphQL"},{language:"groovy",label:"Groovy"},{language:"haml",label:"Haml"},{language:"handlebars",label:"Handlebars"},{language:"haskell",label:"Haskell"},{language:"haxe",label:"Haxe"},{language:"hcl",label:"HCL"},{language:"hlsl",label:"HLSL"},{language:"http",label:"HTTP"},{language:"hpkp",label:"HTTP Public-Key-Pins"},{language:"hsts",label:"HTTP Strict-Transport-Security"},{language:"ichigojam",label:"IchigoJam"},{language:"icon",label:"Icon"},{language:"ignore",label:"Ignore"},{language:"inform7",label:"Inform 7"},{language:"ini",label:"Ini"},{language:"io",label:"Io"},{language:"j",label:"J"},{language:"java",label:"Java"},{language:"javadoc",label:"JavaDoc"},{language:"javadoclike",label:"JavaDoc-like"},{language:"javascript",label:"JavaScript"},{language:"javastacktrace",label:"Java stack trace"},{language:"jolie",label:"Jolie"},{language:"jq",label:"JQ"},{language:"js-extras",label:"JS Extras"},{language:"js-templates",label:"JS Templates"},{language:"jsdoc",label:"JSDoc"},{language:"json",label:"JSON"},{language:"json5",label:"JSON5"},{language:"jsonp",label:"JSONP"},{language:"jsstacktrace",label:"JS stack trace"},{language:"jsx",label:"React JSX"},{language:"julia",label:"Julia"},{language:"keyman",label:"Keyman"},{language:"kotlin",label:"Kotlin"},{language:"latex",label:"LaTeX"},{language:"latte",label:"Latte"},{language:"less",label:"Less"},{language:"lilypond",label:"LilyPond"},{language:"liquid",label:"Liquid"},{language:"lisp",label:"Lisp"},{language:"livescript",label:"LiveScript"},{language:"llvm",label:"LLVM IR"},{language:"log",label:"Log file"},{language:"lolcode",label:"LOLCODE"},{language:"lua",label:"Lua"},{language:"makefile",label:"Makefile"},{language:"markdown",label:"Markdown"},{language:"markup-templating",label:"Markup templating"},{language:"matlab",label:"MATLAB"},{language:"mel",label:"MEL"},{language:"mizar",label:"Mizar"},{language:"mongodb",label:"MongoDB"},{language:"monkey",label:"Monkey"},{language:"moonscript",label:"MoonScript"},{language:"n1ql",label:"N1QL"},{language:"n4js",label:"N4JS"},{language:"nand2tetris-hdl",label:"Nand To Tetris HDL"},{language:"nasm",label:"NASM"},{language:"neon",label:"NEON"},{language:"nginx",label:"nginx"},{language:"nim",label:"Nim"},{language:"nix",label:"Nix"},{language:"nsis",label:"NSIS"},{language:"objectivec",label:"Objective-C"},{language:"ocaml",label:"OCaml"},{language:"opencl",label:"OpenCL"},{language:"oz",label:"Oz"},{language:"parigp",label:"PARI/GP"},{language:"parser",label:"Parser"},{language:"pascal",label:"Pascal"},{language:"pascaligo",label:"Pascaligo"},{language:"pcaxis",label:"PC-Axis"},{language:"peoplecode",label:"PeopleCode"},{language:"perl",label:"Perl"},{language:"php",label:"PHP"},{language:"phpdoc",label:"PHPDoc"},{language:"php-extras",label:"PHP Extras"},{language:"plsql",label:"PL/SQL"},{language:"powerquery",label:"PowerQuery"},{language:"powershell",label:"PowerShell"},{language:"processing",label:"Processing"},{language:"prolog",label:"Prolog"},{language:"properties",label:".properties"},{language:"protobuf",label:"Protocol Buffers"},{language:"pug",label:"Pug"},{language:"puppet",label:"Puppet"},{language:"pure",label:"Pure"},{language:"purebasic",label:"PureBasic"},{language:"python",label:"Python"},{language:"q",label:"Q (kdb+ database)"},{language:"qml",label:"QML"},{language:"qore",label:"Qore"},{language:"r",label:"R"},{language:"racket",label:"Racket"},{language:"jsx",label:"React JSX"},{language:"tsx",label:"React TSX"},{language:"reason",label:"Reason"},{language:"regex",label:"Regex"},{language:"renpy",label:"Ren'py"},{language:"rest",label:"reST (reStructuredText)"},{language:"rip",label:"Rip"},{language:"roboconf",label:"Roboconf"},{language:"robotframework",label:"Robot Framework"},{language:"ruby",label:"Ruby"},{language:"rust",label:"Rust"},{language:"sas",label:"SAS"},{language:"sass",label:"Sass (Sass)"},{language:"scss",label:"Sass (Scss)"},{language:"scala",label:"Scala"},{language:"scheme",label:"Scheme"},{language:"shell-session",label:"Shell session"},{language:"smali",label:"Smali"},{language:"smalltalk",label:"Smalltalk"},{language:"smarty",label:"Smarty"},{language:"solidity",label:"Solidity (Ethereum)"},{language:"solution-file",label:"Solution file"},{language:"soy",label:"Soy (Closure Template)"},{language:"sparql",label:"SPARQL"},{language:"splunk-spl",label:"Splunk SPL"},{language:"sqf",label:"SQF: Status Quo Function (Arma 3)"},{language:"sql",label:"SQL"},{language:"stan",label:"Stan"},{language:"stata",label:"Stata"},{language:"step21",label:"STEP Part 21"},{language:"stylus",label:"Stylus"},{language:"swift",label:"Swift"},{language:"tap",label:"TAP"},{language:"tcl",label:"Tcl"},{language:"textile",label:"Textile"},{language:"toml",label:"TOML"},{language:"tt2",label:"Template Toolkit 2"},{language:"turtle",label:"Turtle"},{language:"twig",label:"Twig"},{language:"typescript",label:"TypeScript"},{language:"t4-cs",label:"T4 Text Templates (C#)"},{language:"t4-vb",label:"T4 Text Templates (VB)"},{language:"t4-templating",label:"T4 templating"},{language:"unrealscript",label:"UnrealScript"},{language:"vala",label:"Vala"},{language:"vbnet",label:"VB.Net"},{language:"velocity",label:"Velocity"},{language:"verilog",label:"Verilog"},{language:"vhdl",label:"VHDL"},{language:"vim",label:"vim"},{language:"visual-basic",label:"Visual Basic"},{language:"warpscript",label:"WarpScript"},{language:"wasm",label:"WebAssembly"},{language:"wiki",label:"Wiki markup"},{language:"xeora",label:"Xeora"},{language:"xojo",label:"Xojo (REALbasic)"},{language:"xquery",label:"XQuery"},{language:"yaml",label:"YAML"},{language:"zephir",label:"Zephir"}]}}).then((t=>{editors[e]=t})).catch((e=>{console.error("Oops, something went wrong!"),console.error("Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:"),console.warn("Build id: 1eo8ioyje2om-vgar4aghypdm"),console.error(e)}))}))}function editPostItem(e){posts.forEach((t=>{t.ID===e&&(document.querySelector("#editPostTitle").value=t.title,document.querySelector("#editIsFeatured").checked=1===t.featured,document.querySelector("#editPostCategories").value=t.categories,document.querySelector("#editPostAbstract").value=t.abstract,editors.CKEditorEditPost.setData(t.body),document.querySelector("#editPostForm input[type='submit']").id=e)}))}function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function showSuccessMessage(e,t){document.querySelector(`#${t}Success`).classList.remove("hidden"),document.querySelector(`#${t}Success div`).innerText=e}function editCVItem(e){if(textareaLoaded=!1,document.querySelector(`#timelineItem${e}`).classList.toggle("editing"),e.includes("e"))return document.querySelector(`#grade${e}`).toggleAttribute("disabled"),void document.querySelector(`#course${e}`).toggleAttribute("disabled");document.querySelector(`#companyName${e}`).toggleAttribute("disabled"),document.querySelector(`#area${e}`).toggleAttribute("disabled"),document.querySelector(`#jobTitle${e}`).toggleAttribute("disabled")}function addEduData(e,t,a,l,o,n=!1){let r=e+"e",i=document.createElement("form");i.id="timelineItem"+r,i.classList.add("timelineItem"),i.onsubmit=t=>updateEduItem(e,t),i.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n Grade: \n \n
\n \n ${o} \n
\n \n \n \n `,n?document.querySelector("#edu").prepend(i):document.getElementById("edu").appendChild(i)}function addWorkData(e,t,a,l,o,n,r=!1){let i=e+"w",d=document.createElement("form");d.id="timelineItem"+i,d.classList.add("timelineItem"),d.onsubmit=t=>updateWorkItem(e,t),d.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n -\n \n
\n \n ${n} \n
\n \n \n \n\t`,r?document.querySelector("#work").prepend(d):document.getElementById("work").appendChild(d)}function updateEduItem(e,t){t.preventDefault();let a={};a.dateFrom=document.querySelector(`#dateFrom${e}e`).value,a.dateTo=document.querySelector(`#dateTo${e}e`).value,a.grade=document.querySelector(`#grade${e}e`).value,a.course=document.querySelector(`#course${e}e`).value,fetch("/api/timelineData/edu/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}e`).innerHTML=new Date(document.querySelector(`#dateFrom${e}e`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}e`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}e`).classList.toggle("editing"),document.querySelector(`#grade${e}e`).setAttribute("disabled",""),void document.querySelector(`#course${e}e`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#eduError${e}e`).classList.remove("hidden"),document.querySelector(`#eduError${e}e div`).innerHTML=t.error})):window.location.href="./"}))}function updateWorkItem(e,t){t.preventDefault();let a={};a.dateFrom=document.querySelector(`#dateFrom${e}w`).value,a.dateTo=document.querySelector(`#dateTo${e}w`).value,a.companyName=document.querySelector(`#companyName${e}w`).value,a.area=document.querySelector(`#area${e}w`).value,a.title=document.querySelector(`#jobTitle${e}w`).value,fetch("/api/timelineData/work/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}w`).innerHTML=new Date(document.querySelector(`#dateFrom${e}w`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}w`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}w`).classList.toggle("editing"),document.querySelector(`#companyName${e}w`).setAttribute("disabled",""),document.querySelector(`#area${e}w`).setAttribute("disabled",""),void document.querySelector(`#jobTitle${e}w`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#workError${e}w`).classList.remove("hidden"),document.querySelector(`#workError${e}w div`).innerHTML=t.error})):window.location.href="./"}))}function deleteEduItem(e){fetch("/api/timelineData/edu/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}e`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function deleteWorkItem(e){fetch("/api/timelineData/work/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}w`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function updateProjectItem(e,t){t.preventDefault();let a={};a.title=document.querySelector(`#title${e}`).value,a.isMainProject=document.querySelector(`#isMainProject${e}`).checked?"true":"false",a.information=document.querySelector(`#info${e}`).value,a.projectLink=document.querySelector(`#viewProj${e}`).value,a.gitLink=document.querySelector(`#git${e}`).value;let l=new FormData;l.append("img",document.querySelector(`#img${e}`).files[0]),fetch("/api/projectData/"+e,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return"undefined"===l.get("img")?("true"===a.isMainProject&&(document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),document.querySelector(`#isMainProject${e}`).checked=!0,document.querySelector("#projList").prepend(document.querySelector(`#projectItem${e}`))),document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).setAttribute("disabled",""),void document.querySelector(`#info${e}`).setAttribute("disabled","")):(console.log("updating image"),fetch("/api/projectImage/"+e,{method:"POST",body:l,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}));401!==t.status?t.json().then((t=>{document.querySelector(`#projError${e}`).classList.remove("hidden"),document.querySelector(`#projError${e} div`).innerHTML=t.error})):window.location.href="./"})).then((t=>t.json().then((a=>{if(t.ok)return"true"===a.isMainProject&&(document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),document.querySelector(`#isMainProject${e}`).checked=!0,document.querySelector("#projList").prepend(document.querySelector(`#projectItem${e}`))),document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).setAttribute("disabled",""),document.querySelector(`#info${e}`).setAttribute("disabled",""),void(document.querySelector(`#projectImage${e}`).src=a.imgLocation);401!==t.status?(document.querySelector(`#projError${e}`).classList.remove("hidden"),document.querySelector(`#projError${e} div`).innerHTML=a.error):window.location.href="./"}))))}function deleteProjectItem(e){fetch("/api/projectData/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#projectItem${e}`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function addProject(e,t,a,l,o,n,r){let i=document.createElement("form"),d=e+"proj";if(i.id="projectItem"+e,i.classList.add("projItem"),i.onsubmit=t=>updateProjectItem(e,t),i.innerHTML=`\n \n \n \n
\n \n \n \n
\n \n \n
\n \n Is It The Main Project\n \n \n \n
\n \n ${o} \n
\n \n \n
\n \n \n
\n \n \n \n `,"true"===t)return document.querySelectorAll(".isMainProject input").forEach((e=>e.checked=!1)),void document.querySelector("#projList").prepend(i);document.querySelector("#projList").appendChild(i)}function deletePostItem(e){fetch("/api/blog/post/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#postInfo${e}`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function addPostInfo(e,t,a,l){let o=document.createElement("tr"),n=e+"post";o.id="postInfo"+e,o.innerHTML=`\n \n ${t}\n \n \n ${new Date(a).toLocaleDateString()}\n \n \n ${new Date(l).toLocaleDateString()}\n \n \n \n \n \n `,document.querySelector("#editPost table tbody").appendChild(o)}document.addEventListener("DOMContentLoaded",(()=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok||(window.location.href="./")})),document.querySelector("#dateFromE").max=(new Date).toISOString().split("T")[0],document.querySelector("#dateFromW").max=(new Date).toISOString().split("T")[0],fetch("/api/timelineData/edu").then((e=>e.json().then((t=>{if(e.ok)for(let e=0;ee.json().then((t=>{if(e.ok)for(let e=0;ee.json().then((t=>{e.ok?t.forEach((e=>{addProject(e.ID,1===e.isMainProject?"true":"false",""===e.imgLocation?"../imgs/placeholder.png":e.imgLocation,e.title,e.information,e.projectLink,e.gitLink)})):document.querySelector("#projList").innerHTML="No project data found"})))),fetch("/api/blog/post").then((e=>e.json().then((t=>{e.ok&&(posts=t,t.forEach((e=>{addPostInfo(e.ID,e.title,e.dateCreated,e.dateModified)})))})))),createEditors("CKEditorAddPost","CKEditorEditPost")})),document.querySelector("body").addEventListener("click",(()=>{if(textareaLoaded)return;const e=document.querySelectorAll("main.editor textarea");for(let t=0;t{e.target.style.height="0",e.target.style.height=e.target.scrollHeight+15+"px"};textareaLoaded=!0})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(()=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"})),document.querySelector("#addEdu").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromE").value),t.append("dateTo",document.querySelector("#dateToE").value),t.append("grade",document.querySelector("#grade").value),t.append("course",document.querySelector("#courseTitle").value),fetch("/api/timelineData/edu",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok)return addEduData(a.ID,t.get("dateFrom"),t.get("dateTo"),t.get("grade"),t.get("course"),!0),void document.querySelector("#addEdu").reset();401!==e.status?showErrorMessage(a.error,"edu"):window.location.href="./"}))))})),document.querySelector("#addWork").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromW").value),t.append("dateTo",document.querySelector("#dateToW").value),t.append("companyName",document.querySelector("#company").value),t.append("area",document.querySelector("#area").value),t.append("title",document.querySelector("#jobTitle").value),fetch("/api/timelineData/work",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok){let e=""===t.get("dateTo")?"Present":t.get("dateTo ");return addWorkData(a.ID,t.get("dateFrom"),e,t.get("companyName"),t.get("area"),t.get("title"),!0),void document.querySelector("#addWork").reset()}401!==e.status?showErrorMessage(a.error,"work"):window.location.href="./"}))))})),document.querySelector("#addProj").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("title",document.querySelector("#projTitle").value),t.append("isMainProject",document.querySelector("#isMainProject").checked?"true":"false"),t.append("information",document.querySelector("#projInfo").value),t.append("projectLink",document.querySelector("#projLink").value?document.querySelector("#projLink").value:"N/A"),t.append("gitLink",document.querySelector("#gitLink").value);let a=new FormData;a.append("img",document.querySelector("#projImg").files[0]);let l=0;fetch("/api/projectData",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok)return"undefined"===a.get("img")?(addProject(o.ID,t.get("isMainProject"),"../imgs/placeholder.png",t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset()):(l=o.ID,fetch("/api/projectImage/"+o.ID,{method:"POST",body:a,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}));401!==e.status?showErrorMessage(o.error,"proj"):window.location.href="./"})).then((e=>e.json().then((a=>{if(e.ok)return addProject(l,t.get("isMainProject"),a.imgLocation,t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset();401!==e.status?showErrorMessage(a.error,"proj"):window.location.href="./"}))))))})),document.querySelector("#addPostForm").addEventListener("submit",(e=>{if(e.preventDefault(),""===editors.CKEditorAddPost.getData())return void showErrorMessage("Post body cannot be empty","addPost");let t=new FormData;t.append("title",document.querySelector("#postTitle").value),t.append("featured",document.querySelector("#isFeatured").checked?"1":"0"),t.append("abstract",document.querySelector("#postAbstract").value),t.append("body",editors.CKEditorAddPost.getData()),t.append("bodyText",viewToPlainText(editors.CKEditorAddPost.editing.view.document.getRoot())),t.append("dateCreated",(new Date).toISOString().slice(0,19).replace("T"," ")),t.append("categories",document.querySelector("#postCategories").value.toLowerCase()),t.append("headerImg",document.querySelector("#headerImg").files[0]),fetch("/api/blog/post",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((a=>{if(e.ok)return document.querySelector("#addPostForm").reset(),editors.CKEditorAddPost.setData(""),addPostInfo(a.ID,t.get("title"),t.get("dateCreated"),t.get("dateModified")),void showSuccessMessage("Post added successfully","addPost");401!==e.status?e.json().then((e=>showErrorMessage(e.error,"addPost"))):window.location.href="./"}))))})),document.querySelector("#editPostForm").addEventListener("submit",(e=>{e.preventDefault();let t=document.querySelector("#editPostForm input[type='submit']").id;if(""===t)return void showErrorMessage("Currently not editing any post","editPost");if(""===editors.CKEditorEditPost.getData())return void showErrorMessage("Post body cannot be empty","editPost");let a={};a.title=document.querySelector("#editPostTitle").value,a.featured=document.querySelector("#editIsFeatured").checked?"1":"0",a.abstract=document.querySelector("#editPostAbstract").value,a.body=editors.CKEditorEditPost.getData(),a.bodyText=viewToPlainText(editors.CKEditorEditPost.editing.view.document.getRoot()),a.dateModified=(new Date).toISOString().slice(0,19).replace("T"," "),a.categories=document.querySelector("#editPostCategories").value.toLowerCase();let l=new FormData;l.append("headerImg",document.querySelector("#editHeaderImg").files[0]),fetch("/api/blog/post/"+t,{method:"PATCH",body:JSON.stringify(a),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>{if(e.ok)return"undefined"===l.get("headerImg")?(document.querySelector("#editPostForm").reset(),document.querySelector("#editPostForm input[type='submit']").id="",editors.CKEditorEditPost.setData(""),void showSuccessMessage("Post edited successfully","editPost")):fetch("/api/blog/headerImage/"+t,{method:"POST",body:l,headers:{Authorization:"Bearer "+localStorage.getItem("token")}});401!==e.status?e.json().then((e=>showErrorMessage(e.error,"editPost"))):window.location.href="./"})).then((e=>e.json().then((t=>{if(e.ok)return document.querySelector("#editPostForm").reset(),document.querySelector("#editPostForm input[type='submit']").id="",console.log(),editors.CKEditorEditPost.setData(""),void showSuccessMessage("Post edited successfully","editPost");401!==e.status?showErrorMessage(t.error.message,"editPost"):window.location.href="./"}))))})),document.querySelector("#goToCV").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToCV"),goToPage("curriculumVitae")})),document.querySelector("#goToProjects").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToProjects"),goToPage("projects")})),document.querySelector("#blog").addEventListener("click",(()=>{document.querySelector("nav.sideNav ul li.dropdown ul").classList.toggle("active"),document.querySelector("#blog i.fa").classList.toggle("fa-caret-down"),document.querySelector("#blog i.fa").classList.toggle("fa-caret-right")})),document.querySelector("#goToAddPost").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToAddPost"),goToPage("addPost"),document.querySelector("#blog").classList.add("active")})),document.querySelector("#goToEditPost").addEventListener("click",(()=>{textareaLoaded=!1,addActiveClass("goToEditPost"),goToPage("editPost"),document.querySelector("#blog").classList.add("active")})),document.querySelector("#logout").addEventListener("click",(()=>{fetch("/api/user/logout").then((e=>{e.ok&&window.location.reload()}))})),document.querySelector("#eduError .close").addEventListener("click",(()=>document.querySelector("#eduError").classList.toggle("hidden"))),document.querySelector("#workError .close").addEventListener("click",(()=>document.querySelector("#workError").classList.toggle("hidden"))),document.querySelector("#projError .close").addEventListener("click",(()=>document.querySelector("#projError").classList.toggle("hidden"))),document.querySelector("#addPostError .close").addEventListener("click",(()=>document.querySelector("#addPostError").classList.toggle("hidden"))),document.querySelector("#addPostSuccess .close").addEventListener("click",(()=>document.querySelector("#addPostSuccess").classList.toggle("hidden"))),document.querySelector("#editPostError .close").addEventListener("click",(()=>document.querySelector("#editPostError").classList.toggle("hidden"))),document.querySelector("#editPostSuccess .close").addEventListener("click",(()=>document.querySelector("#editPostSuccess").classList.toggle("hidden")));
\ No newline at end of file
diff --git a/src/api/blog/blogData.php b/src/api/blog/blogData.php
index 95dd912..a8f8c6f 100644
--- a/src/api/blog/blogData.php
+++ b/src/api/blog/blogData.php
@@ -444,22 +444,87 @@ class blogData
if ($result)
{
- $bodyText = array_column($result, "bodyText");
- // go through each body plain text and get the sentence before, the sentence with the search term and the sentence after and append it to a new array
- foreach ($bodyText as $key => $text)
+ for ($i = 0; $i < count($result); $i++)
{
- $text = strtolower($text);
- $searchTerm = strtolower($searchTerm);
- $pos = strpos($text, $searchTerm);
- $start = strrpos(substr($text, 0, $pos), ".") + 1;
- $end = strpos($text, ".", $pos);
- $result[$key]["bodyText"] = substr($text, $start, $end - $start);
+ $result[$i]["abstract"] = $this->getShortPost($searchTerm, stripcslashes($result[$i]["bodyText"]));
}
-
return $result;
}
return array("errorMessage" => "Error, could not find posts");
}
+
+ /**
+ * Get the short post with the search term
+ * @param string $searchTerm - Search term
+ * @param $text - Body of the post as plain text
+ * @return string - Short post with the search term
+ */
+ private function getShortPost(string $searchTerm, $text): string
+ {
+ $pattern = '/([,:;!?.-]+)/u';
+ $parts = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
+
+ $cleanedParts = [];
+
+ foreach ($parts as $part)
+ {
+ $part = trim($part); // Remove leading/trailing spaces and newline characters
+ if (!empty($part))
+ {
+ $cleanedParts[] = $part;
+ }
+ }
+
+ $combinedParts = [];
+ $currentPart = '';
+
+ foreach ($cleanedParts as $part)
+ {
+ if (preg_match('/[,:;!?.-]/u', $part))
+ {
+ $currentPart .= $part;
+ }
+ else
+ {
+ if (!empty($currentPart))
+ {
+ $combinedParts[] = trim($currentPart);
+ }
+ $currentPart = rtrim($part);
+ }
+ }
+
+ if (!empty($currentPart))
+ {
+ $combinedParts[] = trim($currentPart);
+ }
+
+ $result = "";
+
+
+ for ($i = 0; $i < count($combinedParts); $i++)
+ {
+ $part = $combinedParts[$i];
+
+ if (stripos($part, $searchTerm) !== false)
+ {
+ $before = ($i > 0) ? $combinedParts[$i - 1] : "";
+ $after = ($i < count($combinedParts) - 1) ? $combinedParts[$i + 1] : "";
+
+ if ($before === "" && $i > 0)
+ {
+ $before = $combinedParts[$i - 1];
+ }
+
+ $result = $before . " " . $part . " " . $after;
+
+ // If the search term is found, we don't need to continue checking subsequent parts
+ break;
+ }
+ }
+
+ return $result;
+ }
}
\ No newline at end of file
diff --git a/src/api/blog/blogRoutes.php b/src/api/blog/blogRoutes.php
index 7a7933a..d3c4201 100644
--- a/src/api/blog/blogRoutes.php
+++ b/src/api/blog/blogRoutes.php
@@ -254,7 +254,7 @@ class blogRoutes implements routesInterface
}
$featured = $data["featured"] === "true";
- $insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
+ $insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
if (!is_int($insertedID))
{
// uh oh something went wrong
diff --git a/src/blog/index.html b/src/blog/index.html
index 60fe97d..838afd8 100644
--- a/src/blog/index.html
+++ b/src/blog/index.html
@@ -49,6 +49,22 @@
+
+
diff --git a/src/blog/js/index.js b/src/blog/js/index.js
index bed89d9..fffcaff 100644
--- a/src/blog/js/index.js
+++ b/src/blog/js/index.js
@@ -44,7 +44,6 @@ function goToURL(url)
if (urlArray[2] === 'post')
{
// Create a new URL with the dynamic part
- // window.history.pushState(null, null, url);
loadIndividualPost(urlArray[urlArray.length - 1]).catch(err => console.log(err));
return;
}
@@ -52,14 +51,20 @@ function goToURL(url)
if (urlArray[2] === 'category')
{
// Create a new URL with the dynamic part
- // window.history.pushState(null, null, url);
if (urlArray[3])
{
loadPostsByCategory(urlArray[urlArray.length - 1]);
return;
}
- loadAllCategories();
+ loadAllCategories().catch(err => console.log(err));
+ return;
+ }
+
+ if (urlArray[2] === 'search' && urlArray[3])
+ {
+ // Create a new URL with the dynamic part
+ loadSearchResults(urlArray[urlArray.length - 1]);
return;
}
@@ -67,6 +72,26 @@ function goToURL(url)
}
+document.querySelector('#searchBtn').addEventListener('click', _ =>
+{
+ let searchTerm = document.querySelector('#searchField').value;
+ if (searchTerm.length > 0)
+ {
+ window.history.pushState(null, null, `/blog/search/${searchTerm}`);
+ document.querySelector('#searchField').value = '';
+ document.querySelector('#main').innerHTML = '';
+ goToURL(`/blog/search/${searchTerm}`);
+ }
+});
+
+document.querySelector('#searchField').addEventListener('keyup', e =>
+{
+ if (e.key === 'Enter')
+ {
+ document.querySelector('#searchBtn').click();
+ }
+});
+
/**
* Creates a large post element
* @param post the post object
@@ -116,25 +141,6 @@ function createLargePost(post)
*/
function loadHomeContent()
{
- let menuBar = document.createElement('div');
- menuBar.classList.add('menuBar');
- // language=HTML
- menuBar.innerHTML = `
-
- `;
- document.querySelector('#main').appendChild(menuBar);
-
fetch('/api/blog/post').then(res => res.json().then(json =>
{
for (let i = 0; i < json.length; i++)
@@ -458,6 +464,34 @@ function loadPostsByCategory(category)
}));
}
+function loadSearchResults(searchTerm)
+{
+ document.title = 'Rohit Pai - Search Results for ' + decodeURI(searchTerm);
+ fetch(`/api/blog/search/${searchTerm}`).then(res => res.json().then(json =>
+ {
+ let main = document.querySelector('#main');
+ let posts = document.createElement('section');
+ posts.classList.add('catPosts');
+ posts.id = 'searchResults';
+ let h1 = document.createElement('h1');
+ h1.innerHTML = 'Search Results';
+ main.appendChild(h1);
+ for (let i = 0; i < json.length; i++)
+ {
+ let largePost = document.createElement('section');
+ largePost.classList.add('largePost');
+ if (i < json.length - 1)
+ {
+ largePost.classList.add('categoryPost');
+ }
+ let outerContent = createLargePost(json[i]);
+ largePost.appendChild(outerContent);
+ posts.appendChild(largePost);
+ }
+ main.appendChild(posts);
+ }));
+}
+
/**
* Shows the 404 page
*/
diff --git a/src/css/nav.css b/src/css/nav.css
index 63a0c8b..48540f3 100644
--- a/src/css/nav.css
+++ b/src/css/nav.css
@@ -64,7 +64,6 @@ nav ul li span {
visibility: hidden;
}
-
nav ul li .active::before,
nav ul li .active::after {
visibility: visible;
diff --git a/src/editor/editor.html b/src/editor/editor.html
index 2573b66..455afa1 100644
--- a/src/editor/editor.html
+++ b/src/editor/editor.html
@@ -200,10 +200,7 @@
Categories
-
+
@@ -264,10 +261,7 @@
Categories
-
+
diff --git a/src/editor/js/editor.js b/src/editor/js/editor.js
index 00aadc3..e3f5f8f 100644
--- a/src/editor/js/editor.js
+++ b/src/editor/js/editor.js
@@ -486,11 +486,11 @@ function viewToPlainText(viewItem)
// If item is `Text` or `TextProxy` simple take its text data.
text = viewItem.data;
}
- else if (viewItem.is('element', 'img') && viewItem.hasAttribute('alt'))
- {
- // Special case for images - use alt attribute if it is provided.
- text = viewItem.getAttribute('alt');
- }
+ // else if (viewItem.is('element', 'img') && viewItem.hasAttribute('alt'))
+ // {
+ // // Special case for images - use alt attribute if it is provided.
+ // text = viewItem.getAttribute('alt');
+ // }
else if (viewItem.is('element', 'br'))
{
// A soft break should be converted into a single line break (#8045).