Compare commits

..

No commits in common. "8314c2e48df978c1e55fa6e93e6f938917ba3da8" and "3a82e64901ca3eb84881af8a612b8f52767e1327" have entirely different histories.

28 changed files with 613 additions and 1400 deletions

569
Cargo.lock generated
View file

@ -38,55 +38,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -106,45 +57,18 @@ dependencies = [
"unscanny", "unscanny",
] ]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.15.4" version = "3.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]] [[package]]
name = "camino" name = "camino"
version = "1.1.6" version = "1.1.6"
@ -174,7 +98,7 @@ dependencies = [
"js-sys", "js-sys",
"num-traits", "num-traits",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.4", "windows-targets",
] ]
[[package]] [[package]]
@ -214,58 +138,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim 0.11.1",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.53",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]] [[package]]
name = "codemap" name = "codemap"
version = "0.1.3" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24" checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24"
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]] [[package]]
name = "copy_dir" name = "copy_dir"
version = "0.1.3" version = "0.1.3"
@ -281,46 +159,12 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]] [[package]]
name = "crunchy" name = "crunchy"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.14.4" version = "0.14.4"
@ -341,7 +185,7 @@ dependencies = [
"ident_case", "ident_case",
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim 0.10.0", "strsim",
"syn 1.0.109", "syn 1.0.109",
] ]
@ -356,12 +200,6 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "data-encoding"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]] [[package]]
name = "derive_builder" name = "derive_builder"
version = "0.12.0" version = "0.12.0"
@ -393,16 +231,6 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]] [[package]]
name = "displaydoc" name = "displaydoc"
version = "0.2.4" version = "0.2.4"
@ -435,18 +263,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "filetime"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -462,25 +278,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getopts" name = "getopts"
version = "0.2.21" version = "0.2.21"
@ -593,12 +390,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "html-escape" name = "html-escape"
version = "0.2.13" version = "0.2.13"
@ -608,23 +399,6 @@ dependencies = [
"utf8-width", "utf8-width",
] ]
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]] [[package]]
name = "hypertext" name = "hypertext"
version = "0.5.0" version = "0.5.0"
@ -701,32 +475,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags 1.3.2",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -764,26 +512,6 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "kqueue"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]] [[package]]
name = "lasso" name = "lasso"
version = "0.7.2" version = "0.7.2"
@ -834,45 +562,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]] [[package]]
name = "mio" name = "npezza93-tree-sitter-haskell"
version = "0.8.11" version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" checksum = "cd44dfc09a37bafbed1c28622c662be9b8fb1aaaad0444688370eae11e3d54b0"
dependencies = [ dependencies = [
"libc", "cc",
"log", "tree-sitter",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "notify"
version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [
"bitflags 2.5.0",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"log",
"mio",
"walkdir",
"windows-sys 0.48.0",
]
[[package]]
name = "notify-debouncer-mini"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43"
dependencies = [
"crossbeam-channel",
"log",
"notify",
] ]
[[package]] [[package]]
@ -1005,7 +701,7 @@ name = "pulldown-cmark"
version = "0.10.0" version = "0.10.0"
source = "git+https://github.com/pulldown-cmark/pulldown-cmark.git?branch=branch_0.11#2540d4095d5f94fd972c93b927e9bec83b0c5079" source = "git+https://github.com/pulldown-cmark/pulldown-cmark.git?branch=branch_0.11#2540d4095d5f94fd972c93b927e9bec83b0c5079"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags",
"getopts", "getopts",
"memchr", "memchr",
"pulldown-cmark-escape", "pulldown-cmark-escape",
@ -1076,15 +772,6 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.4" version = "1.10.4"
@ -1193,17 +880,6 @@ dependencies = [
"unsafe-libyaml", "unsafe-libyaml",
] ]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "0.3.11" version = "0.3.11"
@ -1216,7 +892,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"camino", "camino",
"chrono", "chrono",
"clap",
"emojis", "emojis",
"glob", "glob",
"grass", "grass",
@ -1224,27 +899,19 @@ dependencies = [
"hayagriva", "hayagriva",
"hypertext", "hypertext",
"katex", "katex",
"notify", "npezza93-tree-sitter-haskell",
"notify-debouncer-mini",
"once_cell", "once_cell",
"pulldown-cmark", "pulldown-cmark",
"regex", "regex",
"serde", "serde",
"tree-sitter", "tree-sitter",
"tree-sitter-css",
"tree-sitter-haskell",
"tree-sitter-highlight", "tree-sitter-highlight",
"tree-sitter-html",
"tree-sitter-javascript", "tree-sitter-javascript",
"tree-sitter-md", "tree-sitter-md",
"tree-sitter-python", "tree-sitter-python",
"tree-sitter-query", "tree-sitter-query",
"tree-sitter-regex",
"tree-sitter-rust", "tree-sitter-rust",
"tree-sitter-scss", "tree-sitter-scss",
"tree-sitter-toml-ng",
"tree-sitter-typescript",
"tungstenite",
] ]
[[package]] [[package]]
@ -1253,12 +920,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.26.2" version = "0.26.2"
@ -1274,7 +935,7 @@ version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
dependencies = [ dependencies = [
"heck 0.4.1", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustversion", "rustversion",
@ -1317,18 +978,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.59" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.59" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1361,39 +1022,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tree-sitter" name = "tree-sitter"
version = "0.22.6" version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca" checksum = "688200d842c76dd88f9a7719ecb0483f79f5a766fb1c100756d5d8a059abc71b"
dependencies = [ dependencies = [
"cc", "cc",
"regex", "regex",
] ]
[[package]]
name = "tree-sitter-css"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2f806f96136762b0121f5fdd7172a3dcd8f42d37a2f23ed7f11b35895e20eb4"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-haskell"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25a7e6c73cc1cbe0c0b7dbd5406e7b3485b370bd61c5d8d852ae0781f9bf9a"
dependencies = [
"cc",
"tree-sitter",
]
[[package]] [[package]]
name = "tree-sitter-highlight" name = "tree-sitter-highlight"
version = "0.22.6" version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaca0fe34fa96eec6aaa8e63308dbe1bafe65a6317487c287f93938959b21907" checksum = "9442daef896b114ed618a5e11c9ba9663796ab3600e544d57f2dc980fa0d2d78"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"regex", "regex",
@ -1401,21 +1042,11 @@ dependencies = [
"tree-sitter", "tree-sitter",
] ]
[[package]]
name = "tree-sitter-html"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95b3492b08a786bf5cc79feb0ef2ff3b115d5174364e0ddfd7860e0b9b088b53"
dependencies = [
"cc",
"tree-sitter",
]
[[package]] [[package]]
name = "tree-sitter-javascript" name = "tree-sitter-javascript"
version = "0.21.2" version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080880908cb6e8d03cb9ceaeecec9a3d3a2f4e122e74642509bbb22aaefd991b" checksum = "26eca1925fd9518f9439ea122e3f3395abb3fcfc4b0841ef94eeef934871ec59"
dependencies = [ dependencies = [
"cc", "cc",
"tree-sitter", "tree-sitter",
@ -1444,17 +1075,7 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter-query" name = "tree-sitter-query"
version = "0.2.1" version = "0.2.1"
source = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?rev=87b1a3d#87b1a3dc6c5a76c5cedcdfc60efe75805468cb90" source = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?rev=608c01187fb9f525a1e4cf585bb63d73dea280b7#608c01187fb9f525a1e4cf585bb63d73dea280b7"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-regex"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ff1286fe9651b2797484839ffa37aa76c8618d4ccb6836d7e31765dfd60c0d5"
dependencies = [ dependencies = [
"cc", "cc",
"tree-sitter", "tree-sitter",
@ -1480,51 +1101,6 @@ dependencies = [
"tree-sitter", "tree-sitter",
] ]
[[package]]
name = "tree-sitter-toml-ng"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "695d20cd83acf16c02c773f03e76d7b43b19883d4e2ce3652a8f06b5e0da7455"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-typescript"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07523e51e3b88529360a89038c0cca7ee877db40a40141514eece8b4cddcbb4"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tungstenite"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http",
"httparse",
"log",
"rand",
"sha1",
"thiserror",
"url",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "unic-langid" name = "unic-langid"
version = "0.9.4" version = "0.9.4"
@ -1610,24 +1186,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "utf8-width" name = "utf8-width"
version = "0.1.7" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@ -1741,40 +1305,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.4", "windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
] ]
[[package]] [[package]]
@ -1783,93 +1314,51 @@ version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.4", "windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.52.4", "windows_aarch64_msvc",
"windows_i686_gnu 0.52.4", "windows_i686_gnu",
"windows_i686_msvc 0.52.4", "windows_i686_msvc",
"windows_x86_64_gnu 0.52.4", "windows_x86_64_gnu",
"windows_x86_64_gnullvm 0.52.4", "windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.52.4", "windows_x86_64_msvc",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.4" version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.4" version = "0.52.4"

View file

@ -6,7 +6,6 @@ edition = "2021"
[dependencies] [dependencies]
camino = "1.1.6" camino = "1.1.6"
chrono = "0.4.35" chrono = "0.4.35"
clap = { version = "4.5.4", features = ["derive"] }
emojis = "0.6.1" emojis = "0.6.1"
glob = "0.3.1" glob = "0.3.1"
grass = { version = "0.13.2", default-features = false, features = ["random"] } grass = { version = "0.13.2", default-features = false, features = ["random"] }
@ -18,11 +17,6 @@ once_cell = "1.19.0"
regex = "1.10.4" regex = "1.10.4"
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
# Watch
notify = "6.1.1"
notify-debouncer-mini = "0.4.1"
tungstenite = "0.21.0"
# Markdown # Markdown
pulldown-cmark = { git = "https://github.com/pulldown-cmark/pulldown-cmark.git", branch = "branch_0.11" } pulldown-cmark = { git = "https://github.com/pulldown-cmark/pulldown-cmark.git", branch = "branch_0.11" }
@ -32,15 +26,15 @@ tree-sitter-highlight = "0.22"
# Treesitter languages # Treesitter languages
# tree-sitter-astro = { git = "https://github.com/virchau13/tree-sitter-astro.git", rev = "e924787e12e8a03194f36a113290ac11d6dc10f3" } # tree-sitter-astro = { git = "https://github.com/virchau13/tree-sitter-astro.git", rev = "e924787e12e8a03194f36a113290ac11d6dc10f3" }
tree-sitter-css = "0.21" # tree-sitter-css = "0.20.0"
tree-sitter-haskell = "0.21" # tree-sitter-haskell = { git = "https://github.com/tree-sitter/tree-sitter-haskell", rev = "1da347c88599faad7964e63facead5d163ac7dba" }
tree-sitter-html = "0.20.3" npezza93-tree-sitter-haskell = "0.15.1"
tree-sitter-javascript = "0.21" tree-sitter-javascript = "0.21"
tree-sitter-md = "0.2" tree-sitter-md = "0.2"
tree-sitter-python = "0.21" tree-sitter-python = "0.21"
tree-sitter-regex = "0.21" tree-sitter-query = { git = "https://github.com/tree-sitter-grammars/tree-sitter-query", rev = "608c01187fb9f525a1e4cf585bb63d73dea280b7" }
# tree-sitter-regex = "0.20.0"
tree-sitter-rust = "0.21" tree-sitter-rust = "0.21"
tree-sitter-scss = "1" tree-sitter-scss = "1"
tree-sitter-query = { git = "https://github.com/tree-sitter-grammars/tree-sitter-query", rev = "87b1a3d" } # tree-sitter-toml = "0.20.0"
tree-sitter-toml-ng = "0.6" # tree-sitter-typescript = "0.20.5"
tree-sitter-typescript = "0.21"

View file

@ -1,11 +1,8 @@
build: build:
cargo run --release cargo run
watch:
cargo run --release -- watch
serve:
python -m http.server -d ./dist
deploy: build deploy: build
rsync -Pavzq ./dist/ kamoshi:/var/www/kamoshi.org --delete rsync -Pavzq ./dist/ kamoshi:/var/www/kamoshi.org --delete
serve:
python -m http.server -d ./dist

View file

@ -11,22 +11,22 @@ date: 2023-12-17T12:47:29.753Z
あくる日、親に引かれている橇で乗っている嬉しそうな子供を見た。 あくる日、親に引かれている橇で乗っている嬉しそうな子供を見た。
あらゆる公園が白くなって、白すぎて見えた。 あらゆる公園が白くなって、白すぎて見えた。
![白すぎる公園](IMG_20231204_105929.jpg) ![白すぎる公園](@assets/posts/hisasiburi-no-toukou/IMG_20231204_105929.jpg)
その時から雪が全部解けちゃった。 その時から雪が全部解けちゃった。
最近、ヴロツワフではクリスマスマーケットが始まっているので、見に行った。 最近、ヴロツワフではクリスマスマーケットが始まっているので、見に行った。
そこでたくさんの人がいて、いろんな出店もあり、色々なものを買って楽しむことができた。 そこでたくさんの人がいて、いろんな出店もあり、色々なものを買って楽しむことができた。
![眩しいクリスマスライト](IMG_20231209_182036.jpg) ![眩しいクリスマスライト](@assets/posts/hisasiburi-no-toukou/IMG_20231209_182036.jpg)
もっと進んでいくと、大きなレストランみたいなビルに出くわしたんだ。 もっと進んでいくと、大きなレストランみたいなビルに出くわしたんだ。
あのビルでは、「グジャニエッツ」という飲み物を買って楽しむことができた。 あのビルでは、「グジャニエッツ」という飲み物を買って楽しむことができた。
![グジャニエッツのビル](IMG_20231209_183410.jpg) ![グジャニエッツのビル](@assets/posts/hisasiburi-no-toukou/IMG_20231209_183410.jpg)
グジャニエッツとは、ポーランドの伝統的な温かいスパイス入りの飲み物。 グジャニエッツとは、ポーランドの伝統的な温かいスパイス入りの飲み物。
通常は赤ワインやオレンジ、シナモン、クローブが使われる。 通常は赤ワインやオレンジ、シナモン、クローブが使われる。
クリスマスマーケットってとても素晴らしいイベントの一つだけど、 クリスマスマーケットってとても素晴らしいイベントの一つだけど、値段が高く過ぎるからあんまり買い物しなかったwww
値段が高く過ぎるからあんまり買い物しなかったwww

View file

@ -1,78 +0,0 @@
---
title: SSG that packs a punch
date: 2024-05-02T21:17:43Z
desc: >
Let's create a yet another SSG from scratch, because that's just
what this world needs!
---
Long story short, I decided to write my own static site generator in Rust. The
language choice is purely pragmatic and at first I considered using Haskell,
but alas the Rust ecosystem seems better suited for this task. Rust is not only
a very ergonomic and efficient language, but also has lots of high quality
packages to choose from.
## The why
I used many different SSGs made by other people, but over the years I realized
that they simply can't cut it for me. I used simple generators like Hugo, which
offer little to no support for JavaScript. Eventually I ended up using Astro,
which treats JavaScript as a first class citizen.
The thing I didn't like the most about Hugo, was that it used some strange,
clumsy templating language, which was quite annoying to use, but I enjoyed the
fact that nearly everything was built in, and the generation speed was fast.
When it comes to Astro, I enjoyed the fact that in templates you could write
TypeScript, as well the great flexibility with which you could arrange the
structure of the website. However, the JavaScript ecosystem is a mess, so using
that was not that pleasant overall.
Astro was closer to what I wanted, but not quite there.
With time, I realized that what I truly need is the flexibility of Astro,
coupled with a different language. Ideally a fun one like Haskell or Rust.
I started looking around and came across a couple of [blog
posts](https://arne.me/blog/write-your-own-ssg) detailing how people made the
move to their custom generator. This was the inspiration I needed.
I thought that even if it ends up quite bad in the end, at least I'll learn
*something*. And it would be a good chance to learn more Rust, so that's a win
right there. With Haskell it would be an ever bigger win, but hey, can't have
everything in life.
## The what
When trying to write a computer program it's a good idea to think about what it
should ideally be able to do. We should at least know the sketch of the
requirements before we start, so that we know if we are getting any closer to
the goal as we keep writing it.
When it comes to my generator I think I would like for it to have these
qualities:
- The generator must be *simple* and *extensible*
- HTML shouldn't be generated using some bespoke templating language, I should
have the full ecosystem at my disposal.
- Ideally I should not be limited to Markdown, I should be able to use
different file text formats as needed, e.g. Djot, AsciiDoc.
- Code snippets should be highlighted using Tree-sitter.
- Math should be pre-rendered via MathML without any client-side JavaScript.
- There should be a way to render different pages differently, some collections
of Markdown files should output different looking pages.
- I should be able to generate HTML pages that don't have any original source
files related to them, think dynamically generated lists of pages, tags.
With these requirements in mind I decided to go with Rust, because Rust has
lots of up-to-date parsers that can be used while building a generator. On top
of that I can use Tree-sitter without any need for complicated FFI or using
outdated libraries in other ecosystems.
When moving to a non-JavaScript backend for building SSG some issues related to
JavaScript inevitably start to crop up. There is some friction with using tools
like ESBuild, but I feel like the benefits far outweigh the challenges in the
end.
## The how

View file

@ -241,3 +241,41 @@ scala
### Rust ### Rust
rust rust
## Bibliography
:::bibtex
@inproceedings{10.1145/1238844.1238856,
author = {Hudak, Paul and Hughes, John and Peyton Jones, Simon and Wadler, Philip},
title = {A History of Haskell: Being Lazy with Class},
year = {2007},
isbn = {9781595937667},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/1238844.1238856},
doi = {10.1145/1238844.1238856},
abstract = {This paper describes the history of Haskell, including its genesis and principles, technical contributions, implementations and tools, and applications and impact.},
booktitle = {Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages},
pages = {1211255},
location = {San Diego, California},
series = {HOPL III}
}
@online{youtube,
title = {Escape from the ivory tower: the Haskell journey},
date = {2017},
organization = {Youtube},
author = {Simon {Peyton Jones}},
url = {https://youtu.be/re96UgMk6GQ},
}
@book{skinner2023effective,
title = {Effective Haskell: Solving Real-World Problems with Strongly Typed Functional Programming},
author = {Skinner, R.},
isbn = {9781680509342},
series = {Pragmatic Bookshelf},
year = {2023},
publisher = {O'Reilly Media}
}
:::

View file

@ -1,32 +0,0 @@
@inproceedings{10.1145/1238844.1238856,
author = {Hudak, Paul and Hughes, John and Peyton Jones, Simon and Wadler, Philip},
title = {A History of Haskell: Being Lazy with Class},
year = {2007},
isbn = {9781595937667},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/1238844.1238856},
doi = {10.1145/1238844.1238856},
abstract = {This paper describes the history of Haskell, including its genesis and principles, technical contributions, implementations and tools, and applications and impact.},
booktitle = {Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages},
pages = {1211255},
location = {San Diego, California},
series = {HOPL III}
}
@online{youtube,
title = {Escape from the ivory tower: the Haskell journey},
date = {2017},
organization = {Youtube},
author = {Simon {Peyton Jones}},
url = {https://youtu.be/re96UgMk6GQ},
}
@book{skinner2023effective,
title = {Effective Haskell: Solving Real-World Problems with Strongly Typed Functional Programming},
author = {Skinner, R.},
isbn = {9781680509342},
series = {Pragmatic Bookshelf},
year = {2023},
publisher = {O'Reilly Media}
}

View file

@ -20,3 +20,46 @@ It's really powerful.
## Summary ## Summary
It was a pretty fun and interesting adventure, difficult at times, but worth it over all. In hindsight, I regret not paying more attention to mathematics right from the start. If I were to start over I would probably focus more on that and the theory of computation. If you're only just starting out then please remember, writing code is not computer science :cat: It was a pretty fun and interesting adventure, difficult at times, but worth it over all. In hindsight, I regret not paying more attention to mathematics right from the start. If I were to start over I would probably focus more on that and the theory of computation. If you're only just starting out then please remember, writing code is not computer science :cat:
## Bibliography
:::bibtex
@book{gamma1994design,
title = {Design Patterns: Elements of Reusable Object-Oriented Software},
author = {Gamma, E. and Helm, R. and Johnson, R. and Vlissides, J.},
isbn = {9780321700698},
lccn = {94034264},
series = {Addison-Wesley Professional Computing Series},
year = {1994},
publisher = {Pearson Education}
}
@book{chollet2021deep,
title = {Deep Learning with Python, Second Edition},
author = {Chollet, F.},
isbn = {9781617296864},
lccn = {2021425412},
year = {2021},
publisher = {Manning}
}
@article{10.1145/360303.360308,
author = {Tennent, R. D.},
title = {The Denotational Semantics of Programming Languages},
year = {1976},
issue_date = {Aug. 1976},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
volume = {19},
number = {8},
issn = {0001-0782},
url = {https://doi.org/10.1145/360303.360308},
doi = {10.1145/360303.360308},
journal = {Commun. ACM},
month = {aug},
pages = {437453},
numpages = {17},
keywords = {semantics, GEDANKEN, store, environment, LOOP, continuation, applicative, higher-order function, imperative, programming language, theory of computation, recursive definition}
}
:::

View file

@ -1,37 +0,0 @@
@book{gamma1994design,
title = {Design Patterns: Elements of Reusable Object-Oriented Software},
author = {Gamma, E. and Helm, R. and Johnson, R. and Vlissides, J.},
isbn = {9780321700698},
lccn = {94034264},
series = {Addison-Wesley Professional Computing Series},
year = {1994},
publisher = {Pearson Education}
}
@book{chollet2021deep,
title = {Deep Learning with Python, Second Edition},
author = {Chollet, F.},
isbn = {9781617296864},
lccn = {2021425412},
year = {2021},
publisher = {Manning}
}
@article{10.1145/360303.360308,
author = {Tennent, R. D.},
title = {The Denotational Semantics of Programming Languages},
year = {1976},
issue_date = {Aug. 1976},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
volume = {19},
number = {8},
issn = {0001-0782},
url = {https://doi.org/10.1145/360303.360308},
doi = {10.1145/360303.360308},
journal = {Commun. ACM},
month = {aug},
pages = {437453},
numpages = {17},
keywords = {semantics, GEDANKEN, store, environment, LOOP, continuation, applicative, higher-order function, imperative, programming language, theory of computation, recursive definition}
}

View file

@ -1,18 +0,0 @@
---
title: 〜めが
---
め and が can be used as pejorative suffixes at the end of a noun.
An example for め is:
> [馬鹿]{ばか}め!
More can be read [here](https://japanese.stackexchange.com/questions/95851).
Similarly to め, が can be used as a suffix of insult:
> この[小娘]{こむすめ}が(っ)!
More can be read [here](https://japanese.stackexchange.com/questions/60514).
Finally, the two can be used together as in:
> あの…馬鹿者めが…

View file

@ -1,7 +0,0 @@
use std::fs;
pub fn build_styles() {
let css = grass::from_path("styles/styles.scss", &grass::Options::default()).unwrap();
fs::write("dist/styles.css", css).unwrap();
}

View file

@ -1,111 +1,54 @@
use std::collections::HashSet ; use std::collections::HashSet ;
use std::fs::{self, File};
use std::io::Write;
use camino::{Utf8Path, Utf8PathBuf}; use camino::Utf8PathBuf;
use glob::glob; use glob::glob;
use hayagriva::Library;
use crate::html::Linkable;
use super::Sack;
/// Marks whether the item should be treated as a content page, converted into a standalone HTML
/// page, or as a bundled asset.
#[derive(Debug)] #[derive(Debug)]
pub enum FileItemKind { pub enum SourceKind {
/// Convert to `index.html`
Index, Index,
/// Convert to a bundled asset Asset,
Bundle,
} }
/// Metadata for a single item consumed by SSG.
#[derive(Debug)] #[derive(Debug)]
pub struct FileItem { pub struct Source {
/// Kind of an item pub kind: SourceKind,
pub kind: FileItemKind, pub ext: String,
/// Original source file location pub dirs: Utf8PathBuf,
pub path: Utf8PathBuf, pub path: Utf8PathBuf,
} }
/// Marks how the asset should be processed by the SSG
pub enum AssetKind { fn to_source(path: Utf8PathBuf, exts: &HashSet<&'static str>) -> Source {
/// Data renderable to HTML let dir = path.parent().unwrap();
Html(Box<dyn Fn(&Sack) -> String>), let ext = path.extension().unwrap();
/// Bibliographical data
Bibtex(Library), if !exts.contains(ext) {
/// Images return Source {
Image, kind: SourceKind::Asset,
ext: ext.to_owned(),
dirs: dir.to_owned(),
path,
};
} }
/// Asset renderable by the SSG let dirs = match path.file_stem().unwrap() {
pub struct Asset { "index" => dir.to_owned(),
/// Kind of a processed asset name => dir.join(name),
pub kind: AssetKind, };
/// File metadata
pub meta: FileItem,
}
/// Dynamically generated asset not related to any disk file. Source {
pub struct Dynamic(pub Box<dyn Fn(&Sack) -> String>); kind: SourceKind::Index,
ext: ext.to_owned(),
impl Dynamic { dirs,
pub fn new(call: impl Fn(&Sack) -> String + 'static) -> Self { path,
Self(Box::new(call))
}
}
pub enum OutputKind {
Real(Asset),
Fake(Dynamic),
}
impl From<Asset> for OutputKind {
fn from(value: Asset) -> Self {
OutputKind::Real(value)
}
}
impl From<Dynamic> for OutputKind {
fn from(value: Dynamic) -> Self {
OutputKind::Fake(value)
}
}
/// Renderable output
pub struct Output {
pub kind: OutputKind,
pub path: Utf8PathBuf,
/// Optional link to outputted page.
pub link: Option<Linkable>,
}
/// Variants used for filtering static assets.
pub enum PipelineItem {
/// Unclaimed file, unrecognized file extensions.
Skip(FileItem),
/// Data ready to be processed by SSG.
Take(Output),
}
impl From<FileItem> for PipelineItem {
fn from(value: FileItem) -> Self {
Self::Skip(value)
}
}
impl From<Output> for PipelineItem {
fn from(value: Output) -> Self {
Self::Take(value)
} }
} }
pub fn gather(pattern: &str, exts: &HashSet<&'static str>) -> Vec<PipelineItem> { pub fn gather(pattern: &str, exts: &HashSet<&'static str>) -> Vec<Source> {
glob(pattern) glob(pattern)
.expect("Invalid glob pattern") .unwrap()
.filter_map(|path| { .filter_map(|path| {
let path = path.unwrap(); let path = path.unwrap();
let path = Utf8PathBuf::from_path_buf(path).expect("Filename is not valid UTF8"); let path = Utf8PathBuf::from_path_buf(path).expect("Filename is not valid UTF8");
@ -115,62 +58,5 @@ pub fn gather(pattern: &str, exts: &HashSet<&'static str>) -> Vec<PipelineItem>
false => Some(to_source(path, exts)) false => Some(to_source(path, exts))
} }
}) })
.map(Into::into)
.collect() .collect()
} }
fn to_source(path: Utf8PathBuf, exts: &HashSet<&'static str>) -> FileItem {
let hit = path.extension().map_or(false, |ext| exts.contains(ext));
let kind = match hit {
true => FileItemKind::Index,
false => FileItemKind::Bundle,
};
FileItem {
kind,
path,
}
}
pub fn render_all(items: &[Output]) {
for item in items {
let file = match &item.kind {
OutputKind::Real(a) => Some(&a.meta.path),
OutputKind::Fake(_) => None,
};
render(item, &Sack::new(items, &item.path, file));
}
}
fn render(item: &Output, sack: &Sack) {
let o = Utf8Path::new("dist").join(&item.path);
fs::create_dir_all(o.parent().unwrap()).unwrap();
match item.kind {
OutputKind::Real(ref real) => {
let i = &real.meta.path;
match &real.kind {
AssetKind::Html(closure) => {
let mut file = File::create(&o).unwrap();
file.write_all(closure(sack).as_bytes()).unwrap();
println!("HTML: {} -> {}", i, o);
},
AssetKind::Bibtex(_) => { },
AssetKind::Image => {
fs::create_dir_all(o.parent().unwrap()).unwrap();
fs::copy(i, &o).unwrap();
println!("Image: {} -> {}", i, o);
},
};
},
OutputKind::Fake(Dynamic(ref closure)) => {
let mut file = File::create(&o).unwrap();
file.write_all(closure(sack).as_bytes()).unwrap();
println!("Virtual: -> {}", o);
},
}
}

View file

@ -1,17 +1,19 @@
mod load; mod load;
mod render;
mod sack; mod sack;
use camino::Utf8PathBuf; use camino::Utf8PathBuf;
use hayagriva::Library; use hayagriva::Library;
use hypertext::Renderable; use hypertext::Renderable;
pub use load::{gather, render_all, FileItem, FileItemKind, Asset, AssetKind, PipelineItem, Dynamic, Output}; pub use load::{gather, Source, SourceKind};
pub use render::{render, Asset, AssetKind, Virtual, Item};
pub use sack::{TreePage, Sack}; pub use sack::{TreePage, Sack};
use crate::{html::Linkable, text::md::Outline}; use crate::{html::Linkable, text::md::Outline};
/// Represents a piece of content that can be rendered as a page. /// Represents a piece of content that can be rendered into a page.
pub trait Content { pub trait Content {
fn transform<'f, 'm, 's, 'html, T>( fn transform<'f, 'm, 's, 'html, T>(
&'f self, &'f self,

125
src/gen/render.rs Normal file
View file

@ -0,0 +1,125 @@
use std::fmt::Debug;
use std::fs::{self, File};
use std::io::Write;
use camino::{Utf8Path, Utf8PathBuf};
use crate::html::Linkable;
use crate::Sack;
pub enum AssetKind {
Html(Box<dyn Fn(&Sack) -> String>),
Image,
Unknown,
Bib(hayagriva::Library),
}
impl Debug for AssetKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Html(ptr) => f.debug_tuple("Html").field(&format!("{:p}", *ptr)).finish(),
Self::Image => write!(f, "Image"),
Self::Unknown => write!(f, "Unknown"),
Self::Bib(bib) => f.debug_tuple("Bib").field(bib).finish(),
}
}
}
#[derive(Debug)]
pub struct Asset {
pub kind: AssetKind,
pub out: Utf8PathBuf,
pub link: Option<Linkable>,
pub meta: super::Source,
}
pub struct Virtual(pub Utf8PathBuf, pub Box<dyn Fn(&Sack) -> String>);
impl Virtual {
pub fn new<P, F>(path: P, call: F) -> Self
where
P: AsRef<Utf8Path>,
F: Fn(&Sack) -> String + 'static
{
Self(path.as_ref().into(), Box::new(call))
}
}
pub enum Item {
Real(Asset),
Fake(Virtual),
}
impl From<Asset> for Item {
fn from(value: Asset) -> Self {
Item::Real(value)
}
}
impl From<Virtual> for Item {
fn from(value: Virtual) -> Self {
Item::Fake(value)
}
}
pub fn render(items: &[Item]) {
let assets: Vec<&Asset> = items
.iter()
.filter_map(|item| match item {
Item::Real(a) => Some(a),
Item::Fake(_) => None,
})
.collect();
for item in items {
match item {
Item::Real(real) => render_real(real, &Sack::new(&assets, &real.out)),
Item::Fake(fake) => render_fake(fake, &Sack::new(&assets, &fake.0)),
}
}
}
fn render_real(item: &Asset, sack: &Sack) {
match &item.kind {
AssetKind::Html(render) => {
let i = &item.meta.path;
let o = Utf8Path::new("dist").join(&item.out);
fs::create_dir_all(o.parent().unwrap()).unwrap();
let mut file = File::create(&o).unwrap();
file.write_all(render(sack).as_bytes()).unwrap();
println!("HTML: {} -> {}", i, o);
},
AssetKind::Image => {
let i = &item.meta.path;
let o = Utf8Path::new("dist").join(&item.out);
fs::create_dir_all(o.parent().unwrap()).unwrap();
fs::copy(i, &o).unwrap();
println!("Image: {} -> {}", i, o);
},
AssetKind::Bib(_) => (),
AssetKind::Unknown => {
let i = &item.meta.path;
let o = Utf8Path::new("dist").join(&item.out);
fs::create_dir_all(o.parent().unwrap()).unwrap();
fs::copy(i, &o).unwrap();
println!("Unknown: {} -> {}", i, o);
},
}
}
fn render_fake(item: &Virtual, sack: &Sack) {
let Virtual(out, render) = item;
let o = Utf8Path::new("dist").join(out);
fs::create_dir_all(o.parent().unwrap()).unwrap();
let mut file = File::create(&o).unwrap();
file.write_all(render(sack).as_bytes()).unwrap();
println!("Virtual: -> {}", o);
}

View file

@ -1,11 +1,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use camino::{Utf8Path, Utf8PathBuf}; use camino::Utf8PathBuf;
use hayagriva::Library; use hayagriva::Library;
use crate::html::{Link, LinkDate, Linkable}; use crate::html::{Link, LinkDate, Linkable};
use super::{load::{Output, OutputKind}, AssetKind}; use super::{Asset, AssetKind};
#[derive(Debug)] #[derive(Debug)]
@ -34,27 +34,23 @@ impl TreePage {
} }
/// This struct allows for querying the website hierarchy. Separate instance of this struct is /// This struct allows for querying the website hierarchy.
/// passed to each closure contained by some rendered assets. #[derive(Debug)]
pub struct Sack<'a> { pub struct Sack<'a> {
/// Literally everything assets: &'a [&'a Asset],
hole: &'a [Output],
/// Current path for page
path: &'a Utf8PathBuf, path: &'a Utf8PathBuf,
/// Original file location
file: Option<&'a Utf8PathBuf>,
} }
impl<'a> Sack<'a> { impl<'a> Sack<'a> {
pub fn new(hole: &'a [Output], path: &'a Utf8PathBuf, file: Option<&'a Utf8PathBuf>) -> Self { pub fn new(assets: &'a [&'a Asset], path: &'a Utf8PathBuf) -> Self {
Self { hole, path, file } Self { assets, path }
} }
pub fn get_links(&self, path: &str) -> Vec<LinkDate> { pub fn get_links(&self, path: &str) -> Vec<LinkDate> {
let pattern = glob::Pattern::new(path).expect("Bad glob pattern"); let pattern = glob::Pattern::new(path).unwrap();
self.hole.iter() self.assets.iter()
.filter(|item| pattern.matches_path(item.path.as_ref())) .filter(|f| pattern.matches_path(f.out.as_ref()))
.filter_map(|item| match &item.link { .filter_map(|f| match &f.link {
Some(Linkable::Date(link)) => Some(link.clone()), Some(Linkable::Date(link)) => Some(link.clone()),
_ => None, _ => None,
}) })
@ -62,10 +58,10 @@ impl<'a> Sack<'a> {
} }
pub fn get_tree(&self, path: &str) -> TreePage { pub fn get_tree(&self, path: &str) -> TreePage {
let glob = glob::Pattern::new(path).expect("Bad glob pattern"); let glob = glob::Pattern::new(path).unwrap();
let list = self.hole.iter() let list = self.assets.iter()
.filter(|item| glob.matches_path(item.path.as_ref())) .filter(|f| glob.matches_path(f.out.as_ref()))
.filter_map(|item| match &item.link { .filter_map(|f| match &f.link {
Some(Linkable::Link(link)) => Some(link.clone()), Some(Linkable::Link(link)) => Some(link.clone()),
_ => None, _ => None,
}); });
@ -80,32 +76,18 @@ impl<'a> Sack<'a> {
pub fn get_library(&self) -> Option<&Library> { pub fn get_library(&self) -> Option<&Library> {
let glob = format!("{}/*.bib", self.path.parent()?); let glob = format!("{}/*.bib", self.path.parent()?);
let glob = glob::Pattern::new(&glob).expect("Bad glob pattern"); let glob = glob::Pattern::new(&glob).unwrap();
let opts = glob::MatchOptions { let opts = glob::MatchOptions {
case_sensitive: true, case_sensitive: true,
require_literal_separator: true, require_literal_separator: true,
require_literal_leading_dot: false, require_literal_leading_dot: false,
}; };
self.hole.iter() self.assets.iter()
.filter(|item| glob.matches_path_with(item.path.as_ref(), opts)) .filter(|asset| glob.matches_path_with(asset.out.as_ref(), opts))
.filter_map(|asset| match asset.kind {
OutputKind::Real(ref real) => Some(real),
_ => None,
})
.find_map(|asset| match asset.kind { .find_map(|asset| match asset.kind {
AssetKind::Bibtex(ref lib) => Some(lib), AssetKind::Bib(ref lib) => Some(lib),
_ => None, _ => None
}) })
} }
/// Get the path for output
pub fn get_path(&self) -> &'a Utf8Path {
self.path.as_path()
}
/// Get the path for original file location
pub fn get_file(&self) -> Option<&'a Utf8Path> {
self.file.map(Utf8PathBuf::as_ref)
}
} }

View file

@ -1,28 +1,8 @@
use camino::Utf8Path;
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
use crate::REPO; use crate::REPO;
const JS_RELOAD: &str = r#"
const socket = new WebSocket("ws://localhost:1337");
socket.addEventListener("message", (event) => {
console.log(event);
window.location.reload();
});
"#;
const JS_IMPORTS: &str = r#"
{
"imports": {
"splash": "/js/splash.js",
"reveal": "/js/reveal.js",
"photos": "/js/photos.js",
}
}
"#;
pub fn head(title: &str) -> impl Renderable + '_ { pub fn head(title: &str) -> impl Renderable + '_ {
let title = format!("{} | kamoshi.org", title); let title = format!("{} | kamoshi.org", title);
@ -33,6 +13,16 @@ pub fn head(title: &str) -> impl Renderable + '_ {
(title) (title)
} }
script type="importmap" {(Raw(r#"
{
"imports": {
"splash": "/js/splash.js",
"reveal": "/js/reveal.js",
"photos": "/js/photos.js"
}
}
"#))}
// link rel="sitemap" href="/sitemap.xml"; // link rel="sitemap" href="/sitemap.xml";
link rel="stylesheet" href="/styles.css"; link rel="stylesheet" href="/styles.css";
@ -43,10 +33,6 @@ pub fn head(title: &str) -> impl Renderable + '_ {
link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"; link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png";
link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"; link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png";
link rel="icon" href="/favicon.ico" sizes="any"; link rel="icon" href="/favicon.ico" sizes="any";
script type="importmap" {(Raw(JS_IMPORTS))}
script { (Raw(JS_RELOAD)) }
) )
} }
@ -95,15 +81,11 @@ pub fn navbar() -> impl Renderable {
) )
} }
pub fn footer(path: Option<&Utf8Path>) -> impl Renderable { pub fn footer() -> impl Renderable {
let copy = format!("Copyright &copy; {} Maciej Jur", &REPO.year); let copy = format!("Copyright &copy; {} Maciej Jur", &REPO.year);
let mail = "maciej@kamoshi.org"; let mail = "maciej@kamoshi.org";
let href = format!("mailto:{}", mail); let href = format!("mailto:{}", mail);
let link = Utf8Path::new(&REPO.link).join("tree").join(&REPO.hash); let repo = format!("{}/tree/{}", &REPO.link, &REPO.hash);
let link = match path {
Some(path) => link.join(path),
None => link,
};
maud_move!( maud_move!(
footer .footer { footer .footer {
@ -116,7 +98,7 @@ pub fn footer(path: Option<&Utf8Path>) -> impl Renderable {
} }
} }
div .repo { div .repo {
a href=(link.as_str()) { a href=(repo) {
(&REPO.hash) (&REPO.hash)
} }
div { div {

View file

@ -73,5 +73,5 @@ pub fn home<'data, 'home, R>(main: R) -> impl Renderable + 'home
} }
); );
page("Home", main, None) page("Home", main)
} }

View file

@ -45,7 +45,7 @@ pub fn list<'data, 'list>(
} }
); );
page(title, list, None) page(title, list)
} }
fn section(year: i32, group: &[LinkDate]) -> impl Renderable + '_ { fn section(year: i32, group: &[LinkDate]) -> impl Renderable + '_ {

View file

@ -1,4 +1,3 @@
use camino::Utf8Path;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable}; use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
use crate::html::base::{head, navbar, footer}; use crate::html::base::{head, navbar, footer};
@ -20,14 +19,10 @@ pub fn bare<'data, 'html, R>(title: &'data str, main: R) -> impl Renderable + 'h
) )
} }
pub fn page<'data, 'main, 'html, T>( pub fn page<'data, 'main, 'page, T>(title: &'data str, main: T) -> impl Renderable + 'page
title: &'data str,
main: T,
path: Option<&'data Utf8Path>,
) -> impl Renderable + 'html
where where
'main : 'html, 'main : 'page,
'data : 'html, 'data : 'page,
T: Renderable + 'main T: Renderable + 'main
{ {
maud_move!( maud_move!(
@ -38,7 +33,7 @@ pub fn page<'data, 'main, 'html, T>(
body { body {
(navbar()) (navbar())
(main) (main)
(footer(path)) (footer())
} }
} }
) )

