~repos /website

#astro#js#html#css

git clone https://pyrossh.dev/repos/website.git

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


0227637b pyrossh

2 weeks ago
update file icons
bun.lock CHANGED
@@ -21,11 +21,13 @@
21
21
  "@aws-sdk/client-sts": "^3.932.0",
22
22
  "@iconify-json/material-symbols": "^1.2.39",
23
23
  "@iconify-json/mdi": "^1.2.3",
24
+ "@iconify-json/vscode-icons": "^1.2.36",
24
25
  "@playwright/test": "^1.52.0",
25
26
  "@tauri-apps/cli": "^2.9.1",
26
27
  "@types/bun": "^1.3.2",
27
28
  "alchemy": "^0.77.5",
28
29
  "diff2html": "^3.4.52",
30
+ "vscode-icons": "https://github.com/vscode-icons/vscode-icons.git",
29
31
  },
30
32
  },
31
33
  },
@@ -232,6 +234,8 @@
232
234
 
233
235
  "@iconify-json/mdi": ["@iconify-json/mdi@1.2.3", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg=="],
234
236
 
237
+ "@iconify-json/vscode-icons": ["@iconify-json/vscode-icons@1.2.36", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-hs17ocmWK5pGnF5KgFRgHBZVRnMVAIpwPDDvLWSwRiM/uHwIS0Jo0y93DvcHXEsP+d3sqogTGhgkgj3on3eabQ=="],
238
+
235
239
  "@iconify/tools": ["@iconify/tools@4.1.3", "", { "dependencies": { "@iconify/types": "^2.0.0", "@iconify/utils": "^2.3.0", "@types/tar": "^6.1.13", "axios": "^1.12.1", "cheerio": "1.0.0", "domhandler": "^5.0.3", "extract-zip": "^2.0.1", "local-pkg": "^0.5.1", "pathe": "^1.1.2", "svgo": "^3.3.2", "tar": "^6.2.1" } }, "sha512-guPw9jvkrCCGFUvPr+NgUcQIpQcIll38NQzUzrEMK/1vrDmeJ9jstsp/Dx5LIP2na9BUBLHKOKXA6cERTpnGFw=="],
236
240
 
237
241
  "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
@@ -276,6 +280,12 @@
276
280
 
277
281
  "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
278
282
 
283
+ "@inversifyjs/common": ["@inversifyjs/common@1.4.0", "", {}, "sha512-qfRJ/3iOlCL/VfJq8+4o5X4oA14cZSBbpAmHsYj8EsIit1xDndoOl0xKOyglKtQD4u4gdNVxMHx4RWARk/I4QA=="],
284
+
285
+ "@inversifyjs/core": ["@inversifyjs/core@1.3.5", "", { "dependencies": { "@inversifyjs/common": "1.4.0", "@inversifyjs/reflect-metadata-utils": "0.2.4" } }, "sha512-B4MFXabhNTAmrfgB+yeD6wd/GIvmvWC6IQ8Rh/j2C3Ix69kmqwz9pr8Jt3E+Nho9aEHOQCZaGmrALgtqRd+oEQ=="],
286
+
287
+ "@inversifyjs/reflect-metadata-utils": ["@inversifyjs/reflect-metadata-utils@0.2.4", "", { "peerDependencies": { "reflect-metadata": "0.2.2" } }, "sha512-u95rV3lKfG+NT2Uy/5vNzoDujos8vN8O18SSA5UyhxsGYd4GLQn/eUsGXfOsfa7m34eKrDelTKRUX1m/BcNX5w=="],
288
+
279
289
  "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
280
290
 
281
291
  "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
@@ -898,11 +908,13 @@
898
908
 
899
909
  "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
900
910
 
911
+ "inversify": ["inversify@6.2.2", "", { "dependencies": { "@inversifyjs/common": "1.4.0", "@inversifyjs/core": "1.3.5" }, "peerDependencies": { "reflect-metadata": "~0.2.2" } }, "sha512-KB836KHbZ9WrUnB8ax5MtadOwnqQYa+ZJO3KWbPFgcr4RIEnHM621VaqFZzOZd9+U7ln6upt9n0wJei7x2BNqw=="],
912
+
901
913
  "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
902
914
 
903
915
  "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
904
916
 
905
- "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
917
+ "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
906
918
 
907
919
  "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
908
920
 
@@ -914,7 +926,7 @@
914
926
 
915
927
  "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
916
928
 
917
- "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
929
+ "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
918
930
 
919
931
  "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
920
932
 
@@ -938,6 +950,8 @@
938
950
 
939
951
  "local-pkg": ["local-pkg@0.5.1", "", { "dependencies": { "mlly": "^1.7.3", "pkg-types": "^1.2.1" } }, "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ=="],
940
952
 
953
+ "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
954
+
941
955
  "loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="],
942
956
 
943
957
  "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
@@ -1168,6 +1182,8 @@
1168
1182
 
1169
1183
  "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
1170
1184
 
1185
+ "reflect-metadata": ["reflect-metadata@0.1.14", "", {}, "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A=="],
1186
+
1171
1187
  "regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="],
