diff --git a/.eleventy.js b/.eleventy.js index 1a1272b..bb8792b 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,15 +1,35 @@ +const { DateTime } = require("luxon") const markdownIt = require("markdown-it"); const markdownItAnchor = require("markdown-it-anchor"); +const timeToRead = require("eleventy-plugin-time-to-read") module.exports = function(eleventyConfig) { eleventyConfig.addPassthroughCopy({ "static": "/" }) + eleventyConfig.addPlugin(timeToRead, { + language: "en", + style: "long", + hours: "auto", + minutes: true, + }) + 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"); + }) + + // 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'); + }) + return { passthroughFileCopy: true, dir: { diff --git a/README.md b/README.md index d2e261d..7af4082 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,5 @@ -# Eleventy Base +# sofi web -A template for creating [11ty](https://www.11ty.dev/docs/) websites. +My personal website :) -## Getting started - -Run `yarn` to resolve the dependencies. - -Make sure to check the following files and change them according to your needs: -* [src/_includes/base_page.njk](src/_includes/base_page.njk). This is the base page, you should change the title of the -page. -* [static/css/base.css](static/css/base.css). This is the base theme, you should at least change the colors. - -After changing the files, run `yarn serve` to serve the website. +[sofiaritz.com](https://sofiaritz.com) \ No newline at end of file diff --git a/package.json b/package.json index 9a4cea6..aa91861 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "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" }, diff --git a/src/_includes/base_page.njk b/src/_includes/base_page.njk index 9097866..80f74f8 100644 --- a/src/_includes/base_page.njk +++ b/src/_includes/base_page.njk @@ -5,25 +5,76 @@ - - {% if title %} {{ title }} - {% endif %}11ty base + + + + {% if styles %} + {% for style in styles %} + + {% endfor %} + {% endif %} + {% if title %} {{ title }} - {% endif %}sofi web -

11TY BASE

+

sofi web

-
{{ content | safe }}
+
+{% if scripts %} + {% for script in scripts %} + + {% endfor %} +{% endif %} \ No newline at end of file diff --git a/src/_includes/post.njk b/src/_includes/post.njk new file mode 100644 index 0000000..b766a35 --- /dev/null +++ b/src/_includes/post.njk @@ -0,0 +1,45 @@ +--- +layout: base_page.njk +scripts: ["/assets/weblog/comments.js", "/assets/libraries/dompurify.js"] +styles: ["/assets/css/comments.css"] +--- + +

{{ title }}

+
+ {% if date %} + | + {% endif %} + + {% if tags.includes("archived") %} + Archived post | + {% endif %} + + {% if tags %} + {% if tags.length > 1 %} + Tags: + {% else %} + Tag: + {% endif %} + {% set relTags = tags | relevantTags %} + {% for tag in relTags %} + {{ tag }} {% if loop.last == false %}·{% endif %} + {% endfor %} + | + {% endif %} + {{ content | timeToRead }} | + Comments +
+ + + +{{ content | safe }} + +{% if comment_status %} +
+
+
+

comments · post

+
+
+
+{% endif %} \ No newline at end of file diff --git a/src/contact.md b/src/contact.md new file mode 100644 index 0000000..dcb4671 --- /dev/null +++ b/src/contact.md @@ -0,0 +1,25 @@ +--- +layout: base_page.njk +title: contact +permalink: /en/contact.html +lang: "en" +--- + +# contact + +### direct contact + +* 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) + +### encryption and signing + +You can find my public PGP key at [/keys/pub.asc](/keys/pub.asc), it's also available at the +[Ubuntu keyservers](https://keyserver.ubuntu.com/). + +The fingerprint of the cert is: `4BB1 6A74 5DE1 C776 5CF3 8788 90B5 116E 3542 B28F`. \ No newline at end of file diff --git a/src/contacto.md b/src/contacto.md new file mode 100644 index 0000000..e36d893 --- /dev/null +++ b/src/contacto.md @@ -0,0 +1,26 @@ +--- +layout: base_page.njk +title: contacto +permalink: /contact.html +--- + +# contacto + +Si tienes interés en trabajar conmigo, visita mi [página de trabajo](https://work.sofiaritz.com/). + +### 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) + +### cifrado y firma + +Puedes encontrar mi clave PGP pública en [/keys/pub.asc](/keys/pub.asc), también disponible en los +[keyservers de Ubuntu](https://keyserver.ubuntu.com/). + +La huella digital del certificado es: `4BB1 6A74 5DE1 C776 5CF3 8788 90B5 116E 3542 B28F`. \ No newline at end of file diff --git a/src/index.md b/src/index.md index fd5dd1e..dbf0dce 100644 --- a/src/index.md +++ b/src/index.md @@ -2,12 +2,23 @@ layout: base_page.njk --- -# eleventy base +# inicio -This is a template for creating [11ty](https://www.11ty.dev/docs/) websites. +Soy Sofía, aunque la gente me suele llamar Sofi. -The default theme isn't beautiful, but it isn't meant to be. Head over to the `static/css/base.css` file and change -the colors to suit your style. +Pese a ser una estudiante estoy trabajando en algunos [proyectos](/proyectos) centrados en la creación de herramientas +para ayudar a desarrolladores crear sistemas más privados y seguros. Además de esto, colaboro en algunos proyectos cuyo +objetivo es devolver a los usuarios el control sobre sus datos. -Make sure to check the `src/_includes/base_page.njk` to change things like the title and stuff like that. +Trato de usar e impulsar el uso de [estándares abiertos](https://es.wikipedia.org/wiki/Est%C3%A1ndar_abierto) y +sistemas [descentralizados](https://es.wikipedia.org/wiki/Descentralizaci%C3%B3n), ya que se alinean con mis +[objetivos](https://work.sofiaritz.com/objetivos/) a la hora de crear software. +Además del mundo de la computación, tengo un especial interés en el mundo lingüístico, en especial en +las [lenguas construidas](https://es.wikipedia.org/wiki/Lengua_construida) y el +[Toki Pona](https://es.wikipedia.org/wiki/Toki_pona). + +En lo que respecta a las tecnologías que suelo manejar, todo depende del proyecto y sus especificaciones, pero tiendo +a centrarme en [Rust](https://es.wikipedia.org/wiki/Rust_(lenguaje_de_programaci%C3%B3n)) o [Zig](https://ziglang.org/) +y [JavaScript](https://es.wikipedia.org/wiki/JavaScript). Este es un indicador muy simple, pues cada lenguaje +tiene distintas ramificaciones, pero esta página de inicio no es el lugar para detallar el uso que le doy a cada uno. diff --git a/src/meta/archived.md b/src/meta/archived.md new file mode 100644 index 0000000..efd05d4 --- /dev/null +++ b/src/meta/archived.md @@ -0,0 +1,15 @@ +--- +layout: base_page.njk +title: archived +--- + +# archived pages + +Archived pages are left for historical purposes, but should be taken with a grain of salt. + +Archived pages _could_ contain the following problems: +* Their content is not up-to-date. +* Their content is not accurate. +* They do not represent my current views or opinions. +* They contain broken links, images, etc. + * If you find any of these, [contact me](/contacto), and I'll do my best to fix it. \ No newline at end of file diff --git a/src/meta/index.md b/src/meta/index.md new file mode 100644 index 0000000..43e92f6 --- /dev/null +++ b/src/meta/index.md @@ -0,0 +1,12 @@ +--- +layout: base_page.njk +title: meta +--- + +# meta + +The purpose of this page is to serve as an index to the various documents related to non-technical aspects of the +projects I maintain. + +* [archived pages](/meta/archived) +* [maintenance tiers](/meta/maintenance-tiers) \ No newline at end of file diff --git a/src/meta/maintenance-tiers.md b/src/meta/maintenance-tiers.md new file mode 100644 index 0000000..f180ee1 --- /dev/null +++ b/src/meta/maintenance-tiers.md @@ -0,0 +1,54 @@ +--- +layout: base_page.njk +title: maintenance tiers +--- + +# maintenance tiers + +Not all projects are treated equal. Some are in active development, others are finished, others are deprecated, etc. + +The purpose of this page is to show what does each tier mean. Some projects may not adhere to the descriptions here, +any deviation from this page _should_ be documented in the project itself. + +## active development + +**Recommendation:** feel free to use the project. + +* The project is not finished yet and new features will arrive in the future. +* The response time to issues and pull requests is good. +* New features are welcome after some public discussion. + +## finished + +**Recommendation:** feel free to use the project. + +* The project serves its purpose and does not need any more features. +* The response time to issues and pull requests is good, but those related to new features _may_ be rejected. +* Any unexpected behaviour will be fixed by myself (unless a pull request is sent by someone else). + +## low maintenance + +**Recommendation:** feel free to use the project. + +* The project serves its purpose and does not need any more features, but its relevance has decreased. +* The response time to issues and pull requests _can_ be worse. + * Pull requests related to new features _will_ be rejected. +* I will not work on any non-security issues, but will review and merge pull requests. +* Anyone can become a maintainer after [contacting me](/contacto). + +## deprecated + +**Recommendation:** switch to an alternative or start maintaining your own fork. + +* The project is not actively maintained anymore. +* I will not work on any issues, but I will review and merge pull requests related to security issues. +* Feel free to maintain your own fork. + +## decommissioned/archived + +**Recommendation:** switch to an alternative or start maintaining your own fork **as soon as possible**. + +* The project is not maintained at all. +* I will not work on any issues. +* Pull requests will not be reviewed nor merged. +* Feel free to maintain your own fork. \ No newline at end of file diff --git a/src/proyectos.md b/src/proyectos.md new file mode 100644 index 0000000..20a6a83 --- /dev/null +++ b/src/proyectos.md @@ -0,0 +1,22 @@ +--- +layout: base_page.njk +title: proyectos +--- + +# proyectos + +## 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. \ No newline at end of file diff --git a/src/weblog/2023/11/updated-website.md b/src/weblog/2023/11/updated-website.md new file mode 100644 index 0000000..c46e1bd --- /dev/null +++ b/src/weblog/2023/11/updated-website.md @@ -0,0 +1,50 @@ +--- +layout: post.njk +title: Major update +intro: The first major update to this website and the start of a new era. +tags: + - meta + - website + - post + - en +date: 2023-11-28 +--- + +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. The background is a _proper_ pattern now (I still can't recall where I got the old background from) +2. The [weblog index](/weblog) has been streamlined, and now it's the same for both the English and Spanish page. +3. I've added support for [tags](/weblog/tags/meta/)! +4. Some minor usability improvements. + +There are also new additions! Support for comments has been added using the Mastodon API. Graceful degradation has +played an important role in this remake, this website is fully viewable in the +[Nintendo 3DS Browser](https://en.wikipedia.org/wiki/NetFront) with some minor rendering glitches. + +The navbar has a new section: _links_, this section provides quick access to things like the +[Status page](https://status.sofiaritz.com/) and my [Forgejo instance](https://git.sofiaritz.com/explore/repos). + +## a new era + +This is not only a stylistic and QoL change. This major change is part of the +Common Unification Project, a project whose purpose is to develop a set of guidelines around styling, design process, +maintenance and governance of the projects I maintain. These guidelines will be slowly added to the +[_meta_ page](/meta). + +[Some projects](https://status.sofiaritz.com/) have also [been deprecated](/meta/maintenance-tiers/#deprecated), which +means that they may be [decommissioned](/meta/maintenance-tiers/#decommissioned%2Farchived) in the near future. + +This will allow me to focus on some projects that will be released to the public in the following months. + +## technicalities + +This website, like the previous version, uses [11ty](https://www.11ty.dev) to prerender all the pages. + +New weblog entries will follow the following path convention: `/weblog/YYYY/mm/`. Older posts have been +[archived](/meta/archived). + +## to be done + +There are still many things to be done, like RSS feeds, improved internationalization, and +[webmention](https://indieweb.org/Webmention) support. \ No newline at end of file diff --git a/src/weblog/archived/firstpost.md b/src/weblog/archived/firstpost.md new file mode 100755 index 0000000..cb6f82e --- /dev/null +++ b/src/weblog/archived/firstpost.md @@ -0,0 +1,19 @@ +--- +layout: post.njk +title: Primer post +intro: El nacimiento de mi weblog! :) +tags: + - meta + - archived + - es +date: 2023-03-12 +permalink: /weblog/firstpost/ +--- + +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! diff --git a/src/weblog/archived/note-taking-2.md b/src/weblog/archived/note-taking-2.md new file mode 100755 index 0000000..e43b23c --- /dev/null +++ b/src/weblog/archived/note-taking-2.md @@ -0,0 +1,101 @@ +--- +layout: post.njk +title: Note Taking (II). Retos +intro: Retos encontrados por el camino. +tags: + - rust + - experimentos + - note taking + - archived + - es +date: 2023-05-06 +permalink: /weblog/note-taking-2/ +--- + +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. + +Surgió como un prototipo [sobre el que fui iterando](/weblog/note-taking-experiment) hasta llegar a lo que es hoy día: +una plataforma relativamente estable, simple y segura para crear notas. + +Pese a que el concepto es sencillo, en la ejecución lo está todo. Y ahí se yace el propósito de este artículo: mostrar +los retos que me he encontrado en este camino. + +## seguridad + +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: + + + +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)). +* [pwbox](https://github.com/exonum/pwbox-rs) se encarga de encriptar las notas usando el resultado derivado de la +contraseña original. + +Pero ello no implica que tenga algunos problemas, en especial **la imposibilidad de cambiar contraseñas**. + +## cambio de contraseñas + +En un software como este, es frecuente que el usuario quiera cambiar de contraseñas ocasionalmente por variadas razones: +cambio rutinario preventivo, contraseñas que han sido expuestas, etc. + +El sistema actual impide que esto sea posible, pues la contraseña es la base de la encriptación. A día de hoy para poder +cambiar la contraseña sería necesario ir nota por nota desencriptándola y reencriptándola. Esto es un proceso que puede +parecer [sencillo](https://git.sofiaritz.com/sofia/note-taking/src/commit/c97700b29aba660ffe7b6753266d6559a84b8d01/src/password/mod.rs#L59), +pero en cuanto el número de notas crece, una operación de este tipo se vuelve imposible de manejar. + +### posibles soluciones + +Existen varios caminos que se pueden tomar para solucionar esto, pero el que creo que va a ser utilizado va a ser el +siguiente: + +Cada nota contiene una clave única que es la utilizada para encriptar los contenidos de la misma. Esta clave única, +antes de ser almacenada en los _metadatos_ de la nota pasa por el sistema [descrito anteriormente](#seguridad). + +Esto permite lo siguiente: +* Cada nota tiene su clave única de encriptación, por lo tanto, un ataque de fuerza bruta directamente en la nota pierde +utilidad. +* El uso de una clave de encriptación única y permanente por nota permite que el cambio de la contraseña solo tenga que +afectar a un centenar de bits en lugar de varios miles de bits, pues únicamente habría que reencriptar la clave de +cada nota. + +## metadatos + +A día de hoy, todos los metadatos (título, metadatos explícitos, fecha, etc) están sin encriptar. Esto es algo bastante +delicado, pues muchas veces los metadatos son mucho más _dañinos_ de lo que nos podemos imaginar. + +Tengo pensado crear un archivo especial para las notas que pueda contener todas las notas de una manera centralizada +y segura. En un principio una nota tendría una estructura similar a la siguiente: + +* Longitud de la clave encriptada +* Clave encriptada +* Longitud de los metadatos +* Metadatos en JSON encriptados +* Longitud de la nota +* Nota encriptada +* Checksum de la nota + +Además de esto, el archivo estaría versionado y trataría de ser lo más escalable posible en lo que a futuros _metadatos +especiales_ (fecha, autor, etc) respecta. + +## riqueza + +A día de hoy las notas son simplemente texto plano. Otra de las cosas que tengo pensadas añadir es soporte básico de +Markdown (únicamente cosas como **negrita**, _cursiva_, ~~tachado~~, etc.) + +Me encantaría añadir soporte para imágenes, pero usando Markdown _estándar_ es peligroso para la seguridad de los +usuarios. Una alternativa sería aprovechar la creación de un archivo personalizado para añadir una sección de +información arbitraria que funcionara como un [diccionario](https://en.wikipedia.org/wiki/Associative_array), donde cada +conjunto de datos arbitrarios tuviera asociado un identificador único que pudiera ser referenciado en Markdown. + +Pese a ello, esto abre un gran vector de ataque que habría que cuidar, por tanto, el soporte de imágenes es algo que +seguramente tendrá que esperar. + +## conclusión + +Sin duda crear este software está siendo una experiencia bastante interesante que me está ayudando a aprender sobre +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 +:) diff --git a/src/weblog/archived/note-taking-experiment.md b/src/weblog/archived/note-taking-experiment.md new file mode 100755 index 0000000..22fb8ef --- /dev/null +++ b/src/weblog/archived/note-taking-experiment.md @@ -0,0 +1,117 @@ +--- +layout: post.njk +title: Note Taking. Notas encriptadas +intro: Un programa experimental para encriptar notas. +tags: + - rust + - experimentos + - note taking + - archived + - es +date: 2023-03-12 +permalink: /weblog/note-taking-experiment/ +--- + +## 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 +el .txt, abría [Kleopatra](https://www.gpg4win.org/about.html), esperaba a que se cargara la base de datos, etc. + +No es difícil darse cuenta de que este sistema no era _el óptimo_. Por tanto, decidí embarcarme en la búsqueda de +algún programa que cumpliera los siguientes requisitos: +1. **Offline**. No quiero mis notas, encriptadas o no, viajando por lugares desconocidos. +2. **Seguro**. No quiero mis notas siendo expuestas por alguna vulnerabilidad o problema de diseño. +3. **Simple**. No quiero tener que dar mil vueltas para escribir un documento de 50 palabras. + +Y todo lo que encontraba no cumplía todos los requisitos: o tenía _sincronización en la nube_, o la interfaz era muy +compleja, etc. + +Por tanto, decidí que debía arreglar esto yo misma: y así surgió +[note taking](https://git.sofiaritz.com/sofia/note-taking). + +## idea + +He estado un par de semanas experimentando con un concepto relativamente simple: +_un programa que permita crear y almacenar notas encriptadas_. + +Este concepto es sencillo, pero la ejecución es lo importante. Me establecí una serie de objetivos que permitieran +poder tener una base sobre la que trabajar, y estos objetivos eran los siguientes: +- **Simple**. Una aplicación fácil de usar para todo el mundo, con y sin conocimientos. +- **Seguro**. Las notas no deben ser susceptibles de ataques de fuerza bruta y compañía. +- **Completo**. Se debe ofrecer una gran variedad de opciones y posibilidades a la hora de redactar y ver las notas. + +## funcionamiento + +note taking tiene un funcionamiento bastante sencillo. Cuando abres la aplicación ocurre lo siguiente: +1. Te pide que introduzcas la contraseña utilizada para encriptar la "_base de datos_". +2. Comprueba la contraseña utilizando notas existentes. +3. Si es correcta, carga todas las notas encriptadas en memoria para ser desencriptadas bajo demanda. + +Una vez has pasado esta etapa inicial, todo es muy intuitivo. Para añadir una nota haces click en el botón que dice +"_want to add one note?_", para desencriptar una nota haces click en el botón que dice "_decrypt note_", etc. + +Además de esto, el apartado de configuración actualmente tiene la opción de exportar las notas en formato JSON para +poder ser importadas por programas compatibles con el formato. En un futuro el apartado de configuración tendrá más +opciones, como importar notas, cambiar la contraseña y demás. + +## seguridad + +Recientemente, se cambió como se manejaban las contraseñas en note taking. Ahora mismo se sigue el siguiente sistema: +1. El usuario introduce la contraseña +2. La contraseña pasa por una función de derivación +([KDF](https://crypto.stackexchange.com/questions/40757/key-derivation-functions-kdf-what-are-they-what-are-their-main-purposes-and)) + 1. Se calcula el SHA256 de la contraseña, que se utilizará como + [_salt_](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#salting). + 2. Se usa [Argon2](https://en.wikipedia.org/wiki/Argon2) para crear el hash de la contraseña. + 3. Se codifica el resultado en hexadecimal. +3. Se utiliza [pwbox](https://docs.rs/pwbox/0.5.0/pwbox/) con la contraseña derivada. + +Este sistema evita que se puedan forzar las contraseñas: +1. Todas las contraseñas tienen gran entropía al salir del KDF. +2. El KDF tiene gran complejidad, lo que ralentiza los ataques de fuerza bruta. + +Además de esto, se utilizan ciertos sistemas para _sugerir_ al usuario el uso de contraseñas seguras. Un ejemplo de esto +es cómo se le muestran al usuario tanto la longitud como entropía de la contraseña introducida con un sistema de colores +bastante explícito que _invita_ al usuario a emplear contraseñas seguras. + +Todo esto se puede ver en mayor detalle en +[_Security of the encrypted notes_ · sofia@git.sofiaritz.com/note-taking#1](https://git.sofiaritz.com/sofia/note-taking/issues/1). + +## planes de futuro + +En el futuro me gustaría añadir un sistema "_Markdown_" básico para que se puedan añadir cosas como letra en cursiva, +negrita, imágenes, etc. + +Pese a que esto pueda parecer relativamente sencillo, especialmente teniendo en cuenta que +[ya existen librerías](https://crates.io/crates/egui_commonmark) que se encargan de esto, cosas como imágenes pueden +ser un gran vector de ataque para intentar desanonimizar u obtener información del usuario. Por tanto, esta clase de +decisiones deben ser tomadas con mucho estudio y cautela. + +Además de esto, me gustaría mejorar la privacidad de ciertos aspectos de las notas (metadatos, etc.) y expandir los +ajustes. + +## quiero probarlo! + +Ahora mismo [no estoy distribuyendo ejecutables](https://git.sofiaritz.com/sofia/note-taking/issues/2), pero es muy +fácil compilar el proyecto si ya tienes Rust y Cargo. + +Si ya tienes Rust y Cargo [instalados](https://www.rust-lang.org/tools/install) y +[actualizados](https://rust-lang.github.io/rustup/basics.html#keeping-rust-up-to-date), ejecuta los siguientes comandos: +1. `git clone https://git.sofiaritz.com/sofia/note-taking.git` +2. `cd note-taking` +3. `cargo run --release` + +(Si el último paso falla, puede que tengas que utilizar `cargo +nightly build --release`) + +## ideas? + +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 + +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. +Captura de pantalla donde se muestran los botones 'want to add one note?' y 'settings' +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' +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' + diff --git a/src/weblog/en_index.njk b/src/weblog/en_index.njk new file mode 100644 index 0000000..edf881a --- /dev/null +++ b/src/weblog/en_index.njk @@ -0,0 +1,30 @@ +--- +layout: base_page.njk +title: weblog +permalink: /en/weblog.html +lang: "en" +--- + +

weblog

+ +
+ English posts · + Spanish posts +
+ + + +
+

Archived

+ +
\ No newline at end of file diff --git a/src/weblog/index.njk b/src/weblog/index.njk new file mode 100644 index 0000000..18e4b73 --- /dev/null +++ b/src/weblog/index.njk @@ -0,0 +1,28 @@ +--- +layout: base_page.njk +title: weblog +--- + +

weblog

+ +
+ Entradas en español · + Entradas en inglés +
+ + + +
+

Archivado

+ +
\ No newline at end of file diff --git a/src/weblog/tags.njk b/src/weblog/tags.njk new file mode 100644 index 0000000..10546d2 --- /dev/null +++ b/src/weblog/tags.njk @@ -0,0 +1,22 @@ +--- +layout: base_page.njk +pagination: + data: collections + size: 1 + alias: tag + filter: + - archived +permalink: /weblog/tags/{{ tag }}/ +--- +

Tagged “{{ tag }}”

+ +

+ Note: Archived posts may not be listed. +

+ +
    + {% set taglist = collections[ tag ] %} + {% for post in taglist | reverse %} +
  1. {{ post.data.title }} {% if post.data.intro %}{{ post.data.intro }}{% endif %}
  2. + {% endfor %} +
\ No newline at end of file diff --git a/src/weblog/tags/archived.md b/src/weblog/tags/archived.md new file mode 100644 index 0000000..ea20710 --- /dev/null +++ b/src/weblog/tags/archived.md @@ -0,0 +1,7 @@ +--- +layout: base_page.njk +--- + +# Tagged “archived” + +[Archived](/meta/archived) posts are not listed here. \ No newline at end of file diff --git a/static/css/base.css b/static/assets/css/base.css similarity index 64% rename from static/css/base.css rename to static/assets/css/base.css index 5ab4ce9..d020b97 100644 --- a/static/css/base.css +++ b/static/assets/css/base.css @@ -4,10 +4,13 @@ line-height: 24px; font-weight: 400; - min-height: 100%; + min-height: 150vh; color: rgba(255, 255, 255, 0.9); - background: #29468c; + 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; @@ -17,7 +20,7 @@ } a { - color: #b8c3de; + color: #e74cac; } body { @@ -27,23 +30,29 @@ body { 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: #2c9ad5; + text-decoration-color: #d52c9c; } main { width: 40vw; - margin-bottom: 75px; + text-align: justify; + + padding: 1rem; + background-color: rgba(10, 10, 10, 0.35); + border-radius: 5px; } .page-container { display: flex; margin: 0 10px; gap: 15px; + flex-direction: row-reverse; justify-content: center; } @@ -76,8 +85,9 @@ nav div ul a { margin: 10px 0; transition: all 150ms; - background-color: #686b77; - border: solid 3px #2c9ad5; + background-color: #dc3f99; + border: solid 3px; + border-color: #f38cc2 #dc158d #dc158d #f38cc2; color: white; } diff --git a/static/assets/css/comments.css b/static/assets/css/comments.css new file mode 100644 index 0000000..c4b8612 --- /dev/null +++ b/static/assets/css/comments.css @@ -0,0 +1,39 @@ +.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; +} \ No newline at end of file diff --git a/static/assets/css/fonts.css b/static/assets/css/fonts.css new file mode 100644 index 0000000..3f633e8 --- /dev/null +++ b/static/assets/css/fonts.css @@ -0,0 +1,34 @@ +@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"); + font-style: normal; + font-weight: 400 500; +} + +@font-face { + font-family: "Rubik"; + src: url("https://cdn.sofiaritz.com/fonts/ofl/rubik/Rubik-Italic[wght].ttf"); + font-style: italic; + font-weight: 400 500; +} + +@font-face { + font-family: "Nunito"; + src: url("https://cdn.sofiaritz.com/fonts/ofl/nunito/Nunito[wght].ttf"); + font-style: normal; + font-weight: 700; +} \ No newline at end of file diff --git a/static/assets/libraries/dompurify.js b/static/assets/libraries/dompurify.js new file mode 100644 index 0000000..374193f --- /dev/null +++ b/static/assets/libraries/dompurify.js @@ -0,0 +1,2 @@ +/*! @license DOMPurify 3.0.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.1/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,n){return t=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},t(e,n)}function n(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function r(e,o,a){return r=n()?Reflect.construct:function(e,n,r){var o=[null];o.push.apply(o,n);var a=new(Function.bind.apply(e,o));return r&&t(a,r.prototype),a},r.apply(null,arguments)}function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==n)return;var r,o,a=[],i=!0,l=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(a.push(r.value),!t||a.length!==t);i=!0);}catch(e){l=!0,o=e}finally{try{i||null==n.return||n.return()}finally{if(l)throw o}}return a}(e,t)||i(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e){return function(e){if(Array.isArray(e))return l(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||i(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){if(e){if("string"==typeof e)return l(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(e,t):void 0}}function l(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1?n-1:0),o=1;o=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,l=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return l=e.done,e},e:function(e){c=!0,a=e},f:function(){try{l||null==n.return||n.return()}finally{if(c)throw a}}}}(c(e));try{for(r.s();!(t=r.n()).done;){var a=o(t.value,2),l=a[0],u=a[1];n[l]=u}}catch(e){r.e(e)}finally{r.f()}return n}function M(e,t){for(;null!==e;){var n=m(e,t);if(n){if(n.get)return R(n.get);if("function"==typeof n.value)return R(n.value)}e=f(e)}return function(e){return console.warn("fallback value for",e),null}}var I=p(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),U=p(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),F=p(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),z=p(["animate","color-profile","cursor","discard","fedropshadow","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),H=p(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),j=p(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),P=p(["#text"]),B=p(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","xmlns","slot"]),G=p(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),W=p(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),q=p(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),Y=d(/\{\{[\w\W]*|[\w\W]*\}\}/gm),$=d(/<%[\w\W]*|[\w\W]*%>/gm),K=d(/\${[\w\W]*}/gm),V=d(/^data-[\-\w.\u00B7-\uFFFF]/),X=d(/^aria-[\-\w]+$/),Z=d(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),J=d(/^(?:\w+script|data):/i),Q=d(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),ee=d(/^html$/i),te=function(){return"undefined"==typeof window?null:window},ne=function(t,n){if("object"!==e(t)||"function"!=typeof t.createPolicy)return null;var r=null,o="data-tt-policy-suffix";n.currentScript&&n.currentScript.hasAttribute(o)&&(r=n.currentScript.getAttribute(o));var a="dompurify"+(r?"#"+r:"");try{return t.createPolicy(a,{createHTML:function(e){return e},createScriptURL:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+a+" could not be created."),null}};var re=function t(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:te(),r=function(e){return t(e)};if(r.version="3.0.1",r.removed=[],!n||!n.document||9!==n.document.nodeType)return r.isSupported=!1,r;var o=n.document,i=n.document,l=n.DocumentFragment,u=n.HTMLTemplateElement,s=n.Node,f=n.Element,m=n.NodeFilter,d=n.NamedNodeMap,h=void 0===d?n.NamedNodeMap||n.MozNamedAttrMap:d,y=n.HTMLFormElement,g=n.DOMParser,b=n.trustedTypes,v=f.prototype,R=M(v,"cloneNode"),re=M(v,"nextSibling"),oe=M(v,"childNodes"),ae=M(v,"parentNode");if("function"==typeof u){var ie=i.createElement("template");ie.content&&ie.content.ownerDocument&&(i=ie.content.ownerDocument)}var le=ne(b,o),ce=le?le.createHTML(""):"",ue=i,se=ue.implementation,fe=ue.createNodeIterator,me=ue.createDocumentFragment,pe=ue.getElementsByTagName,de=o.importNode,he={};r.isSupported="function"==typeof c&&"function"==typeof ae&&se&&void 0!==se.createHTMLDocument;var ye,ge,be=Y,ve=$,Te=K,Ne=V,Ae=X,Ee=J,we=Q,Se=Z,_e=null,xe=C({},[].concat(a(I),a(U),a(F),a(H),a(P))),ke=null,Oe=C({},[].concat(a(B),a(G),a(W),a(q))),De=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Re=null,Ce=null,Le=!0,Me=!0,Ie=!1,Ue=!0,Fe=!1,ze=!1,He=!1,je=!1,Pe=!1,Be=!1,Ge=!1,We=!0,qe=!1,Ye="user-content-",$e=!0,Ke=!1,Ve={},Xe=null,Ze=C({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),Je=null,Qe=C({},["audio","video","img","source","image","track"]),et=null,tt=C({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),nt="http://www.w3.org/1998/Math/MathML",rt="http://www.w3.org/2000/svg",ot="http://www.w3.org/1999/xhtml",at=ot,it=!1,lt=null,ct=C({},[nt,rt,ot],w),ut=["application/xhtml+xml","text/html"],st="text/html",ft=null,mt=i.createElement("form"),pt=function(e){return e instanceof RegExp||e instanceof Function},dt=function(t){ft&&ft===t||(t&&"object"===e(t)||(t={}),t=L(t),ye=ye=-1===ut.indexOf(t.PARSER_MEDIA_TYPE)?st:t.PARSER_MEDIA_TYPE,ge="application/xhtml+xml"===ye?w:E,_e="ALLOWED_TAGS"in t?C({},t.ALLOWED_TAGS,ge):xe,ke="ALLOWED_ATTR"in t?C({},t.ALLOWED_ATTR,ge):Oe,lt="ALLOWED_NAMESPACES"in t?C({},t.ALLOWED_NAMESPACES,w):ct,et="ADD_URI_SAFE_ATTR"in t?C(L(tt),t.ADD_URI_SAFE_ATTR,ge):tt,Je="ADD_DATA_URI_TAGS"in t?C(L(Qe),t.ADD_DATA_URI_TAGS,ge):Qe,Xe="FORBID_CONTENTS"in t?C({},t.FORBID_CONTENTS,ge):Ze,Re="FORBID_TAGS"in t?C({},t.FORBID_TAGS,ge):{},Ce="FORBID_ATTR"in t?C({},t.FORBID_ATTR,ge):{},Ve="USE_PROFILES"in t&&t.USE_PROFILES,Le=!1!==t.ALLOW_ARIA_ATTR,Me=!1!==t.ALLOW_DATA_ATTR,Ie=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Ue=!1!==t.ALLOW_SELF_CLOSE_IN_ATTR,Fe=t.SAFE_FOR_TEMPLATES||!1,ze=t.WHOLE_DOCUMENT||!1,Pe=t.RETURN_DOM||!1,Be=t.RETURN_DOM_FRAGMENT||!1,Ge=t.RETURN_TRUSTED_TYPE||!1,je=t.FORCE_BODY||!1,We=!1!==t.SANITIZE_DOM,qe=t.SANITIZE_NAMED_PROPS||!1,$e=!1!==t.KEEP_CONTENT,Ke=t.IN_PLACE||!1,Se=t.ALLOWED_URI_REGEXP||Se,at=t.NAMESPACE||ot,De=t.CUSTOM_ELEMENT_HANDLING||{},t.CUSTOM_ELEMENT_HANDLING&&pt(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(De.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&pt(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(De.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(De.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Fe&&(Me=!1),Be&&(Pe=!0),Ve&&(_e=C({},a(P)),ke=[],!0===Ve.html&&(C(_e,I),C(ke,B)),!0===Ve.svg&&(C(_e,U),C(ke,G),C(ke,q)),!0===Ve.svgFilters&&(C(_e,F),C(ke,G),C(ke,q)),!0===Ve.mathMl&&(C(_e,H),C(ke,W),C(ke,q))),t.ADD_TAGS&&(_e===xe&&(_e=L(_e)),C(_e,t.ADD_TAGS,ge)),t.ADD_ATTR&&(ke===Oe&&(ke=L(ke)),C(ke,t.ADD_ATTR,ge)),t.ADD_URI_SAFE_ATTR&&C(et,t.ADD_URI_SAFE_ATTR,ge),t.FORBID_CONTENTS&&(Xe===Ze&&(Xe=L(Xe)),C(Xe,t.FORBID_CONTENTS,ge)),$e&&(_e["#text"]=!0),ze&&C(_e,["html","head","body"]),_e.table&&(C(_e,["tbody"]),delete Re.tbody),p&&p(t),ft=t)},ht=C({},["mi","mo","mn","ms","mtext"]),yt=C({},["foreignobject","desc","title","annotation-xml"]),gt=C({},["title","style","font","a","script"]),bt=C({},U);C(bt,F),C(bt,z);var vt=C({},H);C(vt,j);var Tt=function(e){var t=ae(e);t&&t.tagName||(t={namespaceURI:at,tagName:"template"});var n=E(e.tagName),r=E(t.tagName);return!!lt[e.namespaceURI]&&(e.namespaceURI===rt?t.namespaceURI===ot?"svg"===n:t.namespaceURI===nt?"svg"===n&&("annotation-xml"===r||ht[r]):Boolean(bt[n]):e.namespaceURI===nt?t.namespaceURI===ot?"math"===n:t.namespaceURI===rt?"math"===n&&yt[r]:Boolean(vt[n]):e.namespaceURI===ot?!(t.namespaceURI===rt&&!yt[r])&&(!(t.namespaceURI===nt&&!ht[r])&&(!vt[n]&&(gt[n]||!bt[n]))):!("application/xhtml+xml"!==ye||!lt[e.namespaceURI]))},Nt=function(e){A(r.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){e.remove()}},At=function(e,t){try{A(r.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){A(r.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!ke[e])if(Pe||Be)try{Nt(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Et=function(e){var t,n;if(je)e=""+e;else{var r=S(e,/^[\r\n\t ]+/);n=r&&r[0]}"application/xhtml+xml"===ye&&at===ot&&(e=''+e+"");var o=le?le.createHTML(e):e;if(at===ot)try{t=(new g).parseFromString(o,ye)}catch(e){}if(!t||!t.documentElement){t=se.createDocument(at,"template",null);try{t.documentElement.innerHTML=it?ce:o}catch(e){}}var a=t.body||t.documentElement;return e&&n&&a.insertBefore(i.createTextNode(n),a.childNodes[0]||null),at===ot?pe.call(t,ze?"html":"body")[0]:ze?t.documentElement:a},wt=function(e){return fe.call(e.ownerDocument||e,e,m.SHOW_ELEMENT|m.SHOW_COMMENT|m.SHOW_TEXT,null,!1)},St=function(e){return e instanceof y&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof h)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},_t=function(t){return"object"===e(s)?t instanceof s:t&&"object"===e(t)&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName},xt=function(e,t,n){he[e]&&T(he[e],(function(e){e.call(r,t,n,ft)}))},kt=function(e){var t;if(xt("beforeSanitizeElements",e,null),St(e))return Nt(e),!0;var n=ge(e.nodeName);if(xt("uponSanitizeElement",e,{tagName:n,allowedTags:_e}),e.hasChildNodes()&&!_t(e.firstElementChild)&&(!_t(e.content)||!_t(e.content.firstElementChild))&&O(/<[/\w]/g,e.innerHTML)&&O(/<[/\w]/g,e.textContent))return Nt(e),!0;if(!_e[n]||Re[n]){if(!Re[n]&&Dt(n)){if(De.tagNameCheck instanceof RegExp&&O(De.tagNameCheck,n))return!1;if(De.tagNameCheck instanceof Function&&De.tagNameCheck(n))return!1}if($e&&!Xe[n]){var o=ae(e)||e.parentNode,a=oe(e)||e.childNodes;if(a&&o)for(var i=a.length-1;i>=0;--i)o.insertBefore(R(a[i],!0),re(e))}return Nt(e),!0}return e instanceof f&&!Tt(e)?(Nt(e),!0):"noscript"!==n&&"noembed"!==n||!O(/<\/no(script|embed)/i,e.innerHTML)?(Fe&&3===e.nodeType&&(t=e.textContent,t=_(t,be," "),t=_(t,ve," "),t=_(t,Te," "),e.textContent!==t&&(A(r.removed,{element:e.cloneNode()}),e.textContent=t)),xt("afterSanitizeElements",e,null),!1):(Nt(e),!0)},Ot=function(e,t,n){if(We&&("id"===t||"name"===t)&&(n in i||n in mt))return!1;if(Me&&!Ce[t]&&O(Ne,t));else if(Le&&O(Ae,t));else if(!ke[t]||Ce[t]){if(!(Dt(e)&&(De.tagNameCheck instanceof RegExp&&O(De.tagNameCheck,e)||De.tagNameCheck instanceof Function&&De.tagNameCheck(e))&&(De.attributeNameCheck instanceof RegExp&&O(De.attributeNameCheck,t)||De.attributeNameCheck instanceof Function&&De.attributeNameCheck(t))||"is"===t&&De.allowCustomizedBuiltInElements&&(De.tagNameCheck instanceof RegExp&&O(De.tagNameCheck,n)||De.tagNameCheck instanceof Function&&De.tagNameCheck(n))))return!1}else if(et[t]);else if(O(Se,_(n,we,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==x(n,"data:")||!Je[e]){if(Ie&&!O(Ee,_(n,we,"")));else if(n)return!1}else;return!0},Dt=function(e){return e.indexOf("-")>0},Rt=function(t){var n,o,a,i;xt("beforeSanitizeAttributes",t,null);var l=t.attributes;if(l){var c={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ke};for(i=l.length;i--;){var u=n=l[i],s=u.name,f=u.namespaceURI;if(o="value"===s?n.value:k(n.value),a=ge(s),c.attrName=a,c.attrValue=o,c.keepAttr=!0,c.forceKeepAttr=void 0,xt("uponSanitizeAttribute",t,c),o=c.attrValue,!c.forceKeepAttr&&(At(s,t),c.keepAttr))if(Ue||!O(/\/>/i,o)){Fe&&(o=_(o,be," "),o=_(o,ve," "),o=_(o,Te," "));var m=ge(t.nodeName);if(Ot(m,a,o)){if(!qe||"id"!==a&&"name"!==a||(At(s,t),o=Ye+o),le&&"object"===e(b)&&"function"==typeof b.getAttributeType)if(f);else switch(b.getAttributeType(m,a)){case"TrustedHTML":o=le.createHTML(o);break;case"TrustedScriptURL":o=le.createScriptURL(o)}try{f?t.setAttributeNS(f,s,o):t.setAttribute(s,o),N(r.removed)}catch(e){}}}else At(s,t)}xt("afterSanitizeAttributes",t,null)}},Ct=function e(t){var n,r=wt(t);for(xt("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)xt("uponSanitizeShadowNode",n,null),kt(n)||(n.content instanceof l&&e(n.content),Rt(n));xt("afterSanitizeShadowDOM",t,null)};return r.sanitize=function(e){var t,n,a,i,c=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if((it=!e)&&(e="\x3c!--\x3e"),"string"!=typeof e&&!_t(e)){if("function"!=typeof e.toString)throw D("toString is not a function");if("string"!=typeof(e=e.toString()))throw D("dirty is not a string, aborting")}if(!r.isSupported)return e;if(He||dt(c),r.removed=[],"string"==typeof e&&(Ke=!1),Ke){if(e.nodeName){var u=ge(e.nodeName);if(!_e[u]||Re[u])throw D("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof s)1===(n=(t=Et("\x3c!----\x3e")).ownerDocument.importNode(e,!0)).nodeType&&"BODY"===n.nodeName||"HTML"===n.nodeName?t=n:t.appendChild(n);else{if(!Pe&&!Fe&&!ze&&-1===e.indexOf("<"))return le&&Ge?le.createHTML(e):e;if(!(t=Et(e)))return Pe?null:Ge?ce:""}t&&je&&Nt(t.firstChild);for(var f=wt(Ke?e:t);a=f.nextNode();)kt(a)||(a.content instanceof l&&Ct(a.content),Rt(a));if(Ke)return e;if(Pe){if(Be)for(i=me.call(t.ownerDocument);t.firstChild;)i.appendChild(t.firstChild);else i=t;return(ke.shadowroot||ke.shadowrootmod)&&(i=de.call(o,i,!0)),i}var m=ze?t.outerHTML:t.innerHTML;return ze&&_e["!doctype"]&&t.ownerDocument&&t.ownerDocument.doctype&&t.ownerDocument.doctype.name&&O(ee,t.ownerDocument.doctype.name)&&(m="\n"+m),Fe&&(m=_(m,be," "),m=_(m,ve," "),m=_(m,Te," ")),le&&Ge?le.createHTML(m):m},r.setConfig=function(e){dt(e),He=!0},r.clearConfig=function(){ft=null,He=!1},r.isValidAttribute=function(e,t,n){ft||dt({});var r=ge(e),o=ge(t);return Ot(r,o,n)},r.addHook=function(e,t){"function"==typeof t&&(he[e]=he[e]||[],A(he[e],t))},r.removeHook=function(e){if(he[e])return N(he[e])},r.removeHooks=function(e){he[e]&&(he[e]=[])},r.removeAllHooks=function(){he={}},r}();return re})); diff --git a/static/assets/weblog/archived/note-taking-2/diagram1.svg b/static/assets/weblog/archived/note-taking-2/diagram1.svg new file mode 100755 index 0000000..81f58d7 --- /dev/null +++ b/static/assets/weblog/archived/note-taking-2/diagram1.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +S +H +A +2 +5 +6 +S +a +l +t +N +o +t +a +d +e +s +e +n +c +r +i +p +t +a +d +a +C +o +n +t +r +a +s +e +ñ +a +A +r +g +o +n +2 +p +w +b +o +x +N +o +t +a +e +n +c +r +i +p +t +a +d +a + + diff --git a/static/assets/weblog/archived/note-taking-experimental/note-creation.png b/static/assets/weblog/archived/note-taking-experimental/note-creation.png new file mode 100755 index 0000000..c318521 Binary files /dev/null and b/static/assets/weblog/archived/note-taking-experimental/note-creation.png differ diff --git a/static/assets/weblog/archived/note-taking-experimental/note-list.png b/static/assets/weblog/archived/note-taking-experimental/note-list.png new file mode 100755 index 0000000..bf37274 Binary files /dev/null and b/static/assets/weblog/archived/note-taking-experimental/note-list.png differ diff --git a/static/assets/weblog/archived/note-taking-experimental/password-prompt.png b/static/assets/weblog/archived/note-taking-experimental/password-prompt.png new file mode 100755 index 0000000..3a40b95 Binary files /dev/null and b/static/assets/weblog/archived/note-taking-experimental/password-prompt.png differ diff --git a/static/assets/weblog/archived/note-taking-experimental/top-buttons.png b/static/assets/weblog/archived/note-taking-experimental/top-buttons.png new file mode 100755 index 0000000..d835724 Binary files /dev/null and b/static/assets/weblog/archived/note-taking-experimental/top-buttons.png differ diff --git a/static/assets/weblog/comments.js b/static/assets/weblog/comments.js new file mode 100644 index 0000000..0fc7e08 --- /dev/null +++ b/static/assets/weblog/comments.js @@ -0,0 +1,43 @@ +(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 = `
No comments yet
` + 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 = + ` +
+ +
+ ${sanitize(comment.content)} +
+
+` + el.innerHTML += comment_html + } +})() \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e353b04..577e2d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -459,6 +459,11 @@ ejs@^3.1.9: dependencies: jake "^10.8.5" +eleventy-plugin-time-to-read@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eleventy-plugin-time-to-read/-/eleventy-plugin-time-to-read-1.3.0.tgz#17701132491b522fa013fcc103a24eafe3b56082" + integrity sha512-EefxYZJviQbClwoQ+pXW0YsVoi3gzXJ3prJoOLO1g3n5dM17KyZh81/yyq5Inrdc2pxBz3CXsyo21kk43gK/Gg== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -856,6 +861,11 @@ luxon@^3.3.0: resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.3.tgz#8ddf0358a9492267ffec6a13675fbaab5551315d" integrity sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg== +luxon@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af" + integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA== + markdown-it-anchor@^8.6.7: version "8.6.7" resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634"