View file

@ -1,24 +1,21 @@
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable}; use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
use crate::gen::Sack;
use crate::html::misc::{show_bibliography, show_outline}; use crate::html::misc::{show_bibliography, show_outline};
use crate::html::page; use crate::html::page;
use crate::md::Post; use crate::md::Post;
use crate::text::md::Outline; use crate::text::md::Outline;
pub fn post<'f, 'm, 's, 'html, T>( pub fn post<'fm, 'md, 'post, T>(
fm: &'f Post, fm: &'fm Post,
content: T, content: T,
outline: Outline, outline: Outline,
bib: Option<Vec<String>>, bib: Option<Vec<String>>,
sack: &'s Sack, ) -> impl Renderable + 'post
) -> impl Renderable + 'html
where where
'f: 'html, 'fm: 'post,
'm: 'html, 'md: 'post,
's: 'html, T: Renderable + 'md
T: Renderable + 'm
{ {
let main = maud_move!( let main = maud_move!(
main .wiki-main { main .wiki-main {
@ -49,5 +46,5 @@ pub fn post<'f, 'm, 's, 'html, T>(
} }
); );
page(&fm.title, main, sack.get_file()) page(&fm.title, main)
} }

View file

@ -12,7 +12,7 @@ pub fn map() -> impl Renderable {
(Raw("import 'photos';")) (Raw("import 'photos';"))
} }
} }
), None) ))
} }
pub fn search() -> impl Renderable { pub fn search() -> impl Renderable {
@ -20,5 +20,5 @@ pub fn search() -> impl Renderable {
main { main {
} }
), None) ))
} }