1172
1188
 
1173
1189
  "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
@@ -1348,6 +1364,8 @@
1348
1364
 
1349
1365
  "vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="],
1350
1366
 
1367
+ "vscode-icons": ["vscode-icons@github:vscode-icons/vscode-icons#a0df042", { "dependencies": { "inversify": "^6.0.1", "lodash": "^4.17.21", "open": "^8.4.2", "reflect-metadata": "^0.1.13", "semver": "^7.5.4" } }, "vscode-icons-vscode-icons-a0df042"],
1368
+
1351
1369
  "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
1352
1370
 
1353
1371
  "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
@@ -1410,6 +1428,10 @@
1410
1428
 
1411
1429
  "@antfu/install-pkg/tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
1412
1430
 
1431
+ "@astrojs/telemetry/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
1432
+
1433
+ "@astrojs/telemetry/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
1434
+
1413
1435
  "@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
1414
1436
 
1415
1437
  "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
@@ -1468,6 +1490,8 @@
1468
1490
 
1469
1491
  "htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
1470
1492
 
1493
+ "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
1494
+
1471
1495
  "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
1472
1496
 
1473
1497
  "miniflare/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
@@ -1506,6 +1530,8 @@
1506
1530
 
1507
1531
  "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
1508
1532
 
1533
+ "vscode-icons/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
1534
+
1509
1535
  "wrangler/@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.10", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "^1.20251106.1" }, "optionalPeers": ["workerd"] }, "sha512-mvsNAiJSduC/9yxv1ZpCxwgAXgcuoDvkl8yaHjxoLpFxXy2ugc6TZK20EKgv4yO0vZhAEKwqJm+eGOzf8Oc45w=="],
1510
1536
 
1511
1537
  "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="],
@@ -1522,6 +1548,8 @@
1522
1548
 
1523
1549
  "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
1524
1550
 
1551
+ "wsl-utils/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
1552
+
1525
1553
  "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
1526
1554
 
1527
1555
  "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
@@ -1548,6 +1576,8 @@
1548
1576
 
1549
1577
  "svgo/css-tree/mdn-data": ["mdn-data@2.0.30", "", {}, "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="],
1550
1578
 
1579
+ "vscode-icons/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
1580
+
1551
1581
  "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="],
1552
1582
 
1553
1583
  "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="],
package.json CHANGED
@@ -28,16 +28,18 @@
28
28
  "timeago.js": "^4.0.2"
29
29
  },
30
30
  "devDependencies": {
31
- "@types/bun": "^1.3.2",
32
31
  "@astrojs/rss": "^4.0.12",
33
32
  "@astrojs/sitemap": "^3.4.1",
34
33
  "@aws-sdk/client-s3": "^3.932.0",
35
34
  "@aws-sdk/client-sts": "^3.932.0",
36
35
  "@iconify-json/material-symbols": "^1.2.39",
37
36
  "@iconify-json/mdi": "^1.2.3",
37
+ "@iconify-json/vscode-icons": "^1.2.36",
38
38
  "@playwright/test": "^1.52.0",
39
39
  "@tauri-apps/cli": "^2.9.1",
40
+ "@types/bun": "^1.3.2",
40
41
  "alchemy": "^0.77.5",
41
- "diff2html": "^3.4.52"
42
+ "diff2html": "^3.4.52",
43
+ "vscode-icons": "https://github.com/vscode-icons/vscode-icons.git"
42
44
  }
43
45
  }
src/components/RecursiveList.astro CHANGED
@@ -1,15 +1,17 @@
1
1
  ---
2
2
  import { Icon } from "astro-icon/components";
3
+ import allIcons from "@iconify-json/vscode-icons/icons.json" assert { type: "json" };
3
4
  import prettyBytes from "pretty-bytes";
