Merge pull request 'Rewrite v2' (#1) from rewrite into main
Reviewed-on: #1
10
.editorconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{js,json,yml}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
228
.eleventy.js
|
@ -1,39 +1,213 @@
|
|||
const { DateTime } = require("luxon")
|
||||
const markdownIt = require("markdown-it");
|
||||
const markdownItAnchor = require("markdown-it-anchor");
|
||||
const timeToRead = require("eleventy-plugin-time-to-read")
|
||||
import { createRequire } from "module"
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
module.exports = function(eleventyConfig) {
|
||||
eleventyConfig.addPassthroughCopy({ "static": "/" })
|
||||
import { basename, dirname, extname, join, relative } from "path";
|
||||
import { access, constants, copyFile, mkdir, readdir, readFile, stat, unlink } from "fs/promises";
|
||||
import { createHash } from "crypto";
|
||||
|
||||
eleventyConfig.addPlugin(timeToRead, {
|
||||
import { DateTime } from "luxon";
|
||||
|
||||
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
||||
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
|
||||
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
|
||||
|
||||
import markdownIt from "markdown-it";
|
||||
import markdownItAnchor from "markdown-it-anchor";
|
||||
const markdownItEmoji = require("markdown-it-emoji");
|
||||
import markdownItFootnote from "markdown-it-footnote";
|
||||
|
||||
const HASHED_ASSETS = [".css", ".js"]
|
||||
const assetsManifest = {}
|
||||
|
||||
async function hashFile(filePath) {
|
||||
const content = await readFile(filePath)
|
||||
return createHash("sha1").update(content).digest("hex").slice(0, 12)
|
||||
}
|
||||
|
||||
async function walk(dir) {
|
||||
let files = [];
|
||||
for (const item of await readdir(dir, { withFileTypes: true })) {
|
||||
const fullPath = join(dir, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
files = files.concat(await walk(fullPath));
|
||||
} else if (item.isFile()) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
async function prepareManifest(assetsPath, log = console.log) {
|
||||
const files = await walk(assetsPath);
|
||||
|
||||
if (process.env.ELEVENTY_RUN_MODE === "serve") {
|
||||
log("[sofi-assets] In watch mode, skipping hashing")
|
||||
}
|
||||
|
||||
for (const absPath of files) {
|
||||
if (!(await stat(absPath)).isFile()) continue;
|
||||
|
||||
const ext = extname(absPath)
|
||||
if (!HASHED_ASSETS.includes(ext) || process.env.ELEVENTY_RUN_MODE === "serve") {
|
||||
const rel = relative(assetsPath, absPath)
|
||||
assetsManifest[rel] = rel
|
||||
continue;
|
||||
}
|
||||
|
||||
const base = basename(absPath, ext)
|
||||
if (base.endsWith("__h")) continue;
|
||||
|
||||
const hash = await hashFile(absPath)
|
||||
const newBase = `${base}-${hash}__h${ext}`
|
||||
|
||||
const relDir = dirname(relative(assetsPath, absPath))
|
||||
const newRelPath = relDir === "."
|
||||
? newBase
|
||||
: join(relDir, newBase)
|
||||
|
||||
assetsManifest[relative(assetsPath, absPath)] = newRelPath
|
||||
}
|
||||
}
|
||||
|
||||
async function fileExists(path) {
|
||||
return await access(path, constants.F_OK).then(() => true, () => false);
|
||||
}
|
||||
|
||||
async function processAssets(assetsPath, outputPath, log = console.log) {
|
||||
for (const [origRel, newRel] of Object.entries(assetsManifest)) {
|
||||
const src = join(assetsPath, origRel);
|
||||
const dest = join(outputPath, newRel);
|
||||
|
||||
if (basename(dest, extname(dest)).endsWith("__h") && await fileExists(dest)) {
|
||||
log(`[sofi-assets] Skipped copying '${src}' because it already exists as '${dest}'`)
|
||||
continue
|
||||
}
|
||||
|
||||
await mkdir(dirname(dest), { recursive: true })
|
||||
|
||||
await copyFile(src, dest);
|
||||
log(`[sofi-assets] Copied: '${src}' to '${dest}'`);
|
||||
}
|
||||
}
|
||||
|
||||
const markdownItOptions = {
|
||||
html: true,
|
||||
linkify: true,
|
||||
}
|
||||
|
||||
const feedOptions = {
|
||||
type: "atom",
|
||||
outputPath: "/feed.xml",
|
||||
collection: {
|
||||
name: "weblogActive",
|
||||
limit: 50,
|
||||
},
|
||||
metadata: {
|
||||
language: "en",
|
||||
style: "long",
|
||||
hours: "auto",
|
||||
minutes: true,
|
||||
title: "Sofía Aritz's weblog",
|
||||
subtitle: "Updates and thoughts from Sofía and her projects.",
|
||||
base: "https://sofiaritz.com",
|
||||
author: {
|
||||
name: "Sofía Aritz",
|
||||
email: "sofi@sofiaritz.com",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const dirOptions = {
|
||||
input: "src",
|
||||
output: "www",
|
||||
}
|
||||
|
||||
function dateDesc(a, b) {
|
||||
return DateTime.fromJSDate(b.data.date) - DateTime.fromJSDate(a.data.date);
|
||||
}
|
||||
|
||||
export default async function (eleventyConfig) {
|
||||
const log = eleventyConfig.logger.log.bind(eleventyConfig.logger)
|
||||
|
||||
eleventyConfig.addPassthroughCopy({ "assets/robots.txt": "robots.txt" })
|
||||
|
||||
eleventyConfig.addWatchTarget("./assets/")
|
||||
eleventyConfig.on("eleventy.before", async () => {
|
||||
await prepareManifest("assets", log)
|
||||
})
|
||||
|
||||
eleventyConfig.setLibrary("md", markdownIt({
|
||||
html: true
|
||||
}).use(markdownItAnchor, {
|
||||
level: 2
|
||||
}))
|
||||
|
||||
eleventyConfig.addFilter("relevantTags", tags => tags.filter(v => !["archived", "post"].includes(v)))
|
||||
|
||||
eleventyConfig.addFilter("readableDate", dateObj => {
|
||||
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).setLocale("es-ES").toFormat("dd LLL yyyy");
|
||||
eleventyConfig.on("eleventy.after", async () => {
|
||||
log("[sofi-assets] Build done, performing asset processing")
|
||||
await processAssets("assets", join(dirOptions.output, "/assets/"), log)
|
||||
})
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
||||
eleventyConfig.addFilter('htmlDateString', dateObj => {
|
||||
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
|
||||
eleventyConfig.addShortcode("assetPath", (asset) => {
|
||||
if (assetsManifest[asset] != null) {
|
||||
return `/assets/${assetsManifest[asset]}`
|
||||
} else {
|
||||
throw `Asset '${asset}' is not in asset manifest`
|
||||
}
|
||||
})
|
||||
|
||||
eleventyConfig.addCollection("weblog", (collection) => {
|
||||
return collection.getFilteredByGlob(join(dirOptions.input, "/weblog/*"))
|
||||
.filter(item => !item.page.filePathStem?.endsWith("index"))
|
||||
.sort(dateDesc);
|
||||
})
|
||||
|
||||
eleventyConfig.addCollection("weblogActive", (collection) => {
|
||||
return collection.getFilteredByGlob(join(dirOptions.input, "/weblog/*"))
|
||||
.filter(item => !item.page.filePathStem?.endsWith("index"))
|
||||
.filter(item => !item.data.archived)
|
||||
.sort(dateDesc);
|
||||
})
|
||||
|
||||
eleventyConfig.addCollection("projects", (collection) => {
|
||||
return collection.getFilteredByGlob(join(dirOptions.input, "/projects/*"))
|
||||
.filter(item => !item.page.filePathStem?.endsWith("index"))
|
||||
.sort(dateDesc);
|
||||
})
|
||||
|
||||
const markdown = markdownIt(markdownItOptions)
|
||||
.use(markdownItAnchor)
|
||||
.use(markdownItEmoji.full, { shortcuts: {} })
|
||||
.use(markdownItFootnote);
|
||||
|
||||
eleventyConfig.setLibrary("md", markdown)
|
||||
|
||||
eleventyConfig.addPlugin(syntaxHighlight)
|
||||
eleventyConfig.addPlugin(eleventyImageTransformPlugin)
|
||||
eleventyConfig.addPlugin(feedPlugin, feedOptions)
|
||||
|
||||
eleventyConfig.addGlobalData("permalink", () => {
|
||||
return (data) => eleventyConfig.getFilter("slugify")(data.page.fileSlug).concat("/")
|
||||
})
|
||||
|
||||
eleventyConfig.addFilter("markdown", content => {
|
||||
return markdown.render(content)
|
||||
})
|
||||
|
||||
eleventyConfig.addFilter("readTime", content => {
|
||||
const minutes = content.trim().split(" ").length / 130 // 130 wpm
|
||||
return Math.ceil(minutes)
|
||||
})
|
||||
|
||||
eleventyConfig.addFilter("datetime", date => {
|
||||
return DateTime.fromJSDate(date).toFormat("LLLL dd, yyyy")
|
||||
})
|
||||
|
||||
eleventyConfig.addFilter("HTMLdatetime", date => {
|
||||
return DateTime.fromJSDate(date).toFormat("yyyy-MM-dd")
|
||||
})
|
||||
|
||||
eleventyConfig.addFilter("removeTitle", content => {
|
||||
const match = content.match(/<h1[^>]*>(.*?)<\/h1>/);
|
||||
if (match) {
|
||||
return content.replace(match[0], "").trim()
|
||||
}
|
||||
return content
|
||||
})
|
||||
|
||||
return {
|
||||
passthroughFileCopy: true,
|
||||
dir: {
|
||||
input: "src"
|
||||
}
|
||||
dir: dirOptions,
|
||||
}
|
||||
}
|
4
.gitattributes
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/.yarn/** linguist-vendored
|
||||
/.yarn/releases/* binary
|
||||
/.yarn/plugins/**/* binary
|
||||
/.pnp.* binary linguist-generated
|
24
.gitignore
vendored
|
@ -1,4 +1,20 @@
|
|||
.scripts/
|
||||
.idea/
|
||||
_site/
|
||||
node_modules/
|
||||
www
|
||||
|
||||
# Compat with old site
|
||||
|
||||
_site
|
||||
.scripts
|
||||
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
# Swap the comments on the following lines if you wish to use zero-installs
|
||||
# In that case, don't forget to run `yarn config set enableGlobalCache false`!
|
||||
# Documentation here: https://yarnpkg.com/features/caching#zero-installs
|
||||
|
||||
#!.yarn/cache
|
||||
.pnp.*
|
||||
|
|
|
@ -1,5 +1 @@
|
|||
# sofi web
|
||||
|
||||
My personal website :)
|
||||
|
||||
[sofiaritz.com](https://sofiaritz.com)
|
||||
# sofi-web
|
||||
|
|
|
@ -14,4 +14,4 @@ a/xLBCS5BgMBCAfCfgQYFgoAJhYhBKEVU9yTYwhnuD7hKloUhbTMzdtKBQJneV6n
|
|||
AhsMBQkDwmcAAAoJEFoUhbTMzdtK72kA/0JKzhX51gN4YPrsCL3Qc3+kDlR0xG4z
|
||||
kpeXX7gk1Y7ZAQDagUM1PCkb7vT6stQsPuuhdyvXsYcvWtV15uxPbITUAg==
|
||||
=b5x3
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
57
assets/robots.txt
Normal file
|
@ -0,0 +1,57 @@
|
|||
# AI scrapers
|
||||
User-agent: AI2Bot
|
||||
User-agent: Ai2Bot-Dolma
|
||||
User-agent: aiHitBot
|
||||
User-agent: Amazonbot
|
||||
User-agent: anthropic-ai
|
||||
User-agent: Applebot
|
||||
User-agent: Applebot-Extended
|
||||
User-agent: Brightbot 1.0
|
||||
User-agent: Bytespider
|
||||
User-agent: CCBot
|
||||
User-agent: ChatGPT-User
|
||||
User-agent: Claude-Web
|
||||
User-agent: ClaudeBot
|
||||
User-agent: cohere-ai
|
||||
User-agent: cohere-training-data-crawler
|
||||
User-agent: Cotoyogi
|
||||
User-agent: Crawlspace
|
||||
User-agent: Diffbot
|
||||
User-agent: DuckAssistBot
|
||||
User-agent: FacebookBot
|
||||
User-agent: Factset_spyderbot
|
||||
User-agent: FirecrawlAgent
|
||||
User-agent: FriendlyCrawler
|
||||
User-agent: Google-Extended
|
||||
User-agent: GoogleOther
|
||||
User-agent: GoogleOther-Image
|
||||
User-agent: GoogleOther-Video
|
||||
User-agent: GPTBot
|
||||
User-agent: iaskspider/2.0
|
||||
User-agent: ICC-Crawler
|
||||
User-agent: ImagesiftBot
|
||||
User-agent: img2dataset
|
||||
User-agent: imgproxy
|
||||
User-agent: ISSCyberRiskCrawler
|
||||
User-agent: Kangaroo Bot
|
||||
User-agent: meta-externalagent
|
||||
User-agent: meta-externalfetcher
|
||||
User-agent: NovaAct
|
||||
User-agent: OAI-SearchBot
|
||||
User-agent: omgili
|
||||
User-agent: omgilibot
|
||||
User-agent: Operator
|
||||
User-agent: PanguBot
|
||||
User-agent: Perplexity-User
|
||||
User-agent: PerplexityBot
|
||||
User-agent: PetalBot
|
||||
User-agent: Scrapy
|
||||
User-agent: SemrushBot-OCOB
|
||||
User-agent: SemrushBot-SWA
|
||||
User-agent: Sidetrade indexer bot
|
||||
User-agent: TikTokSpider
|
||||
User-agent: Timpibot
|
||||
User-agent: VelenPublicWebCrawler
|
||||
User-agent: Webzio-Extended
|
||||
User-agent: YouBot
|
||||
Disallow: /
|
15
assets/styles/components.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* Warning */
|
||||
.warning {
|
||||
padding: 1rem;
|
||||
background-color: color-mix(in srgb, var(--color-secondary),#fff 80%);
|
||||
border: 1px solid var(--color-accent);
|
||||
border-radius: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.warning h3 {
|
||||
margin-top: 0;
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-accent);
|
||||
}
|
|
@ -1,17 +1,3 @@
|
|||
@font-face {
|
||||
font-family: "JetBrains Mono";
|
||||
src: url("https://cdn.sofiaritz.com/fonts/ofl/jetbrainsmono/JetBrainsMono-Italic[wght].ttf");
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "JetBrains Mono";
|
||||
src: url("https://cdn.sofiaritz.com/fonts/ofl/jetbrainsmono/JetBrainsMono[wght].ttf");
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
src: url("https://cdn.sofiaritz.com/fonts/ofl/rubik/Rubik[wght].ttf");
|
||||
|
@ -31,4 +17,18 @@
|
|||
src: url("https://cdn.sofiaritz.com/fonts/ofl/nunito/Nunito[wght].ttf");
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Lora";
|
||||
src: url("https://cdn.sofiaritz.com/fonts/ofl/lora/Lora[wght].ttf");
|
||||
font-style: normal;
|
||||
font-weight: 400 500 600 700 800;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Lora";
|
||||
src: url("https://cdn.sofiaritz.com/fonts/ofl/lora/Lora[wght].ttf");
|
||||
font-style: italic;
|
||||
font-weight: 400 500 600 700 800;
|
||||
}
|
187
assets/styles/layout.css
Normal file
|
@ -0,0 +1,187 @@
|
|||
.site-body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
background: var(--color-bg);
|
||||
color: var(--color-text);
|
||||
font-family: "Lora", serif;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.nav-toggle {
|
||||
background: var(--color-footer-bg);
|
||||
color: var(--color-bg);
|
||||
font-size: 1.25rem;
|
||||
border: none;
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-toggle:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
background: var(--color-footer-bg);
|
||||
font-family: "Rubik", sans-serif;
|
||||
width: 15rem;
|
||||
padding: 1rem 1.5rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.site-logo, .site-logo h1 {
|
||||
font-family: "Nunito", sans-serif;
|
||||
text-decoration: none;
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
||||
.nav-section-title {
|
||||
color: var(--color-bg);
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
padding-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.nav-section-list {
|
||||
list-style: none;
|
||||
margin-bottom: 2rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
text-decoration: none;
|
||||
color: var(--color-bg);
|
||||
display: block;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.nav-link:hover,
|
||||
.nav-link:focus {
|
||||
background: var(--color-bg);
|
||||
border-left-color: var(--color-bg);
|
||||
color: var(--color-footer-bg);
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 2rem;
|
||||
max-width: 75rem;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
background: var(--color-footer-bg);
|
||||
color: var(--color-footer-text);
|
||||
padding: 1rem 1.7rem;
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.footer-meta,
|
||||
.footer-source {
|
||||
flex: 1 1 200px;
|
||||
}
|
||||
|
||||
.site-footer a {
|
||||
color: var(--color-footer-text);
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 992px) {
|
||||
.nav-toggle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: last baseline;
|
||||
padding: 0 1rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.site-logo {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.desktop-site-logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-section-title {
|
||||
font-size: 1.3rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-section-list {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
font-size: 1.5rem;
|
||||
padding: 0.7rem 0.5rem;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.site-nav.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-nav.expanded {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background: var(--color-footer-bg);
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
.site-body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.site-body {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-meta,
|
||||
.footer-source {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
339
assets/styles/prism-coldark-cold.css
Normal file
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
Copyright (c) 2015 PrismJS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* Coldark Theme for Prism.js
|
||||
* Theme variation: Cold
|
||||
* Tested with HTML, CSS, JS, JSON, PHP, YAML, Bash script
|
||||
* @author Armand Philippot <contact@armandphilippot.com>
|
||||
* @homepage https://github.com/ArmandPhilippot/coldark-prism
|
||||
* @license MIT
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: #111b27;
|
||||
background: none;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
background: #8da1b9;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
background: #8da1b9;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #e3eaf2;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: 0.1em 0.3em;
|
||||
border-radius: 0.3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #3c526d;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #111b27;
|
||||
}
|
||||
|
||||
.token.delimiter.important,
|
||||
.token.selector .parent,
|
||||
.token.tag,
|
||||
.token.tag .token.punctuation {
|
||||
color: #006d6d;
|
||||
}
|
||||
|
||||
.token.attr-name,
|
||||
.token.boolean,
|
||||
.token.boolean.important,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.selector .token.attribute {
|
||||
color: #755f00;
|
||||
}
|
||||
|
||||
.token.class-name,
|
||||
.token.key,
|
||||
.token.parameter,
|
||||
.token.property,
|
||||
.token.property-access,
|
||||
.token.variable {
|
||||
color: #005a8e;
|
||||
}
|
||||
|
||||
.token.attr-value,
|
||||
.token.inserted,
|
||||
.token.color,
|
||||
.token.selector .token.value,
|
||||
.token.string,
|
||||
.token.string .token.url-link {
|
||||
color: #116b00;
|
||||
}
|
||||
|
||||
.token.builtin,
|
||||
.token.keyword-array,
|
||||
.token.package,
|
||||
.token.regex {
|
||||
color: #af00af;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.selector .token.class,
|
||||
.token.selector .token.id {
|
||||
color: #7c00aa;
|
||||
}
|
||||
|
||||
.token.atrule .token.rule,
|
||||
.token.combinator,
|
||||
.token.keyword,
|
||||
.token.operator,
|
||||
.token.pseudo-class,
|
||||
.token.pseudo-element,
|
||||
.token.selector,
|
||||
.token.unit {
|
||||
color: #a04900;
|
||||
}
|
||||
|
||||
.token.deleted,
|
||||
.token.important {
|
||||
color: #c22f2e;
|
||||
}
|
||||
|
||||
.token.keyword-this,
|
||||
.token.this {
|
||||
color: #005a8e;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.keyword-this,
|
||||
.token.this,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.delimiter.important {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.language-markdown .token.title,
|
||||
.language-markdown .token.title .token.punctuation {
|
||||
color: #005a8e;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.language-markdown .token.blockquote.punctuation {
|
||||
color: #af00af;
|
||||
}
|
||||
|
||||
.language-markdown .token.code {
|
||||
color: #006d6d;
|
||||
}
|
||||
|
||||
.language-markdown .token.hr.punctuation {
|
||||
color: #005a8e;
|
||||
}
|
||||
|
||||
.language-markdown .token.url > .token.content {
|
||||
color: #116b00;
|
||||
}
|
||||
|
||||
.language-markdown .token.url-link {
|
||||
color: #755f00;
|
||||
}
|
||||
|
||||
.language-markdown .token.list.punctuation {
|
||||
color: #af00af;
|
||||
}
|
||||
|
||||
.language-markdown .token.table-header {
|
||||
color: #111b27;
|
||||
}
|
||||
|
||||
.language-json .token.operator {
|
||||
color: #111b27;
|
||||
}
|
||||
|
||||
.language-scss .token.variable {
|
||||
color: #006d6d;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Show Invisibles plugin
|
||||
* https://prismjs.com/plugins/show-invisibles/
|
||||
*/
|
||||
.token.token.tab:not(:empty):before,
|
||||
.token.token.cr:before,
|
||||
.token.token.lf:before,
|
||||
.token.token.space:before {
|
||||
color: #3c526d;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Toolbar plugin
|
||||
* https://prismjs.com/plugins/toolbar/
|
||||
*/
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button {
|
||||
color: #e3eaf2;
|
||||
background: #005a8e;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus {
|
||||
color: #e3eaf2;
|
||||
background: #005a8eda;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {
|
||||
color: #e3eaf2;
|
||||
background: #3c526d;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Line Highlight plugin
|
||||
* http://prismjs.com/plugins/line-highlight/
|
||||
*/
|
||||
.line-highlight.line-highlight {
|
||||
background: #8da1b92f;
|
||||
background: linear-gradient(to right, #8da1b92f 70%, #8da1b925);
|
||||
}
|
||||
|
||||
.line-highlight.line-highlight:before,
|
||||
.line-highlight.line-highlight[data-end]:after {
|
||||
background-color: #3c526d;
|
||||
color: #e3eaf2;
|
||||
box-shadow: 0 1px #8da1b9;
|
||||
}
|
||||
|
||||
pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before {
|
||||
background-color: #3c526d1f;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Line Numbers plugin
|
||||
* http://prismjs.com/plugins/line-numbers/
|
||||
*/
|
||||
.line-numbers.line-numbers .line-numbers-rows {
|
||||
border-right: 1px solid #8da1b97a;
|
||||
background: #d0dae77a;
|
||||
}
|
||||
|
||||
.line-numbers .line-numbers-rows > span:before {
|
||||
color: #3c526dda;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Match Braces plugin
|
||||
* https://prismjs.com/plugins/match-braces/
|
||||
*/
|
||||
.rainbow-braces .token.token.punctuation.brace-level-1,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-5,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-9 {
|
||||
color: #755f00;
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-2,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-6,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-10 {
|
||||
color: #af00af;
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-3,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-7,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-11 {
|
||||
color: #005a8e;
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-4,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-8,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-12 {
|
||||
color: #7c00aa;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Diff Highlight plugin
|
||||
* https://prismjs.com/plugins/diff-highlight/
|
||||
*/
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) {
|
||||
background-color: #c22f2e1f;
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) {
|
||||
background-color: #116b001f;
|
||||
}
|
||||
|
||||
/* overrides color-values for the Command Line plugin
|
||||
* https://prismjs.com/plugins/command-line/
|
||||
*/
|
||||
.command-line .command-line-prompt {
|
||||
border-right: 1px solid #8da1b97a;
|
||||
}
|
||||
|
||||
.command-line .command-line-prompt > span:before {
|
||||
color: #3c526dda;
|
||||
}
|
||||
|
18
assets/styles/root.css
Normal file
|
@ -0,0 +1,18 @@
|
|||
:root {
|
||||
--color-bg: #fefcfb;
|
||||
--color-text: #2d1740;
|
||||
--color-secondary: #f38cc2;
|
||||
--color-accent: #dc158d;
|
||||
--color-footer-bg: rgba(45, 23, 64, 0.9);
|
||||
--color-footer-text: #ffffff;
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: inherit;
|
||||
}
|
56
assets/styles/text.css
Normal file
|
@ -0,0 +1,56 @@
|
|||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
color: var(--color-text);
|
||||
margin: 1.5rem 0 0.75rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
border-bottom: 2px solid var(--color-secondary);
|
||||
padding-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
border-bottom: 1px dashed var(--color-accent);
|
||||
padding-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-accent);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 2rem 0;
|
||||
padding: 1rem 1.5rem;
|
||||
border-left: 4px solid var(--color-accent);
|
||||
background-color: color-mix(in srgb, var(--color-text),#fff 95%);
|
||||
color: var(--color-text);
|
||||
font-style: italic;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
blockquote cite {
|
||||
display: block;
|
||||
margin-top: 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-accent);
|
||||
font-style: normal;
|
||||
}
|
40
package.json
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"name": "eleventy-base",
|
||||
"version": "1.0.0",
|
||||
"description": "A template for creating 11ty websites.",
|
||||
"main": "index.js",
|
||||
"author": "Sofía Aritz",
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^2.0.1",
|
||||
"eleventy-plugin-time-to-read": "^1.3.0",
|
||||
"luxon": "^3.4.4",
|
||||
"markdown-it": "^13.0.2",
|
||||
"markdown-it-anchor": "^8.6.7"
|
||||
},
|
||||
"name": "sofi-web",
|
||||
"type": "module",
|
||||
"packageManager": "yarn@4.4.1",
|
||||
"scripts": {
|
||||
"build": "npx @11ty/eleventy",
|
||||
"serve": "npx @11ty/eleventy --serve",
|
||||
"tree": "tree --gitignore",
|
||||
"fresh-build": "rm -rf _site/ && yarn build",
|
||||
"deploy": "cd .scripts/ && ./deploy.sh"
|
||||
"start": "yarn run clean && yarn exec eleventy --serve",
|
||||
"build": "yarn run clean && yarn exec eleventy",
|
||||
"clean": "rm -rf www/"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
|
||||
"dependencies": {
|
||||
"@11ty/eleventy": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy-img": "^6.0.2",
|
||||
"@11ty/eleventy-plugin-rss": "^2.0.3",
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
|
||||
"@sindresorhus/slugify": "^2.2.1",
|
||||
"luxon": "^3.6.1",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-anchor": "^9.2.0",
|
||||
"markdown-it-emoji": "^3.0.0",
|
||||
"markdown-it-footnote": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
14
src/404.md
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
---
|
||||
|
||||
# not found
|
||||
|
||||
The requested content was not found.
|
||||
|
||||
If you have found a broken link, **please [contact me](/en/contact)**. The following information could be useful:
|
||||
* Where did you find the broken link
|
||||
* What is the broken link
|
||||
|
||||
|
||||
Thank you :)
|
14
src/_data/events.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"featured": [
|
||||
{
|
||||
"title": "SalmorejoTech 2025",
|
||||
"description": "I will be presenting at SalmorejoTech 2025 on FSFE's upcoming project, MP Scrape.",
|
||||
"link": "https://salmorejo.tech/2025"
|
||||
},
|
||||
{
|
||||
"title": "Devconf.CZ 2025",
|
||||
"description": "I will be hosting at Devconf.CZ:\n- An [Upcycling Android Workshop](https://pretalx.devconf.info/devconf-cz-2025/talk/FRXKNL/)\n- A talk about [Munin](/projects/munin): [“Identity: Supporting dementia care with Free Software”](https://pretalx.devconf.info/devconf-cz-2025/talk/P8ZEE8/).",
|
||||
"link": "https://www.devconf.info/cz/"
|
||||
}
|
||||
]
|
||||
}
|
28
src/_data/site.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"title": "sofi web",
|
||||
"description": "Updates and thoughts from Sofía and her projects.",
|
||||
"author": "Sofía Aritz",
|
||||
"url": "https://sofiaritz.com",
|
||||
"repo": "https://git.sofiaritz.com/sofia/sofi-web",
|
||||
"repoSourceBase": "https://git.sofiaritz.com/sofia/sofi-web/src/branch/main/",
|
||||
"nav": [
|
||||
{
|
||||
"title": "pages",
|
||||
"links": [
|
||||
{ "label": "about me", "href": "/" },
|
||||
{ "label": "contact", "href": "/contact" },
|
||||
{ "label": "weblog", "href": "/weblog" },
|
||||
{ "label": "projects", "href": "/projects" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "links",
|
||||
"links": [
|
||||
{ "label": "fediverse", "href": "https://hachyderm.io/@sofiaritz", "rel": "me" },
|
||||
{ "label": "codeberg", "href": "https://codeberg.org/sofiaritz" },
|
||||
{ "label": "git", "href": "https://git.sofiaritz.com" },
|
||||
{ "label": "status", "href": "https://status.sofiaritz.com" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=yes, initial-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<meta name="fediverse:creator" content="@sofiaritz@hachyderm.io">
|
||||
<link href="https://cdn.sofiaritz.com" rel="preconnect" crossorigin>
|
||||
<link href="/assets/css/fonts.css" rel="stylesheet">
|
||||
<link href="/assets/css/base.css" rel="stylesheet">
|
||||
{% if styles %}
|
||||
{% for style in styles %}
|
||||
<link href="{{ style }}" rel="stylesheet">
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<title>{% if title %} {{ title }} - {% endif %}sofi web</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: none !important">
|
||||
<a rel="me" href="https://hachyderm.io/@sofiaritz">Fediverse</a>
|
||||
<a rel="me" href="https://git.sofiaritz.com/sofia">Forgejo</a>
|
||||
</div>
|
||||
<h1><a href="/">sofi web</a></h1>
|
||||
<div class="page-container">
|
||||
<main>
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
<nav>
|
||||
{% if lang != "en" %}
|
||||
<div>
|
||||
<i>yo</i>
|
||||
<ul>
|
||||
<li><a href="/">inicio y sobre mí</a></li>
|
||||
<li><a href="/contacto">contacto</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<i>creaciones</i>
|
||||
<ul>
|
||||
<li><a href="/weblog">weblog</a></li>
|
||||
<li><a href="/proyectos">proyectos</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div>
|
||||
<i>me</i>
|
||||
<ul>
|
||||
<li><a href="/en">home and about me</a></li>
|
||||
<li><a href="/en/contact">contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<i>creations</i>
|
||||
<ul>
|
||||
<li><a href="/en/weblog">weblog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<i>links</i>
|
||||
<ul>
|
||||
<li><a href="https://status.sofiaritz.com">status</a></li>
|
||||
<li><a href="https://git.sofiaritz.com/explore/repos">forgejo</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<i>global</i>
|
||||
<ul>
|
||||
<li><a href="/en">english</a></li>
|
||||
<li><a href="/">spanish</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
{% if scripts %}
|
||||
{% for script in scripts %}
|
||||
<script src="{{ script }}"></script>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
99
src/_includes/layout.liquid
Normal file
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ lang | default: 'en' }}">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ description | default: site.description }}">
|
||||
<meta name="fediverse:creator" content="@sofiaritz@hachyderm.io">
|
||||
<link href="https://cdn.sofiaritz.com" rel="preconnect" crossorigin>
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/root.css' %}">
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/fonts.css' %}">
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/layout.css' %}">
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/text.css' %}">
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/components.css' %}">
|
||||
<link rel="stylesheet" href="{% assetPath 'styles/prism-coldark-cold.css' %}">
|
||||
<title>{% if title %}{{ title }} - {% endif %}{{ site.title }}</title>
|
||||
<link rel="alternate" href="{{ site.url }}/feed.xml" type="application/atom+xml" title="{{ site.title }} Feed">
|
||||
</head>
|
||||
|
||||
<body class="site-body">
|
||||
<header class="site-header">
|
||||
<button class="nav-toggle" id="nav-toggle" aria-label="Toggle navigation" aria-expanded="false">
|
||||
<a href="/" class="site-logo"><h1>sofi web</h1></a>
|
||||
<span>☰ Menu</span>
|
||||
</button>
|
||||
|
||||
<nav class="site-nav" id="site-nav">
|
||||
<a href="/" class="desktop-site-logo site-logo"><h1>sofi web</h1></a>
|
||||
|
||||
{% for section in site.nav %}
|
||||
<span class="nav-section-title">{{ section.title }}</span>
|
||||
<ul class="nav-section-list">
|
||||
{% for link in section.links %}
|
||||
<li><a class="nav-link" href="{{ link.href }}" {% if link.rel %}rel="{{ link.rel }}" {% endif %}>{{
|
||||
link.label }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="layout-main">
|
||||
<div class="content-area">
|
||||
<main class="main-content">
|
||||
{% if archived %}
|
||||
<div class="warning">
|
||||
<h3>Archived Page</h3>
|
||||
<p>This page is archived and preserved for historical purposes. It may contain outdated information,
|
||||
and some links or features might not work. The content may not reflect my current views.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<article>
|
||||
{{ content }}
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="footer-meta">
|
||||
<p>© {{ "now" | date: "%Y" }} {{ site.author }}</p>
|
||||
{% if license == false %}
|
||||
<p>All rights reserved for this article.</p>
|
||||
{% elsif license %}
|
||||
<p>This article is licensed under {{ license }}, unless otherwise stated.</p>
|
||||
{% else %}
|
||||
<p>This article is licensed under
|
||||
<a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">CC BY-NC-ND 4.0</a>, unless
|
||||
otherwise stated.
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="footer-source">
|
||||
{% assign cleanPath = page.inputPath | remove: "./" %}
|
||||
<p>
|
||||
<a href="https://git.sofiaritz.com/sofia/sofi-web/src/branch/main/{{ cleanPath }}">source
|
||||
code</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const toggle = document.getElementById("nav-toggle");
|
||||
const nav = document.getElementById("site-nav");
|
||||
|
||||
toggle.hidden = false;
|
||||
nav.classList.add("collapsed");
|
||||
|
||||
toggle.addEventListener("click", () => {
|
||||
const isCollapsed = nav.classList.contains("collapsed");
|
||||
nav.classList.toggle("collapsed", !isCollapsed);
|
||||
nav.classList.toggle("expanded", isCollapsed);
|
||||
toggle.setAttribute("aria-expanded", isCollapsed);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
18
src/_includes/post.liquid
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
layout: "layout"
|
||||
---
|
||||
|
||||
<div id="title-header">
|
||||
<a href="/weblog" style="text-decoration: none; font-family: 'Nunito', sans-serif">← Weblog</a>
|
||||
<h1 style="margin-top: 0.7rem;">{{ title }}</h1>
|
||||
</div>
|
||||
|
||||
<div style="padding-bottom: 1rem;">
|
||||
<time datetime="{{ date | HTMLdatetime }}">{{ date | datetime }}</time> by {{ author | default:site.author }} in
|
||||
{%for tag in tags %}<span><a href="/weblog/tags/{{ tag }}">#{{ tag }}</a> </span>{% endfor %}
|
||||
| Estimated read time: {{ content | readTime }} minute(s)
|
||||
</div>
|
||||
|
||||
{{ content | removeTitle }}
|
||||
|
||||
<a href="#title-header" style="text-decoration: none; font-family: 'Nunito', sans-serif;">↑ Go back to top</a>
|
|
@ -1,47 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
scripts: ["/assets/weblog/comments.js", "/assets/libraries/dompurify.js"]
|
||||
styles: ["/assets/css/comments.css"]
|
||||
---
|
||||
|
||||
<h1>{{ title }}</h1>
|
||||
<div style="display: inline">
|
||||
{% if date %}
|
||||
<time datetime="{{ date | htmlDateString }}">{{ date | readableDate }}</time> |
|
||||
{% endif %}
|
||||
|
||||
{% if tags.includes("archived") %}
|
||||
<span><a href="/meta/archived">Archived post</a></span> |
|
||||
{% endif %}
|
||||
|
||||
{% if tags %}
|
||||
{% if tags.length > 1 %}
|
||||
<span>Tags:</span>
|
||||
{% else %}
|
||||
<span>Tag:</span>
|
||||
{% endif %}
|
||||
{% set relTags = tags | relevantTags %}
|
||||
{% for tag in relTags %}
|
||||
<span><a href="/weblog/tags/{{ tag }}">{{ tag }}</a> {% if loop.last == false %}·{% endif %}</span>
|
||||
{% endfor %}
|
||||
|
|
||||
{% endif %}
|
||||
{{ content | timeToRead }}
|
||||
{% if comment_status %}
|
||||
| <a href="#comments">Comments</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{{ content | safe }}
|
||||
|
||||
{% if comment_status %}
|
||||
<hr>
|
||||
<div id="comments">
|
||||
<div>
|
||||
<h2 style="display: inline">comments · <a href="https://hachyderm.io/@sofiaritz/{{ comment_status }}">post</a></h2>
|
||||
</div>
|
||||
<section data-status="{{ comment_status }}" id="comment-section"></section>
|
||||
</div>
|
||||
{% endif %}
|
19
src/_includes/project.liquid
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
layout: "layout"
|
||||
---
|
||||
|
||||
<div id="title-header">
|
||||
<a href="/projects" style="text-decoration: none; font-family: 'Nunito', sans-serif">← Projects</a>
|
||||
<h1 style="margin-top: 0.7rem;">{{ title }}</h1>
|
||||
</div>
|
||||
|
||||
{% if inactive == true %}
|
||||
<div class="warning">
|
||||
<h3>Inactive project</h3>
|
||||
<p>This project is now inactive, development has been stalled.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ content | removeTitle }}
|
||||
|
||||
<a href="#title-header" style="text-decoration: none; font-family: 'Nunito', sans-serif;">↑ Go back to top</a>
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
---
|
||||
|
||||
{% if lang == "en" %}
|
||||
<h1>redirect</h1>
|
||||
<p>This page has been moved: {{ content | safe }}</p>
|
||||
{% else %}
|
||||
<h1>redirección</h1>
|
||||
<p>Esta página ha sido movida: {{ content | safe }}</p>
|
||||
{% endif %}
|
|
@ -1,5 +1,17 @@
|
|||
---
|
||||
layout: redirect
|
||||
layout: "layout"
|
||||
---
|
||||
|
||||
[/contacto](/contacto)
|
||||
# contact
|
||||
|
||||
You might use any of the following to contact me:
|
||||
|
||||
- E-mail: [sofi@sofiaritz.com](mailto:sofi@sofiaritz.com) ([public key](/assets/keys/sofi@sofiaritz.com.pub))
|
||||
- Signal: @sofiaritz.01
|
||||
- Matrix: [@sofiaritz:matrix.org](https://matrix.to/#/@sofiaritz:matrix.org)
|
||||
|
||||
## social media
|
||||
|
||||
- Fediverse: [@me@sofiaritz.com](https://hachyderm.io/@sofiaritz) (@sofiaritz@hachyderm.io)
|
||||
- Forgejo: [sofia@git.sofiaritz.com](https://git.sofiaritz.com/sofia)
|
||||
- Codeberg [sofiaritz@codeberg.org](https://codeberg.org/sofiaritz)
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: contacto
|
||||
---
|
||||
|
||||
# contacto
|
||||
|
||||
## contacto directo
|
||||
|
||||
* Correo electrónico: [sofi@sofiaritz.com](mailto:sofi@sofiaritz.com)
|
||||
* Matrix: [@sofiaritz:matrix.org](https://matrix.to/#/@sofiaritz:matrix.org)
|
||||
|
||||
## redes sociales
|
||||
|
||||
* Forgejo: [sofia@git.sofiaritz.com](https://git.sofiaritz.com/sofia)
|
||||
* Fediverse: [@me@sofiaritz.com](https://hachyderm.io/@sofiaritz) (@sofiaritz@hachyderm.io)
|
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: contact
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
# contact
|
||||
|
||||
### direct
|
||||
|
||||
* E-mail: [sofi@sofiaritz.com](mailto:sofi@sofiaritz.com)
|
||||
* Matrix: [@sofiaritz:matrix.org](https://matrix.to/#/@sofiaritz:matrix.org)
|
||||
|
||||
### social media
|
||||
|
||||
* Forgejo: [sofia@git.sofiaritz.com](https://git.sofiaritz.com/sofia)
|
||||
* Fediverse: [@me@sofiaritz.com](https://hachyderm.io/@sofiaritz) (@sofiaritz@hachyderm.io)
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
# home
|
||||
|
||||
I'm Sofía Aritz, a young programmer passionate about technology as a tool for social transformation.
|
||||
I work on projects with social impact —such as [Identity](https://git.sofiaritz.com/sofia/identity), an initiative designed to contribute to palliative care and the treatment of conditions like dementia—
|
||||
seeking solutions that empower individuals and promote digital autonomy.
|
||||
|
||||
I have always been deeply interested in the intersection of the technical, political, and social aspects of Free Software.
|
||||
|
||||
My approach to Software development is deeply shaped by my interest in decentralized and federated systems,
|
||||
which I believe are essential for building a fairer and more sustainable technological ecosystem.
|
||||
|
||||
## affiliations
|
||||
|
||||
- Collaborator at the [Free Software Club of the University of Córdoba](https://uco.es/aulasoftwarelibre/)
|
||||
- Leader and lead developer of [Identity](https://git.sofiaritz.com/sofia/identity)
|
8
src/errors/404.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
layout: "layout"
|
||||
permalink: /errors/404/
|
||||
---
|
||||
|
||||
# 404: Not found
|
||||
|
||||
The requested resource was not found on this server.
|
60
src/index.liquid
Normal file
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
layout: "layout"
|
||||
---
|
||||
|
||||
<h1>home</h1>
|
||||
|
||||
<p>
|
||||
I'm Sofía Aritz, a young programmer passionate about technology as a tool for social transformation.
|
||||
I work on projects with social impact —such as <a href="https://codeberg.org/Identity/munin">Munin</a>, an
|
||||
initiative designed to contribute to palliative care and the treatment of conditions like dementia—
|
||||
seeking solutions that empower individuals and promote digital autonomy.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I have always been deeply interested in the intersection of the technical, political, and social aspects of Free
|
||||
Software.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
My approach to Software development is deeply shaped by my interest in decentralized and federated systems,
|
||||
which I believe are essential for building a fairer and more sustainable technological ecosystem.
|
||||
</p>
|
||||
|
||||
<h2>affiliations</h2>
|
||||
|
||||
<ul>
|
||||
<li>Collaborator at the <a href="https://uco.es/aulasoftwarelibre/">Free Software Club of the University of Córdoba</a></li>
|
||||
<li>Leader and lead developer of <a href="https://codeberg.org/Identity/munin">Munin</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>latest articles</h2>
|
||||
|
||||
{% assign limitedPosts = collections.weblogActive | slice: 0, 2 %}
|
||||
{% for post in limitedPosts %}
|
||||
<div>
|
||||
<h3 style="margin-bottom: 0.2rem;"><a style="text-decoration: none;" href="{{ post.data.permalink }}">{{ post.data.title }}</a></h3>
|
||||
<time datetime="{{ post.data.page.date | HTMLdatetime }}">{{ post.data.page.date | datetime }}</time>
|
||||
{% if post.data.introduction %}
|
||||
<p style="font-size: 0.9rem;">
|
||||
{% if post.data.archived %}
|
||||
<span><strong><span style="font-family: 'Nunito', sans-serif">⚠</span> Archived</strong> | </span>
|
||||
{% endif %}
|
||||
{{ post.data.introduction }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<hr style="color: var(--color-secondary); border: 3px dotted; border-style: none none dotted;">
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if events.featured %}
|
||||
<h2>featured events</h2>
|
||||
|
||||
{% for event in events.featured %}
|
||||
<div style="margin-bottom: 0.5rem;">
|
||||
<h3 style="margin-bottom: 0;"><a style="text-decoration: none;" href="{{ event.link }}">{{ event.title }}</a></h3>
|
||||
<p style="font-size: 0.9rem; margin-top: 0.4rem;">{{ event.description | markdown }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
19
src/index.md
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
---
|
||||
|
||||
# inicio
|
||||
|
||||
Soy Sofía Aritz, una joven programadora apasionada por la tecnología como herramienta de transformación social.
|
||||
Trabajo en proyectos con un trasfondo social —como [Identity](https://git.sofiaritz.com/sofia/identity),
|
||||
una iniciativa diseñada para contribuir a los cuidados paliativos y el tratamiento de condiciones como demencia— buscando soluciones que empoderen a las personas y fomenten la autonomía digital.
|
||||
|
||||
Siempre he tenido un fuerte interés en la relación entre el aspecto técnico, político y social del Software Libre.
|
||||
|
||||
Mi enfoque a la hora de desarrollar Software está profundamente influido por mi interés en los sistemas descentralizados y federados,
|
||||
que considero fundamentales para construir un ecosistema tecnológico más justo y sostenible.
|
||||
|
||||
## afiliaciones
|
||||
|
||||
- Colaboradora del [Aula de Software Libre de la UCO](https://www.uco.es/aulasoftwarelibre/)
|
||||
- Líder y desarrolladora principal de [Identity](https://git.sofiaritz.com/sofia/identity)
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: archived
|
||||
layout: "layout"
|
||||
permalink: /meta/archived/
|
||||
archived: true
|
||||
---
|
||||
|
||||
# archived pages
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: meta
|
||||
layout: "layout"
|
||||
---
|
||||
|
||||
# meta
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: maintenance tiers
|
||||
layout: "layout"
|
||||
permalink: /meta/maintenance-tiers/
|
||||
---
|
||||
|
||||
|
||||
# maintenance tiers
|
||||
|
||||
Not all projects are treated equal. Some are in active development, others are finished, others are deprecated, etc.
|
||||
|
|
13
src/projects/gfonts.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
layout: "project"
|
||||
description: "GFonts is a project aimed at providing a set of tools that together offer an open-source, self-hosted alternative to Google Fonts."
|
||||
inactive: true
|
||||
---
|
||||
|
||||
# GFonts
|
||||
|
||||
[Repositories](https://git.sofiaritz.com/GFonts) · [Website](https://gfonts.sofiaritz.com)
|
||||
|
||||
GFonts is a project aimed at providing a set of tools that together offer an open-source, self-hosted alternative to Google Fonts.
|
||||
|
||||
The project is still under development, and there isn't a post yet that systematically summarizes the project's objectives, motivations, and ideas. In the meantime, you can visit [my mirror of Google Fonts page for more information](https://cdn.sofiaritz.com/fonts/).
|
16
src/projects/index.liquid
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
layout: "layout"
|
||||
title: projects
|
||||
permalink: /projects/index.html
|
||||
---
|
||||
|
||||
<h1>projects</h1>
|
||||
|
||||
Brief introduction to a few projects I've been leading or have created.
|
||||
|
||||
{% for project in collections.projects %}
|
||||
<div>
|
||||
<h2>{{ project.data.title }}</h2>
|
||||
<p>{{ project.data.description }} <a href="{{ project.data.permalink }}">Learn more...</a></p>
|
||||
</div>
|
||||
{% endfor %}
|
36
src/projects/munin.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
layout: "project"
|
||||
description: "Munin (prev. Identity) is a platform for securely preserving your personal heritage in an interoperable and federated system."
|
||||
---
|
||||
|
||||
# Munin
|
||||
|
||||
[Repository](https://codeberg.org/Identity/munin) · [Website](https://munin.id) · [Posts](/weblog/tags/munin)
|
||||
|
||||
Munin (prev. Identity) is a platform for securely preserving your [personal heritage](#personal-heritage) in an interoperable and federated system.
|
||||
|
||||
- You can store your personal heritage, keeping your memories and experiences safe in a structured and meaningful way.
|
||||
- You choose trusted custodians who may request access to your heritage (or a subset) under conditions you define, such as dementia or after your passing.
|
||||
- Identity is built for interoperability, allowing seamless integration with other systems, ensuring broad accessibility and usability.
|
||||
|
||||
## Background
|
||||
|
||||
You can read more about the history and background of Munin in [an interview](https://fsfe.org/news/2025/news-20250107-01.en.html) by the [FSFE](https://fsfe.org) and in the [original repository](https://git.sofiaritz.com/sofia/identity).
|
||||
|
||||
## Contributing
|
||||
|
||||
You can contribute to Munin in many ways!
|
||||
- If you'd like to contribute to its **technical development**, check [the contribution guidelines](https://codeberg.org/Identity/munin/src/branch/main/CONTRIBUTING.md)
|
||||
- If you'd like to **report an issue**, go to our [Issue Tracker](https://codeberg.org/Identity/identity/issues)
|
||||
- If you'd like to share your **thoughts and ideas**, fill the [_Identity: Ideas!_ form](https://cryptpad.fr/form/#/2/form/view/5jagE-jwyIueIHA0EHHXzEEIdSxyCJk4CT20kp8itVQ/)
|
||||
- If you'd like to contribute with your knowledge, fill the [_Group of Experts: Expression of Interest_ form](https://cryptpad.fr/form/#/2/form/view/TBBGrmNwIH4VB95l+ok4P2o9p3Neh+OlRETl8+r4q8I/) and join our Group of Experts
|
||||
|
||||
You can always send an e-mail to [sofia@munin.id](mailto:sofia@munin.id) and it will be forwarded to the right people.
|
||||
|
||||
## Personal heritage
|
||||
|
||||
Personal heritage is the collection of memories, experiences, and key moments that shape an individual.
|
||||
|
||||
Personal heritage represents the unique narrative of someone's life, encompassing their thoughts, emotions, and personal history.
|
||||
|
||||
Personal heritage is deeply individual and can be shared, passed down, or integrated into various contexts, such as healthcare. In medical applications, personal heritage can provide valuable insight into a person's identity, contributing to more compassionate and personalized approaches to care, particularly in dementia and palliative treatment.
|
21
src/projects/projects.11tydata.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import slugify from '@sindresorhus/slugify';
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
eleventyComputed: {
|
||||
title: data => {
|
||||
const content = data.page?.rawInput
|
||||
const match = content?.match(/^#\s+(.+)$/m)
|
||||
return match ? match[1].trim() : data.page.fileSlug
|
||||
},
|
||||
permalink: data => {
|
||||
// Manually set
|
||||
if (typeof data.permalink === "string") {
|
||||
return data.permalink
|
||||
}
|
||||
|
||||
return `/projects/${slugify(data.title)}/`
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: proyectos
|
||||
---
|
||||
|
||||
# proyectos
|
||||
|
||||
## Identity
|
||||
|
||||
[Identity](https://git.sofiaritz.com/sofia/identity) es un proyecto con el objetivo de mejorar el tratamiento de condiciones como demencia y de los cuidados paliativos.
|
||||
|
||||
Ahora mismo el proyecto está bajo construcción.
|
||||
|
||||
## GFonts
|
||||
|
||||
[GFonts](https://git.sofiaritz.com/GFonts) es un proyecto cuyo objetivo es proveer una serie de herramientas que en
|
||||
su conjunto ofrezcan una alternativa de código abierto y
|
||||
[_autohospedada_](https://en.wikipedia.org/wiki/Self-hosting_(web_services)) de
|
||||
[Google Fonts](https://fonts.google.com/).
|
||||
|
||||
El proyecto sigue en desarrollo, y aún no existe un post que resuma los objetivos, motivaciones e ideas del proyecto
|
||||
de una manera sistemática. Mientras tanto, puedes visitar la página en mi
|
||||
[mirror de Google Fonts](https://cdn.sofiaritz.com/fonts/) para obtener más información.
|
||||
|
||||
## otros
|
||||
|
||||
Puedes visitar mi [instancia de Forgejo](https://git.sofiaritz.com/explore/repos) para ver más proyectos míos y también
|
||||
mi [cuenta de GitHub](https://github.com/sofiaritz) para ver mis contribuciones a otros proyectos.
|
11
src/weblog/archived/firstpost.md → src/weblog/20230312-0.md
Executable file → Normal file
|
@ -1,19 +1,20 @@
|
|||
---
|
||||
layout: post.njk
|
||||
title: Primer post
|
||||
intro: El nacimiento de mi weblog! :)
|
||||
layout: "post"
|
||||
introduction: El nacimiento de mi weblog! :)
|
||||
tags:
|
||||
- meta
|
||||
- archived
|
||||
- es
|
||||
date: 2023-03-12
|
||||
permalink: /weblog/firstpost/
|
||||
archived: true
|
||||
---
|
||||
|
||||
# Primer post
|
||||
|
||||
Este es el primer post del weblog! Aquí iré compartiendo ideas, ocurrencias y experiencias a medida que me mueva por
|
||||
los mundos de Internet y la programación.
|
||||
|
||||
Ahora mismo este weblog está parcialmente incompleto, pero dentro de poco añadiré las cosas que faltan para que esté
|
||||
completamente a punto ([RSS](https://es.wikipedia.org/wiki/RSS), etiquetas, comentarios, etc).
|
||||
|
||||
Cualquier sugerencia o idea para este weblog podéis [enviármela](/contact) sin problema!
|
||||
Cualquier sugerencia o idea para este weblog podéis [enviármela](/contact) sin problema!
|
25
src/weblog/archived/note-taking-experiment.md → src/weblog/20230312-1.md
Executable file → Normal file
|
@ -1,17 +1,16 @@
|
|||
---
|
||||
layout: post.njk
|
||||
title: Note Taking. Notas encriptadas
|
||||
intro: Un programa experimental para encriptar notas.
|
||||
layout: "post"
|
||||
introduction: Un programa experimental para encriptar notas.
|
||||
tags:
|
||||
- rust
|
||||
- experimentos
|
||||
- note taking
|
||||
- archived
|
||||
- es
|
||||
- note taking
|
||||
- es
|
||||
date: 2023-03-12
|
||||
permalink: /weblog/note-taking-experiment/
|
||||
archived: true
|
||||
---
|
||||
|
||||
# Note Taking. Notas encriptadas
|
||||
|
||||
## motivación
|
||||
|
||||
Un día me di cuenta de que mi _setup_ para tomar notas era bastante engorroso: abría el bloc de notas, escribía, guardaba
|
||||
|
@ -109,9 +108,7 @@ Cualquier idea es bienvenida! [Ponte en contacto conmigo](/contact) o abre una
|
|||
[issue](https://git.sofiaritz.com/sofia/note-taking/issues) en el repositorio. :)
|
||||
|
||||
## imágenes
|
||||
|
||||
<img alt="Captura de pantalla donde se muestra una entrada de texto con los valores de entropía y longitud a la derecha en color verde, indicando así valores aceptables." src="/assets/weblog/note-taking-experimental/password-prompt.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestran los botones 'want to add one note?' y 'settings'" src="/assets/weblog/note-taking-experimental/top-buttons.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestra la lista de notas. En cada nota se muestra el título y su derecha la fecha. Bajo el título hay un botón que indica 'decrypt note'" src="/assets/weblog/note-taking-experimental/note-list.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestra el formulario de creación de notas, con diversas entradas de texto para el título, texto y metadatos. Al final hay un botón con el texto 'add note'" src="/assets/weblog/note-taking-experimental/note-creation.png" width="85%"/>
|
||||
|
||||
<img alt="Captura de pantalla donde se muestra una entrada de texto con los valores de entropía y longitud a la derecha en color verde, indicando así valores aceptables." src="./images/archived/password-prompt.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestran los botones 'want to add one note?' y 'settings'" src="./images/archived/top-buttons.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestra la lista de notas. En cada nota se muestra el título y su derecha la fecha. Bajo el título hay un botón que indica 'decrypt note'" src="./images/archived/note-list.png" width="85%"/>
|
||||
<img alt="Captura de pantalla donde se muestra el formulario de creación de notas, con diversas entradas de texto para el título, texto y metadatos. Al final hay un botón con el texto 'add note'" src="./images/archived/note-creation.png" width="85%"/>
|
15
src/weblog/archived/note-taking-2.md → src/weblog/20230606-0.md
Executable file → Normal file
|
@ -1,17 +1,16 @@
|
|||
---
|
||||
layout: post.njk
|
||||
title: Note Taking (II). Retos
|
||||
intro: Retos encontrados por el camino.
|
||||
layout: "post"
|
||||
introduction: Retos encontrados por el camino.
|
||||
tags:
|
||||
- rust
|
||||
- experimentos
|
||||
- note taking
|
||||
- archived
|
||||
- es
|
||||
date: 2023-05-06
|
||||
permalink: /weblog/note-taking-2/
|
||||
archived: true
|
||||
---
|
||||
|
||||
# Note Taking (II). Retos
|
||||
|
||||
Hace unos meses comencé a crear [Note Taking](https://git.sofiaritz.com/sofia/note-taking), una aplicación cuyo
|
||||
propósito era la creación de un software que permitiera crear notas encriptadas de una manera sencilla y segura.
|
||||
|
||||
|
@ -26,7 +25,7 @@ los retos que me he encontrado en este camino.
|
|||
La seguridad es sin duda uno de los apartados más importantes y complejos de este software. A día de hoy el sistema
|
||||
utilizado es el siguiente:
|
||||
|
||||
<img src="/assets/weblog/archived/note-taking-2/diagram1.svg" width="100%">
|
||||
<img alt="Diagrama mostrando el sistema utilizado: nota desencriptada, se hace SHA256 de la contraseña y ambos pasan por Argon2, usando eso como clave, se utiliza pwbox para producir la nota encriptada" src="./images/archived/diagram1.svg" width="100%">
|
||||
|
||||
Este sistema actualmente funciona bien:
|
||||
* Todas las contraseñas tienen una alta entropía gracias al uso de Argon2 (un [KDF](https://es.wikipedia.org/wiki/Funci%C3%B3n_de_derivaci%C3%B3n_de_clave)).
|
||||
|
@ -98,4 +97,4 @@ Sin duda crear este software está siendo una experiencia bastante interesante q
|
|||
seguridad computacional y muchas otras cosas.
|
||||
|
||||
A lo largo de los meses venideros trataré de implementar estas y más cosas, subiré una actualización cuando ello ocurra
|
||||
:)
|
||||
:)
|
|
@ -1,15 +1,16 @@
|
|||
---
|
||||
layout: post.njk
|
||||
title: Major update
|
||||
intro: The first major update to this website and the start of a new era.
|
||||
layout: "post"
|
||||
introduction: The first major update to this website and the start of a new era.
|
||||
tags:
|
||||
- meta
|
||||
- website
|
||||
- post
|
||||
- en
|
||||
date: 2023-11-28
|
||||
permalink: /weblog/2023/11/major-update/
|
||||
archived: true
|
||||
---
|
||||
|
||||
# Major update
|
||||
|
||||
This website has received its first major update since
|
||||
[Jan 2, 2023](https://git.sofiaritz.com/sofia/website/commit/cce91e6649575cb2ac5a19cbe4a058115df10a5a)! The design may
|
||||
look familiar, but some things have changed:
|
|
@ -1,14 +1,15 @@
|
|||
---
|
||||
layout: post.njk
|
||||
title: "Identity: What's new? What's next?"
|
||||
intro: It's been 9 months since the last Identity update, what's up?
|
||||
layout: "post"
|
||||
introduction: It's been 9 months since the last Identity update, what's up?
|
||||
tags:
|
||||
- identity
|
||||
- post
|
||||
- munin
|
||||
- en
|
||||
date: 2025-03-03
|
||||
permalink: /weblog/2025/03/whats-new-whats-next-identity/
|
||||
---
|
||||
|
||||
# Identity: What's new? What's next?
|
||||
|
||||
**TLDR;**
|
||||
- The rewrite of Identity has resumed!
|
||||
- The original Identity repository has been archived. Further development will continue in a new repository: <https://codeberg.org/Identity/identity>.
|
|
@ -1,30 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: weblog
|
||||
permalink: /en/weblog.html
|
||||
lang: "en"
|
||||
---
|
||||
|
||||
<h1>weblog</h1>
|
||||
|
||||
<div>
|
||||
<span><a href="/weblog/tags/en">English posts</a></span> ·
|
||||
<span><a href="/weblog/tags/es">Spanish posts</a></span>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{% set taglist = collections["post"] %}
|
||||
{% for post in taglist | reverse %}
|
||||
<li><a href="{{ post.url }}">{{ post.data.title }}</a>{% if post.data.intro %} · <span>{{ post.data.intro }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<details style="margin: 0; padding: 0" open>
|
||||
<summary><h3 id="archived" style="display: inline">Archived</h3></summary>
|
||||
<ul>
|
||||
{% set taglist = collections["archived"] %}
|
||||
{% for post in taglist | reverse %}
|
||||
<li><a href="{{ post.url }}">{{ post.data.title }}</a> {% if post.data.intro %}<span>{{ post.data.intro }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
0
static/assets/weblog/archived/note-taking-2/diagram1.svg → src/weblog/images/archived/diagram1.svg
Executable file → Normal file
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
0
static/assets/weblog/archived/note-taking-experimental/note-creation.png → src/weblog/images/archived/note-creation.png
Executable file → Normal file
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
0
static/assets/weblog/archived/note-taking-experimental/note-list.png → src/weblog/images/archived/note-list.png
Executable file → Normal file
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
0
static/assets/weblog/archived/note-taking-experimental/password-prompt.png → src/weblog/images/archived/password-prompt.png
Executable file → Normal file
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
0
static/assets/weblog/archived/note-taking-experimental/top-buttons.png → src/weblog/images/archived/top-buttons.png
Executable file → Normal file
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
31
src/weblog/index.liquid
Normal file
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
layout: "layout"
|
||||
eleventyExcludeFromCollections: true
|
||||
permalink: /weblog/index.html
|
||||
---
|
||||
|
||||
<h1>weblog</h1>
|
||||
|
||||
<p>Welcome to Sofía's weblog! A place for all kinds of updates, news, and miscellaneous thoughts.</p>
|
||||
|
||||
<h2>latest articles</h2>
|
||||
|
||||
<ul style="list-style-type: none; padding: 0;">
|
||||
{% for post in collections.weblog %}
|
||||
<li>
|
||||
<div>
|
||||
<h3 style="margin-bottom: 0.2rem;"><a style="text-decoration: none;" href="{{ post.data.permalink }}">{{ post.data.title }}</a></h3>
|
||||
<time datetime="{{ post.data.page.date | HTMLdatetime }}">{{ post.data.page.date | datetime }}</time>
|
||||
{% if post.data.introduction %}
|
||||
<p style="font-size: 0.9rem;">
|
||||
{% if post.data.archived %}
|
||||
<span><strong><span style="font-family: 'Nunito', sans-serif">⚠</span> Archived</strong> | </span>
|
||||
{% endif %}
|
||||
{{ post.data.introduction }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<hr style="color: var(--color-secondary); border: 3px dotted; border-style: none none dotted;">
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
title: weblog
|
||||
---
|
||||
|
||||
<h1>weblog</h1>
|
||||
|
||||
<div>
|
||||
<span><a href="/weblog/tags/es">Entradas en español</a></span> ·
|
||||
<span><a href="/weblog/tags/en">Entradas en inglés</a></span>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{% set taglist = collections["post"] %}
|
||||
{% for post in taglist | reverse %}
|
||||
<li><a href="{{ post.url }}">{{ post.data.title }}</a>{% if post.data.intro %} · <span>{{ post.data.intro }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<details style="margin: 0; padding: 0" open>
|
||||
<summary><h3 id="archived" style="display: inline">Archivado</h3></summary>
|
||||
<ul>
|
||||
{% set taglist = collections["archived"] %}
|
||||
{% for post in taglist | reverse %}
|
||||
<li><a href="{{ post.url }}">{{ post.data.title }}</a> {% if post.data.intro %}<span>{{ post.data.intro }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
35
src/weblog/tags.liquid
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
layout: "layout"
|
||||
pagination:
|
||||
data: collections
|
||||
size: 1
|
||||
alias: tag
|
||||
permalink: /weblog/tags/{{ tag }}/
|
||||
---
|
||||
|
||||
<div id="title-header">
|
||||
<a href="/weblog" style="text-decoration: none; font-family: 'Nunito', sans-serif">← Weblog</a>
|
||||
<h1 style="margin-top: 0.7rem;">Tagged “{{ tag }}”</h1>
|
||||
</div>
|
||||
|
||||
{% assign taglist = collections[ tag ] %}
|
||||
{% assign taglist = taglist | reverse %}
|
||||
<ul style="list-style-type: none; padding: 0;">
|
||||
{% for post in taglist %}
|
||||
<li>
|
||||
<div>
|
||||
<h3 style="margin-bottom: 0.2rem;"><a style="text-decoration: none;" href="{{ post.permalink }}">{{ post.data.title }}</a></h3>
|
||||
<time datetime="{{ post.page.date | HTMLdatetime }}">{{ post.page.date | datetime }}</time>
|
||||
{% if post.data.introduction %}
|
||||
<p style="font-size: 0.9rem;">
|
||||
{% if post.archived %}
|
||||
<span><strong><span style="font-family: 'Nunito', sans-serif">⚠</span> Archived</strong> | </span>
|
||||
{% endif %}
|
||||
{{ post.data.introduction }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<hr style="color: var(--color-secondary); border: 3px dotted; border-style: none none dotted;">
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
pagination:
|
||||
data: collections
|
||||
size: 1
|
||||
alias: tag
|
||||
filter:
|
||||
- archived
|
||||
permalink: /weblog/tags/{{ tag }}/
|
||||
---
|
||||
<h1>Tagged “{{ tag }}”</h1>
|
||||
|
||||
<p>
|
||||
Note: <a href="/meta/archived">Archived</a> posts may not be listed.
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
{% set taglist = collections[ tag ] %}
|
||||
{% for post in taglist | reverse %}
|
||||
<li><a href="{{ post.url }}">{{ post.data.title }}</a> {% if post.data.intro %}<span>{{ post.data.intro }}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
layout: base_page.njk
|
||||
---
|
||||
|
||||
# Tagged “archived”
|
||||
|
||||
[Archived](/meta/archived) posts are not listed here.
|
21
src/weblog/weblog.11tydata.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import slugify from '@sindresorhus/slugify';
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
eleventyComputed: {
|
||||
title: data => {
|
||||
const content = data.page?.rawInput
|
||||
const match = content?.match(/^#\s+(.+)$/m)
|
||||
return match ? match[1].trim() : data.page.fileSlug
|
||||
},
|
||||
permalink: data => {
|
||||
// Manually set
|
||||
if (typeof data.permalink === "string") {
|
||||
return data.permalink
|
||||
}
|
||||
|
||||
return `/weblog/${slugify(data.title)}/`
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
:root {
|
||||
font-family: "Rubik", Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
font-weight: 400;
|
||||
|
||||
min-height: 150vh;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
|
||||
background-color: #2d1740;
|
||||
background-image: radial-gradient(hsl(324, 80%, 55%) 0.75px, hsl(273, 48%, 20%) 0.75px), radial-gradient(hsl(324, 80%, 55%) 0.75px, hsl(273, 48%, 20%) 0.75px);
|
||||
background-size: 25px 25px;
|
||||
background-position: 10px 10px;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #e74cac;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body > h1 {
|
||||
font-size: 50px;
|
||||
text-align: center;
|
||||
font-family: "Nunito", "Rubik", Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body > h1 > a {
|
||||
color: #fafafa;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #d52c9c;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 40vw;
|
||||
|
||||
padding: 1rem;
|
||||
padding-bottom: 2rem;
|
||||
background-color: rgba(10, 10, 10, 0.35);
|
||||
border-radius: 5px;
|
||||
|
||||
margin-bottom: 10rem;
|
||||
}
|
||||
|
||||
main > h1 {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
display: flex;
|
||||
margin: 0 10px;
|
||||
gap: 15px;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
.page-container {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
nav ul {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
nav div ul a {
|
||||
display: block;
|
||||
width: 175px;
|
||||
padding: 3px;
|
||||
margin: 10px 0;
|
||||
|
||||
transition: all 150ms;
|
||||
background-color: #dc3f99;
|
||||
border: solid 3px;
|
||||
border-color: #f38cc2 #dc158d #dc158d #f38cc2;
|
||||
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
nav {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
overflow: scroll;
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
.no-comments {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.comment {
|
||||
border: #382e60 solid 1px;
|
||||
border-radius: 7px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
padding: 5px;
|
||||
background-color: hsl(273, 48%, 18%);
|
||||
}
|
||||
|
||||
.comment-author-image {
|
||||
border-radius: 4px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.comment-author-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.comment-author-data > a, .comment-author-link {
|
||||
text-decoration: none;
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
.comment-author-data > a:hover, .comment-author-link:hover {
|
||||
color: #e74cac;
|
||||
}
|
||||
|
||||
.comment-content {
|
||||
padding: 3px 10px;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
(async () => {
|
||||
let el = document.getElementById("comment-section")
|
||||
if (el == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let status_url = `https://hachyderm.io/api/v1/statuses/${el.getAttribute("data-status")}/context`
|
||||
let comments = await (await fetch(status_url)).json()
|
||||
|
||||
if (comments["descendants"] == null || comments["descendants"].length === 0) {
|
||||
el.innerHTML = `<div class="no-comments">No comments yet</div>`
|
||||
return
|
||||
}
|
||||
|
||||
for (let comment of comments["descendants"]) {
|
||||
let date = new Date(comment.created_at).toLocaleDateString(navigator.language || "en-GB", {
|
||||
day: "2-digit",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})
|
||||
let sanitize = DOMPurify.sanitize
|
||||
let comment_html =
|
||||
`
|
||||
<div class="comment">
|
||||
<div class="comment-author">
|
||||
<img class="comment-author-image" src="${sanitize(comment.account.avatar)}" alt="Profile picture of ${sanitize(comment.account.display_name)}">
|
||||
<div class="comment-author-data">
|
||||
<div>
|
||||
<span class="comment-author-name"><a class="comment-author-link" href="${comment.account.url}">${sanitize(comment.account.display_name)}</a></span>
|
||||
</div>
|
||||
<a href="${sanitize(comment.uri)}"><time datetime="${sanitize(comment.created_at)}">${date}</time></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comment-content">
|
||||
${sanitize(comment.content)}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
el.innerHTML += comment_html
|
||||
}
|
||||
})()
|
Before Width: | Height: | Size: 185 KiB |
|
@ -1,2 +0,0 @@
|
|||
User-agent: GPTBot
|
||||
Disallow: /
|