View file

@ -53,5 +53,5 @@ pub fn wiki<'data, 'html, 'sack, T>(
} }
); );
page(&fm.title, main, sack.get_file()) page(&fm.title, main)
} }

View file

@ -1,42 +1,22 @@
use std::process::Command;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::process::Command;
use camino::{Utf8Path, Utf8PathBuf}; use camino::{Utf8Path, Utf8PathBuf};
use chrono::Datelike; use chrono::Datelike;
use clap::{Parser, ValueEnum}; use gen::{Asset, Sack, Content};
use gen::{Asset, AssetKind, Content, FileItemKind, Output, PipelineItem, Sack};
use hayagriva::Library; use hayagriva::Library;
use html::{Link, LinkDate, Linkable}; use html::{Link, LinkDate, Linkable};
use hypertext::{Raw, Renderable}; use hypertext::{Raw, Renderable};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::Deserialize;
use text::md::Outline; use text::md::Outline;
use crate::gen::Dynamic;
use crate::build::build_styles;
mod md; mod md;
mod html; mod html;
mod ts; mod ts;
mod gen; mod gen;
mod utils; mod utils;
mod text; mod text;
mod watch;
mod build;
#[derive(Parser, Debug, Clone)]
struct Args {
#[clap(value_enum, index = 1, default_value = "build")]
mode: Mode,
}
#[derive(ValueEnum, Debug, Clone, Copy)]
enum Mode {
Build,
Watch,
}
#[derive(Debug)] #[derive(Debug)]
@ -74,7 +54,7 @@ impl Content for md::Post {
&'f self, &'f self,
content: T, content: T,
outline: Outline, outline: Outline,
sack: &'s Sack, _: &'s Sack,
bib: Option<Vec<String>>, bib: Option<Vec<String>>,
) -> impl Renderable + 'html ) -> impl Renderable + 'html
where where
@ -82,7 +62,7 @@ impl Content for md::Post {
'm: 'html, 'm: 'html,
's: 'html, 's: 'html,
T: Renderable + 'm { T: Renderable + 'm {
html::post(self, content, outline, bib, sack) html::post(self, content, outline, bib)
} }
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> { fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
@ -191,24 +171,19 @@ fn to_list(list: Vec<LinkDate>) -> String {
html::list("", &groups).render().into() html::list("", &groups).render().into()
} }
fn to_index<T>(item: PipelineItem) -> PipelineItem
where
T: for<'de> Deserialize<'de> + Content + 'static,
{
let meta = match item {
PipelineItem::Skip(meta) if matches!(meta.kind, FileItemKind::Index) => meta,
_ => return item,
};
let dir = meta.path.parent().unwrap().strip_prefix("content").unwrap(); fn transform<T>(meta: gen::Source) -> Asset
let dir = match meta.path.file_stem().unwrap() { where
"index" => dir.to_owned(), T: for<'de> serde::Deserialize<'de>,
name => dir.join(name), T: Content + 'static,
}; {
let dir = meta.dirs.strip_prefix("content").unwrap();
match meta.kind {
gen::SourceKind::Index => match meta.ext.as_str() {
"md" | "mdx" | "lhs" => {
let path = dir.join("index.html"); let path = dir.join("index.html");
match meta.path.extension() {
Some("md" | "mdx" | "lhs") => {
let data = fs::read_to_string(&meta.path).unwrap(); let data = fs::read_to_string(&meta.path).unwrap();
let (fm, md) = md::preflight::<T>(&data); let (fm, md) = md::preflight::<T>(&data);
let link = T::as_link(&fm, Utf8Path::new("/").join(dir)); let link = T::as_link(&fm, Utf8Path::new("/").join(dir));
@ -219,59 +194,52 @@ fn to_index<T>(item: PipelineItem) -> PipelineItem
T::transform(&fm, Raw(html), outline, sack, bib).render().into() T::transform(&fm, Raw(html), outline, sack, bib).render().into()
}; };
Output { gen::Asset {
kind: Asset {
kind: gen::AssetKind::Html(Box::new(call)), kind: gen::AssetKind::Html(Box::new(call)),
meta, out: path,
}.into(),
path,
link, link,
}.into()
},
_ => meta.into(),
}
}
fn to_bundle(item: PipelineItem) -> PipelineItem {
let meta = match item {
PipelineItem::Skip(meta) if matches!(meta.kind, FileItemKind::Bundle) => meta,
_ => return item,
};
let path = meta.path.strip_prefix("content").unwrap().to_owned();
match meta.path.extension() {
// any image
Some("jpg" | "png" | "gif") => {
Output {
kind: Asset {
kind: AssetKind::Image,
meta, meta,
}.into(), }
path,
link: None,
}.into()
}, },
// bibliography _ => gen::Asset {
Some("bib") => { kind: gen::AssetKind::Unknown,
out: dir.join(meta.path.file_name().unwrap()).to_owned(),
link: None,
meta,
}
},
gen::SourceKind::Asset => {
let loc = dir.join(meta.path.file_name().unwrap()).to_owned();
match meta.ext.as_str() {
"jpg" | "png" | "gif" => gen::Asset {
kind: gen::AssetKind::Image,
out: loc,
link: None,
meta,
},
"bib" => {
let data = fs::read_to_string(&meta.path).unwrap(); let data = fs::read_to_string(&meta.path).unwrap();
let data = hayagriva::io::from_biblatex_str(&data).unwrap(); let data = hayagriva::io::from_biblatex_str(&data).unwrap();
Output { gen::Asset {
kind: Asset { kind: gen::AssetKind::Bib(data),
kind: AssetKind::Bibtex(data), out: loc,
meta,
}.into(),
path,
link: None, link: None,
}.into() meta,
}
}, },
_ => meta.into(), _ => gen::Asset {
kind: gen::AssetKind::Unknown,
out: loc,
link: None,
meta,
},
}
}
} }
} }
fn main() {
fn build() {
if fs::metadata("dist").is_ok() { if fs::metadata("dist").is_ok() {
println!("Cleaning dist"); println!("Cleaning dist");
fs::remove_dir_all("dist").unwrap(); fs::remove_dir_all("dist").unwrap();
@ -279,85 +247,69 @@ fn build() {
fs::create_dir("dist").unwrap(); fs::create_dir("dist").unwrap();
let assets: Vec<Output> = [ let assets: Vec<Vec<gen::Item>> = vec![
gen::gather("content/about.md", &["md"].into())
.into_iter()
.map(to_index::<md::Post> as fn(PipelineItem) -> PipelineItem),
gen::gather("content/posts/**/*", &["md", "mdx"].into())
.into_iter()
.map(to_index::<md::Post>),
gen::gather("content/slides/**/*", &["md", "lhs"].into())
.into_iter()
.map(to_index::<md::Slide>),
gen::gather("content/wiki/**/*", &["md"].into())
.into_iter()
.map(to_index::<md::Wiki>),
]
.into_iter()
.flatten()
.map(to_bundle)
.filter_map(|item| match item {
PipelineItem::Skip(skip) => {
println!("Skipping {}", skip.path);
None
},
PipelineItem::Take(take) => Some(take),
})
.collect();
let assets: Vec<Output> = vec![
assets,
vec![ vec![
Output { gen::Virtual::new("map/index.html", |_| html::map().render().to_owned().into()).into(),
kind: Dynamic::new(|_| html::map().render().to_owned().into()).into(), gen::Virtual::new("search/index.html", |_| html::search().render().to_owned().into()).into(),
path: "map/index.html".into(), gen::Asset {
link: None,
},
Output {
kind: Dynamic::new(|_| html::search().render().to_owned().into()).into(),
path: "search/index.html".into(),
link: None,
},
Output {
kind: Asset {
kind: gen::AssetKind::Html(Box::new(|_| { kind: gen::AssetKind::Html(Box::new(|_| {
let data = std::fs::read_to_string("content/index.md").unwrap(); let data = std::fs::read_to_string("content/index.md").unwrap();
let (_, html, _) = text::md::parse(&data, None); let (_, html, bib) = text::md::parse(&data, None);
html::home(Raw(html)).render().to_owned().into() html::home(Raw(html)).render().to_owned().into()
})).into(), })),
meta: gen::FileItem { out: "index.html".into(),
kind: gen::FileItemKind::Index, link: None,
meta: gen::Source {
kind: gen::SourceKind::Index,
ext: "md".into(),
dirs: "".into(),
path: "content/index.md".into() path: "content/index.md".into()
} }
}.into(), }.into(),
path: "index.html".into(), gen::Virtual("posts/index.html".into(), Box::new(|all|
link: None, to_list(all.get_links("posts/**/*.html"))
}.into(), )).into(),
Output { gen::Virtual("slides/index.html".into(), Box::new(|all|
kind: Dynamic::new(|sack| to_list(sack.get_links("posts/**/*.html"))).into(), to_list(all.get_links("slides/**/*.html"))
path: "posts/index.html".into(), )).into(),
link: None,
},
Output {
kind: Dynamic::new(|sack| to_list(sack.get_links("slides/**/*.html"))).into(),
path: "slides/index.html".into(),
link: None,
},
], ],
] gen::gather("content/about.md", &["md"].into())
.into_iter()
.map(transform::<md::Post>)
.map(Into::into)
.collect(),
gen::gather("content/posts/**/*", &["md", "mdx"].into())
.into_iter()
.map(transform::<md::Post>)
.map(Into::into)
.collect(),
gen::gather("content/slides/**/*", &["md", "lhs"].into())
.into_iter()
.map(transform::<md::Slide>)
.map(Into::into)
.collect(),
gen::gather("content/wiki/**/*", &["md"].into())
.into_iter()
.map(transform::<md::Wiki>)
.map(Into::into)
.collect(),
];
let all: Vec<gen::Item> = assets
.into_iter() .into_iter()
.flatten() .flatten()
.collect(); .collect();
{ {
let now = std::time::Instant::now(); let now = std::time::Instant::now();
gen::render_all(&assets); gen::render(&all);
println!("Elapsed: {:.2?}", now.elapsed()); println!("Elapsed: {:.2?}", now.elapsed());
} }
utils::copy_recursively(std::path::Path::new("public"), std::path::Path::new("dist")).unwrap(); utils::copy_recursively(std::path::Path::new("public"), std::path::Path::new("dist")).unwrap();
build_styles(); let css = grass::from_path("styles/styles.scss", &grass::Options::default()).unwrap();
fs::write("dist/styles.css", css).unwrap();
let res = Command::new("pagefind") let res = Command::new("pagefind")
.args(["--site", "dist"]) .args(["--site", "dist"])
@ -378,17 +330,4 @@ fn build() {
.unwrap(); .unwrap();
println!("{}", String::from_utf8(res.stderr).unwrap()); println!("{}", String::from_utf8(res.stderr).unwrap());
}
fn main() {
let args = Args::parse();
match args.mode {
Mode::Build => build(),
Mode::Watch => {
build();
watch::watch().unwrap()
},
}
} }

View file

@ -88,9 +88,6 @@ fn make_bib<'a, 'b>(stream: Vec<Event<'a>>, lib: &'b Library) -> (Vec<Event<'a>>
} }
} }
// add fake citation to make all entries show up
driver.citation(CitationRequest::from_items(lib.iter().map(CitationItem::with_entry).collect(), &STYLE, &LOCALE));
let res = driver.finish(BibliographyRequest { style: &STYLE, locale: None, locale_files: &LOCALE }); let res = driver.finish(BibliographyRequest { style: &STYLE, locale: None, locale_files: &LOCALE });
let mut n = 0; let mut n = 0;

View file

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use tree_sitter::Language;
use tree_sitter_highlight::HighlightConfiguration; use tree_sitter_highlight::HighlightConfiguration;
use super::captures; use super::captures;
@ -16,34 +17,6 @@ macro_rules! query {
}; };
} }
macro_rules! insert {
($_:tt $e:expr) => { $e };
}
macro_rules! merge {
([$($e:expr),+ $(,)?]) => { &format!(concat!($(insert!($e "{} ")),*), $($e),* ) };
($e:expr) => { $e };
}
macro_rules! language {
($name:expr, $lang:expr, $highlights:expr, $injections:expr, $locals:expr $(,)?) => {
(
$name,
{
let mut config = HighlightConfiguration::new(
$lang,
$name,
$highlights,
$injections,
$locals,
).unwrap();
config.configure(captures::NAMES);
config
}
)
};
}
pub static EXTENSIONS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| { pub static EXTENSIONS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
HashMap::from([ HashMap::from([
("hs", "haskell"), ("hs", "haskell"),
@ -51,12 +24,25 @@ pub static EXTENSIONS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(||
("md", "markdown"), ("md", "markdown"),
("mdx", "markdown"), ("mdx", "markdown"),
("py", "python"), ("py", "python"),
("scm", "scheme"), ("query", "query"),
// ("scm", "scheme"),
("scss", "scss"),
("ts", "javascript"), ("ts", "javascript"),
("typescript", "javascript") ("typescript", "javascript")
]) ])
}); });
fn config_for(
lang: Language,
name: &str,
highlights: &str,
injections: &str,
locals: &str,
) -> HighlightConfiguration {
let mut config = HighlightConfiguration::new(lang, name, highlights, injections, locals).unwrap();
config.configure(captures::NAMES);
config
}
pub static CONFIGS: Lazy<HashMap<&'static str, HighlightConfiguration>> = Lazy::new(|| { pub static CONFIGS: Lazy<HashMap<&'static str, HighlightConfiguration>> = Lazy::new(|| {
HashMap::from([ HashMap::from([
@ -69,129 +55,161 @@ pub static CONFIGS: Lazy<HashMap<&'static str, HighlightConfiguration>> = Lazy::
// "", // "",
// ) // )
// ), // ),
language!( // (
"css", // "css",
tree_sitter_css::language(), // config_for(
tree_sitter_css::HIGHLIGHTS_QUERY, // tree_sitter_css::language(),
"", // query!("css/highlights"),
"", // "",
), // "",
language!( // )
// ),
(
"haskell", "haskell",
tree_sitter_haskell::language(), config_for(
tree_sitter_haskell::HIGHLIGHTS_QUERY, npezza93_tree_sitter_haskell::language(),
"haskell",
npezza93_tree_sitter_haskell::HIGHLIGHTS_QUERY,
"", "",
tree_sitter_haskell::LOCALS_QUERY, npezza93_tree_sitter_haskell::LOCALS_QUERY,
)
), ),
language!( // (
"html", // "html",
tree_sitter_html::language(), // config_for(
tree_sitter_html::HIGHLIGHTS_QUERY, // tree_sitter_html::language(),
tree_sitter_html::INJECTIONS_QUERY, // tree_sitter_html::HIGHLIGHTS_QUERY,
"", // tree_sitter_html::INJECTIONS_QUERY,
), // "",
language!( // )
// ),
(
"javascript", "javascript",
config_for(
tree_sitter_javascript::language(), tree_sitter_javascript::language(),
merge!([ "javascript",
&format!("{} {}",
query!("ecma/highlights"), query!("ecma/highlights"),
tree_sitter_javascript::HIGHLIGHT_QUERY, tree_sitter_javascript::HIGHLIGHT_QUERY,
]),
tree_sitter_javascript::INJECTIONS_QUERY,
tree_sitter_javascript::LOCALS_QUERY,
), ),
language!( tree_sitter_javascript::INJECTION_QUERY,
tree_sitter_javascript::LOCALS_QUERY,
)
),
(
"jsx", "jsx",
config_for(
tree_sitter_javascript::language(), tree_sitter_javascript::language(),
merge!([ "jsx",
&format!("{} {} {}",
query!("ecma/highlights"), query!("ecma/highlights"),
tree_sitter_javascript::HIGHLIGHT_QUERY, tree_sitter_javascript::HIGHLIGHT_QUERY,
tree_sitter_javascript::JSX_HIGHLIGHT_QUERY, tree_sitter_javascript::JSX_HIGHLIGHT_QUERY,
]),
tree_sitter_javascript::INJECTIONS_QUERY,
tree_sitter_javascript::LOCALS_QUERY,
), ),
language!( tree_sitter_javascript::INJECTION_QUERY,
tree_sitter_javascript::LOCALS_QUERY,
)
),
(
"markdown", "markdown",
config_for(
tree_sitter_md::language(), tree_sitter_md::language(),
"markdown",
tree_sitter_md::HIGHLIGHT_QUERY_BLOCK, tree_sitter_md::HIGHLIGHT_QUERY_BLOCK,
tree_sitter_md::INJECTION_QUERY_BLOCK, tree_sitter_md::INJECTION_QUERY_BLOCK,
"", "",
)
), ),
language!( (
"python", "python",
config_for(
tree_sitter_python::language(), tree_sitter_python::language(),
"python",
tree_sitter_python::HIGHLIGHTS_QUERY, tree_sitter_python::HIGHLIGHTS_QUERY,
"", "",
"", "",
)
), ),
language!( (
"regex", "query",
tree_sitter_regex::language(), config_for(
query!("regex/highlights"), tree_sitter_query::language(),
"", "query",
tree_sitter_query::HIGHLIGHTS_QUERY,
tree_sitter_query::INJECTIONS_QUERY,
"", "",
)
), ),
language!( // (
// "regex",
// config_for(
// tree_sitter_regex::language(),
// query!("regex/highlights"),
// "",
// "",
// )
// ),
(
"rust", "rust",
config_for(
tree_sitter_rust::language(), tree_sitter_rust::language(),
"rust",
tree_sitter_rust::HIGHLIGHTS_QUERY, tree_sitter_rust::HIGHLIGHTS_QUERY,
tree_sitter_rust::INJECTIONS_QUERY, tree_sitter_rust::INJECTIONS_QUERY,
"", "",
)
), ),
language!( // (
"scss", // "scheme",
tree_sitter_scss::language(), // config_for(
merge!([ // tree_sitter_scheme::language(),
tree_sitter_css::HIGHLIGHTS_QUERY, // tree_sitter_scheme::HIGHLIGHTS_QUERY,
tree_sitter_scss::HIGHLIGHTS_QUERY, // "",
]), // "",
"", // )
"", // ),
), // (
language!( // "toml",
"query", // config_for(
tree_sitter_query::language(), // tree_sitter_toml::language(),
tree_sitter_query::HIGHLIGHTS_QUERY, // tree_sitter_toml::HIGHLIGHT_QUERY,
"", // "",
"", // "",
), // )
language!( // ),
"toml", // (
tree_sitter_toml_ng::language(), // "tsx",
tree_sitter_toml_ng::HIGHLIGHTS_QUERY, // config_for(
"", // tree_sitter_typescript::language_tsx(),
"", // &format!("{} {} {} {}",
), // query!("ecma/highlights"),
language!( // tree_sitter_javascript::HIGHLIGHT_QUERY,
"typescript", // tree_sitter_javascript::JSX_HIGHLIGHT_QUERY,
tree_sitter_typescript::language_typescript(), // tree_sitter_typescript::HIGHLIGHT_QUERY,
merge!([ // ),
query!("ecma/highlights"), // tree_sitter_javascript::INJECTION_QUERY,
tree_sitter_javascript::HIGHLIGHT_QUERY, // &format!("{} {}",
tree_sitter_typescript::HIGHLIGHTS_QUERY, // tree_sitter_javascript::LOCALS_QUERY,
]), // tree_sitter_typescript::LOCALS_QUERY
tree_sitter_javascript::INJECTIONS_QUERY, // )
merge!([ // )
tree_sitter_javascript::LOCALS_QUERY, // ),
tree_sitter_typescript::LOCALS_QUERY, // (
]) // "typescript",
), // config_for(
language!( // tree_sitter_typescript::language_typescript(),
"tsx", // &format!("{} {} {}",
tree_sitter_typescript::language_tsx(), // query!("ecma/highlights"),
merge!([ // tree_sitter_javascript::HIGHLIGHT_QUERY,
query!("ecma/highlights"), // tree_sitter_typescript::HIGHLIGHT_QUERY,
tree_sitter_javascript::HIGHLIGHT_QUERY, // ),
tree_sitter_javascript::JSX_HIGHLIGHT_QUERY, // tree_sitter_javascript::INJECTION_QUERY,
tree_sitter_typescript::HIGHLIGHTS_QUERY, // &format!("{} {}",
]), // tree_sitter_javascript::LOCALS_QUERY,
tree_sitter_javascript::INJECTIONS_QUERY, // tree_sitter_typescript::LOCALS_QUERY
merge!([ // ),
tree_sitter_javascript::LOCALS_QUERY, // )
tree_sitter_typescript::LOCALS_QUERY, // ),
]),
),
]) ])
}); });

