rawfeed 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +20 -21
- data/README.md +13 -112
- data/_data/options.yml +270 -0
- data/_data/resume.yml +8 -9
- data/_includes/alert +3 -1
- data/_includes/chart +13 -32
- data/_includes/details +1 -57
- data/_includes/image +12 -4
- data/_includes/layout/blog_search.html +7 -5
- data/_includes/layout/data.liquid +21 -3
- data/_includes/layout/disqus.html +12 -26
- data/_includes/layout/footer.html +34 -16
- data/_includes/layout/giscus.html +27 -19
- data/_includes/layout/head.html +58 -19
- data/_includes/layout/header.html +127 -101
- data/_includes/layout/maintenance.html +8 -12
- data/_includes/layout/paginator.html +6 -4
- data/_includes/socials +7 -5
- data/_includes/tabs +1 -94
- data/_includes/toc +12 -152
- data/_includes/video +4 -1
- data/_layouts/blog.html +8 -7
- data/_layouts/contact.html +90 -196
- data/_layouts/default.html +42 -339
- data/_layouts/error.html +6 -4
- data/_layouts/home.html +45 -36
- data/_layouts/licenses.html +10 -0
- data/_layouts/page.html +4 -6
- data/_layouts/pixel.html +48 -0
- data/_layouts/pixels.html +71 -0
- data/_layouts/post.html +28 -31
- data/_layouts/resume.html +43 -36
- data/_layouts/tag.html +14 -3
- data/_layouts/tag_posts.html +3 -3
- data/_sass/base/_index.scss +39 -3
- data/_sass/components/_badges.scss +10 -0
- data/_sass/components/_markdown.scss +20 -17
- data/_sass/includes/_footer.scss +18 -8
- data/_sass/includes/_header.scss +24 -19
- data/_sass/includes/_highlight.scss +20 -7
- data/_sass/includes/_maintenance.scss +2 -3
- data/_sass/includes/_terminal.scss +35 -12
- data/_sass/layouts/_blog.scss +13 -9
- data/_sass/layouts/_contact.scss +6 -5
- data/_sass/layouts/_default.scss +5 -5
- data/_sass/layouts/_index.scss +3 -0
- data/_sass/layouts/_licenses.scss +7 -0
- data/_sass/layouts/_page.scss +1 -0
- data/_sass/layouts/_pixel.scss +61 -0
- data/_sass/layouts/_pixels.scss +86 -0
- data/_sass/layouts/_post.scss +4 -11
- data/_sass/layouts/_resume.scss +17 -7
- data/_sass/layouts/_tag-posts.scss +1 -2
- data/_sass/layouts/_tag.scss +12 -1
- data/_sass/main.scss +16 -1
- data/_sass/theme/_dark.scss +15 -5
- data/_sass/theme/_light.scss +9 -2
- data/assets/images/blog/.keep +0 -0
- data/assets/images/pixels/luffy.jpg +0 -0
- data/assets/js/blog.coffee +102 -0
- data/assets/js/contact.coffee +105 -0
- data/assets/js/default.coffee +172 -0
- data/assets/js/discus.coffee +30 -0
- data/assets/js/fallback/README.md +3 -0
- data/assets/js/fallback/blog.js +113 -0
- data/assets/js/fallback/contact.js +116 -0
- data/assets/js/{default.js → fallback/default.js} +50 -0
- data/assets/js/fallback/discus.js +32 -0
- data/{_includes/layout/google_analytics.html → assets/js/fallback/google_analytics.js} +7 -3
- data/assets/js/fallback/home.js +275 -0
- data/assets/js/fallback/no_inframe.js +4 -0
- data/assets/js/fallback/page.js +423 -0
- data/assets/js/fallback/pixels.js +1 -0
- data/assets/js/fallback/resume.js +13 -0
- data/assets/js/fallback/tags.js +1 -0
- data/assets/js/fallback/theme_load.js +4 -0
- data/assets/js/google_analytics.coffee +24 -0
- data/assets/js/home.coffee +250 -0
- data/assets/js/no_inframe.coffee +9 -0
- data/assets/js/page.coffee +379 -0
- data/assets/js/pixels.coffee +2 -0
- data/assets/js/resume.coffee +9 -0
- data/assets/js/tags.coffee +2 -0
- data/assets/js/theme_load.coffee +6 -0
- data/assets/json/blog_search.json +2 -2
- data/lib/rawfeed/author.rb +59 -0
- data/lib/rawfeed/csp_filters.rb +19 -0
- data/lib/rawfeed/draft.rb +1 -1
- data/lib/rawfeed/layout.rb +7 -0
- data/lib/rawfeed/page.rb +4 -2
- data/lib/rawfeed/pixel.rb +32 -0
- data/lib/rawfeed/post.rb +2 -2
- data/lib/rawfeed/resume.rb +1 -0
- data/lib/rawfeed/typescript_liquid.rb +172 -0
- data/lib/rawfeed/utils.rb +1 -0
- data/lib/rawfeed/version.rb +1 -1
- data/lib/rawfeed/with_class.rb +20 -0
- data/lib/rawfeed.rb +5 -0
- metadata +46 -12
- data/assets/js/avatar.js +0 -50
- data/assets/js/terminal.js +0 -18
- data/assets/js/toc.js +0 -22
| @@ -1,9 +1,59 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            ---
         | 
