diff options
author | Telérico Jones <[email protected]> | 2021-05-29 21:09:08 -0300 |
---|---|---|
committer | Telérico Jones <[email protected]> | 2021-05-29 21:09:08 -0300 |
commit | cade848b78d7f06b69a195f5a543b23c25eedd14 (patch) | |
tree | 6f6b4f766a58ccd61452da7a32830f051a89003e | |
download | blog.sh-cade848b78d7f06b69a195f5a543b23c25eedd14.tar.bz2 blog.sh-cade848b78d7f06b69a195f5a543b23c25eedd14.zip |
blog.sh project start
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | footer.sh | 18 | ||||
-rw-r--r-- | header.sh | 106 | ||||
-rw-r--r-- | index.html | 9 | ||||
-rwxr-xr-x | index.sh | 95 | ||||
-rwxr-xr-x | nav.sh | 91 | ||||
-rwxr-xr-x | pages/article.sh | 52 | ||||
-rw-r--r-- | pages/contato.sh | 13 | ||||
-rwxr-xr-x | pages/home.sh | 25 | ||||
-rw-r--r-- | styles.css | 279 |
10 files changed, 689 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb2c80d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/pages/articles/* diff --git a/footer.sh b/footer.sh new file mode 100755 index 0000000..a7125bb --- /dev/null +++ b/footer.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +cat <<FOOTER +<style> + footer { + text-align: center; + } +</style> + +<footer> + <div class="separator-wrap"><div class="separator"></div></div> + <p> + Servidor HTTP: $SERVER_SOFTWARE <br /> + Gateway: $GATEWAY_INTERFACE <br /> + Pré-processador HTML: GNU Bash $BASH_VERSION + </p> +</footer> +FOOTER diff --git a/header.sh b/header.sh new file mode 100644 index 0000000..2e9f467 --- /dev/null +++ b/header.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +cat <<HEADER +<style> + header h1, header h2 { + text-align: left; + line-break: anywhere; + } + + header .separator-wrap { + margin-top: 15px; + } + + .cursor { + background-color: var(--primary-fg); + animation-name: blink-animation; + animation-duration: 500ms; + animation-iteration-count: infinite; + animation-timing-function: cubic-bezier(0.83,-0.22, 0.54, 0.55); + } + + @keyframes blink-animation { + to { + opacity: 0; + } + } + + .mobile { display: none; } + + @media screen and (max-width: 769px) { + .mobile { display: block; } + .desktop { display: none; } + } +</style> + +<script type="text/javascript"> + let mobileText = '$HEADER_TITLE_MOBILE'; + let desktopText = '$HEADER_TITLE'; + let isMobile = window.innerWidth < 769; + + function hideContent() { + let mainContainer = document.querySelector('main'); + let footer = document.querySelector('footer'); + let headerSeparator = document.querySelector('header > .separator-wrap'); + mainContainer.style.opacity = '0'; + footer.style.opacity = '0'; + headerSeparator.style.opacity = '0'; + } + + function showContent() { + let mainContainer = document.querySelector('main'); + let footer = document.querySelector('footer'); + let headerSeparator = document.querySelector('header > .separator-wrap'); + mainContainer.style.transition = '500ms'; + mainContainer.style.opacity = '1'; + footer.style.transition = '500ms'; + footer.style.opacity = '1'; + headerSeparator.style.transition = '500ms'; + headerSeparator.style.opacity = '1'; + + } + + function typingAnimation(el, text, index, cb) { + let char = text[index]; + if (char == ';') { + el.innerHTML += '<br />'; + } else if (char == ' ') { + el.innerHTML += ' '; + } else { + el.innerText += char; + } + + if (index < text.length - 1) { + setTimeout(() => typingAnimation(el, text, index + 1, cb), 30); + } else { + cb(); + } + } + + document.addEventListener('DOMContentLoaded', function(event) { + hideContent(); + let titleMobile = document.querySelector("#header-title-mobile > .text"); + let titleDesktop = document.querySelector('#header-title > .text'); + + if (isMobile) { + titleMobile.innerHTML = ''; + } else { + titleDesktop.innerHTML = ''; + } + + setTimeout(() => { + if (isMobile) { + typingAnimation(titleMobile, mobileText, 0, showContent); + } else { + typingAnimation(titleDesktop, desktopText, 0, showContent); + } + }, 200); + }); +</script> + +<header> + <h1 id="header-title" class="desktop">$ <span class="text">echo "Jefferson Julio" >> ./programadores</span><span class="cursor"> </span></h1> + <h1 id="header-title-mobile" class="mobile">$ <span class="text">echo "Jefferson Julio" \\<br/> >> ./programadores</span><span class="cursor"> </span></h1> + <div class="separator-wrap"><div class="separator"></div></div> +</header> +HEADER diff --git a/index.html b/index.html new file mode 100644 index 0000000..0660d29 --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ +<html> + <head> + <meta charset="utf-8" /> + <title>jefferson.sh - dev</title> + </head> + <body> + <h1>dev - golo golo</h1> + </body> +</html> diff --git a/index.sh b/index.sh new file mode 100755 index 0000000..16eb31c --- /dev/null +++ b/index.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +if [ "$REQUEST_URI" = '/favicon.ico' ]; then + exit 0 +fi + +RESPONSE_CONTENT_TYPE="text/html" +STATUS=200 + +HEADER_TITLE='source ./programadores/Jefferson Júlio/site/home.sh' +HEADER_TITLE_MOBILE='cd ./programadores/ && \\ ;> source Jefferson Júlio/\\ ;> site/home.sh' + +urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; } + +html () { + cat <<HTML +<html lang="pt-br"> + <head> + <meta charset="utf-8" /> + <title>jefferson.sh</title> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + + <style> + $(cat ./styles.css) + </style> + </head> + + <body> + $(source ./nav.sh) + $(source ./header.sh) + + <main> + $BODY + </main> + + $(source ./footer.sh) + </body> +</html> +HTML +} + +router () { + REQUEST_URI=$(urldecode "$REQUEST_URI") + + case "$REQUEST_URI" in + /) + BODY=$(source ./pages/home.sh) + ;; + /contato) + HEADER_TITLE="source ./pages/contato.sh" + HEADER_TITLE_MOBILE="$HEADER_TITLE" + BODY=$(source ./pages/contato.sh) + ;; + /artigo/*.txt) + ARTICLE_FILE=./pages/articles/${REQUEST_URI/\/artigo\//} + HEADER_TITLE="cat $ARTICLE_FILE" + HEADER_TITLE_MOBILE="$HEADER_TITLE" + BODY=$(source ./pages/article.sh) + ;; + /json) + RESPONSE_CONTENT_TYPE="application/json" + STATUS=200 + BODY=$(cat <<JSON +{ + "teste": "JSON" +} +JSON +) + ;; + *) + STATUS=404 + HEADER_TITLE="cat .$REQUEST_URI" + HEADER_TITLE_MOBILE="$HEADER_TITLE" + BODY="<p class='err-404'>cat: .$REQUEST_URI: Arquivo ou diretório inexistente</p>" + ;; + esac +} + +router + +case "$RESPONSE_CONTENT_TYPE" in + "text/html") + RESPONSE_BODY=$(html) + ;; + *) + RESPONSE_BODY=$BODY +esac + + +cat <<INDEX +Content-Type: $RESPONSE_CONTENT_TYPE +Status: $STATUS + +$RESPONSE_BODY +INDEX @@ -0,0 +1,91 @@ +#!/bin/bash + +cat <<NAV +<style> + .top-nav { + position: relative; + display: inline-flex; + background-color: var(--primary-fg); + height: 40px; + width: 100%; + align-items: center; + } + + .nav-header { + padding-left: 25px; + padding-right: 25px; + } + + .nav-header a { + color: black; + text-shadow: #e0e0e0 1px 1px 0; + font-size: 1.4rem; + text-decoration: none; + } + + .nav-links { + padding: 0px 20px 0px 20px; + align-self: center; + } + + .nav-links li { + position: relative; + height: 100%; + padding-left: 5px; + padding-right: 5px; + display: inline-flex; + align-items: center; + } + + .nav-links a { + color: var(--primary-bg); + text-decoration: none; + } + + .nav-links li:hover { + background-color: var(--primary-bg); + } + + .nav-links li:hover a { + text-decoration: underline; + color: var(--primary-fg); + } + + @media screen and (max-width: 601px) { + .top-nav { + flex-direction: column; + height: auto; + padding-bottom: 10px; + } + + .nav-header { + padding-top: 10px; + padding-bottom: 10px; + } + + .nav-header a { + font-size: 1.6rem; + } + + .top-nav ul { + display: contents; + } + + .top-nav ul > li { + width: 100%; + height: 25px; + justify-content: center; + } + } +</style> + +<nav class="top-nav"> + <span class="nav-header"> + <a href="https://jefferson.sh">jefferson.sh</a> + </span> + <ul class="nav-links"> + <li> <a href="/">Início</a> </li> + <li> <a href="/contato">Contato</a> </li> + </ul> +</nav> +NAV diff --git a/pages/article.sh b/pages/article.sh new file mode 100755 index 0000000..9832a76 --- /dev/null +++ b/pages/article.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +ARTICLE_TITLE=$(basename "$ARTICLE_FILE") + +# Pick all file content +ARTICLE_FILE_CONTENT=$(cat "$ARTICLE_FILE") + +# The first 3 lines of the file are metadata information +ARTICLE_METADATA=$(echo "$ARTICLE_FILE_CONTENT" | head -n 3) + +# Skip file metadata, first 3 lines +ARTICLE_CONTENT=$(echo "$ARTICLE_FILE_CONTENT" | tail -n +3) + +# Tags are placed on the first line of the file, delimited by commas +IFS=',' read -ra ARTICLE_TAGS <<< "$(echo "$ARTICLE_METADATA" | head -n 1)" + +ARTICLE_TIME=$(stat --format="Criado em: %w<br/>Última atualização: %z" "$ARTICLE_FILE") +ARTICLE_BYTES=$(stat --format="%o bytes" "$ARTICLE_FILE") + +if [ $? -gt 0 ]; then + STATUS=404 + cat <<ERR +<p class="err-404">cat: $ARTICLE_FILE: Arquivo ou diretório inexistente</p> +ERR + exit 0 +fi + +cat <<ARTICLE +<article class="container"> + <section> + <div class="post-header"> + <h4 class="post-title">stat -c "%o %w %z" $ARTICLE_FILE</h4> + <small>$ARTICLE_BYTES</small> <br/> + <time>$ARTICLE_TIME</time> <br/> + + <ul class="tags"> + $( + for i in "${ARTICLE_TAGS[@]}"; do + echo "<li class="tag">$i</li>" + done + ) + </ul> + </div> + + <div class="post-content"> + <p> + ${ARTICLE_CONTENT} + </p> + </div> + </section> +</article> +ARTICLE diff --git a/pages/contato.sh b/pages/contato.sh new file mode 100644 index 0000000..74d1ad4 --- /dev/null +++ b/pages/contato.sh @@ -0,0 +1,13 @@ +#!/bin/bash +cat <<PAGE +<style> + @media screen and (max-width: 600px) { + .contato-page { + text-align: center; + } + } +</style> + +<article class="contato-page container"> +</article> +PAGE diff --git a/pages/home.sh b/pages/home.sh new file mode 100755 index 0000000..ebb399d --- /dev/null +++ b/pages/home.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +print-all-articles () { + for i in $(find ./pages/articles -type f -name '*.txt'); do + ARTICLE_CONTENT=$(tail -n +3 $i) + cat <<POST +<section class="post-preview"> + <div class="post-header-preview"> + <h5 class="post-title">stat -c "%w %z" $i</h5> + <time>$(stat --format="Criado em: %w<br/>Última atualização: %z" $i)</time> + </div> + + <p>$(echo "$ARTICLE_CONTENT" | head -c 120)...</p> + + <a href="/artigo/$(basename $i)">Ler artigo completo</a> +</section> +POST + done +} + +cat <<PAGE +<article class="home-feed container"> + $(print-all-articles) +</article> +PAGE diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..b17d72f --- /dev/null +++ b/styles.css @@ -0,0 +1,279 @@ +/* normalize.css */ +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} +body { + margin: 0; +} +main { + display: block; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} +a { + background-color: transparent; +} +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} +b, +strong { + font-weight: bolder; +} +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +img { + border-style: none; +} +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} +button, +input { /* 1 */ + overflow: visible; +} +button, +select { /* 1 */ + text-transform: none; +} +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + padding: 0.35em 0.75em 0.625em; +} +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} +progress { + vertical-align: baseline; +} +textarea { + overflow: auto; +} +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} +details { + display: block; +} +summary { + display: list-item; +} +template { + display: none; +} +[hidden] { + display: none; +} + +/* jefferson.sh */ + +@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap'); + +html { + --primary-bg: #2b2b2b; + --primary-fg: #65d84a; + background-color: var(--primary-bg); + color: var(--primary-fg); + font-family: 'VT323', monospace; + font-size: 14px; +} + + +.separator-wrap { + width: 100%; + display: flex; + justify-content: center; +} + +.separator-wrap.left { + justify-content: flex-start; +} + +.separator { + border-top: 1px solid var(--primary-fg); + width: 25px; + margin-left: 25px; + margin-right: 25px; +} + +a { + color: var(--primary-fg); +} + +ul { + padding: 0; + margin: 0; + list-style: none; +} + +nav > * { + display: inline-block; +} + +ul > li { + display: inline-block; +} + +header, footer { + margin: 25px; +} + +header > h1, +header > h2 { + margin: 0; +} + +@media screen and (max-width: 600px) { + h1 { + font-size: 1.4rem; + } +} + +[class^=err-] { + text-align: left; + font-size: 2rem; + margin: 40px; +} + +.container { + padding-left: 25px; + padding-right: 25px; +} + +@media screen and (min-width: 1000px) { + .container { + padding-left: 215px; + padding-right: 215px; + } +} + +.post-header { + border-left: 1px solid; + padding-left: 15px; +} + +.post-title { + font-size: 1.4rem; + margin: 0; + margin-bottom: 10px; + line-break: anywhere; +} + +.post-preview { + border-left: 1px solid; + padding-left: 10px; + margin: 25px 0px; +} + +.post-header time, +.post-header small { + font-size: 0.9rem; +} + +.post-header-preview time, +.post-header-preview small { + font-size: 0.9rem; +} + +.post-header-preview .post-title { + margin: 0; + font-size: 1.1rem; +} +.post-header-preview time { + font-size: 0.8rem; +} + +.tags { + margin-top: 15px; + margin-bottom: 15px; +} + +.tag { + background-color: var(--primary-fg); + color: var(--primary-bg); + padding-left: 4px; + padding-right: 4px; + padding-top: 1.5px; + padding-bottom: 1.5px; +} |