5
+ import { resolveFileIcon } from "@/utils/files";
4
6
 
5
7
  interface FileNode {
6
8
  name: string;
7
9
  path: string;
8
10
  isDirectory: boolean;
11
+ size: number;
12
+ ext: string;
13
+ absolutePath: string;
9
14
  children?: FileNode[];
10
- size?: number;
11
- ext?: string;
12
- absolutePath?: string;
13
15
  }
14
16
 
15
17
  interface Props {
@@ -46,11 +48,19 @@ const { items, repoId, depth = 0 } = Astro.props;
46
48
  </li>
47
49
  );
48
50
  } else {
51
+ const iconName = resolveFileIcon(item.name, item.ext);
52
+ const fileType = allIcons.icons[`file-type-${iconName}`]
53
+ ? `file-type-${iconName}`
54
+ : "default-file";
49
55
  return (
50
56
  <li class="file" style={`padding-left: ${depth * 1}rem;`}>
51
57
  <div class="file-content">
52
58
  <div class="file-name">
59
+ <Icon
60
+ name={`vscode-icons:${fileType}`}
61
+ size="24px"
53
- <Icon name="mdi:file" size="24px" color="hsl(0deg 75% 75%)" />
62
+ color="hsl(0deg 75% 75%)"
63
+ />
54
64
  <a href={`/repos/${repoId}/files/${item.path}`} rel="nofollow">
55
65
  {item.name}
56
66
  </a>
src/layouts/FileLayout.astro CHANGED
@@ -1,8 +1,9 @@
1
1
  ---
2
2
  import { Icon } from "astro-icon/components";
3
3
  import { type CollectionEntry } from "astro:content";
4
+ import allIcons from "@iconify-json/vscode-icons/icons.json" assert { type: "json" };
4
5
  import RepoLayout from "@/layouts/RepoLayout.astro";
5
- import type { FileNode } from "@/utils/files";
6
+ import { resolveFileIcon, type FileNode } from "@/utils/files";
6
7
 
7
8
  type Props = {
8
9
  repo: CollectionEntry<"repos">;
@@ -11,6 +12,10 @@ type Props = {
11
12
 
12
13
  const { repo, file } = Astro.props;
13
14
  const { pathname } = Astro.url;
15
+ const iconName = resolveFileIcon(file.name, file.ext);
16
+ const fileType = allIcons.icons[`file-type-${iconName}`]
17
+ ? `file-type-${iconName}`
18
+ : "default-file";
14
19
  ---
15
20
 
16
21
  <RepoLayout repo={repo}>
@@ -19,8 +24,11 @@ const { pathname } = Astro.url;
19
24
  <div>
20
25
  <hr />
21
26
  <div class="title">
27
+ <Icon
28
+ name={`vscode-icons:${fileType}`}
29
+ size="24px"
22
- <span>file:</span>
30
+ color="hsl(0deg 75% 75%)"
23
- <Icon name="mdi:file" size="24px" color="hsl(0deg 75% 75%)" />
31
+ />
24
32
  <h3>{file.name}</h3>
25
33
  </div>
26
34
  <hr />
@@ -106,11 +114,9 @@ const { pathname } = Astro.url;
106
114
  font-size: 1.1rem;
107
115
  font-weight: 500;
108
116
  }
117
+
109
- span {
118
+ svg[data-icon] {
110
119
  font-weight: 600;
111
120
  margin-right: 4px;
112
121
  }
113
- h3 {
114
- text-decoration: underline;
115
- }
116
122
  </style>
src/pages/repos/[...repoId]/files/[...file]/index.astro CHANGED
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  import fs from "fs/promises";
3
- import path from "path";
4
3
  import { type CollectionEntry, getCollection } from "astro:content";
5
4
  import { Code } from "astro-expressive-code/components";
6
5
  import FileLayout from "@/layouts/FileLayout.astro";
@@ -12,15 +11,15 @@ export async function getStaticPaths() {
12
11
  const routes = [];
13
12
  for (const repo of repos) {
14
13
  const files = await getFiles(repo.data.absolutePath);
14
+ for (const file of files) {
15
- routes.push(
15
+ routes.push({
16
- ...files.map((file) => ( {
17
16
  params: { repoId: repo.id, file: file.name },
18
17
  props: {
19
18
  repo: repo,
20
19
  file: file,
21
20
  },
22
- }))
21
+ });
23
- );
22
+ }
24
23
  }
25
24
  return routes;
26
25
  }
@@ -32,8 +31,7 @@ type Props = {
32
31
 
33
32
  const { repo, file } = Astro.props;
34
33
  const contentBuffer = await fs.readFile(file.absolutePath);
35
- const ext = path.extname(file.name).replace(".", "");
36
- const isBinary = ["apk", "dex", "ap_", "jar", "fnt"].includes(ext);
34
+ const isBinary = ["apk", "dex", "ap_", "jar", "fnt"].includes(file.ext);
37
35
  const isLarge = file.size > 1024 * 512; // 512KB
38
36
  const isImage = [
39
37
  "png",
@@ -46,7 +44,7 @@ const isImage = [
46
44
  "icns",
47
45
  "curve",
48
46
  "atlas",
49
- ].includes(ext);
47
+ ].includes(file.ext);
50
48
  ---
51
49
 
52
50
  <FileLayout repo={repo} file={file}>
@@ -56,7 +54,7 @@ const isImage = [
56
54
  <p>The file is too large to be displayed ({file.size} bytes).</p>
57
55
  ) : isImage ? (
58
56
  <img
59
- src={`data:image/${ext};base64,${Buffer.from(contentBuffer).toString("base64")}`}
57
+ src={`data:image/${file.ext};base64,${Buffer.from(contentBuffer).toString("base64")}`}
60
58
  alt={file.path}
61
59
  />
62
60
  ) : (
@@ -65,10 +63,10 @@ const isImage = [
65
63
  Buffer.from(contentBuffer).toString("utf-8") ||
66
64
  "No content to display."
67
65
  }
68
- lang={ext || "txt"}
66
+ lang={file.ext || "txt"}
69
67
  wrap
70
68
  />
71
69
  )
72
70
  }
73
71
  </div>
74
- </FileLayout>
72
+ </FileLayout>
src/utils/commit.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import Diff2html from "diff2html";
2
2
  import fs from "fs/promises";
3
+ import path from "path";
3
4
  import { simpleGit } from "simple-git";
4
5
  import { type FileNode } from "./files";
5
6
 
@@ -38,10 +39,13 @@ export const getFiles = async (repoPath: string): Promise<FileNode[]> => {
38
39
  for (const p of paths.split("\n").filter((p) => p.length > 0)) {
39
40
  try {
40
41
  const stat = await fs.stat(`${repoPath}/${p}`);
42
+ const ext = path.extname(p).replace(".", "");
41
43
  files.push({
42
44
  name: p,
45
+ ext,
46
+ size: stat.size,
47
+ isDirectory: stat.isDirectory(),
43
48
  absolutePath: `${repoPath}/${p}`,
44
- ...stat,
45
49
  })
46
50
  } catch (e) {
47
51
  // Ignore files not found
src/utils/files.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import fs from "fs/promises";
2
+ import { extensions as folderExtensions } from "vscode-icons/src/iconsManifest/supportedFolders.ts";
3
+ import { extensions as fileExtensions } from "vscode-icons/src/iconsManifest/supportedExtensions.ts";
2
4
 
3
5
  export interface FileNode {
4
6
  name: string;
@@ -73,4 +75,34 @@ export const checkFileExists = async (filePath: string) => {
73
75
  } catch (error) {
74
76
  return false; // File does not exist or cannot be accessed
75
77
  }
76
- }
78
+ }
79
+
80
+ export const resolveFolderIcon = (foldername: string) => {
81
+ for (const item of folderExtensions.supported) {
82
+ if (item.extensions?.includes(foldername)) {
83
+ return item.icon;
84
+ }
85
+ }
86
+ return folderExtensions.default.folder?.icon;
87
+ }
88
+
89
+ export const resolveFileIcon = (filename: string, fileExt: string) => {
90
+ for (const item of fileExtensions.supported) {
91
+ if (item.filename && item.extensions?.includes(filename)) {
92
+ return item.icon;
93
+ }
94
+ }
95
+ for (const item of fileExtensions.supported) {
96
+ if (item.extensions?.includes(fileExt)) {
97
+ return item.icon;
98
+ }
99
+ for (const lang of item.languages ?? []) {
100
+ if (lang?.knownExtensions?.includes(fileExt)) {
101
+ return item.icon;
102
+ }
103
+ }
104
+ }
105
+ return fileExtensions.default.file?.icon;
106
+ }
107
+
108
+ console.log(resolveFileIcon('examples/public/index.html', 'html'));