View file

@ -1,94 +0,0 @@
use std::io::Result;
use std::net::{TcpListener, TcpStream};
use std::path::Path;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use std::thread::JoinHandle;
use std::time::Duration;
use notify::RecursiveMode;
use notify_debouncer_mini::new_debouncer;
use tungstenite::WebSocket;
use crate::build::build_styles;
fn new_thread_ws_incoming(
server: TcpListener,
client: Arc<Mutex<Vec<WebSocket<TcpStream>>>>,
) -> JoinHandle<()> {
std::thread::spawn(move || {
for stream in server.incoming() {
let socket = tungstenite::accept(stream.unwrap()).unwrap();
client.lock().unwrap().push(socket);
}
})
}
fn new_thread_ws_reload(
client: Arc<Mutex<Vec<WebSocket<TcpStream>>>>,
) -> (Sender<()>, JoinHandle<()>) {
let (tx, rx) = std::sync::mpsc::channel();
let thread = std::thread::spawn(move || {
while rx.recv().is_ok() {
let mut clients = client.lock().unwrap();
let mut broken = vec![];
for (i, socket) in clients.iter_mut().enumerate() {
match socket.send("reload".into()) {
Ok(_) => {}
Err(tungstenite::error::Error::Io(e)) => {
if e.kind() == std::io::ErrorKind::BrokenPipe {
broken.push(i);
}
}
Err(e) => {
eprintln!("Error: {:?}", e);
}
}
}
for i in broken.into_iter().rev() {
clients.remove(i);
}
// Close all but the last 10 connections
let len = clients.len();
if len > 10 {
for mut socket in clients.drain(0..len - 10) {
socket.close(None).ok();
}
}
}
});
(tx, thread)
}
pub fn watch() -> Result<()> {
let server = TcpListener::bind("127.0.0.1:1337")?;
let client = Arc::new(Mutex::new(vec![]));
let (tx, rx) = std::sync::mpsc::channel();
let mut debouncer = new_debouncer(Duration::from_secs(1), tx).unwrap();
debouncer
.watcher()
.watch(Path::new("./styles"), RecursiveMode::Recursive)
.unwrap();
let thread_i = new_thread_ws_incoming(server, client.clone());
let (tx_reload, thread_o) = new_thread_ws_reload(client.clone());
while let Ok(ev) = rx.recv().unwrap() {
build_styles();
tx_reload.send(()).unwrap();
}
thread_i.join().unwrap();
thread_o.join().unwrap();
Ok(())
}

View file

@ -1,40 +1,28 @@
.markdown { .markdown {
h1 { > h1 {
font-size: 2.5rem; font-size: 2.0274rem;
} }
h2 { > h2 {
font-size: 1.8rem; font-size: 1.802rem;
} }
h3 { > h3 {
font-size: 1.5rem; font-size: 1.602rem;
} }
h4, > h5, > h6 { > h4, > h5, > h6 {
font-size: 1.2rem; font-size: 1.424rem;
} }
p { > p {
margin: 0.5em 0; margin: 0.5em 0;
line-height: 1.5em;
hyphens: auto; hyphens: auto;
text-align: justify; text-align: justify;
line-height: 1.5em;
} }
ul, ol { a:not([class]) {
padding-left: 1em;
ul, ol {
padding-left: 1em;
}
}
li {
line-height: 1.5em;
}
a {
color: var(--c-primary); color: var(--c-primary);
font-family: var(--serif); font-family: var(--serif);
font-weight: 500; font-weight: 500;
@ -56,6 +44,13 @@
} }
} }
> ul, ol {
padding-left: 1em;
ul, ol {
padding-left: 1em;
}
}
img:not([class]) { img:not([class]) {
max-width: 100%; max-width: 100%;