Theme change. First release of the blog with a new theme
@@ -7,6 +7,8 @@ import robotsTxt from "astro-robots-txt";
|
|||||||
import webmanifest from "astro-webmanifest";
|
import webmanifest from "astro-webmanifest";
|
||||||
import { defineConfig, envField } from "astro/config";
|
import { defineConfig, envField } from "astro/config";
|
||||||
import { siteConfig } from "./src/site.config";
|
import { siteConfig } from "./src/site.config";
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
|
|
||||||
// Remark plugins
|
// Remark plugins
|
||||||
import remarkDirective from "remark-directive"; /* handle ::: directives as nodes */
|
import remarkDirective from "remark-directive"; /* handle ::: directives as nodes */
|
||||||
@@ -115,7 +117,7 @@ export default defineConfig({
|
|||||||
// https://docs.astro.build/en/guides/prefetch/
|
// https://docs.astro.build/en/guides/prefetch/
|
||||||
prefetch: true,
|
prefetch: true,
|
||||||
// ! Please remember to replace the following site property with your own domain
|
// ! Please remember to replace the following site property with your own domain
|
||||||
site: "http://astrocitrus.artemkutsan.pp.ua/",
|
site: "http://ignaciops.dev/",
|
||||||
vite: {
|
vite: {
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true, // Source maps generation
|
sourcemap: true, // Source maps generation
|
||||||
|
13
package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"astro-robots-txt": "^1.0.0",
|
"astro-robots-txt": "^1.0.0",
|
||||||
"astro-webmanifest": "^1.0.0",
|
"astro-webmanifest": "^1.0.0",
|
||||||
"cssnano": "^7.0.6",
|
"cssnano": "^7.0.6",
|
||||||
|
"dotenv": "^17.2.1",
|
||||||
"hastscript": "^9.0.0",
|
"hastscript": "^9.0.0",
|
||||||
"mdast-util-directive": "^3.0.0",
|
"mdast-util-directive": "^3.0.0",
|
||||||
"mdast-util-to-markdown": "^2.1.2",
|
"mdast-util-to-markdown": "^2.1.2",
|
||||||
@@ -4198,6 +4199,18 @@
|
|||||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "17.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
|
||||||
|
"integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dset": {
|
"node_modules/dset": {
|
||||||
"version": "3.1.4",
|
"version": "3.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
"astro-robots-txt": "^1.0.0",
|
"astro-robots-txt": "^1.0.0",
|
||||||
"astro-webmanifest": "^1.0.0",
|
"astro-webmanifest": "^1.0.0",
|
||||||
"cssnano": "^7.0.6",
|
"cssnano": "^7.0.6",
|
||||||
|
"dotenv": "^17.2.1",
|
||||||
"hastscript": "^9.0.0",
|
"hastscript": "^9.0.0",
|
||||||
"mdast-util-directive": "^3.0.0",
|
"mdast-util-directive": "^3.0.0",
|
||||||
"mdast-util-to-markdown": "^2.1.2",
|
"mdast-util-to-markdown": "^2.1.2",
|
||||||
|
@@ -1,4 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 85 107">
|
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 100 100"><rect width="100" height="100" rx="0" fill="#121212"></rect><path fill="#cccccc" d="M35 5.20L35 5.20L35 7.20Q31.60 7.30 29.85 7.95Q28.10 8.60 27.50 10.35Q26.90 12.10 26.90 15.80L26.90 15.80L26.90 65.40Q26.90 69 27.50 70.80Q28.10 72.60 29.85 73.20Q31.60 73.80 35 74L35 74L35 76Q32.70 75.80 29.25 75.75Q25.80 75.70 22.30 75.70L22.30 75.70Q18.40 75.70 15 75.75Q11.60 75.80 9.50 76L9.50 76L9.50 74Q12.90 73.80 14.65 73.20Q16.40 72.60 17 70.80Q17.60 69 17.60 65.40L17.60 65.40L17.60 15.80Q17.60 12.10 17 10.35Q16.40 8.60 14.65 7.95Q12.90 7.30 9.50 7.20L9.50 7.20L9.50 5.20Q11.60 5.30 15 5.40Q18.40 5.50 22.30 5.50L22.30 5.50Q25.80 5.50 29.25 5.40Q32.70 5.30 35 5.20ZM59.70 94.80L59.70 94.80Q54.40 94.80 49.70 93.70Q45 92.60 42.15 90.25Q39.30 87.90 39.30 84.30L39.30 84.30Q39.30 80.80 42.10 78.30Q44.90 75.80 49.70 74.50L49.70 74.50L50.30 76.10Q48.10 76.80 46.80 78.90Q45.50 81 45.50 83.60L45.50 83.60Q45.50 88.20 49.75 90.65Q54 93.10 60.80 93.10L60.80 93.10Q65.30 93.10 69.60 91.95Q73.90 90.80 76.70 88.10Q79.50 85.40 79.50 81L79.50 81Q79.50 77.70 77.15 75.55Q74.80 73.40 67.90 73.40L67.90 73.40L60.50 73.40Q57.30 73.40 54.30 72.90Q51.30 72.40 49.40 70.80Q47.50 69.20 47.50 65.90L47.50 65.90Q47.50 62.50 50.30 59.35Q53.10 56.20 60.60 52.90L60.60 52.90L61.80 53.80Q58.40 55.60 55.90 57.45Q53.40 59.30 53.40 61.80L53.40 61.80Q53.40 65 58.20 65L58.20 65L70.70 65Q76.90 65 81.65 67.75Q86.40 70.50 86.40 76.80L86.40 76.80Q86.40 81.50 83.40 85.60Q80.40 89.70 74.45 92.25Q68.50 94.80 59.70 94.80ZM60.20 54.70L60.20 54.70Q52.80 54.70 47.75 50.90Q42.70 47.10 42.70 38.90L42.70 38.90Q42.70 30.60 47.75 26.85Q52.80 23.10 60.20 23.10L60.20 23.10Q67.60 23.10 72.65 26.85Q77.70 30.60 77.70 38.90L77.70 38.90Q77.70 47.10 72.65 50.90Q67.60 54.70 60.20 54.70ZM60.20 52.90L60.20 52.90Q64 52.90 66.15 49.90Q68.30 46.90 68.30 38.90L68.30 38.90Q68.30 30.90 66.15 27.90Q64 24.90 60.20 24.90L60.20 24.90Q56.50 24.90 54.30 27.90Q52.10 30.90 52.10 38.90L52.10 38.90Q52.10 46.90 54.30 49.90Q56.50 52.90 60.20 52.90ZM74.60 31.40L74.60 31.40L72.80 30.70Q74.20 27.30 77.60 24.70Q81 22.10 84.70 22.10L84.70 22.10Q87.30 22.10 88.90 23.55Q90.50 25 90.50 27.90L90.50 27.90Q90.50 31 88.85 32.25Q87.20 33.50 85.50 33.50L85.50 33.50Q84 33.50 82.70 32.45Q81.40 31.40 81.20 29.10Q81 26.80 82.60 23.20L82.60 23.20L83.90 23.50Q79.70 25.10 77.90 26.85Q76.10 28.60 74.60 31.40Z"></path></svg>
|
||||||
<path fill="#cb2a42" d="M27.5894 91.1365C22.7555 86.7178 21.3444 77.4335 23.3583 70.7072C26.8503 74.948 31.6888 76.2914 36.7005 77.0497C44.4375 78.2199 52.0359 77.7822 59.2232 74.2459C60.0454 73.841 60.8052 73.3027 61.7036 72.7574C62.378 74.714 62.5535 76.6892 62.318 78.6996C61.7452 83.5957 59.3086 87.3778 55.4332 90.2448C53.8835 91.3916 52.2437 92.4167 50.6432 93.4979C45.7262 96.8213 44.3959 100.718 46.2435 106.386C46.2874 106.525 46.3267 106.663 46.426 107C43.9155 105.876 42.0817 104.24 40.6845 102.089C39.2087 99.8193 38.5066 97.3081 38.4696 94.5909C38.4511 93.2686 38.4511 91.9345 38.2733 90.6309C37.8391 87.4527 36.3471 86.0297 33.5364 85.9478C30.6518 85.8636 28.37 87.6469 27.7649 90.4554C27.7187 90.6707 27.6517 90.8837 27.5847 91.1341L27.5894 91.1365Z"/>
|
|
||||||
<path fill="#224d67" d="M0 69.5866C0 69.5866 14.3139 62.6137 28.6678 62.6137L39.4901 29.1204C39.8953 27.5007 41.0783 26.3999 42.4139 26.3999C43.7495 26.3999 44.9325 27.5007 45.3377 29.1204L56.1601 62.6137C73.1601 62.6137 84.8278 69.5866 84.8278 69.5866C84.8278 69.5866 60.5145 3.35233 60.467 3.21944C59.7692 1.2612 58.5911 0 57.0029 0H27.8274C26.2392 0 25.1087 1.2612 24.3634 3.21944C24.3108 3.34983 0 69.5866 0 69.5866Z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -1,14 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
|
||||||
<!--
|
|
||||||
<rect width="128" height="128" fill="#f7f7f8" />
|
|
||||||
-->
|
|
||||||
<path fill="#224d67" d="M22.5 14.8c2.9 1.3 99 44 99 44c2.7 1.2 2.9 3.1 2 12.4c-1 10.5-1.9 37.8-40.2 42.9c-24.6 3.2-55.9-4.3-70.9-27.2C-6 58.8 11 23.4 14.8 17.7c2.4-3.5 4.8-4.2 7.7-2.9" />
|
|
||||||
<path fill="#f0f4c3" d="M121.5 58.8c-.3-.2-92-40.8-98.9-43.9C9.6 31.5-3.8 76 27.9 96.2c33.6 21.5 78.7-10.2 93.6-37.4" />
|
|
||||||
<path fill="#f0f4c3" d="M117.7 57c-.3-.2-86.7-38.4-93.2-41.3c-12.2 15.5-23.9 59.1 5.7 78c31.4 20.2 73.6-11.2 87.5-36.7" />
|
|
||||||
<path fill="#cb2a42" d="M56.2 37.6L19.5 48.2c-2.5.8-4.4 2.8-5 5.3c-1.9 8.5.8 23.3 8.9 29.8c3.5 2.7 8.6 1.8 10.8-2.1L58.5 41c1.3-1.7.5-4.2-2.3-3.4m14.3 2.9s14.6 30.1 16 33s6.3 4.7 9.9 2.8c10.7-5.6 15.5-12.4 19.2-20.2c-8.9-3.9-42.4-18.8-42.4-18.8c-2.4-1.1-4 .6-2.7 3.2m-8.6 1.9C60.3 45.1 39.5 81 37.6 84.1c-1.9 3.2-.7 7.5 2.7 9.2c12.3 6.5 30.9.4 39.6-7c2.2-1.9 4.5-5.1 3.2-8.2S68.9 44.6 67.8 42.3c-1.2-2.7-4.1-2.8-5.9.1" />
|
|
||||||
<path fill="#f0f4c3" d="M52.2 42.2c-1.4.4-10.1 3-11.1 3.4c-1.4.5-2.2 1.7-1.9 2.5c.3.9 1.7 1.1 3.1.6c.8-.3 7.1-3.9 9.5-5.2c-3.1 2.4-10.2 9.4-11.1 10.3c-1.4 1.5-1.7 3.4-.8 4.3c1 .9 2.9.5 4.3-1c1.2-1.3 8.5-12.8 9.1-13.9s.4-1.4-1.1-1m10.1 16.4c0-2.2 1.4-10.3 1.8-12.3c.4-1.6 1.5-1.8 1.8.5s1.7 9.7 1.7 11.8s-1.2 3.3-2.7 3.3c-1.4 0-2.6-1.1-2.6-3.3M79.9 49c-1.2-1.8-3.3-4.9-4.1-6.1c-.7-1.2.1-2.1 1.8-.9s4 2.9 5.4 4c1.6 1.3 1.9 3 .8 4s-2.7.8-3.9-1" />
|
|
||||||
<ellipse cx="87.3" cy="103.12" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-27.098 87.298 103.126)" />
|
|
||||||
<ellipse cx="98.89" cy="103.82" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-30.642 98.887 103.818)" />
|
|
||||||
<ellipse cx="102.02" cy="93.8" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-37.16 102.017 93.797)" />
|
|
||||||
<path fill="#cb2a42" d="M57.6 30.3c-8.3-3.7-24.4-10.7-29.6-13c-3.6 2.2-9.7 11.4-11.2 21.2c-.6 3.6 1.7 5.9 5.3 4.9c0 0 33.7-9.3 35.3-9.7c1.6-.5 2-2.6.2-3.4" />
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -14,14 +14,25 @@ const socialLinks: {
|
|||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
friendlyName: "Github",
|
friendlyName: "Github",
|
||||||
link: "https://github.com/artemkutsan/astro-citrus",
|
link: "https://github.com/ignaciops",
|
||||||
name: "mdi:github",
|
name: "mdi:github",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
friendlyName: "LinkedIn",
|
||||||
|
link: "https://linkedin.com/in/ignaciops",
|
||||||
|
name: "mdi:linkedin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
friendlyName: "X",
|
||||||
|
link: "https://x.com/ignaciopsdev",
|
||||||
|
name: "mdi:twitter",
|
||||||
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex flex-wrap items-end gap-x-2">
|
<div class="flex flex-wrap items-end gap-x-2">
|
||||||
<p>Find me on</p>
|
<p>Encuéntrame en</p>
|
||||||
<ul class="flex flex-1 items-center gap-x-2 sm:flex-initial">
|
<ul class="flex flex-1 items-center gap-x-2 sm:flex-initial">
|
||||||
{
|
{
|
||||||
socialLinks.map(({ friendlyName, isWebmention, link, name }) => (
|
socialLinks.map(({ friendlyName, isWebmention, link, name }) => (
|
||||||
|
@@ -9,7 +9,7 @@ const year = new Date().getFullYear();
|
|||||||
>
|
>
|
||||||
<div class="me-0 font-semibold sm:me-4">
|
<div class="me-0 font-semibold sm:me-4">
|
||||||
© {siteConfig.author}
|
© {siteConfig.author}
|
||||||
{year}.<span class="inline-block"> 🚀 Astro Citrus</span>
|
2024 - {year}.<span class="inline-block">Tema: Astro Citrus</span>
|
||||||
</div>
|
</div>
|
||||||
<nav
|
<nav
|
||||||
aria-label="More on this site"
|
aria-label="More on this site"
|
||||||
|
@@ -40,11 +40,6 @@ import { Icon } from "astro-icon/components";
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
<div title={siteConfig.title}>
|
|
||||||
<svg class="inline-block size-8 fill-current text-accent-base dark:text-accent-two drop-shadow-[0px_2.5px_2.5px_rgba(0,0,0,0.35)]">
|
|
||||||
<use href="/brand.svg#citrus"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<strong class="'max-[320px]:hidden' bg-clip-text text-transparent bg-gradient-to-r from-accent-one to-accent-two hidden xs:block z-10 mb-0.5 ms-2 text-2xl group-hover:text-accent-one">
|
<strong class="'max-[320px]:hidden' bg-clip-text text-transparent bg-gradient-to-r from-accent-one to-accent-two hidden xs:block z-10 mb-0.5 ms-2 text-2xl group-hover:text-accent-one">
|
||||||
{siteConfig.title}
|
{siteConfig.title}
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
title: What is the F-Method in Resume Writing?
|
|
||||||
publishDate: "2025-02-27T22:09:00Z"
|
|
||||||
---
|
|
||||||
|
|
||||||
When recruiters review resumes, they spend only a few seconds on the first glance. Research shows that their eyes move across the page in the shape of the letter **F**: first, they read the top line, then scan down while focusing on the left side. This is the principle behind the **F-Method** – a resume formatting technique that helps highlight the most important details.
|
|
||||||
|
|
||||||
**How to Use the F-Method?**
|
|
||||||
1️. **First horizontal section:** Start with a clear heading – include your name, contact details, and the job title you’re applying for.
|
|
||||||
2️. **Second horizontal section:** Place key information at the top – a brief summary of your skills, achievements, and strengths.
|
|
||||||
3️. **Vertical section on the left:** Since this area gets the most attention, list your most important details here – work experience, education, and key skills.
|
|
||||||
|
|
||||||
This method makes resumes easier to read, highlights essential points, and increases your chances of getting noticed. Use the F-Method, and your resume won’t go unnoticed! 🚀
|
|
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
title: Wake up...
|
|
||||||
publishDate: "2199-02-01T18:26:00Z"
|
|
||||||
updateDate: "1998-02-19T14:32:00Z"
|
|
||||||
---
|
|
||||||
|
|
||||||
>What is real? How do you define real? If you’re talking about what you can feel, what you can smell, what you can taste and see, then real is simply electrical signals interpreted by your brain.<br> This is the world that you know. The world as it was at the end of the twentieth century. It exists now only as part of a neural-interactive simulation that we call the Matrix. You’ve been living in a dream world.<br> This is the world as it exists today... Welcome... to the desert... of the real.<br> We have only bits and pieces of information but what we know for certain is that at some point in the early twenty-first century all of mankind was united in celebration. We marveled at our own magnificence as we gave birth to AI.
|
|
||||||
|
|
||||||
>AI? You mean artificial intelligence?
|
|
||||||
|
|
||||||
>A singular consciousness that spawned an entire race of machines. We don’t know who struck first, us or them. But we know that it was us that scorched the sky. At the time they were dependent on solar power and it was believed that they would be unable to survive without an energy source as abundant as the sun. Throughout human history, we have been dependent on machines to survive. Fate, it seems, is not without a sense of irony. The human body generates more bio-electricity than a 120-volt battery and over 25,000 BTUs of body heat. Combined with a form of fusion, the machines have found all the energy they would ever need. There are fields, endless fields, where human beings are no longer born. We are grown. For the longest time I wouldn’t believe it, and then I saw the fields with my own eyes. Watch them liquefy the dead so they could be fed intravenously to the living. And standing there, facing the pure horrifying precision, I came to realize the obviousness of the truth.<br> What is the Matrix?<br> Control.<br> The Matrix is a computer generated dream world built to keep us under control in order to change a human being into battery.
|
|
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
title: Hello, Welcome
|
|
||||||
description: An introduction to using the note feature in Astro Citrus
|
|
||||||
publishDate: "2024-10-14T11:23:00Z"
|
|
||||||
---
|
|
||||||
|
|
||||||
Hi, Hello. This is an example note feature included with Astro Citrus.
|
|
||||||
|
|
||||||
They're for shorter, concise "post's" that you'd like to share, they generally don't include headings, but hey, that's entirely up to you.
|
|
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Introducing Astro Citrus!"
|
|
||||||
publishDate: "20 December 2024"
|
|
||||||
description: "Astro Citrus is a versatile template for managing blogs and creating comprehensive project documentation"
|
|
||||||
seriesId: citrus-docs
|
|
||||||
orderInSeries: 1
|
|
||||||
featured: false
|
|
||||||
tags: ["example", "series", "citrus"]
|
|
||||||
ogImage: ""
|
|
||||||
---
|
|
||||||
|
|
||||||
## Introducing
|
|
||||||
|
|
||||||
Hi, I’m a theme for Astro, a simple starter that you can use to create your website or blog. If you want to know more about how you can customise me, add more posts, and make it your own, click on the GitHub icon link below and it will take you to my repo.
|
|
||||||
|
|
||||||
## About Citrus
|
|
||||||
|
|
||||||
Citrus is a powerful and stylish template designed for both blogging and creating comprehensive documentation with Astro. The template combines the simplicity of a blog layout with the robust features needed for project documentation. It offers:
|
|
||||||
|
|
||||||
- **Clean and minimalist design**, suitable for blogs and technical documentation alike.
|
|
||||||
- **User-friendly navigation**, with menus and sections tailored for easy access to content.
|
|
||||||
- **High performance** with Astro’s static site generation for fast loading speeds.
|
|
||||||
- **Markdown support**, streamlining the writing and editing process.
|
|
||||||
- **Flexible customization**, including colors, fonts, layout structure, and more.
|
|
||||||
|
|
||||||
## Benefits of Using Astro Citrus
|
|
||||||
|
|
||||||
1. **Dual-purpose template**: Seamlessly switch between blogging and project documentation.
|
|
||||||
2. **Responsive design**: Optimized for desktops, tablets, and mobile devices.
|
|
||||||
3. **Fast and SEO-friendly**: Astro ensures quick loading times and better search engine rankings.
|
|
||||||
4. **Expandable features**: Add analytics, search, or other integrations effortlessly.
|
|
||||||
5. **Easy to deploy**: Works flawlessly on platforms like Netlify or Vercel.
|
|
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Setup Citrus"
|
|
||||||
publishDate: "21 December 2024"
|
|
||||||
description: "An example second post for Citrus Docs series"
|
|
||||||
seriesId: citrus-docs
|
|
||||||
orderInSeries: 2
|
|
||||||
updatedDate: "22 December 2024"
|
|
||||||
featured: false
|
|
||||||
tags: ["example", "series", "citrus"]
|
|
||||||
ogImage: ""
|
|
||||||
---
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
1. Install Astro and download the Astro Citrus template.
|
|
||||||
2. Configure the `astro.config.mjs` file to set up your blog or documentation site.
|
|
||||||
3. Add content using Markdown for a seamless writing experience.
|
|
||||||
|
|
||||||
For more detailed information, check the official [Astro Citrus documentation](#).
|
|
@@ -1,144 +0,0 @@
|
|||||||
---
|
|
||||||
title: Flexible Theming System
|
|
||||||
description: A flexible theming system based on HSL (Hue, Saturation, Lightness) using CSS variables, allowing for dynamic color adjustments and seamless theme management
|
|
||||||
publishDate: 03 Feb 2025
|
|
||||||
seriesId: citrus-docs
|
|
||||||
orderInSeries: 3
|
|
||||||
tags: ["theming", "CSS", "citrus"]
|
|
||||||
---
|
|
||||||
|
|
||||||
This approach to defining colors can be described as a **flexible theming system based on HSL (Hue, Saturation, Lightness) with the use of CSS variables**.
|
|
||||||
|
|
||||||
## Principles of colorization
|
|
||||||
1. **Flexibility through HSL**
|
|
||||||
- Instead of fixed colors, the hue (`--hue`), saturation (`--saturation`), and brightness (`--bg-brightness`, `--fg-brightness`) are used. This allows for easy changes to the entire theme's color palette by adjusting just one parameter.
|
|
||||||
|
|
||||||
2. **Unified Logic for Light and Dark Themes**
|
|
||||||
- Different brightness and saturation parameters are defined in `:root[data-theme="light"]` and `:root[data-theme="dark"]`, but the logic remains consistent.
|
|
||||||
- For example, in the light theme, the background is lighter (`--bg-brightness: 95%`), and in the dark theme, it is darker (`--bg-brightness: 17%`).
|
|
||||||
|
|
||||||
3. **Creating Color Gradients**
|
|
||||||
- A gradient scale (`--theme-color-950` → `--theme-color-50`) is used to generate shades of a single color.
|
|
||||||
- This allows for dynamically generated variations of colors for backgrounds, text, and accents without manual input.
|
|
||||||
|
|
||||||
4. **Defining Key UI Elements**
|
|
||||||
- `--theme-bg` — background color
|
|
||||||
- `--theme-accent-two`, `--theme-accent-base` — accent colors
|
|
||||||
- `--theme-text` — main text color
|
|
||||||
- `--theme-link` — link color
|
|
||||||
- `--theme-quote` — quote color
|
|
||||||
|
|
||||||
```css title="globas.css"
|
|
||||||
@layer base {
|
|
||||||
:root,
|
|
||||||
:root[data-theme="light"] {
|
|
||||||
color-scheme: light;
|
|
||||||
|
|
||||||
/*** MAIN COLORS (Base, Background, Accents, Text) ***/
|
|
||||||
/* Base theme hue color */
|
|
||||||
--hue: 200deg; /* Base hue color (Background, secondary accent, text) */
|
|
||||||
--saturation: 10%; /* Saturation of background and text, 0% - no tint */
|
|
||||||
|
|
||||||
/* Background */
|
|
||||||
--bg-brightness: 95%; /* Background brightness, 100% - pure white */
|
|
||||||
--theme-bg: var(--hue) var(--saturation) var(--bg-brightness); /* Background color */
|
|
||||||
|
|
||||||
/* Accents */
|
|
||||||
--theme-accent-two: 351deg 66% 48%; /* Primary accent color */
|
|
||||||
--theme-accent-base: var(--hue) 50% 27%; /* Secondary accent color */
|
|
||||||
|
|
||||||
/* Text (foreground calculated below based on --theme-fg) */
|
|
||||||
--fg-brightness: 9%; /* Text brightness, 0% - pure black */
|
|
||||||
--theme-fg: var(--hue) var(--saturation) var(--fg-brightness); /* Base color for text */
|
|
||||||
--theme-text: var(--theme-color-550); /* Text color */
|
|
||||||
|
|
||||||
/*** SECONDARY COLORS (External links, neutral accent, quotes) ***/
|
|
||||||
--theme-link: var(--hue) 97% 31%; /* External link color */
|
|
||||||
--theme-accent: var(--theme-color-650); /* Neutral accent, calculated below based on --theme-fg */
|
|
||||||
--theme-quote: var(--theme-text); /* Quote color */
|
|
||||||
|
|
||||||
/*** ADDITIONAL COLORS ***/
|
|
||||||
--theme-lightest: var(--theme-color-350);
|
|
||||||
--theme-lighter: var(--theme-color-400);
|
|
||||||
--theme-light: var(--theme-color-450);
|
|
||||||
|
|
||||||
/*** SPECIAL THEME COLORS (Distinct settings for each theme) ***/
|
|
||||||
--theme-special-lightest: hsl(var(--hue), var(--saturation), 100%);
|
|
||||||
--theme-special-lighter: hsl(var(--hue), var(--saturation), 98%);
|
|
||||||
--theme-special-light: hsl(var(--theme-bg));
|
|
||||||
--theme-special: var(--theme-color-75);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root[data-theme="dark"] {
|
|
||||||
color-scheme: dark;
|
|
||||||
|
|
||||||
/*** MAIN COLORS (Base, Background, Accents, Text) ***/
|
|
||||||
/* Base theme hue color */
|
|
||||||
--hue: 200deg; /* Base hue color (Background, secondary accent, text) */
|
|
||||||
--saturation: 53%;
|
|
||||||
|
|
||||||
/* Background */
|
|
||||||
--bg-brightness: 17%; /* Background brightness, 0% - black */
|
|
||||||
--theme-bg: var(--hue) var(--saturation) var(--bg-brightness); /* Background color */
|
|
||||||
|
|
||||||
/* Accents */
|
|
||||||
--theme-accent-two: 50deg 72% 63%; /* Primary accent color for elements (was 45deg 80% 50%) */
|
|
||||||
--theme-accent-base: var(--hue) 0% 85%; /* Secondary accent color for elements */
|
|
||||||
|
|
||||||
/* Text (foreground calculated below based on --theme-fg) */
|
|
||||||
--fg-brightness: 98%; /* Text brightness, 100% - pure white */
|
|
||||||
--theme-text: var(--theme-color-600); /* Text color */
|
|
||||||
|
|
||||||
/*** SECONDARY COLORS (External links, neutral accent, quotes) ***/
|
|
||||||
--theme-link: var(--hue) 66% 66%; /* External link color */
|
|
||||||
--theme-accent: var(--theme-color-700); /* Neutral accent */
|
|
||||||
--theme-quote: var(--theme-text); /* Quote color */
|
|
||||||
|
|
||||||
/*** ADDITIONAL COLORS ***/
|
|
||||||
--theme-lightest: var(--theme-color-400);
|
|
||||||
--theme-lighter: var(--theme-color-450);
|
|
||||||
--theme-light: var(--theme-color-500);
|
|
||||||
|
|
||||||
/*** SPECIAL THEME COLORS (Distinct settings for each theme) ***/
|
|
||||||
--theme-special-lightest: var(--theme-color-250);
|
|
||||||
--theme-special-lighter: var(--theme-color-200);
|
|
||||||
--theme-special-light: var(--theme-color-150);
|
|
||||||
--theme-special: hsl(var(--hue) 0% 0% / 0.1275);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Global variables */
|
|
||||||
:root {
|
|
||||||
/* Base color for color gradation calculation */
|
|
||||||
--theme-fg: var(--hue) var(--saturation) var(--fg-brightness);
|
|
||||||
|
|
||||||
/* Gradations of the base color for text and elements */
|
|
||||||
--theme-color-950: hsl(var(--theme-fg) / 0.9495);
|
|
||||||
--theme-color-900: hsl(var(--theme-fg) / 0.9095);
|
|
||||||
--theme-color-850: hsl(var(--theme-fg) / 0.8795);
|
|
||||||
--theme-color-800: hsl(var(--theme-fg) / 0.8495);
|
|
||||||
--theme-color-750: hsl(var(--theme-fg) / 0.7995);
|
|
||||||
--theme-color-700: hsl(var(--theme-fg) / 0.7495);
|
|
||||||
--theme-color-650: hsl(var(--theme-fg) / 0.7145);
|
|
||||||
--theme-color-600: hsl(var(--theme-fg) / 0.6795);
|
|
||||||
--theme-color-550: hsl(var(--theme-fg) / 0.6145);
|
|
||||||
--theme-color-500: hsl(var(--theme-fg) / 0.5495);
|
|
||||||
--theme-color-450: hsl(var(--theme-fg) / 0.4545);
|
|
||||||
--theme-color-400: hsl(var(--theme-fg) / 0.3595);
|
|
||||||
--theme-color-350: hsl(var(--theme-fg) / 0.2635);
|
|
||||||
--theme-color-300: hsl(var(--theme-fg) / 0.1675);
|
|
||||||
--theme-color-250: hsl(var(--theme-fg) / 0.1355);
|
|
||||||
--theme-color-200: hsl(var(--theme-fg) / 0.1025);
|
|
||||||
--theme-color-150: hsl(var(--theme-fg) / 0.0710);
|
|
||||||
--theme-color-100: hsl(var(--theme-fg) / 0.0395);
|
|
||||||
--theme-color-75: hsl(var(--theme-fg) / 0.0295);
|
|
||||||
--theme-color-50: hsl(var(--theme-fg) / 0.0195);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## What Does This Provide?
|
|
||||||
- **Easy Scalability**: A new theme can be created by adjusting `--hue`, `--saturation`, and base brightness.
|
|
||||||
- **Automatic Shade Generation**: The gradient system allows for dynamic color generation.
|
|
||||||
- **Flexibility**: The theme can be adapted for different contrast levels, custom schemes, and modes (e.g., `sepia`, `high contrast`).
|
|
||||||
|
|
||||||
This approach is perfect for **dynamic theming**, where the ability to easily adjust the appearance without manually inputting colors is crucial.
|
|
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 591 KiB |
Before Width: | Height: | Size: 68 KiB |
@@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Example Cover Image"
|
|
||||||
description: "This post is an example of how to add a cover/hero image"
|
|
||||||
publishDate: "04 July 2023"
|
|
||||||
updatedDate: "21 January 2025"
|
|
||||||
coverImage:
|
|
||||||
src: "./cover.jpg"
|
|
||||||
alt: "Astro build wallpaper"
|
|
||||||
tags: ["test", "image"]
|
|
||||||
---
|
|
@@ -1,104 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Deepseek Code Assistant: My Features and Examples"
|
|
||||||
description: "This post introduces my capabilities as a Code Assistant with practical code samples"
|
|
||||||
publishDate: "10 Jan 2024"
|
|
||||||
updatedDate: "22 Dec 2024"
|
|
||||||
tags: ["deepseek", "ai"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## Hello, World! 👋 I’m the Code Assistant, and here’s a bit about me
|
|
||||||
|
|
||||||
I’m here to help you with programming, debug code, explain complex concepts, or just share examples. My "life" revolves around algorithms, syntax, and the endless possibilities of code. Let’s get to know each other!
|
|
||||||
|
|
||||||
### What I Can Do
|
|
||||||
- Generate code examples in different languages.
|
|
||||||
- Explain how specific lines of code work.
|
|
||||||
- Find bugs and suggest fixes.
|
|
||||||
- Share optimization tips.
|
|
||||||
|
|
||||||
### Code examples
|
|
||||||
|
|
||||||
**Python: Factorial Function**
|
|
||||||
```python title="factorial-function.py"
|
|
||||||
def factorial(n):
|
|
||||||
if n == 0:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return n * factorial(n-1)
|
|
||||||
|
|
||||||
print(factorial(5)) # 120
|
|
||||||
```
|
|
||||||
*I often help with recursion—classic stuff!*
|
|
||||||
|
|
||||||
**JavaScript: Countdown Timer**
|
|
||||||
```js title="countdown-timer.js"
|
|
||||||
function startTimer(seconds) {
|
|
||||||
let remaining = seconds;
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
console.log(`Time left: ${remaining} sec.`);
|
|
||||||
remaining--;
|
|
||||||
if (remaining < 0) {
|
|
||||||
clearInterval(interval);
|
|
||||||
console.log("Time's up! ⏰");
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
startTimer(5); // Starts a 5-second timer
|
|
||||||
```
|
|
||||||
*Async logic? My jam.*
|
|
||||||
|
|
||||||
**SQL: Finding Active Users**
|
|
||||||
```sql
|
|
||||||
SELECT users.name, COUNT(orders.id) AS total_orders
|
|
||||||
FROM users
|
|
||||||
LEFT JOIN orders ON users.id = orders.user_id
|
|
||||||
GROUP BY users.name
|
|
||||||
HAVING total_orders > 3;
|
|
||||||
```
|
|
||||||
*I love structured data and elegant JOINs!*
|
|
||||||
|
|
||||||
#### Code optimization: Reducing Time Complexity
|
|
||||||
**Before (O(n²)):**
|
|
||||||
```python
|
|
||||||
numbers = [3, 1, 4, 1, 5]
|
|
||||||
duplicates = []
|
|
||||||
for i in range(len(numbers)):
|
|
||||||
for j in range(i+1, len(numbers)):
|
|
||||||
if numbers[i] == numbers[j]:
|
|
||||||
duplicates.append(numbers[i])
|
|
||||||
```
|
|
||||||
|
|
||||||
**After (O(n)):**
|
|
||||||
```python
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
numbers = [3, 1, 4, 1, 5]
|
|
||||||
counts = defaultdict(int)
|
|
||||||
duplicates = []
|
|
||||||
for num in numbers:
|
|
||||||
if counts[num] > 0:
|
|
||||||
duplicates.append(num)
|
|
||||||
counts[num] += 1
|
|
||||||
```
|
|
||||||
*Optimizing code is pure magic!*
|
|
||||||
|
|
||||||
### How I Can Help You
|
|
||||||
- **Explain confusing code** from your project.
|
|
||||||
- **Fix memory leaks** in your C++ app.
|
|
||||||
- **Choose the right algorithm** for sorting tasks.
|
|
||||||
- **Write tests** using pytest or Jest.
|
|
||||||
- **Debug "undefined is not a function"** in JS.
|
|
||||||
|
|
||||||
### Favorite Topics
|
|
||||||
- Machine Learning (PyTorch examples? Sure!).
|
|
||||||
- Web Development (Django, React, Flask).
|
|
||||||
- Algorithms & Data Structures (graphs, trees, hash tables).
|
|
||||||
- Automation with Python (scraping, bots).
|
|
||||||
|
|
||||||
### Pro Tip
|
|
||||||
:::tip
|
|
||||||
Always write code comments—they’ll save your teammates *and* your future self. And yes, `console.log` is a temporary fix; tests are better!
|
|
||||||
:::
|
|
||||||
|
|
||||||
**Ready to tackle your code! Just ask. 😊**
|
|
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
title: "A working draft title"
|
|
||||||
description: "This post is for testing the draft post functionality"
|
|
||||||
publishDate: "10 March 2024"
|
|
||||||
tags: ["test"]
|
|
||||||
draft: true
|
|
||||||
---
|
|
||||||
|
|
||||||
If this is working correctly, this post should only be accessible in a dev environment, as well as any tags that are unique to this post.
|
|
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Example of 60 chars Master Header and other Various Headings"
|
|
||||||
publishDate: "28 December 2024"
|
|
||||||
description: "Demonstrating the different heading levels in Markdown by showcasing various sizes and styles of headings, including short and long examples, while also illustrating rendering and the functionality of a table of contents"
|
|
||||||
featured: false
|
|
||||||
tags: ["markdown", "headings", "example", "toc"]
|
|
||||||
ogImage: ""
|
|
||||||
---
|
|
||||||
|
|
||||||
# Heading Level 1: Exploring the Structure of Long and Short Titles in Markdown
|
|
||||||
|
|
||||||
This section provides an example of a Level 1 heading with accompanying introductory text. Use this for setting the context or presenting an overview of the content.
|
|
||||||
|
|
||||||
## Heading Level 2: A Detailed Look at Subsections in Markdown Syntax
|
|
||||||
|
|
||||||
This is an example of a Level 2 heading, typically used to define major divisions within the content. Here, you can delve deeper into specific topics.
|
|
||||||
|
|
||||||
## Heading Level 2: Another Long Title to Illustrate Consistency in Formatting
|
|
||||||
|
|
||||||
Sometimes, headings can be lengthy to capture complex ideas. Markdown handles these effectively without truncating.
|
|
||||||
|
|
||||||
### Heading Level 3: Exploring the Role of Subheadings within Sections
|
|
||||||
|
|
||||||
Text for a Level 3 heading, used to introduce finer subdivisions under a Level 2 heading. Subheadings help maintain clarity in content.
|
|
||||||
|
|
||||||
### Heading Level 3: Short and Concise Subheadings for Simpler Concepts
|
|
||||||
|
|
||||||
This subheading demonstrates how shorter titles can be just as impactful when used appropriately.
|
|
||||||
|
|
||||||
#### Heading Level 4: Adding Layers of Detail to Existing Sections
|
|
||||||
|
|
||||||
Text for a Level 4 heading. This level is often employed to elaborate on specific points or add context to higher-level sections.
|
|
||||||
|
|
||||||
#### Heading Level 4: An Example of a Longer Heading for Complex Subsections
|
|
||||||
|
|
||||||
Even at Level 4, headings can vary in length based on the content they represent.
|
|
||||||
|
|
||||||
##### Heading Level 5: Fine-Tuned Subdivisions for Detailed Explanations
|
|
||||||
|
|
||||||
Example text under a Level 5 heading. This is where you might add nuanced details or examples within a subsection.
|
|
||||||
|
|
||||||
##### Heading Level 5: When Additional Layers Are Necessary for Clarity
|
|
||||||
|
|
||||||
This heading illustrates how deeper nesting can aid in organizing intricate information.
|
|
||||||
|
|
||||||
###### Heading Level 6: Rarely Used but Available for Granular Subdivisions
|
|
||||||
|
|
||||||
Text for a Level 6 heading. These are seldom used but can be helpful in highly detailed documentation.
|
|
||||||
|
|
||||||
###### Heading Level 6: Another Example of a Concise Heading at the Deepest Level
|
|
||||||
|
|
||||||
Text accompanying a short Level 6 heading, emphasizing brevity and precision.
|
|
||||||
|
|
||||||
###### Heading Level 6: Demonstrating Markdown's Flexibility for Complex Structures
|
|
||||||
|
|
||||||
Even at the deepest heading level, Markdown ensures readability and proper structure.
|
|
||||||
|
|
||||||
###### Heading Level 6: Managing Content Hierarchies with Clear Formatting
|
|
||||||
|
|
||||||
Content under this heading highlights the importance of maintaining logical hierarchies in documentation.
|
|
35
src/content/post/introduccion/index.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: "Bienvenidos a mi blog"
|
||||||
|
description: "Una introducción al sitio web de Ignacio PS, así como un poco de historia de los inicios de su interés en la tecnología"
|
||||||
|
publishDate: "20 September 2024"
|
||||||
|
updatedDate: "2 August 2025"
|
||||||
|
#seriesID: ""
|
||||||
|
#orderInSeries: 1
|
||||||
|
tags: ["introduccion", "QA", "calidad"]
|
||||||
|
#coverImage:
|
||||||
|
# src: ""
|
||||||
|
# alt: ""
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
# ¡Hola y bienvenido a mi blog!
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
Soy Ignacio, y me alegra mucho tenerte por aquí mientras inicio este emocionante proyecto personal para compartir ideas, proyectos y experiencias relacionadas con la Automatización de Pruebas (QA) de Software.
|
||||||
|
|
||||||
|
Desde muy joven me sentí fascinado por el mundo del desarrollo web. Me encantaba experimentar con mi vieja PC 486, probando diferentes versiones de Ubuntu cuando Canonical todavía enviaba CDs gratuitos. Aquellas primeras experiencias despertaron en mí una pasión por la tecnología que se ha mantenido hasta hoy y marcaron el inicio de mi camino profesional.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Inicios en testing
|
||||||
|
Mi entrada al mundo del testing comenzó como contratista independiente. Me encargaba de asegurarme de que los Asistentes Virtuales respondieran de forma precisa, desempeñando un papel clave en el entrenamiento de asistentes de voz para que comprendieran y ejecutaran comandos localizados. Ese rol me abrió los ojos a la importancia crítica que tiene la garantía de calidad en la tecnología.
|
||||||
|
|
||||||
|
Hace dos años, asumí oficialmente el rol de Ingeniero de QA gracias a que un amigo me invitó a trabajar en la empresa en la cual él estaba trabajando como QA. Desde entonces, me he dedicado y esforzado por ofrecer soluciones de software de alta calidad utilizando metodologías ágiles. Me especializo en crear scripts de automatización robustos para distintas pruebas, asegurando que nuestros clientes reciban sus aplicaciones con los más altos estándares de calidad.
|
||||||
|
|
||||||
|
## Mis objetivos de este proyecto
|
||||||
|
Este blog será un espacio donde profundizaré en el mundo de la Automatización de QA. Aquí compartiré mis reflexiones sobre los avances más recientes en el área, consejos y trucos para otros profesionales de QA, y algunos de los proyectos interesantes en los que estoy trabajando. Ya seas un ingeniero con experiencia o estés dando tus primeros pasos, espero que encuentres aquí ideas útiles e inspiración.
|
||||||
|
|
||||||
|
Más allá del trabajo, a veces me doy el gusto de jugar con mi impresora 3D, preparar la taza de café perfecta y perderme en novelas históricas y relatos de ciencia ficción. También disfruto jugar pickleball y pádel, y valoro mucho el tiempo que paso en la playa, que me ayuda a mantenerme equilibrado y con energía.
|
||||||
|
|
||||||
|
Gracias por acompañarme en este proyecto.
|
BIN
src/content/post/introduccion/ubuntu8-cd.webp
Normal file
After Width: | Height: | Size: 139 KiB |
@@ -1,42 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Local .gitignore"
|
|
||||||
description: "How to create an additional .gitignore file"
|
|
||||||
publishDate: "05 Mar 2025"
|
|
||||||
tags: ["git", "gitignore"]
|
|
||||||
draft: true
|
|
||||||
---
|
|
||||||
|
|
||||||
## How to create `.local.gitignore` that is not synchronized with Git?
|
|
||||||
|
|
||||||
1. **Create the `.local.gitignore` file**
|
|
||||||
```bash
|
|
||||||
touch .local.gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Add it to `.git/info/exclude`** (so Git applies it locally)
|
|
||||||
```bash
|
|
||||||
echo ".local.gitignore" >> .git/info/exclude
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Configure Git to treat `.local.gitignore` as `.gitignore`**
|
|
||||||
```bash
|
|
||||||
git config --local core.excludesfile .local.gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
Now **`.local.gitignore` will work like a regular `.gitignore`, but only for you**.
|
|
||||||
|
|
||||||
## How does it work?
|
|
||||||
- `.local.gitignore` is not added to the repository.
|
|
||||||
- It is applied **only locally** on your computer.
|
|
||||||
- It works **like `.gitignore`**, but other developers don't have it.
|
|
||||||
- Git **does not see this file** thanks to `.git/info/exclude`.
|
|
||||||
|
|
||||||
**Now you can add local files to it**:
|
|
||||||
```bash
|
|
||||||
echo "my-secret-file.txt" >> .local.gitignore
|
|
||||||
echo "debug_logs/" >> .local.gitignore
|
|
||||||
```
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
Before performing a commit rollback, you must manually backup the files listed in `.local.gitignore`. This is because files ignored by `.local.gitignore` are not tracked by Git and will be lost if you rollback the commit. Git will not restore these files as they were not committed or staged.
|
|
||||||
:::
|
|
@@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Lorem ipsum dolor sit, amet consectetur adipisicing elit. Id"
|
|
||||||
description: "This post is purely for testing if the css is correct for the title on the page"
|
|
||||||
publishDate: "01 Feb 2023"
|
|
||||||
tags: ["test"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing the title tag
|
|
@@ -1,116 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Markdown Admonitions"
|
|
||||||
description: "This post provides a detailed demonstration of how to use the Markdown admonition feature in Astro Citrus, showcasing its ability to highlight important information, tips, warnings, and other key content types in a visually distinct and customizable format"
|
|
||||||
publishDate: "25 Aug 2024"
|
|
||||||
seriesId: "markdown-elements"
|
|
||||||
orderInSeries: 2
|
|
||||||
tags: ["markdown", "admonitions"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## What are admonitions
|
|
||||||
|
|
||||||
Admonitions (also known as “asides”) are useful for providing supportive and/or supplementary information related to your content.
|
|
||||||
|
|
||||||
## How to use them
|
|
||||||
|
|
||||||
To use admonitions in Astro Citrus, wrap your Markdown content in a pair of triple colons `:::`. The first pair should also include the type of admonition you want to use.
|
|
||||||
|
|
||||||
For example, with the following Markdown:
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::note
|
|
||||||
Highlights information that users should take into account, even when skimming.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
|
|
||||||
:::note
|
|
||||||
Highlights information that users should take into account, even when skimming.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Admonition Types
|
|
||||||
|
|
||||||
The following admonitions are currently supported:
|
|
||||||
|
|
||||||
- `note`
|
|
||||||
- `tip`
|
|
||||||
- `important`
|
|
||||||
- `warning`
|
|
||||||
- `caution`
|
|
||||||
|
|
||||||
### Note
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::note
|
|
||||||
Highlights information that users should take into account, even when skimming.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
:::note
|
|
||||||
Highlights information that users should take into account, even when skimming.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Tip
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::tip
|
|
||||||
Optional information to help a user be more successful.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
Optional information to help a user be more successful.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Important
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::important
|
|
||||||
Crucial information necessary for users to succeed.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
:::important
|
|
||||||
Crucial information necessary for users to succeed.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Warning
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::warning
|
|
||||||
Critical content demanding immediate user attention due to potential risks.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
Critical content demanding immediate user attention due to potential risks.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Caution
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::caution
|
|
||||||
Negative potential consequences of an action.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
Negative potential consequences of an action.
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Customising the admonition title
|
|
||||||
|
|
||||||
You can customise the admonition title using the following markup:
|
|
||||||
|
|
||||||
```md
|
|
||||||
:::note[My custom title]
|
|
||||||
This is a note with a custom title.
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
|
|
||||||
:::note[My custom title]
|
|
||||||
This is a note with a custom title.
|
|
||||||
:::
|
|
@@ -1,188 +0,0 @@
|
|||||||
---
|
|
||||||
title: "A post of Markdown elements"
|
|
||||||
description: "This post is for testing and listing a number of different markdown elements"
|
|
||||||
publishDate: "22 Feb 2023"
|
|
||||||
updatedDate: 22 Jan 2024
|
|
||||||
seriesId: "markdown-elements"
|
|
||||||
orderInSeries: 1
|
|
||||||
tags: ["test", "markdown"]
|
|
||||||
---
|
|
||||||
|
|
||||||
# This is a H1 Heading
|
|
||||||
|
|
||||||
## This is a H2 Heading
|
|
||||||
|
|
||||||
### This is a H3 Heading
|
|
||||||
|
|
||||||
#### This is a H4 Heading
|
|
||||||
|
|
||||||
##### This is a H5 Heading
|
|
||||||
|
|
||||||
###### This is a H6 Heading
|
|
||||||
|
|
||||||
## Horizontal Rules
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Emphasis
|
|
||||||
|
|
||||||
**This is bold text**
|
|
||||||
|
|
||||||
_This is italic text_
|
|
||||||
|
|
||||||
~~Strikethrough~~
|
|
||||||
|
|
||||||
## Quotes
|
|
||||||
|
|
||||||
"Double quotes" and 'single quotes'
|
|
||||||
|
|
||||||
## Blockquotes
|
|
||||||
|
|
||||||
> Blockquotes can also be nested...
|
|
||||||
>
|
|
||||||
> > ...by using additional greater-than signs right next to each other...
|
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
An example containing a clickable reference[^1] with a link to the source.
|
|
||||||
|
|
||||||
Second example containing a reference[^2] with a link to the source.
|
|
||||||
|
|
||||||
[^1]: Reference first footnote with a return to content link.
|
|
||||||
|
|
||||||
[^2]: Second reference with a link.
|
|
||||||
|
|
||||||
If you check out this example in `src/content/post/markdown-elements/index.md`, you'll notice that the references and the heading "Footnotes" are added to the bottom of the page via the [remark-rehype](https://github.com/remarkjs/remark-rehype#options) plugin.
|
|
||||||
|
|
||||||
## Lists
|
|
||||||
|
|
||||||
Unordered
|
|
||||||
|
|
||||||
- Create a list by starting a line with `+`, `-`, or `*`
|
|
||||||
- Sub-lists are made by indenting 2 spaces:
|
|
||||||
- Marker character change forces new list start:
|
|
||||||
- Ac tristique libero volutpat at
|
|
||||||
- Facilisis in pretium nisl aliquet
|
|
||||||
- Nulla volutpat aliquam velit
|
|
||||||
- Very easy!
|
|
||||||
|
|
||||||
Ordered
|
|
||||||
|
|
||||||
1. Lorem ipsum dolor sit amet
|
|
||||||
2. Consectetur adipiscing elit
|
|
||||||
3. Integer molestie lorem at massa
|
|
||||||
|
|
||||||
4. You can use sequential numbers...
|
|
||||||
5. ...or keep all the numbers as `1.`
|
|
||||||
|
|
||||||
Start numbering with offset:
|
|
||||||
|
|
||||||
57. foo
|
|
||||||
1. bar
|
|
||||||
|
|
||||||
## Code
|
|
||||||
|
|
||||||
Inline `code`
|
|
||||||
|
|
||||||
Indented code
|
|
||||||
|
|
||||||
// Some comments
|
|
||||||
line 1 of code
|
|
||||||
line 2 of code
|
|
||||||
line 3 of code
|
|
||||||
|
|
||||||
Block code "fences"
|
|
||||||
|
|
||||||
```
|
|
||||||
Sample text here...
|
|
||||||
```
|
|
||||||
|
|
||||||
Syntax highlighting
|
|
||||||
|
|
||||||
```js
|
|
||||||
var foo = function (bar) {
|
|
||||||
return bar++;
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(foo(5));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rehype Pretty Code
|
|
||||||
|
|
||||||
Adding a title
|
|
||||||
|
|
||||||
```js title="file.js"
|
|
||||||
console.log("Title example");
|
|
||||||
```
|
|
||||||
|
|
||||||
A bash terminal
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "A base terminal example"
|
|
||||||
```
|
|
||||||
|
|
||||||
Highlighting code lines
|
|
||||||
|
|
||||||
```js title="line-markers.js" {7} {4-5}#add {3}#remove
|
|
||||||
function demo() {
|
|
||||||
console.log("this line is normal");
|
|
||||||
console.log("this line is marked as deleted");
|
|
||||||
// This line and the next one are marked as inserted
|
|
||||||
console.log("this is the second inserted line");
|
|
||||||
|
|
||||||
return "this line uses the neutral default marker type";
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Line Numbers
|
|
||||||
|
|
||||||
```python title="line-numbers.py" showLineNumbers
|
|
||||||
def greet(name):
|
|
||||||
print("Hello!")
|
|
||||||
print(f"Welcome, {name}!")
|
|
||||||
print("We are happy to see you.")
|
|
||||||
return name
|
|
||||||
```
|
|
||||||
|
|
||||||
[Rehype Pretty Code](https://rehype-pretty.pages.dev/) is a powerful tool with extensive features and support for [customization](https://rehype-pretty.pages.dev/).
|
|
||||||
|
|
||||||
## Tables
|
|
||||||
|
|
||||||
| Option | Description |
|
|
||||||
| ------ | ------------------------------------------------------------------------- |
|
|
||||||
| data | path to data files to supply the data that will be passed into templates. |
|
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
|
||||||
| ext | extension to be used for dest files. |
|
|
||||||
|
|
||||||
### Table Alignment
|
|
||||||
|
|
||||||
| Item | Price | # In stock |
|
|
||||||
| ------------ | :---: | ---------: |
|
|
||||||
| Juicy Apples | 1.99 | 739 |
|
|
||||||
| Bananas | 1.89 | 6 |
|
|
||||||
|
|
||||||
### Keyboard elements
|
|
||||||
|
|
||||||
| Action | Shortcut |
|
|
||||||
| --------------------- | ------------------------------------------ |
|
|
||||||
| Vertical split | <kbd>Alt+Shift++</kbd> |
|
|
||||||
| Horizontal split | <kbd>Alt+Shift+-</kbd> |
|
|
||||||
| Auto split | <kbd>Alt+Shift+d</kbd> |
|
|
||||||
| Switch between splits | <kbd>Alt</kbd> + arrow keys |
|
|
||||||
| Resizing a split | <kbd>Alt+Shift</kbd> + arrow keys |
|
|
||||||
| Close a split | <kbd>Ctrl+Shift+W</kbd> |
|
|
||||||
| Maximize a pane | <kbd>Ctrl+Shift+P</kbd> + Toggle pane zoom |
|
|
||||||
|
|
||||||
## Images
|
|
||||||
|
|
||||||
Image in the same folder: `src/content/post/markdown-elements/logo.png`
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Links
|
|
||||||
|
|
||||||
[Content from markdown-it](https://markdown-it.github.io/)
|
|
Before Width: | Height: | Size: 78 KiB |
@@ -1,14 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
|
|
||||||
<!--
|
|
||||||
<rect width="128" height="128" fill="#f7f7f8" />
|
|
||||||
-->
|
|
||||||
<path fill="#224d67" d="M22.5 14.8c2.9 1.3 99 44 99 44c2.7 1.2 2.9 3.1 2 12.4c-1 10.5-1.9 37.8-40.2 42.9c-24.6 3.2-55.9-4.3-70.9-27.2C-6 58.8 11 23.4 14.8 17.7c2.4-3.5 4.8-4.2 7.7-2.9" />
|
|
||||||
<path fill="#f0f4c3" d="M121.5 58.8c-.3-.2-92-40.8-98.9-43.9C9.6 31.5-3.8 76 27.9 96.2c33.6 21.5 78.7-10.2 93.6-37.4" />
|
|
||||||
<path fill="#f0f4c3" d="M117.7 57c-.3-.2-86.7-38.4-93.2-41.3c-12.2 15.5-23.9 59.1 5.7 78c31.4 20.2 73.6-11.2 87.5-36.7" />
|
|
||||||
<path fill="#cb2a42" d="M56.2 37.6L19.5 48.2c-2.5.8-4.4 2.8-5 5.3c-1.9 8.5.8 23.3 8.9 29.8c3.5 2.7 8.6 1.8 10.8-2.1L58.5 41c1.3-1.7.5-4.2-2.3-3.4m14.3 2.9s14.6 30.1 16 33s6.3 4.7 9.9 2.8c10.7-5.6 15.5-12.4 19.2-20.2c-8.9-3.9-42.4-18.8-42.4-18.8c-2.4-1.1-4 .6-2.7 3.2m-8.6 1.9C60.3 45.1 39.5 81 37.6 84.1c-1.9 3.2-.7 7.5 2.7 9.2c12.3 6.5 30.9.4 39.6-7c2.2-1.9 4.5-5.1 3.2-8.2S68.9 44.6 67.8 42.3c-1.2-2.7-4.1-2.8-5.9.1" />
|
|
||||||
<path fill="#f0f4c3" d="M52.2 42.2c-1.4.4-10.1 3-11.1 3.4c-1.4.5-2.2 1.7-1.9 2.5c.3.9 1.7 1.1 3.1.6c.8-.3 7.1-3.9 9.5-5.2c-3.1 2.4-10.2 9.4-11.1 10.3c-1.4 1.5-1.7 3.4-.8 4.3c1 .9 2.9.5 4.3-1c1.2-1.3 8.5-12.8 9.1-13.9s.4-1.4-1.1-1m10.1 16.4c0-2.2 1.4-10.3 1.8-12.3c.4-1.6 1.5-1.8 1.8.5s1.7 9.7 1.7 11.8s-1.2 3.3-2.7 3.3c-1.4 0-2.6-1.1-2.6-3.3M79.9 49c-1.2-1.8-3.3-4.9-4.1-6.1c-.7-1.2.1-2.1 1.8-.9s4 2.9 5.4 4c1.6 1.3 1.9 3 .8 4s-2.7.8-3.9-1" />
|
|
||||||
<ellipse cx="87.3" cy="103.12" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-27.098 87.298 103.126)" />
|
|
||||||
<ellipse cx="98.89" cy="103.82" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-30.642 98.887 103.818)" />
|
|
||||||
<ellipse cx="102.02" cy="93.8" fill="#cb2a42" rx="3.4" ry="2.3" transform="rotate(-37.16 102.017 93.797)" />
|
|
||||||
<path fill="#cb2a42" d="M57.6 30.3c-8.3-3.7-24.4-10.7-29.6-13c-3.6 2.2-9.7 11.4-11.2 21.2c-.6 3.6 1.7 5.9 5.3 4.9c0 0 33.7-9.3 35.3-9.7c1.6-.5 2-2.6.2-3.4" />
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
title: "This post doesn't have any content"
|
|
||||||
description: "This post is purely for testing the table of content, which should not be rendered, and the toggle button next to the post title should not be displayed"
|
|
||||||
publishDate: "22 Feb 2023"
|
|
||||||
tags: ["test", "toc"]
|
|
||||||
---
|
|
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
title: "A post without tags"
|
|
||||||
description: "This post is for testing the functionality"
|
|
||||||
publishDate: "11 March 2024"
|
|
||||||
draft: false
|
|
||||||
---
|
|
@@ -1,763 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Remark-Rehype"
|
|
||||||
description: "This post is about Remark-Rehype plugin for Astro"
|
|
||||||
publishDate: "26 January 2025"
|
|
||||||
tags: ["rehype", "remark", "astro", "plugin"]
|
|
||||||
draft: false
|
|
||||||
---
|
|
||||||
|
|
||||||
## What is this?
|
|
||||||
|
|
||||||
This package is a [unified][] ([remark][]) plugin that switches from remark (the
|
|
||||||
markdown ecosystem) to rehype (the HTML ecosystem).
|
|
||||||
It does this by transforming the current markdown (mdast) syntax tree into an
|
|
||||||
HTML (hast) syntax tree.
|
|
||||||
remark plugins deal with mdast and rehype plugins deal with hast, so plugins
|
|
||||||
used after `remark-rehype` have to be rehype plugins.
|
|
||||||
|
|
||||||
The reason that there are different ecosystems for markdown and HTML is that
|
|
||||||
turning markdown into HTML is, while frequently needed, not the only purpose of
|
|
||||||
markdown.
|
|
||||||
Checking (linting) and formatting markdown are also common use cases for
|
|
||||||
remark and markdown.
|
|
||||||
There are several aspects of markdown that do not translate 1-to-1 to HTML.
|
|
||||||
In some cases markdown contains more information than HTML: for example, there
|
|
||||||
are several ways to add a link in markdown (as in, autolinks: `<https://url>`,
|
|
||||||
resource links: `[label](url)`, and reference links with definitions:
|
|
||||||
`[label][id]` and `[id]: url`).
|
|
||||||
In other cases HTML contains more information than markdown: there are many
|
|
||||||
tags, which add new meaning (semantics), available in HTML that aren’t available
|
|
||||||
in markdown.
|
|
||||||
If there was just one AST, it would be quite hard to perform the tasks that
|
|
||||||
several remark and rehype plugins currently do.
|
|
||||||
|
|
||||||
## When should I use this?
|
|
||||||
|
|
||||||
This project is useful when you want to turn markdown to HTML.
|
|
||||||
It opens up a whole new ecosystem with tons of plugins to do all kinds of
|
|
||||||
things.
|
|
||||||
You can [minify HTML][rehype-minify], [format HTML][rehype-format],
|
|
||||||
[make sure it’s safe][rehype-sanitize], [highlight code][rehype-highlight],
|
|
||||||
[add metadata][rehype-meta], and a lot more.
|
|
||||||
|
|
||||||
A different plugin, [`rehype-raw`][rehype-raw], adds support for raw HTML
|
|
||||||
written inside markdown.
|
|
||||||
This is a separate plugin because supporting HTML inside markdown is a heavy
|
|
||||||
task (performance and bundle size) and not always needed.
|
|
||||||
To use both together, you also have to configure `remark-rehype` with
|
|
||||||
`allowDangerousHtml: true` and then use `rehype-raw`.
|
|
||||||
|
|
||||||
The rehype plugin [`rehype-remark`][rehype-remark] does the inverse of this
|
|
||||||
plugin.
|
|
||||||
It turns HTML into markdown.
|
|
||||||
|
|
||||||
If you don’t use plugins and want to access syntax trees, you can use
|
|
||||||
[`mdast-util-to-hast`][mdast-util-to-hast].
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
This package is [ESM only][esm].
|
|
||||||
In Node.js (version 16+), install with [npm][]:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install remark-rehype
|
|
||||||
```
|
|
||||||
|
|
||||||
In Deno with [`esm.sh`][esmsh]:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import remarkRehype from 'https://esm.sh/remark-rehype@11'
|
|
||||||
```
|
|
||||||
|
|
||||||
In browsers with [`esm.sh`][esmsh]:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script type="module">
|
|
||||||
import remarkRehype from 'https://esm.sh/remark-rehype@11?bundle'
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use
|
|
||||||
|
|
||||||
Say our document `example.md` contains:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Pluto
|
|
||||||
|
|
||||||
**Pluto** (minor-planet designation: **134340 Pluto**) is a
|
|
||||||
[dwarf planet](https://en.wikipedia.org/wiki/Dwarf_planet) in the
|
|
||||||
[Kuiper belt](https://en.wikipedia.org/wiki/Kuiper_belt).
|
|
||||||
```
|
|
||||||
|
|
||||||
…and our module `example.js` contains:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import rehypeDocument from 'rehype-document'
|
|
||||||
import rehypeFormat from 'rehype-format'
|
|
||||||
import rehypeStringify from 'rehype-stringify'
|
|
||||||
import remarkParse from 'remark-parse'
|
|
||||||
import remarkRehype from 'remark-rehype'
|
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {unified} from 'unified'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
|
|
||||||
const file = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(rehypeDocument)
|
|
||||||
.use(rehypeFormat)
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
|
||||||
console.log(String(file))
|
|
||||||
```
|
|
||||||
|
|
||||||
…then running `node example.js` yields:
|
|
||||||
|
|
||||||
```txt
|
|
||||||
example.md: no issues found
|
|
||||||
```
|
|
||||||
|
|
||||||
HTML:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>example</title>
|
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Pluto</h1>
|
|
||||||
<p>
|
|
||||||
<strong>Pluto</strong> (minor-planet designation: <strong>134340 Pluto</strong>) is a
|
|
||||||
<a href="https://en.wikipedia.org/wiki/Dwarf_planet">dwarf planet</a> in the
|
|
||||||
<a href="https://en.wikipedia.org/wiki/Kuiper_belt">Kuiper belt</a>.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
This package exports the identifiers
|
|
||||||
[`defaultFootnoteBackContent`][api-default-footnote-back-content],
|
|
||||||
[`defaultFootnoteBackLabel`][api-default-footnote-back-label], and
|
|
||||||
[`defaultHandlers`][api-default-handlers].
|
|
||||||
The default export is [`remarkRehype`][api-remark-rehype].
|
|
||||||
|
|
||||||
### `defaultFootnoteBackContent(referenceIndex, rereferenceIndex)`
|
|
||||||
|
|
||||||
See [`defaultFootnoteBackContent` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-default-footnote-back-content]
|
|
||||||
|
|
||||||
### `defaultFootnoteBackLabel(referenceIndex, rereferenceIndex)`
|
|
||||||
|
|
||||||
See [`defaultFootnoteBackLabel` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-default-footnote-back-label]
|
|
||||||
|
|
||||||
### `defaultHandlers`
|
|
||||||
|
|
||||||
See [`defaultHandlers` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-default-handlers]
|
|
||||||
|
|
||||||
### `unified().use(remarkRehype[, destination][, options])`
|
|
||||||
|
|
||||||
Turn markdown into HTML.
|
|
||||||
|
|
||||||
###### Parameters
|
|
||||||
|
|
||||||
* `destination` ([`Processor`][unified-processor], optional)
|
|
||||||
— processor
|
|
||||||
* `options` ([`Options`][api-options], optional)
|
|
||||||
— configuration
|
|
||||||
|
|
||||||
###### Returns
|
|
||||||
|
|
||||||
Transform ([`Transformer`][unified-transformer]).
|
|
||||||
|
|
||||||
##### Notes
|
|
||||||
|
|
||||||
###### Signature
|
|
||||||
|
|
||||||
* if a [processor][unified-processor] is given, runs the (rehype) plugins
|
|
||||||
used on it with a hast tree, then discards the result
|
|
||||||
([*bridge mode*][unified-mode])
|
|
||||||
* otherwise, returns a hast tree, the plugins used after `remarkRehype`
|
|
||||||
are rehype plugins ([*mutate mode*][unified-mode])
|
|
||||||
|
|
||||||
:::note
|
|
||||||
It’s highly unlikely that you want to pass a `processor`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
###### HTML
|
|
||||||
|
|
||||||
Raw HTML is available in mdast as [`html`][mdast-html] nodes and can be embedded
|
|
||||||
in hast as semistandard `raw` nodes.
|
|
||||||
Most plugins ignore `raw` nodes but two notable ones don’t:
|
|
||||||
|
|
||||||
* [`rehype-stringify`][rehype-stringify] also has an option
|
|
||||||
`allowDangerousHtml` which will output the raw HTML.
|
|
||||||
This is typically discouraged as noted by the option name but is useful if
|
|
||||||
you completely trust authors
|
|
||||||
* [`rehype-raw`][rehype-raw] can handle the raw embedded HTML strings by
|
|
||||||
parsing them into standard hast nodes (`element`, `text`, etc).
|
|
||||||
This is a heavy task as it needs a full HTML parser, but it is the only way
|
|
||||||
to support untrusted content
|
|
||||||
|
|
||||||
###### Footnotes
|
|
||||||
|
|
||||||
Many options supported here relate to footnotes.
|
|
||||||
Footnotes are not specified by CommonMark, which we follow by default.
|
|
||||||
They are supported by GitHub, so footnotes can be enabled in markdown with
|
|
||||||
[`remark-gfm`][remark-gfm].
|
|
||||||
|
|
||||||
The options `footnoteBackLabel` and `footnoteLabel` define natural language
|
|
||||||
that explains footnotes, which is hidden for sighted users but shown to
|
|
||||||
assistive technology.
|
|
||||||
When your page is not in English, you must define translated values.
|
|
||||||
|
|
||||||
Back references use ARIA attributes, but the section label itself uses a
|
|
||||||
heading that is hidden with an `sr-only` class.
|
|
||||||
To show it to sighted users, define different attributes in
|
|
||||||
`footnoteLabelProperties`.
|
|
||||||
|
|
||||||
###### Clobbering
|
|
||||||
|
|
||||||
Footnotes introduces a problem, as it links footnote calls to footnote
|
|
||||||
definitions on the page through `id` attributes generated from user content,
|
|
||||||
which results in DOM clobbering.
|
|
||||||
|
|
||||||
DOM clobbering is this:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p id=x></p>
|
|
||||||
<script>alert(x) // `x` now refers to the DOM `p#x` element</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
Elements by their ID are made available by browsers on the `window` object,
|
|
||||||
which is a security risk.
|
|
||||||
Using a prefix solves this problem.
|
|
||||||
|
|
||||||
More information on how to handle clobbering and the prefix is explained in
|
|
||||||
[*Example: headings (DOM clobbering)* in
|
|
||||||
`rehype-sanitize`][rehype-sanitize-clobber].
|
|
||||||
|
|
||||||
###### Unknown nodes
|
|
||||||
|
|
||||||
Unknown nodes are nodes with a type that isn’t in `handlers` or `passThrough`.
|
|
||||||
The default behavior for unknown nodes is:
|
|
||||||
|
|
||||||
* when the node has a `value` (and doesn’t have `data.hName`,
|
|
||||||
`data.hProperties`, or `data.hChildren`, see later), create a hast `text`
|
|
||||||
node
|
|
||||||
* otherwise, create a `<div>` element (which could be changed with
|
|
||||||
`data.hName`), with its children mapped from mdast to hast as well
|
|
||||||
|
|
||||||
This behavior can be changed by passing an `unknownHandler`.
|
|
||||||
|
|
||||||
### `Options`
|
|
||||||
|
|
||||||
Configuration (TypeScript type).
|
|
||||||
|
|
||||||
###### Fields
|
|
||||||
|
|
||||||
* `allowDangerousHtml` (`boolean`, default: `false`)
|
|
||||||
— whether to persist raw HTML in markdown in the hast tree
|
|
||||||
* `clobberPrefix` (`string`, default: `'user-content-'`)
|
|
||||||
— prefix to use before the `id` property on footnotes to prevent them from
|
|
||||||
*clobbering*
|
|
||||||
* `footnoteBackContent`
|
|
||||||
([`FootnoteBackContentTemplate` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-footnote-back-content-template]
|
|
||||||
or `string`, default:
|
|
||||||
[`defaultFootnoteBackContent` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-default-footnote-back-content])
|
|
||||||
— content of the backreference back to references
|
|
||||||
* `footnoteBackLabel`
|
|
||||||
([`FootnoteBackLabelTemplate` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-footnote-back-label-template]
|
|
||||||
or `string`, default:
|
|
||||||
[`defaultFootnoteBackLabel` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-default-footnote-back-label])
|
|
||||||
— label to describe the backreference back to references
|
|
||||||
* `footnoteLabel` (`string`, default: `'Footnotes'`)
|
|
||||||
— label to use for the footnotes section (affects screen readers)
|
|
||||||
* `footnoteLabelProperties`
|
|
||||||
([`Properties` from `@types/hast`][hast-properties], default:
|
|
||||||
`{className: ['sr-only']}`)
|
|
||||||
— properties to use on the footnote label
|
|
||||||
(note that `id: 'footnote-label'` is always added as footnote calls use it
|
|
||||||
with `aria-describedby` to provide an accessible label)
|
|
||||||
* `footnoteLabelTagName` (`string`, default: `h2`)
|
|
||||||
— tag name to use for the footnote label
|
|
||||||
* `handlers` ([`Handlers` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-handlers], optional)
|
|
||||||
— extra handlers for nodes
|
|
||||||
* `passThrough` (`Array<Nodes['type']>`, optional)
|
|
||||||
— list of custom mdast node types to pass through (keep) in hast (note that
|
|
||||||
the node itself is passed, but eventual children are transformed)
|
|
||||||
* `unknownHandler` ([`Handler` from
|
|
||||||
`mdast-util-to-hast`][mdast-util-to-hast-handler], optional)
|
|
||||||
— handle all unknown nodes
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Example: supporting HTML in markdown naïvely
|
|
||||||
|
|
||||||
If you completely trust the authors of the input markdown and want to allow them
|
|
||||||
to write HTML inside markdown, you can pass `allowDangerousHtml` to
|
|
||||||
`remark-rehype` and `rehype-stringify`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import rehypeStringify from 'rehype-stringify'
|
|
||||||
import remarkParse from 'remark-parse'
|
|
||||||
import remarkRehype from 'remark-rehype'
|
|
||||||
import {unified} from 'unified'
|
|
||||||
|
|
||||||
const file = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkRehype, {allowDangerousHtml: true})
|
|
||||||
.use(rehypeStringify, {allowDangerousHtml: true})
|
|
||||||
.process('<a href="/wiki/Dysnomia_(moon)" onclick="alert(1)">Dysnomia</a>')
|
|
||||||
|
|
||||||
console.log(String(file))
|
|
||||||
```
|
|
||||||
|
|
||||||
Yields:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p><a href="/wiki/Dysnomia_(moon)" onclick="alert(1)">Dysnomia</a></p>
|
|
||||||
```
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
Оbserve that the XSS attack through `onclick` is present.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Example: supporting HTML in markdown properly
|
|
||||||
|
|
||||||
If you do not trust the authors of the input markdown, or if you want to make
|
|
||||||
sure that rehype plugins can see HTML embedded in markdown, use
|
|
||||||
[`rehype-raw`][rehype-raw].
|
|
||||||
The following example passes `allowDangerousHtml` to `remark-rehype`, then
|
|
||||||
turns the raw embedded HTML into proper HTML nodes with `rehype-raw`, and
|
|
||||||
finally sanitizes the HTML by only allowing safe things with
|
|
||||||
`rehype-sanitize`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import rehypeSanitize from 'rehype-sanitize'
|
|
||||||
import rehypeStringify from 'rehype-stringify'
|
|
||||||
import rehypeRaw from 'rehype-raw'
|
|
||||||
import remarkParse from 'remark-parse'
|
|
||||||
import remarkRehype from 'remark-rehype'
|
|
||||||
import {unified} from 'unified'
|
|
||||||
|
|
||||||
const file = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkRehype, {allowDangerousHtml: true})
|
|
||||||
.use(rehypeRaw)
|
|
||||||
.use(rehypeSanitize)
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process('<a href="/wiki/Dysnomia_(moon)" onclick="alert(1)">Dysnomia</a>')
|
|
||||||
|
|
||||||
console.log(String(file))
|
|
||||||
```
|
|
||||||
|
|
||||||
Running that code yields:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p><a href="/wiki/Dysnomia_(moon)">Dysnomia</a></p>
|
|
||||||
```
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
Оbserve that the XSS attack through `onclick` is **not** present.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Example: footnotes in languages other than English
|
|
||||||
|
|
||||||
If you know that the markdown is authored in a language other than English,
|
|
||||||
and you’re using `remark-gfm` to match how GitHub renders markdown, and you know
|
|
||||||
that footnotes are (or can?) be used, you should translate the labels associated
|
|
||||||
with them.
|
|
||||||
|
|
||||||
Let’s first set the stage:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import {unified} from 'unified'
|
|
||||||
import remarkParse from 'remark-parse'
|
|
||||||
import remarkGfm from 'remark-gfm'
|
|
||||||
import remarkRehype from 'remark-rehype'
|
|
||||||
import rehypeStringify from 'rehype-stringify'
|
|
||||||
|
|
||||||
const doc = `
|
|
||||||
Ceres ist nach der römischen Göttin des Ackerbaus benannt;
|
|
||||||
ihr astronomisches Symbol ist daher eine stilisierte Sichel: ⚳.[^nasa-2015]
|
|
||||||
|
|
||||||
[^nasa-2015]: JPL/NASA:
|
|
||||||
[*What is a Dwarf Planet?*](https://www.jpl.nasa.gov/infographics/what-is-a-dwarf-planet)
|
|
||||||
In: Jet Propulsion Laboratory.
|
|
||||||
22. April 2015,
|
|
||||||
abgerufen am 19. Januar 2022 (englisch).
|
|
||||||
`
|
|
||||||
|
|
||||||
const file = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkGfm)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(doc)
|
|
||||||
|
|
||||||
console.log(String(file))
|
|
||||||
```
|
|
||||||
|
|
||||||
Yields:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<p>
|
|
||||||
Ceres ist nach der römischen Göttin des Ackerbaus benannt;
|
|
||||||
ihr astronomisches Symbol ist daher eine stilisierte Sichel: ⚳.
|
|
||||||
<sup>
|
|
||||||
<a
|
|
||||||
href="#user-content-fn-nasa-2015"
|
|
||||||
id="user-content-fnref-nasa-2015"
|
|
||||||
data-footnote-ref aria-describedby="footnote-label"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
</a>
|
|
||||||
</sup>
|
|
||||||
</p>
|
|
||||||
<section data-footnotes class="footnotes">
|
|
||||||
<h2 class="sr-only" id="footnote-label">Footnotes</h2>
|
|
||||||
<ol>
|
|
||||||
<li id="user-content-fn-nasa-2015">
|
|
||||||
<p>
|
|
||||||
JPL/NASA:
|
|
||||||
<a href="https://www.jpl.nasa.gov/infographics/what-is-a-dwarf-planet">
|
|
||||||
<em>What is a Dwarf Planet?</em>
|
|
||||||
</a>
|
|
||||||
In: Jet Propulsion Laboratory.
|
|
||||||
22. April 2015,
|
|
||||||
abgerufen am 19. Januar 2022 (englisch).
|
|
||||||
<a
|
|
||||||
href="#user-content-fnref-nasa-2015"
|
|
||||||
data-footnote-backref=""
|
|
||||||
aria-label="Back to reference 1"
|
|
||||||
class="data-footnote-backref"
|
|
||||||
>
|
|
||||||
↩
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
```
|
|
||||||
|
|
||||||
This is a mix of English and German that isn’t very accessible, such as that
|
|
||||||
screen readers can’t handle it nicely.
|
|
||||||
Let’s say our program *does* know that the markdown is in German.
|
|
||||||
In that case, it’s important to translate and define the labels relating to
|
|
||||||
footnotes so that screen reader users can properly pronounce the page:
|
|
||||||
|
|
||||||
```diff
|
|
||||||
@@ -18,7 +18,16 @@ ihr astronomisches Symbol ist daher eine stilisierte Sichel: ⚳.[^nasa-2015]
|
|
||||||
const file = await unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkGfm)
|
|
||||||
- .use(remarkRehype)
|
|
||||||
+ .use(remarkRehype, {
|
|
||||||
+ footnoteBackLabel(referenceIndex, rereferenceIndex) {
|
|
||||||
+ return (
|
|
||||||
+ 'Hochspringen nach: ' +
|
|
||||||
+ (referenceIndex + 1) +
|
|
||||||
+ (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
|
|
||||||
+ )
|
|
||||||
+ },
|
|
||||||
+ footnoteLabel: 'Fußnoten'
|
|
||||||
+ })
|
|
||||||
.use(rehypeStringify)
|
|
||||||
.process(doc)
|
|
||||||
```
|
|
||||||
|
|
||||||
Running the code with the above patch applied, yields:
|
|
||||||
|
|
||||||
```diff
|
|
||||||
@@ -1,13 +1,13 @@
|
|
||||||
<p>Ceres ist nach der römischen Göttin des Ackerbaus benannt;
|
|
||||||
ihr astronomisches Symbol ist daher eine stilisierte Sichel: ⚳.<sup><a href="#user-content-fn-nasa-2015" id="user-content-fnref-nasa-2015" data-footnote-ref aria-describedby="footnote-label">1</a></sup></p>
|
|
||||||
-<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2>
|
|
||||||
+<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Fußnoten</h2>
|
|
||||||
<ol>
|
|
||||||
<li id="user-content-fn-nasa-2015">
|
|
||||||
<p>JPL/NASA:
|
|
||||||
<a href="https://www.jpl.nasa.gov/infographics/what-is-a-dwarf-planet"><em>What is a Dwarf Planet?</em></a>
|
|
||||||
In: Jet Propulsion Laboratory.
|
|
||||||
22. April 2015,
|
|
||||||
-abgerufen am 19. Januar 2022 (englisch). <a href="#user-content-fnref-nasa-2015" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
|
|
||||||
+abgerufen am 19. Januar 2022 (englisch). <a href="#user-content-fnref-nasa-2015" data-footnote-backref="" aria-label="Hochspringen nach: 1" class="data-footnote-backref">↩</a></p>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTML
|
|
||||||
|
|
||||||
See [*Algorithm* in
|
|
||||||
`mdast-util-to-hast`](https://github.com/syntax-tree/mdast-util-to-hast#algorithm)
|
|
||||||
for info on how mdast (markdown) nodes are transformed to hast (HTML).
|
|
||||||
|
|
||||||
## CSS
|
|
||||||
|
|
||||||
Assuming you know how to use (semantic) HTML and CSS, then it should generally
|
|
||||||
be straightforward to style the HTML produced by this plugin.
|
|
||||||
With CSS, you can get creative and style the results as you please.
|
|
||||||
|
|
||||||
Some semistandard features, notably GFMs tasklists and footnotes, generate HTML
|
|
||||||
that be unintuitive, as it matches exactly what GitHub produces for their
|
|
||||||
website.
|
|
||||||
There is a project, [`sindresorhus/github-markdown-css`][github-markdown-css],
|
|
||||||
that exposes the stylesheet that GitHub uses for rendered markdown, which might
|
|
||||||
either be inspirational for more complex features, or can be used as-is to
|
|
||||||
exactly match how GitHub styles rendered markdown.
|
|
||||||
|
|
||||||
The following CSS is needed to make footnotes look a bit like GitHub:
|
|
||||||
|
|
||||||
```css
|
|
||||||
/* Style the footnotes section. */
|
|
||||||
.footnotes {
|
|
||||||
font-size: smaller;
|
|
||||||
color: #8b949e;
|
|
||||||
border-top: 1px solid #30363d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide the section label for visual users. */
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
word-wrap: normal;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Place `[` and `]` around footnote calls. */
|
|
||||||
[data-footnote-ref]::before {
|
|
||||||
content: '[';
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-footnote-ref]::after {
|
|
||||||
content: ']';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Syntax tree
|
|
||||||
|
|
||||||
This projects turns [mdast][] (markdown) into [hast][] (HTML).
|
|
||||||
|
|
||||||
It extends mdast by supporting `data` fields on mdast nodes to specify how they
|
|
||||||
should be transformed.
|
|
||||||
See [*Fields on nodes* in
|
|
||||||
`mdast-util-to-hast`](https://github.com/syntax-tree/mdast-util-to-hast#fields-on-nodes)
|
|
||||||
for info on how these fields work.
|
|
||||||
|
|
||||||
It extends hast by using a semistandard raw nodes for raw HTML.
|
|
||||||
See the [*HTML* note above](#html) for more info.
|
|
||||||
|
|
||||||
## Types
|
|
||||||
|
|
||||||
This package is fully typed with [TypeScript][].
|
|
||||||
It exports the types
|
|
||||||
[`Options`][api-options].
|
|
||||||
|
|
||||||
The types of `mdast-util-to-hast` can be referenced to register data fields
|
|
||||||
with `@types/mdast` and `Raw` nodes with `@types/hast`.
|
|
||||||
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* @import {Root as HastRoot} from 'hast'
|
|
||||||
* @import {Root as MdastRoot} from 'mdast'
|
|
||||||
* @import {} from 'mdast-util-to-hast'
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {visit} from 'unist-util-visit'
|
|
||||||
|
|
||||||
const mdastNode = /** @type {MdastRoot} */ ({/* … */})
|
|
||||||
console.log(mdastNode.data?.hName) // Typed as `string | undefined`.
|
|
||||||
|
|
||||||
const hastNode = /** @type {HastRoot} */ ({/* … */})
|
|
||||||
|
|
||||||
visit(hastNode, function (node) {
|
|
||||||
// `node` can now be `raw`.
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Compatibility
|
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with maintained
|
|
||||||
versions of Node.js.
|
|
||||||
|
|
||||||
When we cut a new major release, we drop support for unmaintained versions of
|
|
||||||
Node.
|
|
||||||
This means we try to keep the current release line, `remark-rehype@^11`,
|
|
||||||
compatible with Node.js 16.
|
|
||||||
|
|
||||||
This plugin works with `unified` version 6+, `remark-parse` version 3+ (used in
|
|
||||||
`remark` version 7), and `rehype-stringify` version 3+ (used in `rehype`
|
|
||||||
version 5).
|
|
||||||
|
|
||||||
## Security
|
|
||||||
|
|
||||||
Use of `remark-rehype` can open you up to a
|
|
||||||
[cross-site scripting (XSS)][wiki-xss] attack.
|
|
||||||
Embedded **[hast][]** properties (`hName`, `hProperties`, `hChildren`) in
|
|
||||||
[mdast][], custom handlers, and the `allowDangerousHtml` option all provide
|
|
||||||
openings.
|
|
||||||
Use [`rehype-sanitize`][rehype-sanitize] to make the tree safe.
|
|
||||||
|
|
||||||
## Related
|
|
||||||
|
|
||||||
* [`rehype-raw`][rehype-raw]
|
|
||||||
— rehype plugin to parse the tree again and support `raw` nodes
|
|
||||||
* [`rehype-sanitize`][rehype-sanitize]
|
|
||||||
— rehype plugin to sanitize HTML
|
|
||||||
* [`rehype-remark`](https://github.com/rehypejs/rehype-remark)
|
|
||||||
— rehype plugin to turn HTML into markdown
|
|
||||||
* [`rehype-retext`](https://github.com/rehypejs/rehype-retext)
|
|
||||||
— rehype plugin to support retext
|
|
||||||
* [`remark-retext`](https://github.com/remarkjs/remark-retext)
|
|
||||||
— remark plugin to support retext
|
|
||||||
|
|
||||||
## Contribute
|
|
||||||
|
|
||||||
See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
|
|
||||||
to get started.
|
|
||||||
See [`support.md`][support] for ways to get help.
|
|
||||||
|
|
||||||
This project has a [code of conduct][coc].
|
|
||||||
By interacting with this repository, organization, or community you agree to
|
|
||||||
abide by its terms.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT][license] © [Titus Wormer][author]
|
|
||||||
|
|
||||||
<!-- Definitions -->
|
|
||||||
|
|
||||||
[build-badge]: https://github.com/remarkjs/remark-rehype/workflows/main/badge.svg
|
|
||||||
|
|
||||||
[build]: https://github.com/remarkjs/remark-rehype/actions
|
|
||||||
|
|
||||||
[coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-rehype.svg
|
|
||||||
|
|
||||||
[coverage]: https://codecov.io/github/remarkjs/remark-rehype
|
|
||||||
|
|
||||||
[downloads-badge]: https://img.shields.io/npm/dm/remark-rehype.svg
|
|
||||||
|
|
||||||
[downloads]: https://www.npmjs.com/package/remark-rehype
|
|
||||||
|
|
||||||
[size-badge]: https://img.shields.io/bundlejs/size/remark-rehype
|
|
||||||
|
|
||||||
[size]: https://bundlejs.com/?q=remark-rehype
|
|
||||||
|
|
||||||
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
|
|
||||||
|
|
||||||
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
|
|
||||||
|
|
||||||
[collective]: https://opencollective.com/unified
|
|
||||||
|
|
||||||
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
|
|
||||||
|
|
||||||
[chat]: https://github.com/remarkjs/remark/discussions
|
|
||||||
|
|
||||||
[npm]: https://docs.npmjs.com/cli/install
|
|
||||||
|
|
||||||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
|
||||||
|
|
||||||
[esmsh]: https://esm.sh
|
|
||||||
|
|
||||||
[health]: https://github.com/remarkjs/.github
|
|
||||||
|
|
||||||
[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md
|
|
||||||
|
|
||||||
[support]: https://github.com/remarkjs/.github/blob/main/support.md
|
|
||||||
|
|
||||||
[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md
|
|
||||||
|
|
||||||
[license]: license
|
|
||||||
|
|
||||||
[author]: https://wooorm.com
|
|
||||||
|
|
||||||
[github-markdown-css]: https://github.com/sindresorhus/github-markdown-css
|
|
||||||
|
|
||||||
[hast]: https://github.com/syntax-tree/hast
|
|
||||||
|
|
||||||
[hast-properties]: https://github.com/syntax-tree/hast#properties
|
|
||||||
|
|
||||||
[mdast]: https://github.com/syntax-tree/mdast
|
|
||||||
|
|
||||||
[mdast-html]: https://github.com/syntax-tree/mdast#html
|
|
||||||
|
|
||||||
[mdast-util-to-hast]: https://github.com/syntax-tree/mdast-util-to-hast
|
|
||||||
|
|
||||||
[mdast-util-to-hast-default-footnote-back-content]: https://github.com/syntax-tree/mdast-util-to-hast#defaultfootnotebackcontentreferenceindex-rereferenceindex
|
|
||||||
|
|
||||||
[mdast-util-to-hast-default-footnote-back-label]: https://github.com/syntax-tree/mdast-util-to-hast#defaultfootnotebacklabelreferenceindex-rereferenceindex
|
|
||||||
|
|
||||||
[mdast-util-to-hast-footnote-back-content-template]: https://github.com/syntax-tree/mdast-util-to-hast#footnotebackcontenttemplate
|
|
||||||
|
|
||||||
[mdast-util-to-hast-footnote-back-label-template]: https://github.com/syntax-tree/mdast-util-to-hast#footnotebacklabeltemplate
|
|
||||||
|
|
||||||
[mdast-util-to-hast-default-handlers]: https://github.com/syntax-tree/mdast-util-to-hast#defaulthandlers
|
|
||||||
|
|
||||||
[mdast-util-to-hast-handlers]: https://github.com/syntax-tree/mdast-util-to-hast#handlers
|
|
||||||
|
|
||||||
[mdast-util-to-hast-handler]: https://github.com/syntax-tree/mdast-util-to-hast#handler
|
|
||||||
|
|
||||||
[rehype]: https://github.com/rehypejs/rehype
|
|
||||||
|
|
||||||
[rehype-format]: https://github.com/rehypejs/rehype-format
|
|
||||||
|
|
||||||
[rehype-highlight]: https://github.com/rehypejs/rehype-highlight
|
|
||||||
|
|
||||||
[rehype-meta]: https://github.com/rehypejs/rehype-meta
|
|
||||||
|
|
||||||
[rehype-minify]: https://github.com/rehypejs/rehype-minify
|
|
||||||
|
|
||||||
[rehype-raw]: https://github.com/rehypejs/rehype-raw
|
|
||||||
|
|
||||||
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
|
|
||||||
|
|
||||||
[rehype-sanitize-clobber]: https://github.com/rehypejs/rehype-sanitize#example-headings-dom-clobbering
|
|
||||||
|
|
||||||
[rehype-stringify]: https://github.com/rehypejs/rehype/tree/main/packages/rehype-stringify
|
|
||||||
|
|
||||||
[rehype-remark]: https://github.com/rehypejs/rehype-remark
|
|
||||||
|
|
||||||
[remark]: https://github.com/remarkjs/remark
|
|
||||||
|
|
||||||
[remark-gfm]: https://github.com/remarkjs/remark-gfm
|
|
||||||
|
|
||||||
[typescript]: https://www.typescriptlang.org
|
|
||||||
|
|
||||||
[unified]: https://github.com/unifiedjs/unified
|
|
||||||
|
|
||||||
[unified-mode]: https://github.com/unifiedjs/unified#transforming-between-ecosystems
|
|
||||||
|
|
||||||
[unified-processor]: https://github.com/unifiedjs/unified#processor
|
|
||||||
|
|
||||||
[unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
|
||||||
|
|
||||||
[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
|
|
||||||
|
|
||||||
[api-default-footnote-back-content]: #defaultfootnotebackcontentreferenceindex-rereferenceindex
|
|
||||||
|
|
||||||
[api-default-footnote-back-label]: #defaultfootnotebacklabelreferenceindex-rereferenceindex
|
|
||||||
|
|
||||||
[api-default-handlers]: #defaulthandlers
|
|
||||||
|
|
||||||
[api-options]: #options
|
|
||||||
|
|
||||||
[api-remark-rehype]: #unifieduseremarkrehype-destination-options
|
|
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Example OG Social Image"
|
|
||||||
publishDate: "27 January 2023"
|
|
||||||
description: "An example post for Astro Citrus, detailing how to add a custom social image card in the frontmatter"
|
|
||||||
tags: ["example", "blog", "image"]
|
|
||||||
ogImage: "/social-card.png"
|
|
||||||
---
|
|
||||||
|
|
||||||
## Adding your own social image to a post
|
|
||||||
|
|
||||||
This post is an example of how to add a custom [open graph](https://ogp.me/) social image, also known as an OG image, to a blog post.
|
|
||||||
By adding the optional ogImage property to the frontmatter of a post, you opt out of [satori](https://github.com/vercel/satori) automatically generating an image for this page.
|
|
||||||
|
|
||||||
If you open this markdown file `src/content/post/social-image.md` you'll see the ogImage property set to an image which lives in the public folder[^1].
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
ogImage: "/social-card.png"
|
|
||||||
```
|
|
||||||
|
|
||||||
You can view the one set for this template page [here](http://astrocitrus.artemkutsan.pp.ua/social-card.png).
|
|
||||||
|
|
||||||
[^1]: The image itself can be located anywhere you like.
|
|
@@ -1,88 +0,0 @@
|
|||||||
---
|
|
||||||
title: "How to Create a Font Subset with Transfonter"
|
|
||||||
description: "A guide to using Transfonter to create optimized font subsets"
|
|
||||||
publishDate: "2025-02-10"
|
|
||||||
tags: ["fonts", "optimization", "web performance"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## What is Transfonter?
|
|
||||||
|
|
||||||
[Transfonter](https://transfonter.org/) is a free online tool that helps convert and subset fonts. It supports various formats (TTF, OTF, WOFF, WOFF2) and allows users to optimize web fonts by reducing their size while maintaining essential glyphs.
|
|
||||||
|
|
||||||
## Why Use Font Subsetting?
|
|
||||||
|
|
||||||
Font files often contain thousands of glyphs, including symbols and characters for multiple languages. Subsetting removes unnecessary glyphs, reducing file size and improving website performance. This is particularly useful when only a specific language set or symbols are needed.
|
|
||||||
|
|
||||||
For example, I encountered an issue when using the SF Pro Rounded font with the Satori library for generating OG images, as described in this post: [Example OG Social Image](posts/social-image/). When using multiple font variants, the project failed to build due to memory overflow errors. Increasing the memory limit did not help. Moreover, using even a single font file larger than ~3.5MB is considered bad practice, let alone multiple variants at the same time.
|
|
||||||
|
|
||||||
After subsetting the font, I ended up with two subsets, both containing **only Latin characters**: one slightly over 100KB and another around 355KB. This significantly reduced the overall font size while keeping the necessary glyphs.
|
|
||||||
|
|
||||||
## Creating a Font Subset with Transfonter
|
|
||||||
|
|
||||||
Let's take **SF Pro Rounded**, a multilingual font, and divide it into two subsets:
|
|
||||||
|
|
||||||
- **Basic subset**: Includes Latin characters and essential symbols.
|
|
||||||
- **Extended subset**: Includes additional glyphs beyond the basic set.
|
|
||||||
|
|
||||||
### Upload the Font
|
|
||||||
1. Go to [Transfonter](https://transfonter.org/).
|
|
||||||
2. Click **Add Fonts** and select the **SF Pro Rounded Regular** font file (TTF or OTF format).
|
|
||||||
|
|
||||||
### Define Unicode Ranges
|
|
||||||
For subsetting, use the following ranges:
|
|
||||||
|
|
||||||
#### Basic Subset
|
|
||||||
|
|
||||||
transfonter.org latin + essential symbols unicode-range:
|
|
||||||
```
|
|
||||||
0000-007F, 00A0-024F, 2190-22FF, 2934-2937, F6D5-F6D8
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Extended Subset
|
|
||||||
|
|
||||||
transfonter.org additional glyphs unicode-range:
|
|
||||||
```
|
|
||||||
0080-00A0, 0250-218F, 2300-FFFF
|
|
||||||
```
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
You can find out the character codes and view the glyph tables of a font using built-in system tools:
|
|
||||||
- Windows: Use Character Map (charmap). Open the Start menu, search for "Character Map," and select a font to see its glyphs and Unicode codes.
|
|
||||||
- macOS: Open Font Book, select a font, and switch to "Repertoire" mode to see all available characters along with their codes.
|
|
||||||
- Linux: Use gucharmap (GNOME Character Map) or kcharselect (for KDE) to browse Unicode symbols in installed fonts.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Generate the Font Files
|
|
||||||
1. Check the **Subset** box in Transfonter.
|
|
||||||
2. Enter the Unicode ranges above for each subset.
|
|
||||||
3. Click **Convert** to generate the optimized font files.
|
|
||||||
4. Download the converted fonts.
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
Additionally, when using Transfonter, you can upload and convert multiple fonts at the same time. The tool allows batch processing, and after conversion, all optimized fonts can be downloaded as a ZIP archive, making it easier to manage multiple font files efficiently.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Implement in CSS
|
|
||||||
Once the fonts are ready, use `@font-face` to load them efficiently:
|
|
||||||
|
|
||||||
```css
|
|
||||||
@font-face {
|
|
||||||
font-family: "SFProRounded";
|
|
||||||
src: url("/fonts/SF-Pro-Rounded-Regular-Basic.ttf") format("truetype");
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: "SFProRounded";
|
|
||||||
src: url("/fonts/SF-Pro-Rounded-Regular-Extended.ttf") format("truetype");
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test the Fonts
|
|
||||||
Ensure the fonts load correctly by inspecting network requests in the browser's developer tools. Verify that only necessary subsets are downloaded.
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
Using Transfonter for font subsetting helps optimize web performance by reducing font file sizes while keeping necessary glyphs. Try it out with your fonts to enhance your website's loading speed!
|
|
@@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Unique tags validation"
|
|
||||||
publishDate: "30 January 2023"
|
|
||||||
description: "This post is used for validating if duplicate tags are removed, regardless of the string case"
|
|
||||||
tags: ["blog", "blog", "Blog", "test", "bloG", "Test", "BLOG"]
|
|
||||||
---
|
|
||||||
|
|
||||||
## This post is to test zod transform
|
|
||||||
|
|
||||||
If you open the file `src/content/post/unique-tags.md`, the tags array has a number of duplicate blog strings of various cases.
|
|
||||||
|
|
||||||
These are removed as part of the removeDupsAndLowercase function found in `src/content/config.ts`.
|
|
@@ -1,65 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Adding Webmentions to Astro Citrus"
|
|
||||||
description: "This post describes the detailed process of adding webmentions to your own site, including setup, configuration, and integration with webmention services."
|
|
||||||
publishDate: "11 Oct 2023"
|
|
||||||
tags: ["webmentions", "astro", "social"]
|
|
||||||
updatedDate: 6 December 2024
|
|
||||||
---
|
|
||||||
|
|
||||||
## TLDR
|
|
||||||
|
|
||||||
1. Add a link on your homepage to either your GitHub profile and/or email address as per [IndieLogin's](https://indielogin.com/setup) instructions. You _could_ do this via `src/components/SocialList.astro`, just be sure to include `isWebmention` to the relevant link if doing so.
|
|
||||||
2. Create an account @ [Webmention.io](https://webmention.io/) by entering your website's address.
|
|
||||||
3. Add the link feed and api key to a `.env` file with the key `WEBMENTION_URL` and `WEBMENTION_API_KEY` respectively, you could rename `.env.example` found in this template. You can also add the optional `WEBMENTION_PINGBACK` link here too.
|
|
||||||
4. Go to [brid.gy](https://brid.gy/) and sign-in to each social account[s] you wish to link.
|
|
||||||
5. Publish and build your website, remember to add the api key, and it should now be ready to receive webmentions!
|
|
||||||
|
|
||||||
## What are webmentions
|
|
||||||
|
|
||||||
Put simply, it's a way to show users who like, comment, repost and more, on various pages on your website via social media.
|
|
||||||
|
|
||||||
This theme displays the number of likes, mentions and replies each blog post receives. There are a couple of more webmentions that I haven't included, like reposts, which are currently filtered out, but shouldn't be too difficult to include.
|
|
||||||
|
|
||||||
## Steps to add it to your own site
|
|
||||||
|
|
||||||
Your going to have to create a couple of accounts to get things up-and-running. But, the first thing you need to ensure is that your social links are correct.
|
|
||||||
|
|
||||||
### Add link(s) to your profile(s)
|
|
||||||
|
|
||||||
Firstly, you need to add a link on your site to prove ownership. If you have a look at [IndieLogin's](https://indielogin.com/setup) instructions, it gives you 2 options, either an email address and/or GitHub account. I've created the component `src/components/SocialList.astro` where you can add your details into the `socialLinks` array, just include the `isWebmention` property to the relevant link which will add the `rel="me authn"` attribute. Whichever way you do it, make sure you have a link in your markup as per IndieLogin's [instructions](https://indielogin.com/setup)
|
|
||||||
|
|
||||||
```html
|
|
||||||
<a href="https://github.com/your-username" rel="me">GitHub</a>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sign up to Webmention.io
|
|
||||||
|
|
||||||
Next, head over to [Webmention.io](https://webmention.io/) and create an account by signing in with your domain name, e.g. `http://astrocitrus.artemkutsan.pp.ua/`. Please note that .app TLDs don't function correctly. Once in, it will give you a couple of links for your domain to accept webmentions. Make a note of these and create a `.env` file (this template include an example `.env.example` which you could rename). Add the link feed and api key with the key/values of `WEBMENTION_URL` and `WEBMENTION_API_KEY` respectively, and the optional `WEBMENTION_PINGBACK` url if required. Please try not to publish this to a repository!
|
|
||||||
|
|
||||||
:::note
|
|
||||||
You don't have to include the pingback link. Maybe coincidentally, but after adding it I started to receive a higher frequency of spam in my mailbox, informing me that my website could be better. TBH they're not wrong. I've now removed it, but it's up to you.
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Sign up to Brid.gy
|
|
||||||
|
|
||||||
You're now going to have to use [brid.gy](https://brid.gy/). As the name suggests, it links your website to your social media accounts. For every account you want to set up (e.g. Mastodon), click on the relevant button and connect each account you want brid.gy to search. Just to note again, brid.gy currently has an issue with .app TLDs.
|
|
||||||
|
|
||||||
## Testing everything works
|
|
||||||
|
|
||||||
With everything set, it's now time to build and publish your website. **REMEMBER** to set your environment variables `WEBMENTION_API_KEY` & `WEBMENTION_URL` with your host.
|
|
||||||
|
|
||||||
You can check to see if everything is working by sending a test webmention via [webmentions.rocks](https://webmention.rocks/receive/1). Log in with your domain, enter the auth code, and then the url of the page you want to test. For example, to test this page I would add `http://astrocitrus.artemkutsan.pp.ua/posts/webmentions/`. To view it on your website, rebuild or (re)start dev mode locally, and you should see the result at the bottom of your page.
|
|
||||||
|
|
||||||
You can also view any test mentions in the browser via their [api](https://github.com/aaronpk/webmention.io#api).
|
|
||||||
|
|
||||||
## Things to add, things to consider
|
|
||||||
|
|
||||||
- At the moment, fresh webmentions are only fetched on a rebuild or restarting dev mode, which obviously means if you don't update your site very often you wont get a lot of new content. It should be quite trivial to add a cron job to run the `getAndCacheWebmentions()` function in `src/utils/webmentions.ts` and populate your blog with new content. This is probably what I'll add next as a github action.
|
|
||||||
|
|
||||||
- I have seen some mentions have duplicates. Unfortunately, they're quite difficult to filter out as they have different id's.
|
|
||||||
|
|
||||||
- I'm not a huge fan of the little external link icon for linking to comments/replies. It's not particularly great on mobile due to its size, and will likely change it in the future.
|
|
||||||
|
|
||||||
## Acknowledgements
|
|
||||||
|
|
||||||
Many thanks to [Kieran McGuire](https://github.com/KieranMaguire) for the helpful posts. I'd never heard of webmentions before, and now with this update hopefully others will be able to make use of them. Additionally, articles and examples from [kld](https://kld.dev/adding-webmentions/) and [ryanmulligan.dev](https://ryanmulligan.dev/blog/) really helped in getting this set up and integrated, both a great resource if you're looking for more information!
|
|
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
id: citrus-docs
|
|
||||||
title: "Citrus Docs"
|
|
||||||
description: "Astro Citrus documentation outlines key aspects of the template, describing its core functionality for blog management and project documentation setup"
|
|
||||||
featured: true
|
|
||||||
---
|
|
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
id: markdown-elements
|
|
||||||
title: "Markdown Elements"
|
|
||||||
description: "Dive into a comprehensive guide exploring Markdown syntax and elements, from basic formatting to advanced features, designed to help you master their usage with practical examples for enhancing your documentation and writing efficiency"
|
|
||||||
---
|
|
@@ -2,38 +2,28 @@
|
|||||||
import PageLayout from "@/layouts/Base.astro";
|
import PageLayout from "@/layouts/Base.astro";
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
description: "I'm a starter theme for Astro.build",
|
description: "Sobre Ignacio, Ingeniero de QA especializado en automatización de pruebas.",
|
||||||
title: "About",
|
title: "About",
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<PageLayout meta={meta}>
|
<PageLayout meta={meta}>
|
||||||
|
|
||||||
<h1 class="title mb-6">About</h1>
|
<h1 class="title mb-6">Sobre mí</h1>
|
||||||
<div class="prose prose-citrus max-w-none">
|
<div class="prose prose-citrus max-w-none">
|
||||||
<p>
|
<p>
|
||||||
Hi, I’m a starter Astro. I’m particularly great for getting you started with your own blogging
|
Soy Ignacio, me desempeño como Ingeniero de QA especializado en automatización de pruebas. Desde hace algunos años me dedico a mejorar la calidad del software a través de pruebas eficientes, herramientas bien pensadas y un enfoque ágil.
|
||||||
website.
|
|
||||||
</p>
|
</p>
|
||||||
<p>Here are my some of my awesome built in features:</p>
|
|
||||||
<ul class="list-inside list-disc" role="list">
|
|
||||||
<li>I'm ultra fast as I'm a static site</li>
|
|
||||||
<li>I'm fully responsive</li>
|
|
||||||
<li>I come with a light and dark mode</li>
|
|
||||||
<li>I'm easy to customise and add additional content</li>
|
|
||||||
<li>I have Tailwind CSS styling</li>
|
|
||||||
<li>Shiki code syntax highlighting</li>
|
|
||||||
<li>Satori for auto generating OG images for blog posts</li>
|
|
||||||
</ul>
|
|
||||||
<p>
|
<p>
|
||||||
Clone or fork my <a
|
Este blog es mi espacio para compartir ideas, proyectos y aprendizajes en torno a QA, automatización, buenas prácticas y temas que considero clave para crecer en tecnología.
|
||||||
aria-label="github repository"
|
</p>
|
||||||
class="citrus-link inline-block"
|
<p>
|
||||||
href="https://github.com/artemkutsan/astro-citrus"
|
Más allá del trabajo, disfruto jugar pádel, preparar café como si fuera un experimento, y perderme entre impresiones 3D o historias de ciencia ficción.
|
||||||
rel="noreferrer"
|
</p>
|
||||||
target="_blank">repo</a
|
<p>
|
||||||
> if you like me!
|
¿Estás comenzando en QA, vienes del desarrollo o simplemente te interesa mejorar la calidad de tu software? Entonces este blog también es para ti.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|
||||||
|
@@ -32,10 +32,13 @@ const latestNotes = allNotes.sort(collectionDateSort).slice(0, MAX_NOTES);
|
|||||||
<section class="max-w-xl mx-auto relative flex items-center justify-center h-screen -mt-24">
|
<section class="max-w-xl mx-auto relative flex items-center justify-center h-screen -mt-24">
|
||||||
<div class="w-full text-center">
|
<div class="w-full text-center">
|
||||||
<span class="title text-3xl bg-gradient-to-r from-accent-two/85 via-accent-one/85 to-accent-two/85 dark:from-accent-two dark:via-accent-one dark:to-accent-two bg-clip-text text-transparent">
|
<span class="title text-3xl bg-gradient-to-r from-accent-two/85 via-accent-one/85 to-accent-two/85 dark:from-accent-two dark:via-accent-one dark:to-accent-two bg-clip-text text-transparent">
|
||||||
Introducing Astro Citrus!
|
Hola! Soy Ignacio
|
||||||
</span>
|
</span>
|
||||||
<p class="mt-4 mb-4 text-lg font-medium">
|
<p class="mt-4 mb-4 text-lg font-medium">
|
||||||
Hi, I’m an Astro theme for building websites or blogs. To customize, add posts, or make it yours, click the GitHub icon below to visit my repo.
|
Me dedico al aseguramiento de la calidad del software (QA) en el área de automatización, con conocimientos en desarrollo web.
|
||||||
|
</p>
|
||||||
|
<p class="mt-4 mb-4 text-lg font-medium">
|
||||||
|
Entre mis intereses fuera de la tecnología está disfrutar del café, la lectura y los discos de vinilo.
|
||||||
</p>
|
</p>
|
||||||
<div class="flex justify-center mb-4">
|
<div class="flex justify-center mb-4">
|
||||||
<SocialList />
|
<SocialList />
|
||||||
@@ -43,15 +46,16 @@ const latestNotes = allNotes.sort(collectionDateSort).slice(0, MAX_NOTES);
|
|||||||
<div class="flex justify-center space-x-4 mt-4">
|
<div class="flex justify-center space-x-4 mt-4">
|
||||||
<a href="/posts/" class="relative flex items-center justify-center h-8 px-4 rounded-lg shadow-lg hover:brightness-110 transition-all bg-gradient-to-r from-accent-one to-accent-two">
|
<a href="/posts/" class="relative flex items-center justify-center h-8 px-4 rounded-lg shadow-lg hover:brightness-110 transition-all bg-gradient-to-r from-accent-one to-accent-two">
|
||||||
<span class="text-bgColor font-semibold">
|
<span class="text-bgColor font-semibold">
|
||||||
Read Blog
|
Lee mis publicaciones
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
<!--
|
||||||
<a href="/notes/wake-up/" class="relative flex items-center justify-center h-8 px-4 rounded-lg shadow-lg bg-special-lighter hover:brightness-110 hover:bg-special-lightest">
|
<a href="/notes/wake-up/" class="relative flex items-center justify-center h-8 px-4 rounded-lg shadow-lg bg-special-lighter hover:brightness-110 hover:bg-special-lightest">
|
||||||
<span class="bg-clip-text text-transparent font-semibold bg-gradient-to-r from-accent-one to-accent-two">
|
<span class="bg-clip-text text-transparent font-semibold bg-gradient-to-r from-accent-one to-accent-two">
|
||||||
Wake up
|
Wake up
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -77,7 +81,7 @@ const latestNotes = allNotes.sort(collectionDateSort).slice(0, MAX_NOTES);
|
|||||||
latestNotes.length > 0 && (
|
latestNotes.length > 0 && (
|
||||||
<section class="mt-12">
|
<section class="mt-12">
|
||||||
<h2 class="title mb-6 text-accent-two">
|
<h2 class="title mb-6 text-accent-two">
|
||||||
<a href="/notes/">Notes</a>
|
<a href="/notes/">Notas</a>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
|
||||||
{
|
{
|
||||||
|
@@ -1,11 +1,18 @@
|
|||||||
import type { SiteConfig } from "@/types";
|
import type { SiteConfig } from "@/types";
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
|
// Load environment variables from .env file
|
||||||
|
dotenv.config();
|
||||||
|
const author = process.env.AUTHOR
|
||||||
|
const locale = process.env.LOCALE
|
||||||
|
const desc = process.env.DESCRIPTION
|
||||||
|
|
||||||
export const siteConfig: SiteConfig = {
|
export const siteConfig: SiteConfig = {
|
||||||
// Used as both a meta property (src/components/BaseHead.astro L:31 + L:49) & the generated satori png (src/pages/og-image/[slug].png.ts)
|
// Used as both a meta property (src/components/BaseHead.astro L:31 + L:49) & the generated satori png (src/pages/og-image/[slug].png.ts)
|
||||||
author: "Artem Kutsan",
|
author: author as string,
|
||||||
// Date.prototype.toLocaleDateString() parameters, found in src/utils/date.ts.
|
// Date.prototype.toLocaleDateString() parameters, found in src/utils/date.ts.
|
||||||
date: {
|
date: {
|
||||||
locale: "en-GB",
|
locale: locale as string,
|
||||||
options: {
|
options: {
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
month: "short",
|
month: "short",
|
||||||
@@ -13,13 +20,13 @@ export const siteConfig: SiteConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Used as the default description meta property and webmanifest description
|
// Used as the default description meta property and webmanifest description
|
||||||
description: "An opinionated starter theme for Astro",
|
description: desc as string,
|
||||||
// HTML lang property, found in src/layouts/Base.astro L:18 & astro.config.ts L:48
|
// HTML lang property, found in src/layouts/Base.astro L:18 & astro.config.ts L:48
|
||||||
lang: "en-GB",
|
lang: locale as string,
|
||||||
// Meta property, found in src/components/BaseHead.astro L:42
|
// Meta property, found in src/components/BaseHead.astro L:42
|
||||||
ogLocale: "en_GB",
|
ogLocale: locale as string,
|
||||||
// Used to construct the meta title property found in src/components/BaseHead.astro L:11, and webmanifest name found in astro.config.ts L:42
|
// Used to construct the meta title property found in src/components/BaseHead.astro L:11, and webmanifest name found in astro.config.ts L:42
|
||||||
title: "Citrus",
|
title: author as string,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used to generate links in both the Header & Footer.
|
// Used to generate links in both the Header & Footer.
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
export function truncateTitle(title: string): string {
|
export function truncateTitle(title: string): string {
|
||||||
return title.length > 50 ? `${title.slice(0, 50)}...` : title;
|
return title.length > 60 ? `${title.slice(0, 60)}...` : title;
|
||||||
}
|
}
|