| 3 | 
            +
             | 
| 1 4 | 
             
            document.addEventListener("DOMContentLoaded", () => {
         | 
| 2 5 | 
             
              /* lock menu context (click right mouse)
         | 
| 3 6 | 
             
              --------------------------------------------------------------------------------------------------
         | 
| 4 7 | 
             
              */
         | 
| 5 8 | 
             
              document.addEventListener('contextmenu', e => e.preventDefault());
         | 
| 6 9 |  | 
| 10 | 
            +
              /* avatar
         | 
| 11 | 
            +
              -------------------------------------------------------------------------------------------------
         | 
| 12 | 
            +
              */
         | 
| 13 | 
            +
              const modalEl = document.getElementById('avatarModal');
         | 
| 14 | 
            +
              if (modalEl) {
         | 
| 15 | 
            +
                const flipperAvatars = document.querySelectorAll('.avatar-flipper__open-true');
         | 
| 16 | 
            +
                const modalAvatar = document.getElementById('modalAvatar');
         | 
| 17 | 
            +
                const header = document.querySelector('.header');
         | 
| 18 | 
            +
                const bsModal = new bootstrap.Modal(modalEl);
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                flipperAvatars.forEach((flipper) => {
         | 
| 21 | 
            +
                  flipper.addEventListener("click", () => {
         | 
| 22 | 
            +
                    const card = flipper.querySelector('.avatar-card');
         | 
| 23 | 
            +
                    const backImage = flipper.querySelector('.avatar-back img');
         | 
| 24 | 
            +
                    const backImageSrc = backImage.src;
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    card.classList.add("flip-avatar");
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    card.addEventListener(
         | 
| 29 | 
            +
                      "animationend",
         | 
| 30 | 
            +
                      () => {
         | 
| 31 | 
            +
                        card.classList.remove("flip-avatar");
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                        modalAvatar.src = backImageSrc;
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                        bsModal.show();
         | 
| 36 | 
            +
                      },
         | 
| 37 | 
            +
                      { once: true }
         | 
| 38 | 
            +
                    );
         | 
| 39 | 
            +
                  });
         | 
| 40 | 
            +
                });
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                modalEl.addEventListener("shown.bs.modal", () => {
         | 
| 43 | 
            +
                  modalAvatar.classList.remove("modal-avatar");
         | 
| 44 | 
            +
                  void modalAvatar.offsetWidth;
         | 
| 45 | 
            +
                  modalAvatar.classList.add("modal-avatar");
         | 
| 46 | 
            +
                  header.classList.remove("modal-active");
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  flipperAvatars.forEach((flipper) => flipper.classList.add("hidden"));
         | 
| 49 | 
            +
                });
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                modalEl.addEventListener("hidden.bs.modal", () => {
         | 
| 52 | 
            +
                  flipperAvatars.forEach((flipper) => flipper.classList.remove("hidden"));
         | 
| 53 | 
            +
                });
         | 
| 54 | 
            +
              }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
             | 
| 7 57 | 
             
              /* Show/disappear top button
         | 
| 8 58 | 
             
              --------------------------------------------------------------------------------------------------
         | 
| 9 59 | 
             
              */
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            ---
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            {%- include layout/data.liquid -%}
         | 
| 5 | 
            +
             | 
| 6 | 
            +
             | 
| 7 | 
            +
            document.addEventListener("DOMContentLoaded", () => {
         | 
| 8 | 
            +
              const discus = document.getElementById('disqus_thread');
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              if (discus) {
         | 
| 11 | 
            +
                /**
         | 
| 12 | 
            +
                 * RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES
         | 
| 13 | 
            +
                 */
         | 
| 14 | 
            +
                var disqus_shortname = '{{ blog_.post.comments.disqus.shortname }}';
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                // The unique URL for the discussion, usually the post's permalink.
         | 
| 17 | 
            +
                var disqus_config = function () {
         | 
| 18 | 
            +
                  this.page.url = '{{ page.url | absolute_url }}'; // Replace with your full permalink
         | 
| 19 | 
            +
                  this.page.identifier = '{{ page.id }}'; // Unique ID for the discussion, use page.id or page.url
         | 
| 20 | 
            +
                  this.page.disable_ads = true; // disabled ads
         | 
| 21 | 
            +
                  this.page.recommendations = false; // disabled recommendations
         | 
| 22 | 
            +
                };
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                (function() {
         | 
| 25 | 
            +
                  var d = document, s = d.createElement('script');
         | 
| 26 | 
            +
                  s.src = '//' + disqus_shortname + '.disqus.com/embed.js';
         | 
| 27 | 
            +
                  s.setAttribute('data-timestamp', +new Date());
         | 
| 28 | 
            +
                  (d.head || d.body).appendChild(s);
         | 
| 29 | 
            +
                })();
         | 
| 30 | 
            +
              }
         | 
| 31 | 
            +
            });
         | 
| 32 | 
            +
             | 
| @@ -1,11 +1,15 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            ---
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            {%- include layout/data.liquid -%}
         | 
| 5 | 
            +
             | 
| 6 | 
            +
             | 
| 2 7 | 
             
            if(!(window.doNotTrack === "1" || navigator.doNotTrack === "1" || navigator.doNotTrack === "yes" || navigator.msDoNotTrack === "1")) {
         | 
| 3 8 | 
             
              (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
         | 
| 4 9 | 
             
              (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
         | 
| 5 10 | 
             
              m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
         | 
| 6 11 | 
             
              })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
         | 
| 7 12 |  | 
| 8 | 
            -
              ga('create', '{{  | 
| 13 | 
            +
              ga('create', '{{ head_.google.analytics.id }}', 'auto');
         | 
| 9 14 | 
             
              ga('send', 'pageview');
         | 
| 10 15 | 
             
            }
         | 
| 11 | 
            -
            </script>
         | 
| @@ -0,0 +1,275 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            ---
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            {%- include layout/data.liquid -%}
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            document.addEventListener("DOMContentLoaded", () => {
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              const terminal = document.getElementById("terminal");
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              if (terminal) {
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                // effects terminal: maximize
         | 
| 13 | 
            +
                // ----------------------------------------------------------------------------------------------
         | 
| 14 | 
            +
                const btnMax = terminal.querySelector(".terminal-header__max");
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                let isFullscreen = false;
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                // maximize/restore
         | 
| 19 | 
            +
                btnMax.addEventListener("click", () => {
         | 
| 20 | 
            +
                  isFullscreen = !isFullscreen;
         | 
| 21 | 
            +
                  terminal.classList.toggle("terminal-fullscreen", isFullscreen);
         | 
| 22 | 
            +
                });
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                // populate the terminal
         | 
| 25 | 
            +
                // ----------------------------------------------------------------------------------------------
         | 
| 26 | 
            +
                const socialsEl = document.getElementById("terminal-screen--socials");
         | 
| 27 | 
            +
                const screen = document.getElementById("screen");
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                const commands = {
         | 
| 30 | 
            +
                  // Multiple string is the same as using ` in Javascript
         | 
| 31 | 
            +
                  help: `{{ home_.terminal.help.menu }}`,
         | 
| 32 | 
            +
                  about: document.getElementById("home-content").innerHTML,
         | 
| 33 | 
            +
                  socials: socialsEl ? socialsEl.innerHTML : "{{ home_.terminal.no_socials }}"
         | 
| 34 | 
            +
                };
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                const createInputLine = () => {
         | 
| 37 | 
            +
                  const line = document.createElement("div");
         | 
| 38 | 
            +
                  line.className = "line";
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  const prompt = document.createElement("span");
         | 
| 41 | 
            +
                  prompt.className = "prompt";
         | 
| 42 | 
            +
                  prompt.textContent = "[{{ home_.terminal.user }}@{{ home_.terminal.hostname }} ~]$";
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  // wrapper para conter input, cursor e measure
         | 
| 45 | 
            +
                  const wrapper = document.createElement("span");
         | 
| 46 | 
            +
                  wrapper.className = "input-wrapper";
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  const input = document.createElement("input");
         | 
| 49 | 
            +
                  input.type = "text";
         | 
| 50 | 
            +
                  input.className = "input";
         | 
| 51 | 
            +
                  input.placeholder = `{{ home_.terminal.welcome }}`;
         | 
| 52 | 
            +
                  input.spellcheck = false;
         | 
| 53 | 
            +
                  input.autocomplete = "off";
         | 
| 54 | 
            +
                  input.autocorrect = "off";
         | 
| 55 | 
            +
                  input.autocapitalize = "off";
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  const cursor = document.createElement("span");
         | 
| 58 | 
            +
                  cursor.className = "cursor";
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  const measure = document.createElement("span");
         | 
| 61 | 
            +
                  measure.className = "measure";
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  wrapper.appendChild(input);
         | 
| 64 | 
            +
                  wrapper.appendChild(cursor);
         | 
| 65 | 
            +
                  wrapper.appendChild(measure);
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  line.appendChild(prompt);
         | 
| 68 | 
            +
                  line.appendChild(wrapper);
         | 
| 69 | 
            +
                  screen.appendChild(line);
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  input.focus();
         | 
| 72 | 
            +
                  screen.scrollTop = screen.scrollHeight;
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  // Updates the fake cursor position based on the input"s selectionStart
         | 
| 75 | 
            +
                  const updateCursor = () => {
         | 
| 76 | 
            +
                    const sel = input.selectionStart || 0;
         | 
| 77 | 
            +
                    // measure the text to the position of the caret
         | 
| 78 | 
            +
                    measure.textContent = input.value.slice(0, sel);
         | 
| 79 | 
            +
                    const textWidth = measure.offsetWidth; // largura do texto sem scroll
         | 
| 80 | 
            +
                    const visibleLeft = textWidth - input.scrollLeft;
         | 
| 81 | 
            +
                    cursor.style.left = `${visibleLeft}px`;
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    // ensure the caret is visible (for long texts): adjust input"s scrollLeft
         | 
| 84 | 
            +
                    const paddingRight = 10;
         | 
| 85 | 
            +
                    if (textWidth - input.scrollLeft > input.clientWidth - paddingRight) {
         | 
| 86 | 
            +
                      input.scrollLeft = textWidth - input.clientWidth + paddingRight;
         | 
| 87 | 
            +
                      cursor.style.left = `${textWidth - input.scrollLeft}px`;
         | 
| 88 | 
            +
                    } else if (textWidth < input.scrollLeft) {
         | 
| 89 | 
            +
                      input.scrollLeft = textWidth;
         | 
| 90 | 
            +
                      cursor.style.left = `${textWidth - input.scrollLeft}px`;
         | 
| 91 | 
            +
                    }
         | 
| 92 | 
            +
                  };
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  // show/hide cursor animation as focus changes
         | 
| 95 | 
            +
                  const onFocus = () => {
         | 
| 96 | 
            +
                    cursor.style.opacity = "1";
         | 
| 97 | 
            +
                    updateCursor();
         | 
| 98 | 
            +
                  };
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  const onBlur = () => {
         | 
| 101 | 
            +
                    cursor.style.opacity = "0";
         | 
| 102 | 
            +
                  };
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  input.addEventListener("input", updateCursor);
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  input.addEventListener("keydown", (e) => {
         | 
| 107 | 
            +
                    // Update position on keys that do not trigger input immediately (arrows, delete, etc.)
         | 
| 108 | 
            +
                    setTimeout(updateCursor, 0);
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    if (e.key === "Enter") {
         | 
| 111 | 
            +
                      e.preventDefault();
         | 
| 112 | 
            +
                      const cmd = input.value.trim().toLowerCase();
         | 
| 113 | 
            +
                      if (cmd) {
         | 
| 114 | 
            +
                        // remove input/cursor/measure and place fixed text
         | 
| 115 | 
            +
                        wrapper.removeChild(input);
         | 
| 116 | 
            +
                        wrapper.removeChild(cursor);
         | 
| 117 | 
            +
                        wrapper.removeChild(measure);
         | 
| 118 | 
            +
                        const cmdText = document.createElement("span");
         | 
| 119 | 
            +
                        cmdText.textContent = cmd;
         | 
| 120 | 
            +
                        wrapper.appendChild(cmdText);
         | 
| 121 | 
            +
                        processCommand(cmd);
         | 
| 122 | 
            +
                      } else {
         | 
| 123 | 
            +
                        // if you enter without command, it just creates a new empty line (with prompt)
         | 
| 124 | 
            +
                        wrapper.removeChild(input);
         | 
| 125 | 
            +
                        wrapper.removeChild(cursor);
         | 
| 126 | 
            +
                        wrapper.removeChild(measure);
         | 
| 127 | 
            +
                        const blank = document.createElement("span");
         | 
| 128 | 
            +
                        blank.textContent = "";
         | 
| 129 | 
            +
                        wrapper.appendChild(blank);
         | 
| 130 | 
            +
                      }
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                      // New line input
         | 
| 133 | 
            +
                      createInputLine();
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    } else if (e.key === "Escape") {
         | 
| 136 | 
            +
                      e.preventDefault();
         | 
| 137 | 
            +
                      screen.innerHTML = "";
         | 
| 138 | 
            +
                      createInputLine();
         | 
| 139 | 
            +
                    }
         | 
| 140 | 
            +
                  });
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  // arrows, mouse click, mouseup (position caret), etc.
         | 
| 143 | 
            +
                  input.addEventListener("keyup", updateCursor);
         | 
| 144 | 
            +
                  input.addEventListener("click", () => setTimeout(updateCursor, 0));
         | 
| 145 | 
            +
                  input.addEventListener("mouseup", () => setTimeout(updateCursor, 0));
         | 
| 146 | 
            +
                  input.addEventListener("focus", onFocus);
         | 
| 147 | 
            +
                  input.addEventListener("blur", onBlur);
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  updateCursor();
         | 
| 150 | 
            +
                };
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                // function show date
         | 
| 153 | 
            +
                function dateShow() {
         | 
| 154 | 
            +
                  const langBrowser = navigator.language || navigator.userLanguage;
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                  const options = {
         | 
| 157 | 
            +
                    weekday: 'long',
         | 
| 158 | 
            +
                    year: 'numeric',
         | 
| 159 | 
            +
                    month: 'long',
         | 
| 160 | 
            +
                    day: 'numeric',
         | 
| 161 | 
            +
                    hour: '2-digit',
         | 
| 162 | 
            +
                    minute: '2-digit'
         | 
| 163 | 
            +
                  };
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  let brMessage = "";
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  if (langBrowser === "pt-BR" ) {
         | 
| 168 | 
            +
                    brMessage = " (Horário de Brasília)";
         | 
| 169 | 
            +
                  }
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  try {
         | 
| 172 | 
            +
                    return new Date().toLocaleString(langBrowser, options) + brMessage;
         | 
| 173 | 
            +
                  } catch (e) {
         | 
| 174 | 
            +
                    // Fallback for en-US
         | 
| 175 | 
            +
                    return new Date().toLocaleString('en-US', options) + brMessage;
         | 
| 176 | 
            +
                  }
         | 
| 177 | 
            +
                }
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                // processes commands
         | 
| 180 | 
            +
                const processCommand = (cmd) => {
         | 
| 181 | 
            +
                  if (cmd === "help") {
         | 
| 182 | 
            +
                    helpWriteHTML(commands.help, "html");
         | 
| 183 | 
            +
                  } else if (cmd === "date") {
         | 
| 184 | 
            +
                    commandsPrint(dateShow(), "text");
         | 
| 185 | 
            +
                  // else if (cmd.startsWith("echo "))
         | 
| 186 | 
            +
                  //   commandsPrint(cmd.split(" ").slice(1).join(" "))
         | 
| 187 | 
            +
                  } else if (cmd === "about") {
         | 
| 188 | 
            +
                    aboutWriteHTML(commands.about);
         | 
| 189 | 
            +
                  } else if (cmd === "socials") {
         | 
| 190 | 
            +
                    socialsWriteHTML(commands.socials);
         | 
| 191 | 
            +
                  } else if (cmd === "clear") {
         | 
| 192 | 
            +
                    screen.innerHTML = "";
         | 
| 193 | 
            +
                  } else if (cmd) {
         | 
| 194 | 
            +
                    commandsPrint(cmd + `{{ home_.terminal.error }}`, "text");
         | 
| 195 | 
            +
                  }
         | 
| 196 | 
            +
                };
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                const helpWriteHTML = (text, mode = "html") => {
         | 
| 199 | 
            +
                  const wrapper = document.createElement("div");
         | 
| 200 | 
            +
                  wrapper.className = "line-wrapper";
         | 
| 201 | 
            +
                  const helpDescription = document.createElement("span");
         | 
| 202 | 
            +
                  helpDescription.className = "help-description";
         | 
| 203 | 
            +
                  helpDescription.innerHTML = `{{ home_.terminal.help.description | markdownify }}`;
         | 
| 204 | 
            +
                  const helpCommandTitle = document.createElement("span");
         | 
| 205 | 
            +
                  helpCommandTitle.className = "help-commands__title";
         | 
| 206 | 
            +
                  helpCommandTitle.textContent = "{{ home_.terminal.help.commands.title }}";
         | 
| 207 | 
            +
                  const helpCommandDesc = document.createElement("span");
         | 
| 208 | 
            +
                  helpCommandDesc.className = "help-commands__desc";
         | 
| 209 | 
            +
                  helpCommandDesc.textContent = `{{ home_.terminal.help.commands.description }}`;
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                  wrapper.appendChild(helpDescription);
         | 
| 212 | 
            +
                  wrapper.appendChild(helpCommandTitle);
         | 
| 213 | 
            +
                  wrapper.appendChild(helpCommandDesc);
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                  text.split("\n").forEach((t) => {
         | 
| 216 | 
            +
                    const line = document.createElement("div");
         | 
| 217 | 
            +
                    line.className = "line";
         | 
| 218 | 
            +
                    if (mode === "html") line.innerHTML = t; else line.textContent = t;
         | 
| 219 | 
            +
                    wrapper.appendChild(line);
         | 
| 220 | 
            +
                  });
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                  screen.appendChild(wrapper);
         | 
| 223 | 
            +
                  screen.scrollTop = screen.scrollHeight;
         | 
| 224 | 
            +
                };
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                const socialsWriteHTML = (content, mode = "html") => {
         | 
| 227 | 
            +
                  const wrapper = document.createElement("div");
         | 
| 228 | 
            +
                  wrapper.className = "line-wrapper";
         | 
| 229 | 
            +
                  const socialsCommandDesc = document.createElement("span");
         | 
| 230 | 
            +
                  socialsCommandDesc.className = "socials-command__desc";
         | 
| 231 | 
            +
                  socialsCommandDesc.textContent = `{{ socials_.description.terminal.command.description }}`;
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                  screen.appendChild(socialsCommandDesc);
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                  if (mode === "html") wrapper.innerHTML = content; else wrapper.textContent = content;
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                  screen.appendChild(wrapper);
         | 
| 238 | 
            +
                  screen.scrollTop = screen.scrollHeight;
         | 
| 239 | 
            +
                };
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                const aboutWriteHTML = (content, mode = "html") => {
         | 
| 242 | 
            +
                  const wrapper = document.createElement("div");
         | 
| 243 | 
            +
                  wrapper.className = "line-wrapper";
         | 
| 244 | 
            +
                  if (mode === "html") wrapper.innerHTML = content; else wrapper.textContent = content;
         | 
| 245 | 
            +
                  screen.appendChild(wrapper);
         | 
| 246 | 
            +
                  screen.scrollTop = screen.scrollHeight;
         | 
| 247 | 
            +
                };
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                const commandsPrint = (text, mode = "html") => {
         | 
| 250 | 
            +
                  // creates the wrapper to group all the lines
         | 
| 251 | 
            +
                  const wrapper = document.createElement("div");
         | 
| 252 | 
            +
                  wrapper.className = "line-wrapper";
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                  text.split("\n").forEach((t) => {
         | 
| 255 | 
            +
                    const line = document.createElement("div");
         | 
| 256 | 
            +
                    line.className = "line";
         | 
| 257 | 
            +
                    if (mode === "html") line.innerHTML = t; else line.textContent = t;
         | 
| 258 | 
            +
                    wrapper.appendChild(line);
         | 
| 259 | 
            +
                  });
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                  screen.appendChild(wrapper);
         | 
| 262 | 
            +
                  screen.scrollTop = screen.scrollHeight;
         | 
| 263 | 
            +
                };
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                // start terminal
         | 
| 266 | 
            +
                createInputLine();
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                // when clicking on the terminal, it always focuses on the last existing input
         | 
| 269 | 
            +
                terminal.addEventListener("click", (e) => {
         | 
| 270 | 
            +
                  // avoids focusing when clicking a header button, etc.
         | 
| 271 | 
            +
                  const lastInput = screen.querySelector(".input:last-of-type");
         | 
| 272 | 
            +
                  if (lastInput) lastInput.focus();
         | 
| 273 | 
            +
                });
         | 
| 274 | 
            +
              }
         | 
| 275 | 
            +
            });
         |