diff --git a/astro.config.mjs b/astro.config.mjs
index 8d42a0a..372ace5 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,7 +1,10 @@
// @ts-check
import { defineConfig } from 'astro/config';
+import expressiveCode from 'astro-expressive-code';
+
// https://astro.build/config
export default defineConfig({
site: 'https://jrdx0.dev',
-});
+ integrations: [expressiveCode()],
+});
\ No newline at end of file
diff --git a/bun.lock b/bun.lock
index de9ad1b..b0b0fb4 100644
--- a/bun.lock
+++ b/bun.lock
@@ -5,8 +5,10 @@
"": {
"name": "jrdx0",
"dependencies": {
+ "jrdx0": ".",
"@fontsource-variable/jetbrains-mono": "^5.2.8",
"astro": "^6.1.7",
+ "astro-expressive-code": "^0.41.7",
},
"devDependencies": {
"prettier": "^3.8.3",
@@ -39,6 +41,8 @@
"@clack/prompts": ["@clack/prompts@1.2.0", "", { "dependencies": { "@clack/core": "1.2.0", "fast-string-width": "^1.1.0", "fast-wrap-ansi": "^0.1.3", "sisteransi": "^1.0.5" } }, "sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w=="],
+ "@ctrl/tinycolor": ["@ctrl/tinycolor@4.2.0", "", {}, "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="],
+
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="],
@@ -93,6 +97,14 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="],
+ "@expressive-code/core": ["@expressive-code/core@0.41.7", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg=="],
+
+ "@expressive-code/plugin-frames": ["@expressive-code/plugin-frames@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA=="],
+
+ "@expressive-code/plugin-shiki": ["@expressive-code/plugin-shiki@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "shiki": "^3.2.2" } }, "sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ=="],
+
+ "@expressive-code/plugin-text-markers": ["@expressive-code/plugin-text-markers@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7" } }, "sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw=="],
+
"@fontsource-variable/jetbrains-mono": ["@fontsource-variable/jetbrains-mono@5.2.8", "", {}, "sha512-WBA9elru6Jdp5df2mES55wuOO0WIrn3kpXnI4+W2ek5u3ZgLS9XS4gmIlcQhiZOWEKl95meYdvK7xI+ETLCq/Q=="],
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
@@ -243,10 +255,14 @@
"astro": ["astro@6.1.7", "", { "dependencies": { "@astrojs/compiler": "^3.0.1", "@astrojs/internal-helpers": "0.8.0", "@astrojs/markdown-remark": "7.1.0", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^1.1.1", "devalue": "^5.6.3", "diff": "^8.0.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.27.3", "flattie": "^1.1.1", "fontace": "~0.4.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.1.1", "magic-string": "^0.30.21", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.3", "rehype": "^13.0.2", "semver": "^7.7.4", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "svgo": "^4.0.1", "tinyclip": "^0.1.12", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unist-util-visit": "^5.1.0", "unstorage": "^1.17.4", "vfile": "^6.0.3", "vite": "^7.3.1", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0" }, "bin": { "astro": "bin/astro.mjs" } }, "sha512-pvZysIUV2C2nRv8N7cXAkCLcfDQz/axAxF09SqiTz1B+xnvbhy6KzL2I6J15ZBXk8k0TfMD75dJ151QyQmAqZA=="],
+ "astro-expressive-code": ["astro-expressive-code@0.41.7", "", { "dependencies": { "rehype-expressive-code": "^0.41.7" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, "sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ=="],
+
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
+ "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="],
+
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
@@ -277,10 +293,14 @@
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
+ "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="],
+
"css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
"css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
+ "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
+
"csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
@@ -301,6 +321,8 @@
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
+ "direction": ["direction@2.0.1", "", { "bin": { "direction": "cli.js" } }, "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA=="],
+
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
@@ -325,6 +347,8 @@
"eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
+ "expressive-code": ["expressive-code@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "@expressive-code/plugin-frames": "^0.41.7", "@expressive-code/plugin-shiki": "^0.41.7", "@expressive-code/plugin-text-markers": "^0.41.7" } }, "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA=="],
+
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
"fast-string-truncated-width": ["fast-string-truncated-width@1.2.1", "", {}, "sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow=="],
@@ -351,16 +375,22 @@
"hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="],
+ "hast-util-has-property": ["hast-util-has-property@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA=="],
+
"hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="],
"hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="],
"hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="],
+ "hast-util-select": ["hast-util-select@6.0.4", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "bcp-47-match": "^2.0.0", "comma-separated-tokens": "^2.0.0", "css-selector-parser": "^3.0.0", "devlop": "^1.0.0", "direction": "^2.0.0", "hast-util-has-property": "^3.0.0", "hast-util-to-string": "^3.0.0", "hast-util-whitespace": "^3.0.0", "nth-check": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw=="],
+
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
"hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="],
+ "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="],
+
"hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="],
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
@@ -383,6 +413,8 @@
"is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="],
+ "jrdx0": ["jrdx0@root:", {}],
+
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
@@ -527,6 +559,10 @@
"postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="],
+ "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
+
+ "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
+
"prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="],
"prettier-plugin-astro": ["prettier-plugin-astro@0.14.1", "", { "dependencies": { "@astrojs/compiler": "^2.9.1", "prettier": "^3.0.0", "sass-formatter": "^0.7.6" } }, "sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw=="],
@@ -547,6 +583,8 @@
"rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="],
+ "rehype-expressive-code": ["rehype-expressive-code@0.41.7", "", { "dependencies": { "expressive-code": "^0.41.7" } }, "sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ=="],
+
"rehype-parse": ["rehype-parse@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag=="],
"rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="],
@@ -645,6 +683,8 @@
"unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="],
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
+
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
@@ -669,6 +709,8 @@
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
+ "@expressive-code/plugin-shiki/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="],
+
"anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
"astro/@astrojs/compiler": ["@astrojs/compiler@3.0.1", "", {}, "sha512-z97oYbdebO5aoWzuJ/8q5hLK232+17KcLZ7cJ8BCWk6+qNzVxn/gftC0KzMBUTD8WAaBkPpNSQK6PXLnNrZ0CA=="],
@@ -677,6 +719,18 @@
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
+ "@expressive-code/plugin-shiki/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="],
+
+ "@expressive-code/plugin-shiki/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="],
+
+ "@expressive-code/plugin-shiki/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="],
+
+ "@expressive-code/plugin-shiki/shiki/@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="],
+
+ "@expressive-code/plugin-shiki/shiki/@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="],
+
+ "@expressive-code/plugin-shiki/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="],
+
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
}
}
diff --git a/package.json b/package.json
index de4a514..a0affc7 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,9 @@
},
"dependencies": {
"@fontsource-variable/jetbrains-mono": "^5.2.8",
- "astro": "^6.1.7"
+ "astro": "^6.1.7",
+ "astro-expressive-code": "^0.41.7",
+ "jrdx0": "."
},
"devDependencies": {
"prettier": "^3.8.3",
diff --git a/src/components/ArticleCard.astro b/src/components/ArticleCard.astro
new file mode 100644
index 0000000..d5f6334
--- /dev/null
+++ b/src/components/ArticleCard.astro
@@ -0,0 +1,52 @@
+---
+import { formatDate } from '@/utils';
+
+interface Props {
+ id: string;
+ title: string;
+ description: string;
+ pubDate: Date;
+}
+
+const { id, title, description, pubDate } = Astro.props;
+const pubDateFmt = formatDate(pubDate);
+---
+
+
+
+
{title}
+
{description}
+
+ {pubDateFmt}
+
+
+
diff --git a/src/components/Header.astro b/src/components/Header.astro
new file mode 100644
index 0000000..e4e01d8
--- /dev/null
+++ b/src/components/Header.astro
@@ -0,0 +1,67 @@
+---
+import { Image } from 'astro:assets';
+
+import profileImg from '@/assets/profile-picture.jpg';
+
+const githubLink = 'https://github.com/jrdx0';
+const workLink = 'https://walcu.com';
+---
+
+
+
+
+
+
Status: Working at Walcu
+
+
+
+
diff --git a/src/components/LatestArticle.astro b/src/components/LatestArticle.astro
new file mode 100644
index 0000000..33e0e9d
--- /dev/null
+++ b/src/components/LatestArticle.astro
@@ -0,0 +1,45 @@
+---
+interface Props {
+ id: string;
+ title: string;
+ description: string;
+}
+
+const { id, title, description } = Astro.props;
+---
+
+
+
+
diff --git a/src/content.config.ts b/src/content.config.ts
new file mode 100644
index 0000000..34ea1cd
--- /dev/null
+++ b/src/content.config.ts
@@ -0,0 +1,14 @@
+import { defineCollection } from 'astro:content';
+import { glob } from 'astro/loaders';
+import { z } from 'astro/zod';
+
+const blog = defineCollection({
+ loader: glob({ base: './src/content/blog', pattern: '**/*.md' }),
+ schema: z.object({
+ title: z.string(),
+ description: z.string(),
+ pubDate: z.coerce.date(),
+ }),
+});
+
+export const collections = { blog };
diff --git a/src/content/blog/fix-cosmic-flameshot-tray-icon.md b/src/content/blog/fix-cosmic-flameshot-tray-icon.md
new file mode 100644
index 0000000..e50cec3
--- /dev/null
+++ b/src/content/blog/fix-cosmic-flameshot-tray-icon.md
@@ -0,0 +1,151 @@
+---
+title: 'Flameshot: Arreglar icono del tray en COSMIC DE'
+description: 'Si eres usuario de COSMIC DE y de Flameshot es posible que te hayas encontrado con un problema que, pese a no afectar directamente al funcionamiento de la aplicación ni al sistema operativo como tal, puede llegar a ser incómodo para la vista. El icono de Flameshot no se muestra correctamente en el panel superior de COSMIC. En esta guía podrás encontrar la solución que me ha funcionado para corregir dicho error.'
+pubDate: '2026-04-19'
+---
+
+> Si quieres ir directo a la guía paso a paso para solucionar el error, [haz clic aquí](#solución-guía-paso-a-paso). Si quieren saber más sobre el contexto, sigan leyendo.
+
+Si bien no es un problema que afecte de forma critica al sistema operativo o al funcionamiento de mi equipo, era imposible evitar mirar ese icono gris horrible. Desentonaba mucho. Así que un fin de semana me senté a intentar solucionar el problema. Fueron dos días de investigar cómo hacer que COSMIC mostrara correctamente el icono que debía mostrar, y después de varias pestañas del navegador abiertas, pláticas extensas con CLAUDE y cuestionarme en repetidas ocasiones si de verdad valía el tiempo y esfuerzo; lo pude lograr.
+
+## ¿Qué sucedía?
+
+Por temas de compatibilidad tuve que instalar Flameshot desde la COSMIC Store, la cual hace uso de Flatpak para realizar las instalaciones de las aplicaciones. Hasta el día de hoy no es posible la instalación de Flameshot por `apt`.
+
+Es con Flatpak donde surge el error de no mostrar correctamente el icono en el tray (panel superior de COSMIC), ya que Flatpak no exporta correctamente dicho icono por defecto. La solución consiste en crear un symlink al icono correcto dentro de una carpeta donde COSMIC sí pueda encontrarlo.
+
+## Solución: Guía paso a paso
+
+Los primeros 4 pasos nos ayudarán a localizar el nombre que el tray de COSMIC espera encontrar y donde se encuentra el archivo original dentro de la instalación de Flameshot.
+
+### 1. Verificar que Flameshot está registrado en el tray
+
+Antes que nada debemos tener Flameshot corriendo en nuestra tray (si vemos el icono feo del engrane y al darle clic se nos abre la GUI para hacer capturas de pantalla, vamos bien. Por lo tanto hay que verificar que Flameshot se ha registrado en los whatchers de COSMIC.
+
+```bash
+busctl --user get-property org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems
+```
+
+Al ejecutar dicho comando esperamos obtener una lista de bus names. En mi caso:
+
+```
+NotifierItems
+as 3 ":1.149" ":1.151" ":1.159"
+```
+
+Si en tu caso no aparece la información deseada, lo siento pero los siguientes pasos no funcionarán. Puede que tu problema no sea tema de los iconos.
+
+### 2. Localizar el objeto D-Bus de Flameshot
+
+[D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) en Linux es un sistema de mensajería. Básicamente, al ejecutar Flameshot, éste se conecta a un D-Bus para exponer un objeto que le dirá al tray de COSMIC dónde puede encontrar los recursos para mostrarse correctamente en el panel.
+
+Vamos a enlistar aquellos que estén relacionados con flameshot con el siguiente comando:
+
+```bash
+busctl --user list | grep -i flameshot
+```
+
+El comando imprimirá una lista de bus names de la forma `:1.XXX` correspondientes a Flameshot:
+
+```
+:1.124 5248 flameshot userName :1.124 user@1000.service - -
+:1.149 5248 flameshot userName :1.149 user@1000.service - -
+org.flameshot.Flameshot 5248 flameshot userName :1.124 user@1000.service - -
+```
+
+Ahora inspeccionaremos su árbol de objetos para confirmar que `/StatusNotifierItem` existe:
+
+```bash
+busctl --user tree :1.149 # sustituye :1.149 por tu bus name
+```
+
+Si todo sale bien, podremos confirmar la existencia de `/StatusNotifierItem` por el siguiente output:
+
+```
+├─ /MenuBar
+└─ /StatusNotifierItem
+```
+
+### 3. Obtener el valor de IconName que anuncia Flameshot
+
+Aquí empieza la parte importante. Es necesario saber el nombre real del icono que Flameshot anuncia. Este paso es sumamente importante pues utilizaremos dicho valor para crear el icono nosotros mismos. Recuerden sustituir el valor del bus name por el que hayan obtenido en el [paso 2](#2-localizar-el-objeto-d-bus-de-flameshot):
+
+```bash
+busctl --user get-property :1.149 /StatusNotifierItem org.kde.StatusNotifierItem IconName
+```
+
+Obtendremos un output anunciando el verdadero nombre del icono:
+
+```
+s "flameshot-tray"
+```
+
+¡Perfecto! Ya tenemos todo para empezar a solucionar el problema.
+
+### 4. Localizar el SVG correcto dentro de Flatpak
+
+Como dije en un principio, por alguna extraña razón Flatpak no expone el icono correcto para que COSMIC lo muestre en el panel superior. Es necesario que lo localicemos nosotros mismos dentro de los archivos de instalación.
+
+Para ello hay que localizar la carpeta donde Flatpak gestiona todos sus archivos, en mi caso: `~/.local/share/flatpak`. Ahora es momento de buscar el nombre del icono que no se exporta correctamente:
+
+```bash
+find ~/.local/share/flatpak -name "*flameshot-tray*" 2>/dev/null
+```
+
+El comando `find` enlistará todos los archivos cuyo nombre tenga `flameshot-tray` sin importar el contenido antes y después de dicho nombre. Se enlistarán las rutas de los archivos encontrados:
+
+```
+~/.local/share/flatpak/runtime/org.kde.Platform/x86_64/6.9//files/share/icons/breeze/status/22/flameshot-tray.svg
+~/.local/share/flatpak/runtime/org.kde.Platform/x86_64/6.9//files/share/icons/breeze/status/22/flameshot-tray-symbolic.svg
+```
+
+La ruta que se te muestra puede ser más larga debido a que he acortado el valor para el hash de la carpeta con ``. Si somos más curiosos podremos observar que en la carpeta `~/.local/share/flatpak/runtime/org.kde.Platform/x86_64/6.9/` podremos encontrar un symlink que apunta al directorio del ``. Esto nos puede ayudar para mantener algo de persistencia en caso de que el `hash` llegue a cambiar. Puedes confirmar esto ejecutando (recuerda cambiar la ruta para tu caso):
+
+```bash
+ls -l ~/.local/share/flatpak/runtime/org.kde.Platform/x86_64/6.9/
+```
+
+Obtendremos algo como lo siguiente, donde el symlink que nos interesa se llama `active`:
+
+```
+lrwxrwxrwx 1 userName userName 64 Feb 26 16:42 active ->
+drwxr-xr-x 3 userName userName 4096 Feb 26 16:42
+```
+
+### 5. Crear un symlink donde COSMIC pueda encontrarlo
+
+Ahora toca crear un symlink al archivo que encontramos en el [paso anterior](#4-localizar-el-svg-correcto-dentro-de-flatpak). Un lugar en el que es visible y no es necesario entrar en demasiados directorios es la ruta `~/.local/share/icons/hicolor`. Navegando a dicha carpeta encontraremos diferentes directorios que agrupan los iconos según su tamaño. Al tratarse de un SVG, podemos agregar el icono de Flameshot dentro del directorio `scalable`. Dentro del mismo habrá que crear una carpeta llamada `status`:
+
+```bash
+mkdir -p ~/.local/share/icons/hicolor/scalable/status
+```
+
+Posteriormente crearemos la referencia al archivo original con ayuda de un symlink:
+
+```bash
+ln -sf \
+ ~/.local/share/flatpak/runtime/org.kde.Platform/x86_64/6.9/active/files/share/icons/breeze/status/22/flameshot-tray.svg \
+ ~/.local/share/icons/hicolor/scalable/status/flameshot-tray.svg
+```
+
+Listo. Problema solucionado. Solo queda recargar el caché de iconos y comprobar que todo ha funcionado.
+
+### 6. Reconstruir el caché y reiniciar el panel
+
+Pese a que los archivos se encuentran en el lugar correcto, aún no se deberían de mostrar en el panel. COSMIC cachea los iconos, por lo que es necesario recargar dicho caché para que obtenga el que hemos creado nosotros mismos. Para ello es necesario ejecutar el siguiente comando:
+
+```bash
+gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor
+```
+
+Finalmente hay que reiniciar el panel para comprobar si todo ha salido bien. Para no tener que reiniciar la computadora entera, basta con matar el proceso del panel y COSMIC lo arrancará de manera automática por nosotros:
+
+```bash
+pkill cosmic-panel
+```
+
+Ahora deberíamos dejar de ver el icono del engrane gris y mirar el icono correspondiente de flameshot.
+
+### Conclusión
+
+Es lo que tiene Linux: a veces solucionar un problema menor requiere más investigación de la esperada, pero la gratificación que produce lograrlo lo vale. Espero que esta guía le haya sido de utilidad a alguien.
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
new file mode 100644
index 0000000..fe826da
--- /dev/null
+++ b/src/layouts/BaseLayout.astro
@@ -0,0 +1,24 @@
+---
+// Supports weights 100-800
+import '@fontsource-variable/jetbrains-mono/wght.css';
+
+import '@/styles/global.css';
+
+interface Props {
+ title?: string;
+}
+
+const { title = 'Jared' } = Astro.props;
+---
+
+
+
+
+
+
+ {title}
+
+
+
+
+
diff --git a/src/layouts/PostLayout.astro b/src/layouts/PostLayout.astro
new file mode 100644
index 0000000..f496f58
--- /dev/null
+++ b/src/layouts/PostLayout.astro
@@ -0,0 +1,154 @@
+---
+// Supports weights 100-800
+import '@fontsource-variable/jetbrains-mono/wght.css';
+
+import '@/styles/global.css';
+
+import Header from '@/components/Header.astro';
+
+interface Props {
+ title: string;
+ description: string;
+ pubDate: Date;
+}
+
+const { title, description, pubDate } = Astro.props;
+
+const pageTitle = `${title} — jrdx0`;
+const pubDateISO = pubDate.toISOString();
+---
+
+
+
+
+
+
+ {pageTitle}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 7347e1f..dd8bc21 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,101 +1,72 @@
---
-// Supports weights 100-800
-import '@fontsource-variable/jetbrains-mono/wght.css';
+import { getCollection } from 'astro:content';
-import '@/styles/global.css';
+import BaseLayout from '@/layouts/BaseLayout.astro';
+import ArticleCard from '@/components/ArticleCard.astro';
+import Header from '@/components/Header.astro';
+import LatestArticle from '@/components/LatestArticle.astro';
-import { Image } from 'astro:assets';
+const allPosts = await getCollection('blog');
+const posts = allPosts.sort(
+ (a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime()
+);
-import profileImg from '@/assets/profile-picture.jpg';
-
-const githubLink = 'https://github.com/jrdx0';
-const workLink = 'https://walcu.com';
+const [latest, ...articles] = posts;
---
-
-
-
-
-
- jrdx0
-
-
-
-
+
+
-
-
-
- Status: Working at
-
- Walcu
-
-
-
-
-
-
-
-
+ {
+ latest && (
+
+ )
+ }
+
+ {
+ articles.length > 0 && (
+
+ Más artículos
+
+ {articles.map(({ id, data }) => (
+ -
+
+
+ ))}
+
+
+
+ )
+ }
+
diff --git a/src/pages/posts/[id].astro b/src/pages/posts/[id].astro
new file mode 100644
index 0000000..84b9bb1
--- /dev/null
+++ b/src/pages/posts/[id].astro
@@ -0,0 +1,25 @@
+---
+import { getCollection, render } from 'astro:content';
+
+import PostLayout from '@/layouts/PostLayout.astro';
+
+export async function getStaticPaths() {
+ const posts = await getCollection('blog');
+
+ return posts.map((post) => ({
+ params: { id: post.id },
+ props: { post },
+ }));
+}
+
+const { post } = Astro.props;
+const { Content } = await render(post);
+---
+
+
+
+
diff --git a/src/styles/global.css b/src/styles/global.css
index fc291c5..4343488 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -1,19 +1,39 @@
-html {
- background-color: #141414;
+:root {
+ --bg: #1d1f1d;
+ --bg-alt: #3c3e39;
+ --border: rgba(236, 223, 200, 0.09);
+ --border-strong: rgba(236, 223, 200, 0.18);
+ --fg: #ecdfc8;
+ --fg-dim: rgba(236, 223, 200, 0.62);
+ --fg-muted: rgba(236, 223, 200, 0.38);
+ --accent: #6f7d68;
+}
+
+* {
margin: 0;
padding: 0;
}
+html {
+ background-color: var(--bg);
+}
+
body {
+ color: var(--fg);
font-family: 'JetBrains Mono Variable', monospace;
+ font-size: 0.9rem;
+ line-height: 1.55;
margin: 0 auto;
- max-width: 900px;
- padding-top: 1rem;
+ max-width: 60rem;
+ padding: 2.5rem 3.5rem;
+}
+
+a {
+ color: var(--accent);
}
@media (max-width: 900px) {
body {
- padding: 1rem 1rem 0 1rem;
+ padding: 1rem;
}
}
-
diff --git a/src/utils/formatDate.utils.ts b/src/utils/formatDate.utils.ts
new file mode 100644
index 0000000..583f88e
--- /dev/null
+++ b/src/utils/formatDate.utils.ts
@@ -0,0 +1,9 @@
+export function formatDate(date: Date): string {
+ return new Intl.DateTimeFormat('es-MX', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric',
+ })
+ .format(date)
+ .replace(/\//g, '·');
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..cb325c9
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1 @@
+export { formatDate } from './formatDate.utils';
diff --git a/tsconfig.json b/tsconfig.json
index 990abae..2c19484 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,6 +6,8 @@
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
- }
+ },
+ "strictNullChecks": true,
+ "allowJs": true
}
}