Added new box style for page headers, support for hint when hovering interactible elements, add support for expanding 88x31 pictures on click, updated index look and feel/text, switch to macros for reusable elements, fix ccd path, rename main.js to music to better reflect it's purpose and update i18n.js export global strings.

This commit is contained in:
天クマ 2026-04-21 20:32:49 -03:00
commit b56fe21a2b
22 changed files with 1247 additions and 131 deletions

View file

@ -1,5 +1,6 @@
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const i18n = require('./_data/i18n.js');
module.exports = function(eleventyConfig) { module.exports = function(eleventyConfig) {
eleventyConfig.addCollection("post", function(collectionApi) { eleventyConfig.addCollection("post", function(collectionApi) {
@ -21,7 +22,8 @@ module.exports = function(eleventyConfig) {
eleventyConfig.addCollection("88x31", () => { eleventyConfig.addCollection("88x31", () => {
return fs.readdirSync("static/images/88x31") return fs.readdirSync("static/images/88x31")
.map(file => ({ .map(file => ({
url: `/static/images/88x31/${file}` url: `/static/images/88x31/${file}`,
fileSlug: file
})); }));
}); });

View file

@ -9,11 +9,21 @@ const globalValues = {
xmpp: { url: "xmpp:adrianvictor@disroot.org", username: "adrianvictor@disroot.org" }, xmpp: { url: "xmpp:adrianvictor@disroot.org", username: "adrianvictor@disroot.org" },
email: "adrianvictor@disroot.org", email: "adrianvictor@disroot.org",
margarinaRecordsWebsite: "https://margarina-records.rf.gd", margarinaRecordsWebsite: "https://margarina-records.rf.gd",
genius: { url: "https://genius.com/tenkuma", username: "tenkuma" } genius: { url: "https://genius.com/tenkuma", username: "tenkuma" },
homeVideoLink: "https://www.youtube.com/watch?v=6bnNAnSY9Uo",
homeVideoImage: "/thumbnails/fl_studio_linux.png",
homeVideoWebsite: "YouTube",
homeVideoDuration: "5:53",
homeSongTitle: "Velkommen",
homeSongLink: "https://margarina.bandcamp.com/album/velkommen",
homeSongImage: "/songs/velkommen.jpg",
homeSongWebsite: "Bandcamp",
homeSongDuration: "5:39",
homeSongAccent: "#482948"
}; };
module.exports = { module.exports = {
// global: globalValues, global: globalValues,
en: { en: {
language: "english", language: "english",
availableInOtherLanguages: "Also available in other languages", availableInOtherLanguages: "Also available in other languages",
@ -23,9 +33,14 @@ module.exports = {
welcome: "welcome", welcome: "welcome",
homeWelcomeParagraph: "It seems that you have found my website! Hi, I am <b>Adrian Victor</b> (or <b>tenkuma</b>), a Brazilian guy who likes to mess around with computers, computer programs and <i>enimatpyrtlyhtemids</i>.", homeWelcomeParagraph: "It seems that you have found my website! Hi, I am <b>Adrian Victor</b> (or <b>tenkuma</b>), a Brazilian guy who likes to mess around with computers, computer programs and <i>enimatpyrtlyhtemids</i>.",
socialsAndContact: "socials and contact", socialsAndContact: "socials and contact",
aboutMe: "about me",
myMusic: "my music", myMusic: "my music",
myVideos: "my videos", myVideos: "my videos",
mySoftware: "my software", mySoftware: "my software",
homeAboutMeParagraph: `
My name is Adrian Victor, but I go by tenkuma on-line. I'm in high school's last year, also studying computing. My hobbies are music and music production, programming, selfhosting, Linux, and a lot more.
`,
homeAboutMeParagraphTwo: `Tenkuma, or 天くま in japanese, means celestial bear and was given by a friend of mine that I lost contact a long time ago. Sakata is gone, but the name stayed and turned into an integral part of my digital self.`,
homeSocialsAndContactParagraph: ` homeSocialsAndContactParagraph: `
I'm publicly available at Mastodon <a href='${globalValues.mastodon.url}'>(${globalValues.mastodon.username})</a>, I'm publicly available at Mastodon <a href='${globalValues.mastodon.url}'>(${globalValues.mastodon.username})</a>,
GitHub <a href='${globalValues.github.url}'>(${globalValues.github.username})</a>, GitHub <a href='${globalValues.github.url}'>(${globalValues.github.username})</a>,
@ -38,9 +53,9 @@ module.exports = {
`, `,
homeSocialsAndContactParagraphTwo: `You can message me on my E-mail <a href="mailto:${globalValues.email}">(${globalValues.email})</a> or feel free to get in touch through any of the other places mentioned above. For project-specific subjects, check for the project's contact field or if there's no such field add <i>+projectname</i> to my E-mail address (example: adrianvictor+coolproject@disroot.org).</p> homeSocialsAndContactParagraphTwo: `You can message me on my E-mail <a href="mailto:${globalValues.email}">(${globalValues.email})</a> or feel free to get in touch through any of the other places mentioned above. For project-specific subjects, check for the project's contact field or if there's no such field add <i>+projectname</i> to my E-mail address (example: adrianvictor+coolproject@disroot.org).</p>
<p><i><b>Please, avoid reaching me through ways not mentioned above :)</b></i>`, <p><i><b>Please, avoid reaching me through ways not mentioned above :)</b></i>`,
homeMyMusicParagraph: `Me and my friends have an amateur record label called <span class="margarinaColor">Margarina Records</span>, things usually move slowly with my musical works, usually because of college and the lack of proper music production knowledge, but I'm working my way through it.`, homeMyMusicParagraph: `I've always loved music, and lately I've been finding music production very interesting. I publish my songs as <i>tenkuma</i>, and have founded an amateur label called <a href="${globalValues.margarinaRecordsWebsite}">Margarina Records</a> with my friends.`,
homeMyMusicParagraphTwo: `You can follow my latest songs at the <a href="${globalValues.margarinaRecordsWebsite}">label website</a> and on <a href="${globalValues.genius.url}">Genius</a>. You'd probably also like the other member's works as well, so take a look at all songs from MGR.`, homeMyMusicParagraphTwo: `You can find my latest on songs <a href="${globalValues.genius.url}">Genius</a>.`,
homeMyVideoParagraph: "I have a YouTube channel where I post mostly Minecraft videos, but I want to have other types of content in the future. There's no scedule for my videos because it takes a lot of editing time to put a video together, and I have little time to work on my own projects, you should subscribe if you want to know when I post something!", homeMyVideoParagraph: "I make videos for my <a href='${globalValues.youtube.url}'>YouTube channel</a>. Videos do not come regularly, there's no schedule—just a guy wanting to show something.",
homeMyVideoRandomVideoParagraph: "Here's a random video I'm proud of:", homeMyVideoRandomVideoParagraph: "Here's a random video I'm proud of:",
homeVideoTitle: "Installing FL Studio on linux.", homeVideoTitle: "Installing FL Studio on linux.",
homeMySoftwareParagraph: `I am studying computing at IFC (SC, Brazil) but in my free time I have some projects like computer applications, Minecraft plugins, Minecraft servers, etc... Anything that is public should be in my <a href="${globalValues.github.url}">GitHub profile</a>.`, homeMySoftwareParagraph: `I am studying computing at IFC (SC, Brazil) but in my free time I have some projects like computer applications, Minecraft plugins, Minecraft servers, etc... Anything that is public should be in my <a href="${globalValues.github.url}">GitHub profile</a>.`,
@ -57,7 +72,8 @@ module.exports = {
options: "Options", options: "Options",
alsoAvailableAsVideo: "Also available as video", alsoAvailableAsVideo: "Also available as video",
websiteDescription: "Personal website/blog of Adrian Victor.", websiteDescription: "Personal website/blog of Adrian Victor.",
miscellaneous: "Miscellaneous" miscellaneous: "Miscellaneous",
i88x31hover: "Click to expand"
}, },
pt: { pt: {
language: "português", language: "português",
@ -68,9 +84,14 @@ module.exports = {
welcome: "bem-vindo", welcome: "bem-vindo",
homeWelcomeParagraph: "Parece que você encontrou meu website! Olá, sou <b>Adrian Victor</b> (ou <b>tenkuma</b>), um cara brasileiro que gosta de mexer com computadores, programas de computadores e <i>enimatpirtlitemídios</i>.", homeWelcomeParagraph: "Parece que você encontrou meu website! Olá, sou <b>Adrian Victor</b> (ou <b>tenkuma</b>), um cara brasileiro que gosta de mexer com computadores, programas de computadores e <i>enimatpirtlitemídios</i>.",
socialsAndContact: "redes sociais e contato", socialsAndContact: "redes sociais e contato",
aboutMe: "sobre mim",
myMusic: "música", myMusic: "música",
myVideos: "vídeos", myVideos: "vídeos",
mySoftware: "software", mySoftware: "software",
homeAboutMeParagraph: `
Meu nome é Adrian Victor, mas on-line eu uso o nickname tenkuma. Estou no último ano do ensino médio e estudo informática. Meus hobbies são escutar e produzir música, programação, selfhosting, Linux, e muito mais.
`,
homeAboutMeParagraphTwo: `Tenkuma, ou 天くま em japonês, significa urso celestial e foi um nome dado a mim por um amigo que eu já perdi contato há muito tempo. Sakata se foi, mas o nome ficou e se tornou parte integral da personalidade do meu eu digital até hoje.`,
homeSocialsAndContactParagraph: ` homeSocialsAndContactParagraph: `
Estou publicamente disponível no Mastodon <a href='${globalValues.mastodon.url}'>(${globalValues.mastodon.username})</a>, Estou publicamente disponível no Mastodon <a href='${globalValues.mastodon.url}'>(${globalValues.mastodon.username})</a>,
GitHub <a href='${globalValues.github.url}'>(${globalValues.github.username})</a>, GitHub <a href='${globalValues.github.url}'>(${globalValues.github.username})</a>,
@ -81,11 +102,10 @@ module.exports = {
Modrinth <a href='${globalValues.modrinth.url}'>(${globalValues.modrinth.username})</a> Modrinth <a href='${globalValues.modrinth.url}'>(${globalValues.modrinth.username})</a>
e XMPP <a href='${globalValues.xmpp.url}'>(${globalValues.xmpp.username})</a>. e XMPP <a href='${globalValues.xmpp.url}'>(${globalValues.xmpp.username})</a>.
`, `,
homeSocialsAndContactParagraphTwo: `Você pode enviar um correio eletrônico para <a href="mailto:${globalValues.email}">(${globalValues.email})</a> ou me contactar por qualquer outro meio citado acima. Para assuntos relativos a projetos específicos, verifique o campo de contato do projeto, caso não haja um adicione <i>+nomedoprojeto</i> ao meu endereço de E-mail (exemplo: adrianvictor+projetolegal@disroot.org).</p> homeSocialsAndContactParagraphTwo: `Você pode enviar um correio eletrônico para <a href="mailto:${globalValues.email}">(${globalValues.email})</a> ou me contactar por qualquer outro meio citado acima. Para assuntos relativos a projetos específicos, verifique o campo de contato do projeto, caso não haja um adicione <i>+nomedoprojeto</i> ao meu endereço de E-mail (exemplo: adrianvictor+projetolegal@disroot.org).`,
<p><i><b>Por favor, evite me contactar por meios não citados acima :)</b></i>`, homeMyMusicParagraph: `Sempre amei música, e tenho achado produção musical algo muito interessante ultimamente. Publico minhas músicas como <i>tenkuma</i>, junto com meus amigos formei a <a href="${globalValues.margarinaRecordsWebsite}">Margarina Records</a>—uma label amadora.`,
homeMyMusicParagraph: `Eu e meus amigos temos uma gravadora de música amadora chamada <span class="margarinaColor">Margarina Records</span>, as coisas andam devagar com meus projetos musicais, geralmente por causa da escola ou falta de conhecimento no campo, mas eu estou dando um jeito.`, homeMyMusicParagraphTwo: `Você pode conferir minhas músicas mais recentes no meu perfil do <a href="${globalValues.genius.url}">Genius</a>.`,
homeMyMusicParagraphTwo: `Você pode conferir minhas músicas mais recentes no <a href="${globalValues.margarinaRecordsWebsite}">site da gravadora</a> e no <a href="${globalValues.genius.url}">Genius</a>. Você provavelmente vai gostar do trabalho dos outros membros, então dê uma olhada nas outras tracks da MGR.`, homeMyVideoParagraph: "Eu faço vídeos para o <a href='${globalValues.youtube.url}'>meu canal do YouTube</a>. Não posto regularmente; não tem calendário—apenas eu mostrando alguma coisa em vídeo.",
homeMyVideoParagraph: "Eu tenho um canal no YouTube em que na maioria das vezes eu posto vídeos de Minecraft, mas pretendo expandir a variedade de conteúdos no futuro. Não tenho nenhuma previsão de publicação no meu canal, pois editar os vídeos leva tempo e eu tenho pouco tempo para trabalhar nos meus projetos, você deveria se inscrever se quiser saber quando eu posto meus vídeos!",
homeMyVideoRandomVideoParagraph: "Aqui está um vídeo aleatório que eu me orgulho de ter postado:", homeMyVideoRandomVideoParagraph: "Aqui está um vídeo aleatório que eu me orgulho de ter postado:",
homeVideoTitle: "Como instalar o FL Studio no Linux?", homeVideoTitle: "Como instalar o FL Studio no Linux?",
homeMySoftwareParagraph: `Estou estudando informática no IFC (SC, Brazil) mas no meu tempo livre tenho projetos como programas de computador, plugins para Minecraft, servidores Minecraft, etc... Todos meus projetos públicos estão disponíveis no meu <a href="${globalValues.github.url}">perfil do GitHub</a>.`, homeMySoftwareParagraph: `Estou estudando informática no IFC (SC, Brazil) mas no meu tempo livre tenho projetos como programas de computador, plugins para Minecraft, servidores Minecraft, etc... Todos meus projetos públicos estão disponíveis no meu <a href="${globalValues.github.url}">perfil do GitHub</a>.`,
@ -102,6 +122,7 @@ module.exports = {
options: "Opções", options: "Opções",
alsoAvailableAsVideo: "Também disponível em vídeo", alsoAvailableAsVideo: "Também disponível em vídeo",
websiteDescription: "Website/blog pessoal de Adrian Victor.", websiteDescription: "Website/blog pessoal de Adrian Victor.",
miscellaneous: "Miscelâneo" miscellaneous: "Miscelâneo",
i88x31hover: "Clique para expandir"
} }
}; };

View file

@ -6,8 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/main.css?fixcache=1"> <link rel="stylesheet" href="/static/main.css?fixcache=1">
<script src="/static/scripts/ccd.js"></script> <script src="/static/scripts/ccd.js"></script>
<script src="/static/scripts/main.js" defer></script> <script src="/static/scripts/music.js" defer></script>
<script src="/static/scripts/88x31.js" defer></script> <script src="/static/scripts/88x31.js" defer></script>
<script src="/static/scripts/tips.js" defer></script>
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">

35
_includes/macros.njk Normal file
View file

@ -0,0 +1,35 @@
{% macro i88x31(link) %}
<img class="i88x31" src="/static/images/88x31/{{ link }}" data-tip="<b>{{ i18n[langKey].i88x31hover }}</b> ({{ link }})">
{% endmacro %}
{% macro videoCard(videoLink, videoTitle, videoImage, videoWebsite, videoDuration, videoAccent) %}
<div class="youtubeCardHolderHelper">
<div class="youtubeCardHolder">
<a href="{{ videoLink }}">
<div class="blogpostYoutubeVideo" {% if videoAccent %}style="border-color: {{ videoAccent }};"{% endif %}>
<img src="/static/images{{ videoImage }}">
<div class="videoHeader">
<!-- <p class="alsoAvailable">{{ i18n[langKey].alsoAvailableAsVideo }}:</p> -->
<h2 class="videoTitle" {% if videoAccent %}style="color: {{ videoAccent }};"{% endif %}>{{ videoTitle }}</h2>
<p>{{ videoWebsite }}{% if videoDuration %} ({{ videoDuration }}){% endif %}</p>
</div>
<!-- <p class="goLabel">ir</p> -->
</div>
</a>
</div>
</div>
{% endmacro %}
{% macro projectCard(projectName, projectDescription, projectLink, projectImage, projectImageAlt) %}
<div class="hsProject">
<div class="hsProjectHeader">
<div class="hsProjectImage"><img src="{{ projectImage }}" alt="{{ projectImageAlt or projectName }}"></div>
<a href="{{ projectLink }}" class="hsProjectHeaderIcon">
<img src="/static/visual/github.svg" class="invertedc">
</a>
</div>
<div class="hsProjectContent">
<p>{{ projectDescription }}</p>
</div>
</div>
{% endmacro %}

View file

@ -3,6 +3,8 @@ layout: base.njk
title: Adrian Victor:Blog title: Adrian Victor:Blog
--- ---
{% set altLanguages = collections.post | alternateLanguages(postId, langKey) %} {% set altLanguages = collections.post | alternateLanguages(postId, langKey) %}
{% from "macros.njk" import videoCard with context %}
<main> <main>
<article> <article>
<div id="postHeader"> <div id="postHeader">
@ -20,18 +22,9 @@ title: Adrian Victor:Blog
{% endif %} {% endif %}
</div> </div>
{% if postVideoLink and postVideoImage and postVideoTitle and postVideoWebsite %} {% if postVideoLink and postVideoImage and postVideoTitle and postVideoWebsite %}
<a href="{{ postVideoLink }}"> {{ videoCard(postVideoLink, postVideoTitle, postVideoImage, postVideoWebsite, postVideoDuration) }}
<div class="blogpostYoutubeVideo">
<img src="/static/images/thumbnails/{{ postVideoImage }}">
<div class="videoHeader">
<p class="alsoAvailable">{{ i18n[langKey].alsoAvailableAsVideo }}:</p>
<h2 class="videoTitle">{{ postVideoTitle }}</h2>
<p>{{ postVideoWebsite }}{% if postVideoDuration %} ({{ postVideoDuration }}){% endif %}</p>
</div>
<!-- <p class="goLabel">ir</p> -->
</div>
</a>
{% endif %} {% endif %}
{{ content | safe }} {{ content | safe }}
</article> </article>
</main> </main>

118
index.njk
View file

@ -6,6 +6,9 @@ pagination:
permalink: "/{{ langKey }}/index.html" permalink: "/{{ langKey }}/index.html"
layout: base.njk layout: base.njk
--- ---
{% from "macros.njk" import i88x31 with context %}
{% from "macros.njk" import videoCard with context %}
{% from "macros.njk" import projectCard %}
<div id="homeSquares"> <div id="homeSquares">
</div> </div>
@ -19,90 +22,79 @@ layout: base.njk
display: none; display: none;
} }
</style></noscript> </style></noscript>
<div class="hs" id="hsDefault"> <div class="hs" id="hsDefault">
<div class="box pageHeaderBox">
<h1 id="homeTitle">{{ i18n[langKey].welcome | smartTitle }}</h1> <h1 id="homeTitle">{{ i18n[langKey].welcome | smartTitle }}</h1>
<p>{{ i18n[langKey].homeWelcomeParagraph | safe }}</p> <p>{{ i18n[langKey].homeWelcomeParagraph | safe }}</p>
<img class="i88x31" src="/static/images/88x31/tenkuma.gif"> {{ i88x31("tenkuma.gif") }}
<img class="i88x31" src="/static/images/88x31/anybrowser6.gif"> {{ i88x31("anybrowser6.gif") }}
<img class="i88x31" src="/static/images/88x31/ai.gif"> {{ i88x31("ai.gif") }}
<img class="i88x31" src="/static/images/88x31/WEBP.gif"> {{ i88x31("WEBP.gif") }}
<img class="i88x31" src="/static/images/88x31/rainbowrain.gif"> {{ i88x31("rainbowrain.gif") }}
<img class="i88x31" src="/static/images/88x31/rave.gif"> {{ i88x31("blasphemy.gif") }}
<img class="i88x31" src="/static/images/88x31/blasphemy.gif"> </div>
<hr>
<h2>{{ i18n[langKey].aboutMe | smartTitle }}</h2>
<p>{{ i18n[langKey].homeAboutMeParagraph | safe }}</p>
<p>{{ i18n[langKey].homeAboutMeParagraphTwo | safe }}</p>
<h2>{{ i18n[langKey].socialsAndContact | smartTitle }}</h2> <h2>{{ i18n[langKey].socialsAndContact | smartTitle }}</h2>
<p>{{ i18n[langKey].homeSocialsAndContactParagraph | safe }}</p> <p>{{ i18n[langKey].homeSocialsAndContactParagraph | safe }}</p>
<p>{{ i18n[langKey].homeSocialsAndContactParagraphTwo | safe }}</p> <p>{{ i18n[langKey].homeSocialsAndContactParagraphTwo | safe }}</p>
</div> </div>
<div class="hs" id="hsMusic"> <div class="hs" id="hsMusic">
<div class="box pageHeaderBox">
<h1>{{ i18n[langKey].myMusic | smartTitle }}</h1> <h1>{{ i18n[langKey].myMusic | smartTitle }}</h1>
<p>{{ i18n[langKey].homeMyMusicParagraph | safe }}</p> <p>{{ i18n[langKey].homeMyMusicParagraph | safe }}</p>
<p>{{ i18n[langKey].homeMyMusicParagraphTwo | safe }}</p> <p>{{ i18n[langKey].homeMyMusicParagraphTwo | safe }}</p>
{{ i88x31("rave.gif") }}
{{ i88x31("happymix.gif") }}
</div>
<hr>
<div class="hsMusicCard">
{{
videoCard(
i18n["global"].homeSongLink,
i18n["global"].homeSongTitle,
i18n["global"].homeSongImage,
i18n["global"].homeSongWebsite,
i18n["global"].homeSongDuration,
i18n["global"].homeSongAccent
)
}}
</div>
</div> </div>
<div class="hs" id="hsVideo"> <div class="hs" id="hsVideo">
<div class="box pageHeaderBox">
<h1>{{ i18n[langKey].myVideos | smartTitle }}</h1> <h1>{{ i18n[langKey].myVideos | smartTitle }}</h1>
<p>{{ i18n[langKey].homeMyVideoParagraph | safe }}</p> <p>{{ i18n[langKey].homeMyVideoParagraph | safe }}</p>
<p>{{ i18n[langKey].homeMyVideoRandomVideoParagraph | safe }}</p> </div>
<a href="https://www.youtube.com/watch?v=6bnNAnSY9Uo"> <hr>
<div style="margin-bottom: 1em;" class="blogpostYoutubeVideo"> {{
<img src="/static/images/thumbnails/fl_studio_linux.png"> videoCard(
<div class="videoHeader"> i18n["global"].homeVideoLink,
<h2 class="videoTitle">{{ i18n[langKey].homeVideoTitle | safe }}</h2> i18n[langKey].homeVideoTitle,
<p>YouTube (5:53)</p> i18n["global"].homeVideoImage,
</div> i18n["global"].homeVideoWebsite,
</div> i18n["global"].homeVideoDuration
</a> )
}}
</div> </div>
<div class="hs" id="hsCode"> <div class="hs" id="hsCode">
<div class="box pageHeaderBox">
<h1>{{ i18n[langKey].mySoftware | smartTitle }}</h1> <h1>{{ i18n[langKey].mySoftware | smartTitle }}</h1>
<p>{{ i18n[langKey].homeMySoftwareParagraph | safe }}</p> <p>{{ i18n[langKey].homeMySoftwareParagraph | safe }}</p>
{# <p>{{ i18n[langKey].homeMySoftwareNotableProjects | safe }}</p> #} {# <p>{{ i18n[langKey].homeMySoftwareNotableProjects | safe }}</p> #}
</div>
<hr>
<div class="hsProjects"> <div class="hsProjects">
<div class="hsProject"> {{ projectCard("Jamfish", i18n[langKey].jamfishProjectDesctiption, "https://github.com/adrianvic/jamfish", "/static/images/jamfish-wide.png") }}
<div class="hsProjectHeader"> {{ projectCard("ItemEconomy", i18n[langKey].itemeconomyProjectDesctiption, "https://github.com/adrianvic/ItemEconomy", "/static/images/itemeconomy2-wide.png") }}
<div class="hsProjectImage"><img src="/static/images/jamfish-wide.png" alt="{{ i18n[langKey].pestoWikiLogoAlt | safe }}"></div> {{ projectCard("Eye of Nemesis", i18n[langKey].eyeofnemesisProjectDesctiption, "https://github.com/adrianvic/NemesisEye", "/static/images/eye_of_nemesis.png") }}
<a href="https://github.com/adrianvic/jamfish" class="hsProjectHeaderIcon"> {{ projectCard("PestoWiki", i18n[langKey].pestoProjectDesctiption, "https://github.com/Margarina-not-butter/PestoWiki", "/static/images/pestowikifullwhite.png") }}
<img src="/static/visual/github.svg" class="invertedc">
</a>
</div>
<div class="hsProjectContent">
<p>{{ i18n[langKey].jamfishProjectDesctiption | safe }}</p>
</div>
</div>
<div class="hsProject">
<div class="hsProjectHeader">
<div class="hsProjectImage"><img src="/static/images/eye_of_nemesis.png" alt="{{ i18n[langKey].eyeofnemesisLogoAlt | safe }}"></div>
<a href="https://github.com/adrianvic/NemesisEye" class="hsProjectHeaderIcon">
<img src="/static/visual/github.svg" class="invertedc">
</a>
</div>
<div class="hsProjectContent">
<p>{{ i18n[langKey].eyeofnemesisProjectDesctiption | safe }}</p>
</div>
</div>
<div class="hsProject">
<div class="hsProjectHeader">
<div class="hsProjectImage"><img src="/static/images/itemeconomy2-wide.png" alt="{{ i18n[langKey].itemeconomyLogoAlt | safe }}"></div>
<a href="https://github.com/adrianvic/ItemEconomy" class="hsProjectHeaderIcon">
<img src="/static/visual/github.svg" class="invertedc">
</a>
</div>
<div class="hsProjectContent">
<p>{{ i18n[langKey].itemeconomyProjectDesctiption | safe }}</p>
</div>
</div>
<div class="hsProject">
<div class="hsProjectHeader">
<div class="hsProjectImage"><img src="/static/images/pestowikifullwhite.png" alt="{{ i18n[langKey].jamfishLogoAlt | safe }}"></div>
<a href="https://github.com/Margarina-not-butter/PestoWiki" class="hsProjectHeaderIcon">
<img src="/static/visual/github.svg" class="invertedc">
</a>
</div>
<div class="hsProjectContent">
<p>{{ i18n[langKey].pestoProjectDesctiption | safe }}</p>
</div>
</div>
</div> </div>
</div> </div>
</main> </main>

191
maintenance/edit-i18n.js Normal file
View file

@ -0,0 +1,191 @@
// Coded entirely by ChatGPT
// :(
const express = require("express");
const fs = require("fs");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const generate = require("@babel/generator").default;
const t = require("@babel/types");
const app = express();
app.use(express.json());
const FILE = "../_data/i18n.js";
function loadAST() {
const code = fs.readFileSync(FILE, "utf8");
return parser.parse(code, { sourceType: "module" });
}
function extract(ast) {
const out = {};
traverse(ast, {
AssignmentExpression(path) {
if (
path.node.left.object?.name === "module" &&
path.node.left.property?.name === "exports"
) {
path.node.right.properties.forEach(langProp => {
const lang = langProp.key.name || langProp.key.value;
out[lang] = {};
langProp.value.properties.forEach(p => {
const key = p.key.name || p.key.value;
out[lang][key] = p.value.extra?.raw || generate(p.value).code;
});
});
}
}
});
return out;
}
function write(ast, newData) {
traverse(ast, {
AssignmentExpression(path) {
if (
path.node.left.object?.name === "module" &&
path.node.left.property?.name === "exports"
) {
path.node.right.properties.forEach(langProp => {
const lang = langProp.key.name || langProp.key.value;
const existingKeys = new Set(
langProp.value.properties.map(p => p.key.name || p.key.value)
);
// update existing
langProp.value.properties.forEach(p => {
const key = p.key.name || p.key.value;
if (key in (newData[lang] || {})) {
p.value = parser.parseExpression(newData[lang][key]);
}
});
// add new keys
Object.keys(newData[lang] || {}).forEach(key => {
if (!existingKeys.has(key)) {
langProp.value.properties.push(
t.objectProperty(
t.identifier(key),
parser.parseExpression(newData[lang][key])
)
);
}
});
});
}
}
});
const output = generate(ast, { retainLines: true }).code;
fs.writeFileSync(FILE, output);
}
app.get("/data", (req, res) => {
const ast = loadAST();
res.json(extract(ast));
});
app.post("/save", (req, res) => {
const ast = loadAST();
write(ast, req.body);
res.send("ok");
});
app.get("/", (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<body>
<h2>i18n Editor</h2>
<table id="t"></table>
<button onclick="addRow()">Add</button>
<button onclick="save()">Save</button>
<script>
let data;
fetch('/data').then(r=>r.json()).then(d=>{
data=d;
render();
});
function render(){
const table=document.getElementById('t');
table.innerHTML='';
const langs=Object.keys(data);
const keys=[...new Set(langs.flatMap(l=>Object.keys(data[l]||{})))];
// header
const headRow=document.createElement('tr');
const thKey=document.createElement('th');
thKey.textContent='key';
headRow.appendChild(thKey);
langs.forEach(l=>{
const th=document.createElement('th');
th.textContent=l;
headRow.appendChild(th);
});
table.appendChild(headRow);
// rows
keys.forEach(k=>{
const tr=document.createElement('tr');
const tdKey=document.createElement('td');
tdKey.textContent=k;
tr.appendChild(tdKey);
langs.forEach(l=>{
const td=document.createElement('td');
const input=document.createElement('input');
input.value = (data[l] && data[l][k]) || '';
input.addEventListener('change', (e)=>{
upd(l, k, e.target.value);
});
td.appendChild(input);
tr.appendChild(td);
});
table.appendChild(tr);
});
}
function upd(lang,key,val){
if(!data[lang])data[lang]={};
data[lang][key]=val;
}
function addRow(){
const k=prompt('key');
if(!k)return;
Object.keys(data).forEach(l=>data[l][k]='');
render();
}
function save(){
fetch('/save',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify(data)
});
}
</script>
</body>
</html>
`);
});
app.listen(3000,()=>console.log('http://localhost:3000'));

View file

@ -8,6 +8,7 @@ pagination:
pageTitle: 88x31 pageTitle: 88x31
tags: misc tags: misc
--- ---
{% from "macros.njk" import i88x31 with context %}
<main> <main>
<div class="box pageHeaderBox"> <div class="box pageHeaderBox">
@ -16,11 +17,11 @@ tags: misc
</div> </div>
<hr> <hr>
<h2>{{ t.me }}</h2> <h2>{{ t.me }}</h2>
<img class="i88x31" src="/static/images/88x31/tenkuma.gif"> {{ i88x31("tenkuma.gif") }}
<h2>{{ t.others }}</h2> <h2>{{ t.others }}</h2>
<div class=""> <div class="">
{% for image in collections.88x31 %} {% for image in collections.88x31 %}
<img class="i88x31" src="{{ image.url }}"> {{ i88x31(image.fileSlug) }}
{% endfor %} {% endfor %}
</div> </div>
</main> </main>

View file

@ -1,6 +1,6 @@
{ {
"pageTitle": "Bookmarks", "pageTitle": "Bookmarks",
"pageDescription": "Minha coleção de sites e páginas interessantes.", "pageDescription": "My collection of interesting websites/pages.",
"profiles": "Profiles", "profiles": "Profiles",
"downloads": "Downloads" "downloads": "Downloads"
} }

View file

@ -8,12 +8,13 @@ tags: misc
background: towers.jpg background: towers.jpg
backgroundOpacity: .2 backgroundOpacity: .2
--- ---
{% from "macros.njk" import i88x31 with context %}
<main> <main>
<div class="box pageHeaderBox"> <div class="box pageHeaderBox">
<h1>{{ t.pageTitle }}</h1> <h1>{{ t.pageTitle }}</h1>
<p>{{ t.intro }}</p> <p>{{ t.intro }}</p>
<img class="i88x31" src="/static/images/88x31/BOOKMARKthispageNOW.png" alt=""> {{ i88x31("BOOKMARKthispageNOW.png") }}
</div> </div>
<hr> <hr>
{% for sectionName, section in c.links %} {% for sectionName, section in c.links %}
@ -24,7 +25,7 @@ backgroundOpacity: .2
<dd> <dd>
{% if link.88x31 %} {% if link.88x31 %}
{% for 88x31 in link.88x31 %} {% for 88x31 in link.88x31 %}
<img class="i88x31" style="margin-top: .6em;" src="/static/images/88x31/{{ 88x31 }}"> {{ i88x31(88x31) }}
{% endfor %} {% endfor %}
<br> <br>
{% endif %} {% endif %}

912
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,11 @@
"license": "ISC", "license": "ISC",
"type": "commonjs", "type": "commonjs",
"devDependencies": { "devDependencies": {
"eleventy-plugin-citations": "^0.1.10" "@babel/generator": "^7.29.1",
"@babel/parser": "^7.29.2",
"@babel/traverse": "^7.29.0",
"eleventy-plugin-citations": "^0.1.10",
"express": "^5.2.1",
"readline-sync": "^1.4.10"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/images/88x31/cd.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

View file

@ -102,6 +102,7 @@ header div {
mask-size: 100% 100%; mask-size: 100% 100%;
user-select: none; user-select: none;
transition: .4s; transition: .4s;
-webkit-user-drag: none;
} }
header ul { header ul {
@ -147,7 +148,7 @@ blockquote, main p {
} }
main h1, main h2 { main h1, main h2 {
/* margin-bottom: .2em; */ margin-bottom: .2em;
} }
main h2 { main h2 {
@ -169,6 +170,7 @@ hr {
2px 7px 5px rgba(0,0,0,0.3), 2px 7px 5px rgba(0,0,0,0.3),
0px -4px 10px rgba(0,0,0,0.3); 0px -4px 10px rgba(0,0,0,0.3);
/* margin: .5em 0; */ /* margin: .5em 0; */
margin-bottom: 1em;
} }
.box { .box {
@ -297,6 +299,15 @@ header div:first-child {
gap: 10px; gap: 10px;
} }
.youtubeCardHolderHelper {
display: flex;
justify-content: center;
}
.hsMusicCard .youtubeCardHolder {
width: 50%;
}
div.hs { div.hs {
display: none; display: none;
} }
@ -785,6 +796,8 @@ hs {
.i88x31 { .i88x31 {
transition: .2s; transition: .2s;
image-rendering: pixelated; image-rendering: pixelated;
width: 88px;
height: 31px;
} }
.i88x31.selected { .i88x31.selected {

View file

@ -5,7 +5,7 @@ document.addEventListener('keydown', function(event) {
if (event.code === konamiCode[keyIndex]) { if (event.code === konamiCode[keyIndex]) {
keyIndex++; keyIndex++;
if (keyIndex === konamiCode.length) { if (keyIndex === konamiCode.length) {
window.location.href = './static/toyourdreams.txt' window.location.href = '/static/toyourdreams.txt'
keyIndex = 0; keyIndex = 0;
} }
} else { } else {

15
static/scripts/tips.js Normal file
View file

@ -0,0 +1,15 @@
/* This script provides functionality similar to FL Studio's hint panel. */
const elements = document.querySelectorAll('[data-tip]');
const hint = document.querySelector("#headerSubtitle");
const hintPanelDefaultText = hint.innerHTML;
elements.forEach(el => {
el.addEventListener('mouseenter', function() {
hint.innerHTML = `${this.dataset.tip}`;
});
el.addEventListener('mouseleave', function() {
hint.innerHTML = hintPanelDefaultText;
});
})